]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: improve s390x sign/zero extension removal
authorMichael Munday <mike.munday@ibm.com>
Thu, 25 Apr 2019 13:41:46 +0000 (09:41 -0400)
committerMichael Munday <mike.munday@ibm.com>
Tue, 10 Sep 2019 13:17:24 +0000 (13:17 +0000)
This CL gets rid of the MOVDreg and MOVDnop SSA operations on
s390x. They were originally inserted to help avoid situations
where a sign/zero extension was elided but a spill invalidated
the optimization. It's not really clear we need to do this though
(amd64 doesn't have these ops for example) so long as we are
careful when removing sign/zero extensions. Also, the MOVDreg
technique doesn't work if the register is spilled before the
MOVDreg op (I haven't seen that in practice).

Removing these ops reduces the complexity of the rules and also
allows us to unblock optimizations. For example, the compiler can
now merge the loads in binary.{Big,Little}Endian.PutUint16 which
it wasn't able to do before. This CL reduces the size of the .text
section in the go tool by about 4.7KB (0.09%).

Change-Id: Icaddae7f2e4f9b2debb6fabae845adb3f73b41db
Reviewed-on: https://go-review.googlesource.com/c/go/+/173897
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/s390x/ssa.go
src/cmd/compile/internal/ssa/gen/S390X.rules
src/cmd/compile/internal/ssa/gen/S390XOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteS390X.go
test/codegen/memcombine.go

index 7ddebe7b6480cfaf02e5b12eb74fe514add6e0b8..fc828946b9bd909ec1794c8cf59a359380a5c290 100644 (file)
@@ -482,7 +482,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.To.Type = obj.TYPE_MEM
                p.To.Reg = v.Args[0].Reg()
                gc.AddAux2(&p.To, v, sc.Off())
-       case ssa.OpCopy, ssa.OpS390XMOVDreg:
+       case ssa.OpCopy:
                if v.Type.IsMemory() {
                        return
                }
@@ -491,11 +491,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                if x != y {
                        opregreg(s, moveByType(v.Type), y, x)
                }
-       case ssa.OpS390XMOVDnop:
-               if v.Reg() != v.Args[0].Reg() {
-                       v.Fatalf("input[0] and output not in same register %s", v.LongString())
-               }
-               // nothing to do
        case ssa.OpLoadReg:
                if v.Type.IsFlags() {
                        v.Fatalf("load flags not implemented: %v", v.LongString())
index ee670a908de522beeeaccf03c1e53b9a146d3e38..91f88a1d63cad01aa915b108c64be7dbb149b315 100644 (file)
 // ***************************
 // TODO: Should the optimizations be a separate pass?
 
-// Fold unnecessary type conversions.
-(MOVDreg <t> x) && t.Compare(x.Type) == types.CMPeq -> x
-(MOVDnop <t> x) && t.Compare(x.Type) == types.CMPeq -> x
-
-// Propagate constants through type conversions.
-(MOVDreg (MOVDconst [c])) -> (MOVDconst [c])
-(MOVDnop (MOVDconst [c])) -> (MOVDconst [c])
-
-// If a register move has only 1 use, just use the same register without emitting instruction.
-// MOVDnop doesn't emit instruction, only for ensuring the type.
-(MOVDreg x) && x.Uses == 1 -> (MOVDnop x)
-
-// Fold type changes into loads.
-(MOVDreg <t> x:(MOVBZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZload <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVBload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBload  <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVHZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZload <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVHload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHload  <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVWZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZload <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVWload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload  <t> [off] {sym} ptr mem)
-(MOVDreg <t> x:(MOVDload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDload  <t> [off] {sym} ptr mem)
-
-(MOVDnop <t> x:(MOVBZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZload <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVBload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBload  <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVHZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZload <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVHload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHload  <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVWZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZload <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVWload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload  <t> [off] {sym} ptr mem)
-(MOVDnop <t> x:(MOVDload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDload  <t> [off] {sym} ptr mem)
-
-(MOVDreg <t> x:(MOVBZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVBloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVHZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVHloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVWloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDreg <t> x:(MOVDloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDloadidx  <t> [off] {sym} ptr idx mem)
-
-(MOVDnop <t> x:(MOVBZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVBloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVHZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVHloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVWloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx  <t> [off] {sym} ptr idx mem)
-(MOVDnop <t> x:(MOVDloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVDloadidx  <t> [off] {sym} ptr idx mem)
-
-// Fold sign extensions into conditional moves of constants.
-// Designed to remove the MOVBZreg inserted by the If lowering.
-(MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
-(MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+// Note: when removing unnecessary sign/zero extensions.
+//
+// After a value is spilled it is restored using a sign- or zero-extension
+// to register-width as appropriate for its type. For example, a uint8 will
+// be restored using a MOVBZ (llgc) instruction which will zero extend the
+// 8-bit value to 64-bits.
+//
+// This is a hazard when folding sign- and zero-extensions since we need to
+// ensure not only that the value in the argument register is correctly
+// extended but also that it will still be correctly extended if it is
+// spilled and restored.
+//
+// In general this means we need type checks when the RHS of a rule is an
+// OpCopy (i.e. "(... x:(...) ...) -> x").
+
+// Merge double extensions.
+(MOV(H|HZ)reg e:(MOV(B|BZ)reg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(W|WZ)reg e:(MOV(B|BZ)reg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(W|WZ)reg e:(MOV(H|HZ)reg x)) && clobberIfDead(e) -> (MOV(H|HZ)reg x)
+
+// Bypass redundant sign extensions.
+(MOV(B|BZ)reg e:(MOVBreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVHreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVWreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(H|HZ)reg e:(MOVHreg x)) && clobberIfDead(e) -> (MOV(H|HZ)reg x)
+(MOV(H|HZ)reg e:(MOVWreg x)) && clobberIfDead(e) -> (MOV(H|HZ)reg x)
+(MOV(W|WZ)reg e:(MOVWreg x)) && clobberIfDead(e) -> (MOV(W|WZ)reg x)
+
+// Bypass redundant zero extensions.
+(MOV(B|BZ)reg e:(MOVBZreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVHZreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(B|BZ)reg e:(MOVWZreg x)) && clobberIfDead(e) -> (MOV(B|BZ)reg x)
+(MOV(H|HZ)reg e:(MOVHZreg x)) && clobberIfDead(e) -> (MOV(H|HZ)reg x)
+(MOV(H|HZ)reg e:(MOVWZreg x)) && clobberIfDead(e) -> (MOV(H|HZ)reg x)
+(MOV(W|WZ)reg e:(MOVWZreg x)) && clobberIfDead(e) -> (MOV(W|WZ)reg x)
+
+// Remove zero extensions after zero extending load.
+// Note: take care that if x is spilled it is restored correctly.
+(MOV(B|H|W)Zreg x:(MOVBZload    _   _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) -> x
+(MOV(B|H|W)Zreg x:(MOVBZloadidx _ _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) -> x
+(MOV(H|W)Zreg   x:(MOVHZload    _   _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) -> x
+(MOV(H|W)Zreg   x:(MOVHZloadidx _ _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) -> x
+(MOVWZreg       x:(MOVWZload    _   _)) && (!x.Type.IsSigned() || x.Type.Size() > 4) -> x
+(MOVWZreg       x:(MOVWZloadidx _ _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 4) -> x
+
+// Remove sign extensions after sign extending load.
+// Note: take care that if x is spilled it is restored correctly.
+(MOV(B|H|W)reg x:(MOVBload    _   _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+(MOV(B|H|W)reg x:(MOVBloadidx _ _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+(MOV(H|W)reg   x:(MOVHload    _   _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+(MOV(H|W)reg   x:(MOVHloadidx _ _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+(MOVWreg       x:(MOVWload    _   _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+(MOVWreg       x:(MOVWloadidx _ _ _)) && (x.Type.IsSigned() || x.Type.Size() == 8) -> x
+
+// Remove sign extensions after zero extending load.
+// These type checks are probably unnecessary but do them anyway just in case.
+(MOV(H|W)reg x:(MOVBZload    _   _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) -> x
+(MOV(H|W)reg x:(MOVBZloadidx _ _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 1) -> x
+(MOVWreg     x:(MOVHZload    _   _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) -> x
+(MOVWreg     x:(MOVHZloadidx _ _ _)) && (!x.Type.IsSigned() || x.Type.Size() > 2) -> x
+
+// Fold sign and zero extensions into loads.
+//
+// Note: The combined instruction must end up in the same block
+// as the original load. If not, we end up making a value with
+// memory type live in two different blocks, which can lead to
+// multiple memory values alive simultaneously.
+//
+// Make sure we don't combine these ops if the load has another use.
+// This prevents a single load from being split into multiple loads
+// which then might return different values.  See test/atomicload.go.
+(MOV(B|H|W)Zreg <t> x:(MOV(B|H|W)load [o] {s} p mem))
+  && x.Uses == 1
+  && clobber(x)
+  -> @x.Block (MOV(B|H|W)Zload <t> [o] {s} p mem)
+(MOV(B|H|W)reg <t> x:(MOV(B|H|W)Zload [o] {s} p mem))
+  && x.Uses == 1
+  && clobber(x)
+  -> @x.Block (MOV(B|H|W)load <t> [o] {s} p mem)
+(MOV(B|H|W)Zreg <t> x:(MOV(B|H|W)loadidx [o] {s} p i mem))
+  && x.Uses == 1
+  && clobber(x)
+  -> @x.Block (MOV(B|H|W)Zloadidx <t> [o] {s} p i mem)
+(MOV(B|H|W)reg <t> x:(MOV(B|H|W)Zloadidx [o] {s} p i mem))
+  && x.Uses == 1
+  && clobber(x)
+  -> @x.Block (MOV(B|H|W)loadidx <t> [o] {s} p i mem)
+
+// Remove zero extensions after argument load.
+(MOVBZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() == 1 -> x
+(MOVHZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() <= 2 -> x
+(MOVWZreg x:(Arg <t>)) && !t.IsSigned() && t.Size() <= 4 -> x
+
+// Remove sign extensions after argument load.
+(MOVBreg x:(Arg <t>)) && t.IsSigned() && t.Size() == 1 -> x
+(MOVHreg x:(Arg <t>)) && t.IsSigned() && t.Size() <= 2 -> x
+(MOVWreg x:(Arg <t>)) && t.IsSigned() && t.Size() <= 4 -> x
+
+// Fold zero extensions into constants.
+(MOVBZreg (MOVDconst [c])) -> (MOVDconst [int64( uint8(c))])
+(MOVHZreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))])
+(MOVWZreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))])
+
+// Fold sign extensions into constants.
+(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64( int8(c))])
+(MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))])
+(MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))])
+
+// Remove zero extension of conditional move.
+// Note: only for MOVBZreg for now since it is added as part of 'if' statement lowering.
+(MOVBZreg x:(MOVD(LT|LE|GT|GE|EQ|NE|GTnoinv|GEnoinv) (MOVDconst [c]) (MOVDconst [d]) _))
+  && int64(uint8(c)) == c
+  && int64(uint8(d)) == d
+  && (!x.Type.IsSigned() || x.Type.Size() > 1)
+  -> x
 
 // Fold boolean tests into blocks.
 (NE (CMPWconst [0] (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LT cmp yes no)
        -> (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst <typ.UInt32> [c&63] y))
 (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst [c] y)) && c&63 == 63
        -> (S(LD|RD|RAD|LW|RW|RAW) x y)
-(SLD  x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SLD  x y)
-(SRD  x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SRD  x y)
-(SRAD x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SRAD x y)
-(SLW  x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SLW  x y)
-(SRW  x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SRW  x y)
-(SRAW x (MOV(D|W|H|B|WZ|HZ|BZ)reg y)) -> (SRAW x y)
+(SLD  x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SLD  x y)
+(SRD  x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SRD  x y)
+(SRAD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SRAD x y)
+(SLW  x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SLW  x y)
+(SRW  x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SRW  x y)
+(SRAW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) -> (SRAW x y)
 
 // Constant rotate generation
 (RLL  x (MOVDconst [c])) -> (RLLconst  x [c&31])
 (MOVDEQ x y (InvertFlags cmp)) -> (MOVDEQ x y cmp)
 (MOVDNE x y (InvertFlags cmp)) -> (MOVDNE x y cmp)
 
-// don't extend after proper load
-(MOVBreg x:(MOVBload _ _)) -> (MOVDreg x)
-(MOVBZreg x:(MOVBZload _ _)) -> (MOVDreg x)
-(MOVHreg x:(MOVBload _ _)) -> (MOVDreg x)
-(MOVHreg x:(MOVBZload _ _)) -> (MOVDreg x)
-(MOVHreg x:(MOVHload _ _)) -> (MOVDreg x)
-(MOVHZreg x:(MOVBZload _ _)) -> (MOVDreg x)
-(MOVHZreg x:(MOVHZload _ _)) -> (MOVDreg x)
-(MOVWreg x:(MOVBload _ _)) -> (MOVDreg x)
-(MOVWreg x:(MOVBZload _ _)) -> (MOVDreg x)
-(MOVWreg x:(MOVHload _ _)) -> (MOVDreg x)
-(MOVWreg x:(MOVHZload _ _)) -> (MOVDreg x)
-(MOVWreg x:(MOVWload _ _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVBZload _ _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVHZload _ _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVWZload _ _)) -> (MOVDreg x)
-
-// don't extend if argument is already extended
-(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> (MOVDreg x)
-(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> (MOVDreg x)
-(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> (MOVDreg x)
-(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> (MOVDreg x)
-(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> (MOVDreg x)
-(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> (MOVDreg x)
-
-// fold double extensions
-(MOVBreg x:(MOVBreg _)) -> (MOVDreg x)
-(MOVBZreg x:(MOVBZreg _)) -> (MOVDreg x)
-(MOVHreg x:(MOVBreg _)) -> (MOVDreg x)
-(MOVHreg x:(MOVBZreg _)) -> (MOVDreg x)
-(MOVHreg x:(MOVHreg _)) -> (MOVDreg x)
-(MOVHZreg x:(MOVBZreg _)) -> (MOVDreg x)
-(MOVHZreg x:(MOVHZreg _)) -> (MOVDreg x)
-(MOVWreg x:(MOVBreg _)) -> (MOVDreg x)
-(MOVWreg x:(MOVBZreg _)) -> (MOVDreg x)
-(MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
-(MOVWreg x:(MOVHZreg _)) -> (MOVDreg x)
-(MOVWreg x:(MOVWreg _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVBZreg _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVHZreg _)) -> (MOVDreg x)
-(MOVWZreg x:(MOVWZreg _)) -> (MOVDreg x)
-
-(MOVBreg (MOVBZreg x)) -> (MOVBreg x)
-(MOVBZreg (MOVBreg x)) -> (MOVBZreg x)
-(MOVHreg (MOVHZreg x)) -> (MOVHreg x)
-(MOVHZreg (MOVHreg x)) -> (MOVHZreg x)
-(MOVWreg (MOVWZreg x)) -> (MOVWreg x)
-(MOVWZreg (MOVWreg x)) -> (MOVWZreg x)
-
-// fold extensions into constants
-(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
-(MOVBZreg (MOVDconst [c])) -> (MOVDconst [int64(uint8(c))])
-(MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))])
-(MOVHZreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))])
-(MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))])
-(MOVWZreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))])
-
-// sign extended loads
-// Note: The combined instruction must end up in the same block
-// as the original load. If not, we end up making a value with
-// memory type live in two different blocks, which can lead to
-// multiple memory values alive simultaneously.
-// Make sure we don't combine these ops if the load has another use.
-// This prevents a single load from being split into multiple loads
-// which then might return different values.  See test/atomicload.go.
-(MOVBreg  x:(MOVBZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBload  <v.Type> [off] {sym} ptr mem)
-(MOVBreg  x:(MOVBload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBload  <v.Type> [off] {sym} ptr mem)
-(MOVBZreg x:(MOVBZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZload <v.Type> [off] {sym} ptr mem)
-(MOVBZreg x:(MOVBload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZload <v.Type> [off] {sym} ptr mem)
-(MOVHreg  x:(MOVHZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHload  <v.Type> [off] {sym} ptr mem)
-(MOVHreg  x:(MOVHload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHload  <v.Type> [off] {sym} ptr mem)
-(MOVHZreg x:(MOVHZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZload <v.Type> [off] {sym} ptr mem)
-(MOVHZreg x:(MOVHload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZload <v.Type> [off] {sym} ptr mem)
-(MOVWreg  x:(MOVWZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload  <v.Type> [off] {sym} ptr mem)
-(MOVWreg  x:(MOVWload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload  <v.Type> [off] {sym} ptr mem)
-(MOVWZreg x:(MOVWZload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZload <v.Type> [off] {sym} ptr mem)
-(MOVWZreg x:(MOVWload  [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZload <v.Type> [off] {sym} ptr mem)
-
-(MOVBreg  x:(MOVBZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVBreg  x:(MOVBloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVBZreg x:(MOVBZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZloadidx <v.Type> [off] {sym} ptr idx mem)
-(MOVBZreg x:(MOVBloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBZloadidx <v.Type> [off] {sym} ptr idx mem)
-(MOVHreg  x:(MOVHZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVHreg  x:(MOVHloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVHZreg x:(MOVHZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZloadidx <v.Type> [off] {sym} ptr idx mem)
-(MOVHZreg x:(MOVHloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVHZloadidx <v.Type> [off] {sym} ptr idx mem)
-(MOVWreg  x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVWreg  x:(MOVWloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx  <v.Type> [off] {sym} ptr idx mem)
-(MOVWZreg x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
-(MOVWZreg x:(MOVWloadidx  [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
-
 // replace load from same location as preceding store with copy
-(MOVDload  [off] {sym} ptr1 (MOVDstore  [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> (MOVDreg x)
+(MOVDload  [off] {sym} ptr1 (MOVDstore  [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> x
 (MOVWload  [off] {sym} ptr1 (MOVWstore  [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> (MOVWreg x)
 (MOVHload  [off] {sym} ptr1 (MOVHstore  [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> (MOVHreg x)
 (MOVBload  [off] {sym} ptr1 (MOVBstore  [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> (MOVBreg x)
 
 // remove unnecessary FPR <-> GPR moves
 (LDGR (LGDR x)) -> x
-(LGDR (LDGR x)) -> (MOVDreg x)
+(LGDR (LDGR x)) -> x
 
 // Don't extend before storing
 (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
index 943b9c2661c86d143f226691677c3fbe5c9b00ad..d8d7fd1ef632254edc922d05e564812c3dc50f8d 100644 (file)
@@ -373,9 +373,6 @@ func init() {
                {name: "MOVHZreg", argLength: 1, reg: gp11sp, asm: "MOVHZ", typ: "UInt64"}, // zero extend arg0 from int16 to int64
                {name: "MOVWreg", argLength: 1, reg: gp11sp, asm: "MOVW", typ: "Int64"},    // sign extend arg0 from int32 to int64
                {name: "MOVWZreg", argLength: 1, reg: gp11sp, asm: "MOVWZ", typ: "UInt64"}, // zero extend arg0 from int32 to int64
-               {name: "MOVDreg", argLength: 1, reg: gp11sp, asm: "MOVD"},                  // move from arg0
-
-               {name: "MOVDnop", argLength: 1, reg: gp11, resultInArg0: true}, // nop, return arg0 in same register
 
                {name: "MOVDconst", reg: gp01, asm: "MOVD", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
 
index 5785e361dcd73174e7927782795489be150191ca..959f1defa8f3f30d98365700adbbeefb5b1a1f17 100644 (file)
@@ -1979,8 +1979,6 @@ const (
        OpS390XMOVHZreg
        OpS390XMOVWreg
        OpS390XMOVWZreg
-       OpS390XMOVDreg
-       OpS390XMOVDnop
        OpS390XMOVDconst
        OpS390XLDGR
        OpS390XLGDR
@@ -26605,32 +26603,6 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
-       {
-               name:   "MOVDreg",
-               argLen: 1,
-               asm:    s390x.AMOVD,
-               reg: regInfo{
-                       inputs: []inputInfo{
-                               {0, 56319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
-                       },
-                       outputs: []outputInfo{
-                               {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
-                       },
-               },
-       },
-       {
-               name:         "MOVDnop",
-               argLen:       1,
-               resultInArg0: true,
-               reg: regInfo{
-                       inputs: []inputInfo{
-                               {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
-                       },
-                       outputs: []outputInfo{
-                               {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
-                       },
-               },
-       },
        {
                name:              "MOVDconst",
                auxType:           auxInt64,
index 2de5e1b83f421a405b9c5bbb28afae0f9a71c1e6..20276ed6477240cb4063c9a67d2ef7190a08fbd5 100644 (file)
@@ -560,13 +560,13 @@ func rewriteValueS390X(v *Value) bool {
        case OpS390XMOVBZloadidx:
                return rewriteValueS390X_OpS390XMOVBZloadidx_0(v)
        case OpS390XMOVBZreg:
-               return rewriteValueS390X_OpS390XMOVBZreg_0(v) || rewriteValueS390X_OpS390XMOVBZreg_10(v)
+               return rewriteValueS390X_OpS390XMOVBZreg_0(v) || rewriteValueS390X_OpS390XMOVBZreg_10(v) || rewriteValueS390X_OpS390XMOVBZreg_20(v)
        case OpS390XMOVBload:
                return rewriteValueS390X_OpS390XMOVBload_0(v)
        case OpS390XMOVBloadidx:
                return rewriteValueS390X_OpS390XMOVBloadidx_0(v)
        case OpS390XMOVBreg:
-               return rewriteValueS390X_OpS390XMOVBreg_0(v)
+               return rewriteValueS390X_OpS390XMOVBreg_0(v) || rewriteValueS390X_OpS390XMOVBreg_10(v)
        case OpS390XMOVBstore:
                return rewriteValueS390X_OpS390XMOVBstore_0(v) || rewriteValueS390X_OpS390XMOVBstore_10(v)
        case OpS390XMOVBstoreconst:
@@ -591,10 +591,6 @@ func rewriteValueS390X(v *Value) bool {
                return rewriteValueS390X_OpS390XMOVDload_0(v)
        case OpS390XMOVDloadidx:
                return rewriteValueS390X_OpS390XMOVDloadidx_0(v)
-       case OpS390XMOVDnop:
-               return rewriteValueS390X_OpS390XMOVDnop_0(v) || rewriteValueS390X_OpS390XMOVDnop_10(v)
-       case OpS390XMOVDreg:
-               return rewriteValueS390X_OpS390XMOVDreg_0(v) || rewriteValueS390X_OpS390XMOVDreg_10(v)
        case OpS390XMOVDstore:
                return rewriteValueS390X_OpS390XMOVDstore_0(v)
        case OpS390XMOVDstoreconst:
@@ -638,7 +634,7 @@ func rewriteValueS390X(v *Value) bool {
        case OpS390XMOVWloadidx:
                return rewriteValueS390X_OpS390XMOVWloadidx_0(v)
        case OpS390XMOVWreg:
-               return rewriteValueS390X_OpS390XMOVWreg_0(v) || rewriteValueS390X_OpS390XMOVWreg_10(v)
+               return rewriteValueS390X_OpS390XMOVWreg_0(v) || rewriteValueS390X_OpS390XMOVWreg_10(v) || rewriteValueS390X_OpS390XMOVWreg_20(v)
        case OpS390XMOVWstore:
                return rewriteValueS390X_OpS390XMOVWstore_0(v) || rewriteValueS390X_OpS390XMOVWstore_10(v)
        case OpS390XMOVWstoreconst:
@@ -682,23 +678,23 @@ func rewriteValueS390X(v *Value) bool {
        case OpS390XRLLG:
                return rewriteValueS390X_OpS390XRLLG_0(v)
        case OpS390XSLD:
-               return rewriteValueS390X_OpS390XSLD_0(v) || rewriteValueS390X_OpS390XSLD_10(v)
+               return rewriteValueS390X_OpS390XSLD_0(v)
        case OpS390XSLW:
-               return rewriteValueS390X_OpS390XSLW_0(v) || rewriteValueS390X_OpS390XSLW_10(v)
+               return rewriteValueS390X_OpS390XSLW_0(v)
        case OpS390XSRAD:
-               return rewriteValueS390X_OpS390XSRAD_0(v) || rewriteValueS390X_OpS390XSRAD_10(v)
+               return rewriteValueS390X_OpS390XSRAD_0(v)
        case OpS390XSRADconst:
                return rewriteValueS390X_OpS390XSRADconst_0(v)
        case OpS390XSRAW:
-               return rewriteValueS390X_OpS390XSRAW_0(v) || rewriteValueS390X_OpS390XSRAW_10(v)
+               return rewriteValueS390X_OpS390XSRAW_0(v)
        case OpS390XSRAWconst:
                return rewriteValueS390X_OpS390XSRAWconst_0(v)
        case OpS390XSRD:
-               return rewriteValueS390X_OpS390XSRD_0(v) || rewriteValueS390X_OpS390XSRD_10(v)
+               return rewriteValueS390X_OpS390XSRD_0(v)
        case OpS390XSRDconst:
                return rewriteValueS390X_OpS390XSRDconst_0(v)
        case OpS390XSRW:
-               return rewriteValueS390X_OpS390XSRW_0(v) || rewriteValueS390X_OpS390XSRW_10(v)
+               return rewriteValueS390X_OpS390XSRW_0(v)
        case OpS390XSTM2:
                return rewriteValueS390X_OpS390XSTM2_0(v)
        case OpS390XSTMG2:
@@ -10676,14 +10672,15 @@ func rewriteValueS390X_OpS390XLEDBR_0(v *Value) bool {
 func rewriteValueS390X_OpS390XLGDR_0(v *Value) bool {
        // match: (LGDR (LDGR x))
        // cond:
-       // result: (MOVDreg x)
+       // result: x
        for {
                v_0 := v.Args[0]
                if v_0.Op != OpS390XLDGR {
                        break
                }
                x := v_0.Args[0]
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
@@ -10953,116 +10950,248 @@ func rewriteValueS390X_OpS390XMOVBZloadidx_0(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpS390XMOVBZreg_0(v *Value) bool {
-       // match: (MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       b := v.Block
+       // match: (MOVBZreg e:(MOVBreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDLT {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBreg {
                        break
                }
-               _ = x.Args[2]
-               x_0 := x.Args[0]
-               if x_0.Op != OpS390XMOVDconst {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               c := x_0.AuxInt
-               x_1 := x.Args[1]
-               if x_1.Op != OpS390XMOVDconst {
+               v.reset(OpS390XMOVBZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg e:(MOVHreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHreg {
                        break
                }
-               d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVBZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDLE {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
                        break
                }
-               _ = x.Args[2]
-               x_0 := x.Args[0]
-               if x_0.Op != OpS390XMOVDconst {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               c := x_0.AuxInt
-               x_1 := x.Args[1]
-               if x_1.Op != OpS390XMOVDconst {
+               v.reset(OpS390XMOVBZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg e:(MOVBZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBZreg {
                        break
                }
-               d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVBZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg e:(MOVHZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg x:(MOVBZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDGT {
+               if x.Op != OpS390XMOVBZload {
                        break
                }
-               _ = x.Args[2]
-               x_0 := x.Args[0]
-               if x_0.Op != OpS390XMOVDconst {
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               c := x_0.AuxInt
-               x_1 := x.Args[1]
-               if x_1.Op != OpS390XMOVDconst {
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBZloadidx {
                        break
                }
-               d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDGE {
+               if x.Op != OpS390XMOVBZloadidx {
                        break
                }
                _ = x.Args[2]
-               x_0 := x.Args[0]
-               if x_0.Op != OpS390XMOVDconst {
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               c := x_0.AuxInt
-               x_1 := x.Args[1]
-               if x_1.Op != OpS390XMOVDconst {
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg <t> x:(MOVBload [o] {s} p mem))
+       // cond: x.Uses == 1 && clobber(x)
+       // result: @x.Block (MOVBZload <t> [o] {s} p mem)
+       for {
+               t := v.Type
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBload {
                        break
                }
-               d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               o := x.AuxInt
+               s := x.Aux
+               mem := x.Args[1]
+               p := x.Args[0]
+               if !(x.Uses == 1 && clobber(x)) {
+                       break
+               }
+               b = x.Block
+               v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, t)
+               v.reset(OpCopy)
+               v.AddArg(v0)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(mem)
+               return true
+       }
+       return false
+}
+func rewriteValueS390X_OpS390XMOVBZreg_10(v *Value) bool {
+       b := v.Block
+       // match: (MOVBZreg <t> x:(MOVBloadidx [o] {s} p i mem))
+       // cond: x.Uses == 1 && clobber(x)
+       // result: @x.Block (MOVBZloadidx <t> [o] {s} p i mem)
+       for {
+               t := v.Type
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBloadidx {
+                       break
+               }
+               o := x.AuxInt
+               s := x.Aux
+               mem := x.Args[2]
+               p := x.Args[0]
+               i := x.Args[1]
+               if !(x.Uses == 1 && clobber(x)) {
+                       break
+               }
+               b = x.Block
+               v0 := b.NewValue0(v.Pos, OpS390XMOVBZloadidx, t)
+               v.reset(OpCopy)
+               v.AddArg(v0)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
+               v0.AddArg(mem)
+               return true
+       }
+       // match: (MOVBZreg x:(Arg <t>))
+       // cond: !t.IsSigned() && t.Size() == 1
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpArg {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               t := x.Type
+               if !(!t.IsSigned() && t.Size() == 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64( uint8(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(uint8(c))
+               return true
+       }
+       // match: (MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDEQ {
+               if x.Op != OpS390XMOVDLT {
                        break
                }
                _ = x.Args[2]
@@ -11076,19 +11205,20 @@ func rewriteValueS390X_OpS390XMOVBZreg_0(v *Value) bool {
                        break
                }
                d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDNE {
+               if x.Op != OpS390XMOVDLE {
                        break
                }
                _ = x.Args[2]
@@ -11102,19 +11232,20 @@ func rewriteValueS390X_OpS390XMOVBZreg_0(v *Value) bool {
                        break
                }
                d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDGTnoinv {
+               if x.Op != OpS390XMOVDGT {
                        break
                }
                _ = x.Args[2]
@@ -11128,19 +11259,20 @@ func rewriteValueS390X_OpS390XMOVBZreg_0(v *Value) bool {
                        break
                }
                d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _))
-       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-       // result: (MOVDreg x)
+       // match: (MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVDGEnoinv {
+               if x.Op != OpS390XMOVDGE {
                        break
                }
                _ = x.Args[2]
@@ -11154,187 +11286,125 @@ func rewriteValueS390X_OpS390XMOVBZreg_0(v *Value) bool {
                        break
                }
                d := x_1.AuxInt
-               if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVBZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               if x.Op != OpS390XMOVDEQ {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
-               v.AddArg(x)
-               return true
-       }
-       // match: (MOVBZreg x:(Arg <t>))
-       // cond: is8BitInt(t) && !isSigned(t)
-       // result: (MOVDreg x)
-       for {
-               x := v.Args[0]
-               if x.Op != OpArg {
+               _ = x.Args[2]
+               x_0 := x.Args[0]
+               if x_0.Op != OpS390XMOVDconst {
                        break
                }
-               t := x.Type
-               if !(is8BitInt(t) && !isSigned(t)) {
+               c := x_0.AuxInt
+               x_1 := x.Args[1]
+               if x_1.Op != OpS390XMOVDconst {
                        break
                }
-               v.reset(OpS390XMOVDreg)
-               v.AddArg(x)
-               return true
-       }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVBZreg_10(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (MOVBZreg x:(MOVBZreg _))
-       // cond:
-       // result: (MOVDreg x)
-       for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZreg {
+               d := x_1.AuxInt
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg (MOVBreg x))
-       // cond:
-       // result: (MOVBZreg x)
+       // match: (MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVBreg {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVDNE {
                        break
                }
-               x := v_0.Args[0]
-               v.reset(OpS390XMOVBZreg)
-               v.AddArg(x)
-               return true
-       }
-       // match: (MOVBZreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(uint8(c))])
-       for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               _ = x.Args[2]
+               x_0 := x.Args[0]
+               if x_0.Op != OpS390XMOVDconst {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(uint8(c))
-               return true
-       }
-       // match: (MOVBZreg x:(MOVBZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZload <v.Type> [off] {sym} ptr mem)
-       for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               c := x_0.AuxInt
+               x_1 := x.Args[1]
+               if x_1.Op != OpS390XMOVDconst {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               d := x_1.AuxInt
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVBload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZload <v.Type> [off] {sym} ptr mem)
+       // match: (MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
+               if x.Op != OpS390XMOVDGTnoinv {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               x_0 := x.Args[0]
+               if x_0.Op != OpS390XMOVDconst {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, v.Type)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVBZreg x:(MOVBZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZloadidx <v.Type> [off] {sym} ptr idx mem)
-       for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZloadidx {
+               c := x_0.AuxInt
+               x_1 := x.Args[1]
+               if x_1.Op != OpS390XMOVDconst {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               d := x_1.AuxInt
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBZloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVBZreg x:(MOVBloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZloadidx <v.Type> [off] {sym} ptr idx mem)
+       return false
+}
+func rewriteValueS390X_OpS390XMOVBZreg_20(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _))
+       // cond: int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBloadidx {
+               if x.Op != OpS390XMOVDGEnoinv {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               x_0 := x.Args[0]
+               if x_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := x_0.AuxInt
+               x_1 := x.Args[1]
+               if x_1.Op != OpS390XMOVDconst {
+                       break
+               }
+               d := x_1.AuxInt
+               if !(int64(uint8(c)) == c && int64(uint8(d)) == d && (!x.Type.IsSigned() || x.Type.Size() > 1)) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBZloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
        // match: (MOVBZreg (ANDWconst [m] x))
@@ -11589,176 +11659,240 @@ func rewriteValueS390X_OpS390XMOVBloadidx_0(v *Value) bool {
 }
 func rewriteValueS390X_OpS390XMOVBreg_0(v *Value) bool {
        b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (MOVBreg x:(MOVBload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVBreg e:(MOVBreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBreg x:(Arg <t>))
-       // cond: is8BitInt(t) && isSigned(t)
-       // result: (MOVDreg x)
+       // match: (MOVBreg e:(MOVHreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpArg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHreg {
                        break
                }
-               t := x.Type
-               if !(is8BitInt(t) && isSigned(t)) {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVBreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBreg x:(MOVBreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVBreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBreg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVBreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBreg (MOVBZreg x))
-       // cond:
+       // match: (MOVBreg e:(MOVBZreg x))
+       // cond: clobberIfDead(e)
        // result: (MOVBreg x)
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVBZreg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               x := v_0.Args[0]
                v.reset(OpS390XMOVBreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVBreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(int8(c))])
+       // match: (MOVBreg e:(MOVHZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHZreg {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(int8(c))
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBreg)
+               v.AddArg(x)
                return true
        }
-       // match: (MOVBreg x:(MOVBZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+       // match: (MOVBreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBreg x:(MOVBload _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               if x.Op != OpS390XMOVBload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[1]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVBreg x:(MOVBload [off] {sym} ptr mem))
+       // match: (MOVBreg <t> x:(MOVBZload [o] {s} p mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBload <v.Type> [off] {sym} ptr mem)
+       // result: @x.Block (MOVBload <t> [o] {s} p mem)
        for {
+               t := v.Type
                x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
+               if x.Op != OpS390XMOVBZload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[1]
-               ptr := x.Args[0]
+               p := x.Args[0]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBload, v.Type)
+               v0 := b.NewValue0(x.Pos, OpS390XMOVBload, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVBreg x:(MOVBZloadidx [off] {sym} ptr idx mem))
+       return false
+}
+func rewriteValueS390X_OpS390XMOVBreg_10(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (MOVBreg <t> x:(MOVBZloadidx [o] {s} p i mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBloadidx <v.Type> [off] {sym} ptr idx mem)
+       // result: @x.Block (MOVBloadidx <t> [o] {s} p i mem)
        for {
+               t := v.Type
                x := v.Args[0]
                if x.Op != OpS390XMOVBZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
+               p := x.Args[0]
+               i := x.Args[1]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBloadidx, v.Type)
+               v0 := b.NewValue0(v.Pos, OpS390XMOVBloadidx, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVBreg x:(MOVBloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBloadidx <v.Type> [off] {sym} ptr idx mem)
+       // match: (MOVBreg x:(Arg <t>))
+       // cond: t.IsSigned() && t.Size() == 1
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBloadidx {
+               if x.Op != OpArg {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               t := x.Type
+               if !(t.IsSigned() && t.Size() == 1) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64( int8(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(int8(c))
                return true
        }
        // match: (MOVBreg (ANDWconst [m] x))
@@ -14677,7 +14811,7 @@ func rewriteValueS390X_OpS390XMOVDaddridx_0(v *Value) bool {
 func rewriteValueS390X_OpS390XMOVDload_0(v *Value) bool {
        // match: (MOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _))
        // cond: isSamePtr(ptr1, ptr2)
-       // result: (MOVDreg x)
+       // result: x
        for {
                off := v.AuxInt
                sym := v.Aux
@@ -14699,7 +14833,8 @@ func rewriteValueS390X_OpS390XMOVDload_0(v *Value) bool {
                if !(isSamePtr(ptr1, ptr2)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
@@ -14934,844 +15069,6 @@ func rewriteValueS390X_OpS390XMOVDloadidx_0(v *Value) bool {
        }
        return false
 }
-func rewriteValueS390X_OpS390XMOVDnop_0(v *Value) bool {
-       b := v.Block
-       // match: (MOVDnop <t> x)
-       // cond: t.Compare(x.Type) == types.CMPeq
-       // result: x
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if !(t.Compare(x.Type) == types.CMPeq) {
-                       break
-               }
-               v.reset(OpCopy)
-               v.Type = x.Type
-               v.AddArg(x)
-               return true
-       }
-       // match: (MOVDnop (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [c])
-       for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
-                       break
-               }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = c
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVBZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVBload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVHZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVHload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVWZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVWload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVDload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVDload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVDload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVBZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVDnop_10(v *Value) bool {
-       b := v.Block
-       // match: (MOVDnop <t> x:(MOVBloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVHZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVHloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVWZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVWloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDnop <t> x:(MOVDloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVDloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVDloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVDreg_0(v *Value) bool {
-       b := v.Block
-       // match: (MOVDreg <t> x)
-       // cond: t.Compare(x.Type) == types.CMPeq
-       // result: x
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if !(t.Compare(x.Type) == types.CMPeq) {
-                       break
-               }
-               v.reset(OpCopy)
-               v.Type = x.Type
-               v.AddArg(x)
-               return true
-       }
-       // match: (MOVDreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [c])
-       for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
-                       break
-               }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = c
-               return true
-       }
-       // match: (MOVDreg x)
-       // cond: x.Uses == 1
-       // result: (MOVDnop x)
-       for {
-               x := v.Args[0]
-               if !(x.Uses == 1) {
-                       break
-               }
-               v.reset(OpS390XMOVDnop)
-               v.AddArg(x)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVBZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVBload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVBload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVHZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVHload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVWZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWZload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVWload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVDload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVDload <t> [off] {sym} ptr mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDload {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVDload, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
-               return true
-       }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVDreg_10(v *Value) bool {
-       b := v.Block
-       // match: (MOVDreg <t> x:(MOVBZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVBloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVBloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVBloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVHZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVHloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVWZloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWZloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWZloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVWloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       // match: (MOVDreg <t> x:(MOVDloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVDloadidx <t> [off] {sym} ptr idx mem)
-       for {
-               t := v.Type
-               x := v.Args[0]
-               if x.Op != OpS390XMOVDloadidx {
-                       break
-               }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
-                       break
-               }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVDloadidx, t)
-               v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
-               return true
-       }
-       return false
-}
 func rewriteValueS390X_OpS390XMOVDstore_0(v *Value) bool {
        // match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
        // cond: is20Bit(off1+off2)
@@ -17431,206 +16728,275 @@ func rewriteValueS390X_OpS390XMOVHZloadidx_0(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpS390XMOVHZreg_0(v *Value) bool {
-       b := v.Block
-       // match: (MOVHZreg x:(MOVBZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHZreg e:(MOVBZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBZreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(MOVHZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHZreg e:(MOVHreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(Arg <t>))
-       // cond: (is8BitInt(t) || is16BitInt(t)) && !isSigned(t)
-       // result: (MOVDreg x)
+       // match: (MOVHZreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHZreg e:(MOVHZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHZreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHZreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHZreg x:(MOVBZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpArg {
+               if x.Op != OpS390XMOVBZload {
                        break
                }
-               t := x.Type
-               if !((is8BitInt(t) || is16BitInt(t)) && !isSigned(t)) {
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(MOVBZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZreg {
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(MOVHZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZreg {
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg (MOVHreg x))
-       // cond:
-       // result: (MOVHZreg x)
+       // match: (MOVHZreg x:(MOVHZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVHreg {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZload {
                        break
                }
-               x := v_0.Args[0]
-               v.reset(OpS390XMOVHZreg)
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(uint16(c))])
+       // match: (MOVHZreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(uint16(c))
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(MOVHZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZload <v.Type> [off] {sym} ptr mem)
+       return false
+}
+func rewriteValueS390X_OpS390XMOVHZreg_10(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (MOVHZreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVHZreg x:(MOVHload [off] {sym} ptr mem))
+       // match: (MOVHZreg <t> x:(MOVHload [o] {s} p mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZload <v.Type> [off] {sym} ptr mem)
+       // result: @x.Block (MOVHZload <t> [o] {s} p mem)
        for {
+               t := v.Type
                x := v.Args[0]
                if x.Op != OpS390XMOVHload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[1]
-               ptr := x.Args[0]
+               p := x.Args[0]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, v.Type)
+               v0 := b.NewValue0(x.Pos, OpS390XMOVHZload, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVHZreg x:(MOVHZloadidx [off] {sym} ptr idx mem))
+       // match: (MOVHZreg <t> x:(MOVHloadidx [o] {s} p i mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZloadidx <v.Type> [off] {sym} ptr idx mem)
+       // result: @x.Block (MOVHZloadidx <t> [o] {s} p i mem)
        for {
+               t := v.Type
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZloadidx {
+               if x.Op != OpS390XMOVHloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
+               p := x.Args[0]
+               i := x.Args[1]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHZloadidx, v.Type)
+               v0 := b.NewValue0(v.Pos, OpS390XMOVHZloadidx, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
                v0.AddArg(mem)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVHZreg_10(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (MOVHZreg x:(MOVHloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHZloadidx <v.Type> [off] {sym} ptr idx mem)
+       // match: (MOVHZreg x:(Arg <t>))
+       // cond: !t.IsSigned() && t.Size() <= 2
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHloadidx {
+               if x.Op != OpArg {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               t := x.Type
+               if !(!t.IsSigned() && t.Size() <= 2) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHZloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHZreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64(uint16(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(uint16(c))
                return true
        }
        // match: (MOVHZreg (ANDWconst [m] x))
@@ -17885,147 +17251,169 @@ func rewriteValueS390X_OpS390XMOVHloadidx_0(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpS390XMOVHreg_0(v *Value) bool {
-       b := v.Block
-       // match: (MOVHreg x:(MOVBload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg e:(MOVBreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVBZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg e:(MOVHreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVHload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(Arg <t>))
-       // cond: (is8BitInt(t) || is16BitInt(t)) && isSigned(t)
-       // result: (MOVDreg x)
+       // match: (MOVHreg e:(MOVHZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpArg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHZreg {
                        break
                }
-               t := x.Type
-               if !((is8BitInt(t) || is16BitInt(t)) && isSigned(t)) {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVHreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVBreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBreg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVHreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVBZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg x:(MOVBload _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZreg {
+               if x.Op != OpS390XMOVBload {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[1]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVHreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVHreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHreg {
+               if x.Op != OpS390XMOVBloadidx {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg (MOVHZreg x))
-       // cond:
-       // result: (MOVHreg x)
+       // match: (MOVHreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVHZreg {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBloadidx {
                        break
                }
-               x := v_0.Args[0]
-               v.reset(OpS390XMOVHreg)
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVHreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(int16(c))])
+       // match: (MOVHreg x:(MOVHload _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHload {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(int16(c))
+               _ = x.Args[1]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVHreg x:(MOVHZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHload <v.Type> [off] {sym} ptr mem)
+       // match: (MOVHreg x:(MOVHloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
+               if x.Op != OpS390XMOVHloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
        return false
@@ -18033,83 +17421,156 @@ func rewriteValueS390X_OpS390XMOVHreg_0(v *Value) bool {
 func rewriteValueS390X_OpS390XMOVHreg_10(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (MOVHreg x:(MOVHload [off] {sym} ptr mem))
+       // match: (MOVHreg x:(MOVHloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHreg x:(MOVBZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBZload {
+                       break
+               }
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHreg <t> x:(MOVHZload [o] {s} p mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHload <v.Type> [off] {sym} ptr mem)
+       // result: @x.Block (MOVHload <t> [o] {s} p mem)
        for {
+               t := v.Type
                x := v.Args[0]
-               if x.Op != OpS390XMOVHload {
+               if x.Op != OpS390XMOVHZload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[1]
-               ptr := x.Args[0]
+               p := x.Args[0]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVHload, v.Type)
+               v0 := b.NewValue0(x.Pos, OpS390XMOVHload, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVHreg x:(MOVHZloadidx [off] {sym} ptr idx mem))
+       // match: (MOVHreg <t> x:(MOVHZloadidx [o] {s} p i mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHloadidx <v.Type> [off] {sym} ptr idx mem)
+       // result: @x.Block (MOVHloadidx <t> [o] {s} p i mem)
        for {
+               t := v.Type
                x := v.Args[0]
                if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
+               p := x.Args[0]
+               i := x.Args[1]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHloadidx, v.Type)
+               v0 := b.NewValue0(v.Pos, OpS390XMOVHloadidx, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVHreg x:(MOVHloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVHloadidx <v.Type> [off] {sym} ptr idx mem)
+       // match: (MOVHreg x:(Arg <t>))
+       // cond: t.IsSigned() && t.Size() <= 2
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHloadidx {
+               if x.Op != OpArg {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               t := x.Type
+               if !(t.IsSigned() && t.Size() <= 2) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVHloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVHreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64(int16(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(int16(c))
                return true
        }
        // match: (MOVHreg (ANDWconst [m] x))
@@ -20264,230 +19725,309 @@ func rewriteValueS390X_OpS390XMOVWZloadidx_0(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpS390XMOVWZreg_0(v *Value) bool {
-       b := v.Block
-       // match: (MOVWZreg x:(MOVBZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg e:(MOVBZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBZreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVHZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg e:(MOVHZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHZreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVWZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVWZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpS390XMOVWZload {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVWZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(Arg <t>))
-       // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)
-       // result: (MOVDreg x)
+       // match: (MOVWZreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVWZreg x)
        for {
-               x := v.Args[0]
-               if x.Op != OpArg {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
                        break
                }
-               t := x.Type
-               if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)) {
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpS390XMOVWZreg)
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVBZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg x:(MOVBZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZreg {
+               if x.Op != OpS390XMOVBZload {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVHZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZreg {
+               if x.Op != OpS390XMOVBZloadidx {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVWZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWZreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWZreg {
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg (MOVWreg x))
-       // cond:
-       // result: (MOVWZreg x)
+       // match: (MOVWZreg x:(MOVHZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVWreg {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZload {
                        break
                }
-               x := v_0.Args[0]
-               v.reset(OpS390XMOVWZreg)
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(uint32(c))])
+       // match: (MOVWZreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(uint32(c))
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVWZreg x:(MOVWZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZload <v.Type> [off] {sym} ptr mem)
+       // match: (MOVWZreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWZload {
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
        return false
 }
 func rewriteValueS390X_OpS390XMOVWZreg_10(v *Value) bool {
        b := v.Block
-       // match: (MOVWZreg x:(MOVWload [off] {sym} ptr mem))
+       // match: (MOVWZreg x:(MOVWZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 4)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVWZload {
+                       break
+               }
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 4) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWZreg x:(MOVWZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 4)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVWZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 4) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWZreg x:(MOVWZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 4)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVWZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 4) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWZreg <t> x:(MOVWload [o] {s} p mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZload <v.Type> [off] {sym} ptr mem)
+       // result: @x.Block (MOVWZload <t> [o] {s} p mem)
        for {
+               t := v.Type
                x := v.Args[0]
                if x.Op != OpS390XMOVWload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[1]
-               ptr := x.Args[0]
+               p := x.Args[0]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, v.Type)
+               v0 := b.NewValue0(x.Pos, OpS390XMOVWZload, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVWZreg x:(MOVWZloadidx [off] {sym} ptr idx mem))
+       // match: (MOVWZreg <t> x:(MOVWloadidx [o] {s} p i mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
+       // result: @x.Block (MOVWZloadidx <t> [o] {s} p i mem)
        for {
+               t := v.Type
                x := v.Args[0]
-               if x.Op != OpS390XMOVWZloadidx {
+               if x.Op != OpS390XMOVWloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
+               p := x.Args[0]
+               i := x.Args[1]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWZloadidx, v.Type)
+               v0 := b.NewValue0(v.Pos, OpS390XMOVWZloadidx, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVWZreg x:(MOVWloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
+       // match: (MOVWZreg x:(Arg <t>))
+       // cond: !t.IsSigned() && t.Size() <= 4
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWloadidx {
+               if x.Op != OpArg {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               t := x.Type
+               if !(!t.IsSigned() && t.Size() <= 4) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWZloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWZreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64(uint32(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(uint32(c))
                return true
        }
        return false
@@ -20725,279 +20265,415 @@ func rewriteValueS390X_OpS390XMOVWloadidx_0(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpS390XMOVWreg_0(v *Value) bool {
+       // match: (MOVWreg e:(MOVBreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVBreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVBreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVBreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWreg e:(MOVHreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVHreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVHreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVHreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWreg e:(MOVWreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVWreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVWreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWreg e:(MOVWZreg x))
+       // cond: clobberIfDead(e)
+       // result: (MOVWreg x)
+       for {
+               e := v.Args[0]
+               if e.Op != OpS390XMOVWZreg {
+                       break
+               }
+               x := e.Args[0]
+               if !(clobberIfDead(e)) {
+                       break
+               }
+               v.reset(OpS390XMOVWreg)
+               v.AddArg(x)
+               return true
+       }
        // match: (MOVWreg x:(MOVBload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
                if x.Op != OpS390XMOVBload {
                        break
                }
                _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVBZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZload {
+               if x.Op != OpS390XMOVBloadidx {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWreg x:(MOVBloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVBloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
        // match: (MOVWreg x:(MOVHload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
                if x.Op != OpS390XMOVHload {
                        break
                }
                _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVHZload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVHloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZload {
+               if x.Op != OpS390XMOVHloadidx {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVWload _ _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVHloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWload {
+               if x.Op != OpS390XMOVHloadidx {
                        break
                }
-               _ = x.Args[1]
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(Arg <t>))
-       // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)
-       // result: (MOVDreg x)
+       return false
+}
+func rewriteValueS390X_OpS390XMOVWreg_10(v *Value) bool {
+       b := v.Block
+       // match: (MOVWreg x:(MOVWload _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpArg {
+               if x.Op != OpS390XMOVWload {
                        break
                }
-               t := x.Type
-               if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)) {
+               _ = x.Args[1]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVBreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVWloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBreg {
+               if x.Op != OpS390XMOVWloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVBZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVWloadidx _ _ _))
+       // cond: (x.Type.IsSigned() || x.Type.Size() == 8)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVBZreg {
+               if x.Op != OpS390XMOVWloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(x.Type.IsSigned() || x.Type.Size() == 8) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVHreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVBZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHreg {
+               if x.Op != OpS390XMOVBZload {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVHZreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVHZreg {
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XMOVWreg_10(v *Value) bool {
-       b := v.Block
-       // match: (MOVWreg x:(MOVWreg _))
-       // cond:
-       // result: (MOVDreg x)
+       // match: (MOVWreg x:(MOVBZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 1)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWreg {
+               if x.Op != OpS390XMOVBZloadidx {
+                       break
+               }
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 1) {
                        break
                }
-               v.reset(OpS390XMOVDreg)
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg (MOVWZreg x))
-       // cond:
-       // result: (MOVWreg x)
+       // match: (MOVWreg x:(MOVHZload _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVWZreg {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZload {
                        break
                }
-               x := v_0.Args[0]
-               v.reset(OpS390XMOVWreg)
+               _ = x.Args[1]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
                v.AddArg(x)
                return true
        }
-       // match: (MOVWreg (MOVDconst [c]))
-       // cond:
-       // result: (MOVDconst [int64(int32(c))])
+       // match: (MOVWreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpS390XMOVDconst {
+               x := v.Args[0]
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpS390XMOVDconst)
-               v.AuxInt = int64(int32(c))
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVWZload [off] {sym} ptr mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+       // match: (MOVWreg x:(MOVHZloadidx _ _ _))
+       // cond: (!x.Type.IsSigned() || x.Type.Size() > 2)
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWZload {
+               if x.Op != OpS390XMOVHZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[1]
-               ptr := x.Args[0]
-               if !(x.Uses == 1 && clobber(x)) {
+               _ = x.Args[2]
+               if !(!x.Type.IsSigned() || x.Type.Size() > 2) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWload, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
                return true
        }
-       // match: (MOVWreg x:(MOVWload [off] {sym} ptr mem))
+       // match: (MOVWreg <t> x:(MOVWZload [o] {s} p mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWload <v.Type> [off] {sym} ptr mem)
+       // result: @x.Block (MOVWload <t> [o] {s} p mem)
        for {
+               t := v.Type
                x := v.Args[0]
-               if x.Op != OpS390XMOVWload {
+               if x.Op != OpS390XMOVWZload {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[1]
-               ptr := x.Args[0]
+               p := x.Args[0]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(x.Pos, OpS390XMOVWload, v.Type)
+               v0 := b.NewValue0(x.Pos, OpS390XMOVWload, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVWreg x:(MOVWZloadidx [off] {sym} ptr idx mem))
+       return false
+}
+func rewriteValueS390X_OpS390XMOVWreg_20(v *Value) bool {
+       b := v.Block
+       // match: (MOVWreg <t> x:(MOVWZloadidx [o] {s} p i mem))
        // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWloadidx <v.Type> [off] {sym} ptr idx mem)
+       // result: @x.Block (MOVWloadidx <t> [o] {s} p i mem)
        for {
+               t := v.Type
                x := v.Args[0]
                if x.Op != OpS390XMOVWZloadidx {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
+               o := x.AuxInt
+               s := x.Aux
                mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
+               p := x.Args[0]
+               i := x.Args[1]
                if !(x.Uses == 1 && clobber(x)) {
                        break
                }
                b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWloadidx, v.Type)
+               v0 := b.NewValue0(v.Pos, OpS390XMOVWloadidx, t)
                v.reset(OpCopy)
                v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
+               v0.AuxInt = o
+               v0.Aux = s
+               v0.AddArg(p)
+               v0.AddArg(i)
                v0.AddArg(mem)
                return true
        }
-       // match: (MOVWreg x:(MOVWloadidx [off] {sym} ptr idx mem))
-       // cond: x.Uses == 1 && clobber(x)
-       // result: @x.Block (MOVWloadidx <v.Type> [off] {sym} ptr idx mem)
+       // match: (MOVWreg x:(Arg <t>))
+       // cond: t.IsSigned() && t.Size() <= 4
+       // result: x
        for {
                x := v.Args[0]
-               if x.Op != OpS390XMOVWloadidx {
+               if x.Op != OpArg {
                        break
                }
-               off := x.AuxInt
-               sym := x.Aux
-               mem := x.Args[2]
-               ptr := x.Args[0]
-               idx := x.Args[1]
-               if !(x.Uses == 1 && clobber(x)) {
+               t := x.Type
+               if !(t.IsSigned() && t.Size() <= 4) {
                        break
                }
-               b = x.Block
-               v0 := b.NewValue0(v.Pos, OpS390XMOVWloadidx, v.Type)
                v.reset(OpCopy)
-               v.AddArg(v0)
-               v0.AuxInt = off
-               v0.Aux = sym
-               v0.AddArg(ptr)
-               v0.AddArg(idx)
-               v0.AddArg(mem)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVWreg (MOVDconst [c]))
+       // cond:
+       // result: (MOVDconst [int64(int32(c))])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpS390XMOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpS390XMOVDconst)
+               v.AuxInt = int64(int32(c))
                return true
        }
        return false
@@ -37836,22 +37512,6 @@ func rewriteValueS390X_OpS390XSLD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SLD x (MOVDreg y))
-       // cond:
-       // result: (SLD x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSLD)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SLD x (MOVWreg y))
        // cond:
        // result: (SLD x y)
@@ -37932,9 +37592,6 @@ func rewriteValueS390X_OpS390XSLD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSLD_10(v *Value) bool {
        // match: (SLD x (MOVBZreg y))
        // cond:
        // result: (SLD x y)
@@ -38041,22 +37698,6 @@ func rewriteValueS390X_OpS390XSLW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SLW x (MOVDreg y))
-       // cond:
-       // result: (SLW x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSLW)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SLW x (MOVWreg y))
        // cond:
        // result: (SLW x y)
@@ -38137,9 +37778,6 @@ func rewriteValueS390X_OpS390XSLW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSLW_10(v *Value) bool {
        // match: (SLW x (MOVBZreg y))
        // cond:
        // result: (SLW x y)
@@ -38246,22 +37884,6 @@ func rewriteValueS390X_OpS390XSRAD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SRAD x (MOVDreg y))
-       // cond:
-       // result: (SRAD x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSRAD)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SRAD x (MOVWreg y))
        // cond:
        // result: (SRAD x y)
@@ -38342,9 +37964,6 @@ func rewriteValueS390X_OpS390XSRAD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSRAD_10(v *Value) bool {
        // match: (SRAD x (MOVBZreg y))
        // cond:
        // result: (SRAD x y)
@@ -38468,22 +38087,6 @@ func rewriteValueS390X_OpS390XSRAW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SRAW x (MOVDreg y))
-       // cond:
-       // result: (SRAW x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSRAW)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SRAW x (MOVWreg y))
        // cond:
        // result: (SRAW x y)
@@ -38564,9 +38167,6 @@ func rewriteValueS390X_OpS390XSRAW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSRAW_10(v *Value) bool {
        // match: (SRAW x (MOVBZreg y))
        // cond:
        // result: (SRAW x y)
@@ -38690,22 +38290,6 @@ func rewriteValueS390X_OpS390XSRD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SRD x (MOVDreg y))
-       // cond:
-       // result: (SRD x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSRD)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SRD x (MOVWreg y))
        // cond:
        // result: (SRD x y)
@@ -38786,9 +38370,6 @@ func rewriteValueS390X_OpS390XSRD_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSRD_10(v *Value) bool {
        // match: (SRD x (MOVBZreg y))
        // cond:
        // result: (SRD x y)
@@ -38926,22 +38507,6 @@ func rewriteValueS390X_OpS390XSRW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       // match: (SRW x (MOVDreg y))
-       // cond:
-       // result: (SRW x y)
-       for {
-               _ = v.Args[1]
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpS390XMOVDreg {
-                       break
-               }
-               y := v_1.Args[0]
-               v.reset(OpS390XSRW)
-               v.AddArg(x)
-               v.AddArg(y)
-               return true
-       }
        // match: (SRW x (MOVWreg y))
        // cond:
        // result: (SRW x y)
@@ -39022,9 +38587,6 @@ func rewriteValueS390X_OpS390XSRW_0(v *Value) bool {
                v.AddArg(y)
                return true
        }
-       return false
-}
-func rewriteValueS390X_OpS390XSRW_10(v *Value) bool {
        // match: (SRW x (MOVBZreg y))
        // cond:
        // result: (SRW x y)
index 747e23001d52ad2e31f5bf87590880c21593cad0..d5f3af76921e767109f8187c9c156a8ae4a76a36 100644 (file)
@@ -57,6 +57,7 @@ func load_le16(b []byte) {
        // amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
        // ppc64le:`MOVHZ\s`,-`MOVBZ`
        // arm64:`MOVHU\s\(R[0-9]+\),`,-`MOVB`
+       // s390x:`MOVHBR\s\(.*\),`
        sink16 = binary.LittleEndian.Uint16(b)
 }
 
@@ -64,6 +65,7 @@ func load_le16_idx(b []byte, idx int) {
        // amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
        // ppc64le:`MOVHZ\s`,-`MOVBZ`
        // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
+       // s390x:`MOVHBR\s\(.*\)\(.*\*1\),`
        sink16 = binary.LittleEndian.Uint16(b[idx:])
 }
 
@@ -103,6 +105,7 @@ func load_be16(b []byte) {
        // amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
        // arm64:`REV16W`,`MOVHU\s\(R[0-9]+\),`,-`MOVB`
        // ppc64le:`MOVHBR`
+       // s390x:`MOVHZ\s\(.*\),`,-`OR`,-`ORW`,-`SLD`,-`SLW`
        sink16 = binary.BigEndian.Uint16(b)
 }
 
@@ -110,6 +113,7 @@ func load_be16_idx(b []byte, idx int) {
        // amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
        // arm64:`REV16W`,`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
        // ppc64le:`MOVHBR`
+       // s390x:`MOVHZ\s\(.*\)\(.*\*1\),`,-`OR`,-`ORW`,-`SLD`,-`SLW`
        sink16 = binary.BigEndian.Uint16(b[idx:])
 }
 
@@ -351,6 +355,7 @@ func store_le64(b []byte) {
        // amd64:`MOVQ\s.*\(.*\)$`,-`SHR.`
        // arm64:`MOVD`,-`MOV[WBH]`
        // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+       // s390x:`MOVDBR\s.*\(.*\)$`
        binary.LittleEndian.PutUint64(b, sink64)
 }
 
@@ -358,6 +363,7 @@ func store_le64_idx(b []byte, idx int) {
        // amd64:`MOVQ\s.*\(.*\)\(.*\*1\)$`,-`SHR.`
        // arm64:`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`
        // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+       // s390x:`MOVDBR\s.*\(.*\)\(.*\*1\)$`
        binary.LittleEndian.PutUint64(b[idx:], sink64)
 }
 
@@ -365,6 +371,7 @@ func store_le32(b []byte) {
        // amd64:`MOVL\s`
        // arm64:`MOVW`,-`MOV[BH]`
        // ppc64le:`MOVW\s`
+       // s390x:`MOVWBR\s.*\(.*\)$`
        binary.LittleEndian.PutUint32(b, sink32)
 }
 
@@ -372,6 +379,7 @@ func store_le32_idx(b []byte, idx int) {
        // amd64:`MOVL\s`
        // arm64:`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`
        // ppc64le:`MOVW\s`
+       // s390x:`MOVWBR\s.*\(.*\)\(.*\*1\)$`
        binary.LittleEndian.PutUint32(b[idx:], sink32)
 }
 
@@ -379,6 +387,7 @@ func store_le16(b []byte) {
        // amd64:`MOVW\s`
        // arm64:`MOVH`,-`MOVB`
        // ppc64le:`MOVH\s`
+       // s390x:`MOVHBR\s.*\(.*\)$`
        binary.LittleEndian.PutUint16(b, sink16)
 }
 
@@ -386,6 +395,7 @@ func store_le16_idx(b []byte, idx int) {
        // amd64:`MOVW\s`
        // arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
        // ppc64le:`MOVH\s`
+       // s390x:`MOVHBR\s.*\(.*\)\(.*\*1\)$`
        binary.LittleEndian.PutUint16(b[idx:], sink16)
 }
 
@@ -393,6 +403,7 @@ func store_be64(b []byte) {
        // amd64:`BSWAPQ`,-`SHR.`
        // arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W`
        // ppc64le:`MOVDBR`
+       // s390x:`MOVD\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint64(b, sink64)
 }
 
@@ -400,6 +411,7 @@ func store_be64_idx(b []byte, idx int) {
        // amd64:`BSWAPQ`,-`SHR.`
        // arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW`
        // ppc64le:`MOVDBR`
+       // s390x:`MOVD\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint64(b[idx:], sink64)
 }
 
@@ -407,6 +419,7 @@ func store_be32(b []byte) {
        // amd64:`BSWAPL`,-`SHR.`
        // arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W`
        // ppc64le:`MOVWBR`
+       // s390x:`MOVW\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint32(b, sink32)
 }
 
@@ -414,6 +427,7 @@ func store_be32_idx(b []byte, idx int) {
        // amd64:`BSWAPL`,-`SHR.`
        // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W`
        // ppc64le:`MOVWBR`
+       // s390x:`MOVW\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint32(b[idx:], sink32)
 }
 
@@ -421,6 +435,7 @@ func store_be16(b []byte) {
        // amd64:`ROLW\s\$8`,-`SHR.`
        // arm64:`MOVH`,`REV16W`,-`MOVB`
        // ppc64le:`MOVHBR`
+       // s390x:`MOVH\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint16(b, sink16)
 }
 
@@ -428,6 +443,7 @@ func store_be16_idx(b []byte, idx int) {
        // amd64:`ROLW\s\$8`,-`SHR.`
        // arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`MOVB`
        // ppc64le:`MOVHBR`
+       // s390x:`MOVH\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
        binary.BigEndian.PutUint16(b[idx:], sink16)
 }