]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: PPC64, elide unnecessary sign extension
authorDavid Chase <drchase@google.com>
Wed, 5 Oct 2016 20:21:09 +0000 (13:21 -0700)
committerDavid Chase <drchase@google.com>
Mon, 10 Oct 2016 12:22:40 +0000 (12:22 +0000)
Inputs to store[BHW] and cmpW(U) need not be correct
in more bits than are used by the instruction.

Added a pattern tailored to what appears to be cgo boilerplate.
Added a pattern (also seen in cgo boilerplate and hashing)
to replace {EQ,NE}-CMP-ANDconst with {EQ-NE}-ANDCCconst.
Added a pattern to clean up ANDconst shift distance inputs
(this was seen in hashing).

Simplify repeated and,or,xor.

Fixes #17109.

Change-Id: I68eac83e3e614d69ffe473a08953048c8b066d88
Reviewed-on: https://go-review.googlesource.com/30455
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ppc64/ssa.go
src/cmd/compile/internal/ssa/gen/PPC64.rules
src/cmd/compile/internal/ssa/gen/PPC64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritePPC64.go

index 966ee39118d2fd7dc075e18342da01f2be9b12ee..8387692f860f76614ca869b60c6cb129171e3d26 100644 (file)
@@ -352,6 +352,21 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
 
+       case ssa.OpPPC64ANDCCconst:
+               p := gc.Prog(v.Op.Asm())
+               p.Reg = v.Args[0].Reg()
+
+               if v.Aux != nil {
+                       p.From.Type = obj.TYPE_CONST
+                       p.From.Offset = gc.AuxOffset(v)
+               } else {
+                       p.From.Type = obj.TYPE_CONST
+                       p.From.Offset = v.AuxInt
+               }
+
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = ppc64.REGTMP // discard result
+
        case ssa.OpPPC64MOVDaddr:
                p := gc.Prog(ppc64.AMOVD)
                p.From.Type = obj.TYPE_ADDR
index 87e9fd0ce44186df7bda9b2dae88d4eca1770358..1df8b3ca0eae03b56d9c058c4f6aef8de999a0dd 100644 (file)
 (Rsh8Ux8 x y) -> (SRW  (ZeroExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
 (Lsh8x8 x y)  -> (SLW  x                (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
 
+// Cleaning up shift ops when input is masked
+(MaskIfNotCarry (ADDconstForCarry [c] (ANDconst [d] _))) && c < 0 && d > 0 && c + d < 0 -> (MOVDconst [-1])
+(ORN x (MOVDconst [-1])) -> x
+
 // Potentially useful optimizing rewrites.
 // (ADDconstForCarry [k] c), k < 0 && (c < 0 || k+c >= 0) -> CarrySet
 // (ADDconstForCarry [k] c), K < 0 && (c >= 0 && k+c < 0) -> CarryClear
 // (NE (CMPWconst [0] (FGreaterThan cc)) yes no) -> (FGT cc yes no)
 // (NE (CMPWconst [0] (FGreaterEqual cc)) yes no) -> (FGE cc yes no)
 
+// Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
+(EQ (CMPconst [0] (ANDconst [c] x)) yes no) -> (EQ (ANDCCconst [c] x) yes no)
+(NE (CMPconst [0] (ANDconst [c] x)) yes no) -> (NE (ANDCCconst [c] x) yes no)
+(EQ (CMPWconst [0] (ANDconst [c] x)) yes no) -> (EQ (ANDCCconst [c] x) yes no)
+(NE (CMPWconst [0] (ANDconst [c] x)) yes no) -> (NE (ANDCCconst [c] x) yes no)
+
 // absorb flag constants into branches
 (EQ (FlagEQ) yes no) -> (First nil yes no)
 (EQ (FlagLT) yes no) -> (First nil no yes)
 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
 
 // Optimizations
+// Note that PPC "logical" immediates come in 0:15 and 16:31 unsigned immediate forms,
+// so ORconst, XORconst easily expand into a pair.
+
+// Include very-large constants in the const-const case.
+(AND (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c&d])
+(OR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c|d])
+(XOR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c^d])
+
+// Discover consts
+(AND x (MOVDconst [c])) && isU16Bit(c) -> (ANDconst [c] x)
+(XOR x (MOVDconst [c])) && isU32Bit(c) -> (XORconst [c] x)
+(OR x (MOVDconst [c])) && isU32Bit(c) -> (ORconst [c] x)
+(AND (MOVDconst [c]) x) && isU16Bit(c) -> (ANDconst [c] x)
+(XOR (MOVDconst [c]) x) && isU32Bit(c) -> (XORconst [c] x)
+(OR (MOVDconst [c]) x) && isU32Bit(c) -> (ORconst [c] x)
+
+// Simplify consts
+(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
+(ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x)
+(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
+(ANDconst [-1] x) -> x
+(ANDconst [0] _) -> (MOVDconst [0])
+(XORconst [0] x) -> x
+(ORconst [-1] _) -> (MOVDconst [-1])
+(ORconst [0] x) -> x
+
+// zero-extend of small and -> small and
+(MOVBZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFF -> y
+(MOVHZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF -> y
+(MOVWZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFFFFFF -> y
+(MOVWZreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0xFFFFFFFF -> y
+
+// sign extend of small-positive and -> small-positive-and
+(MOVBreg y:(ANDconst [c] _)) && uint64(c) <= 0x7F -> y
+(MOVHreg y:(ANDconst [c] _)) && uint64(c) <= 0x7FFF -> y
+(MOVWreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF -> y // 0xFFFF is largest immediate constant, when regarded as 32-bit is > 0
+(MOVWreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0x7FFFFFFF -> y
+
+// small and of zero-extend -> either zero-extend or small and
+  // degenerate-and
+(ANDconst [c] y:(MOVBZreg _)) && c&0xFF == 0xFF -> y
+(ANDconst [c] y:(MOVHZreg _))  && c&0xFFFF == 0xFFFF -> y
+(ANDconst [c] y:(MOVWZreg _))  && c&0xFFFFFFFF == 0xFFFFFFFF -> y
+  // normal case
+(ANDconst [c] (MOVBZreg x)) -> (ANDconst [c&0xFF] x)
+(ANDconst [c] (MOVHZreg x)) -> (ANDconst [c&0xFFFF] x)
+(ANDconst [c] (MOVWZreg x)) -> (ANDconst [c&0xFFFFFFFF] x)
+
+// Various redundant zero/sign extension combinations.
+(MOVBZreg y:(MOVBZreg _)) -> y  // repeat
+(MOVBreg y:(MOVBreg _)) -> y // repeat
+(MOVBreg (MOVBZreg x)) -> (MOVBreg x)
+(MOVBZreg (MOVBreg x)) -> (MOVBZreg x)
+
+// H - there are more combinations than these
+
+(MOVHZreg y:(MOVHZreg _)) -> y // repeat
+(MOVHZreg y:(MOVBZreg _)) -> y // wide of narrow
+
+(MOVHreg y:(MOVHreg _)) -> y // repeat
+(MOVHreg y:(MOVBreg _)) -> y // wide of narrow
+
+(MOVHreg y:(MOVHZreg x)) -> (MOVHreg x)
+(MOVHZreg y:(MOVHreg x)) -> (MOVHZreg x)
+
+// W - there are more combinations than these
+
+(MOVWZreg y:(MOVWZreg _)) -> y // repeat
+(MOVWZreg y:(MOVHZreg _)) -> y // wide of narrow
+(MOVWZreg y:(MOVBZreg _)) -> y // wide of narrow
+
+(MOVWreg y:(MOVWreg _)) -> y // repeat
+(MOVWreg y:(MOVHreg _)) -> y // wide of narrow
+(MOVWreg y:(MOVBreg _)) -> y // wide of narrow
+
+(MOVWreg y:(MOVWZreg x)) -> (MOVWreg x)
+(MOVWZreg y:(MOVWreg x)) -> (MOVWZreg x)
+
+// Arithmetic constant ops
 
 (ADD (MOVDconst [c]) x) && is32Bit(c) -> (ADDconst [c] x)
 (ADD x (MOVDconst [c])) && is32Bit(c) -> (ADDconst [c] x)
 (ADDconst [c] (ADDconst [d] x)) && is32Bit(c+d) -> (ADDconst [c+d] x)
-(ADDconst [c] (MOVDaddr [d] {sym} x)) -> (MOVDaddr [c+d] {sym} x)
 (ADDconst [0] x) -> x
-(ANDconst [-1] x) -> x
-(ANDconst [0] _) -> (MOVDconst [0])
-(XORconst [0] x) -> x
+(SUB x (MOVDconst [c])) && is32Bit(-c) -> (ADDconst [-c] x)
+// TODO deal with subtract-from-const
 
-(XOR (MOVDconst [0]) x) -> x
-(XOR x (MOVDconst [0])) -> x
-(ADD (MOVDconst [0]) x) -> x
-(ADD x (MOVDconst [0])) -> x
+(ADDconst [c] (MOVDaddr [d] {sym} x)) -> (MOVDaddr [c+d] {sym} x)
 
 // Fold offsets for stores.
 (MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} x val mem)
 (MOVHZreg (MOVDconst [c]))  -> (MOVDconst [int64(uint16(c))])
 (MOVHreg (MOVDconst [c]))  -> (MOVDconst [int64(int16(c))])
 
+// Lose widening ops fed to to stores
 (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
 (MOVBstore [off] {sym} ptr (MOVBZreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
 (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
 (MOVHstore [off] {sym} ptr (MOVHZreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
+(MOVWstore [off] {sym} ptr (MOVWZreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
+
+// Lose W-widening ops fed to compare-W
+(CMPW x (MOVWreg y)) -> (CMPW x y)
+(CMPW (MOVWreg x) y) -> (CMPW x y)
+(CMPWU x (MOVWZreg y)) -> (CMPWU x y)
+(CMPWU (MOVWZreg x) y) -> (CMPWU x y)
 
 (CMP x (MOVDconst [c])) && is16Bit(c) -> (CMPconst x [c])
 (CMP (MOVDconst [c]) y) && is16Bit(c) -> (InvertFlags (CMPconst y [c]))
 (CMPU (MOVDconst [c]) y) && isU16Bit(c) -> (InvertFlags (CMPUconst y [c]))
 (CMPWU x (MOVDconst [c])) && isU16Bit(c) -> (CMPWUconst x [c])
 (CMPWU (MOVDconst [c]) y) && isU16Bit(c) -> (InvertFlags (CMPWUconst y [c]))
+
+// A particular pattern seen in cgo code:
+(AND (MOVDconst [c]) x:(MOVBZload _ _)) -> (ANDconst [c&0xFF] x)
+(AND x:(MOVBZload _ _) (MOVDconst [c])) -> (ANDconst [c&0xFF] x)
index a3233912c0f64aba8eb7b90650d76122ea4bbfc2..4b4f799668243db598746d2241c70cd8bbfb312c 100644 (file)
@@ -226,6 +226,7 @@ func init() {
                {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"},                                                                                     // arg0|aux
                {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"},                                                                                   // arg0^aux
                {name: "ANDconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, asm: "ANDCC", aux: "Int64", clobberFlags: true}, // arg0&aux // and-immediate sets CC on PPC, always.
+               {name: "ANDCCconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}}, asm: "ANDCC", aux: "Int64", typ: "Flags"},                             // arg0&aux == 0 // and-immediate sets CC on PPC, always.
 
                {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB", typ: "Int64"},                                            // sign extend int8 to int64
                {name: "MOVBZreg", argLength: 1, reg: gp11, asm: "MOVBZ", typ: "Int64"},                                          // zero extend uint8 to uint64
@@ -256,9 +257,9 @@ func init() {
 
                {name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{sp | sb}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
 
-               {name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", rematerializeable: true},     //
-               {name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", rematerializeable: true}, //
-               {name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float32", asm: "FMOVS", rematerializeable: true}, //
+               {name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "Int64", rematerializeable: true}, //
+               {name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", rematerializeable: true},           //
+               {name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float32", asm: "FMOVS", rematerializeable: true},           //
                {name: "FCMPU", argLength: 2, reg: fp2cr, asm: "FCMPU", typ: "Flags"},
 
                {name: "CMP", argLength: 2, reg: gp2cr, asm: "CMP", typ: "Flags"},     // arg0 compare to arg1
index 42f7071a8ad5e269820a0d466cd2bef3e546a5ec..cd897198d4c3c68ec308799700dd4a6cd389af79 100644 (file)
@@ -1176,6 +1176,7 @@ const (
        OpPPC64ORconst
        OpPPC64XORconst
        OpPPC64ANDconst
+       OpPPC64ANDCCconst
        OpPPC64MOVBreg
        OpPPC64MOVBZreg
        OpPPC64MOVHreg
@@ -14652,6 +14653,17 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:    "ANDCCconst",
+               auxType: auxInt64,
+               argLen:  1,
+               asm:     ppc64.AANDCC,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+                       },
+               },
+       },
        {
                name:   "MOVBreg",
                argLen: 1,
index 0a419f6e4e4ec56e762b2bfb44fa3a787f7e0e63..b3555c1fed5f5c1da4fe1e2ddfc069e9c2827e16 100644 (file)
@@ -229,11 +229,16 @@ func is16Bit(n int64) bool {
        return n == int64(int16(n))
 }
 
-// is16Bit reports whether n can be represented as an unsigned 16 bit integer.
+// isU16Bit reports whether n can be represented as an unsigned 16 bit integer.
 func isU16Bit(n int64) bool {
        return n == int64(uint16(n))
 }
 
+// isU32Bit reports whether n can be represented as an unsigned 32 bit integer.
+func isU32Bit(n int64) bool {
+       return n == int64(uint32(n))
+}
+
 // is20Bit reports whether n can be represented as a signed 20 bit integer.
 func is20Bit(n int64) bool {
        return -(1<<19) <= n && n < (1<<19)
index d898568f02e1023591c6ac45243acf4177266813..defda0aa6325c9144b9bcb6f20445fac01af97ec 100644 (file)
@@ -342,6 +342,8 @@ func rewriteValuePPC64(v *Value, config *Config) bool {
                return rewriteValuePPC64_OpPPC64ADD(v, config)
        case OpPPC64ADDconst:
                return rewriteValuePPC64_OpPPC64ADDconst(v, config)
+       case OpPPC64AND:
+               return rewriteValuePPC64_OpPPC64AND(v, config)
        case OpPPC64ANDconst:
                return rewriteValuePPC64_OpPPC64ANDconst(v, config)
        case OpPPC64CMP:
@@ -408,14 +410,28 @@ func rewriteValuePPC64(v *Value, config *Config) bool {
                return rewriteValuePPC64_OpPPC64MOVHstorezero(v, config)
        case OpPPC64MOVWZload:
                return rewriteValuePPC64_OpPPC64MOVWZload(v, config)
+       case OpPPC64MOVWZreg:
+               return rewriteValuePPC64_OpPPC64MOVWZreg(v, config)
        case OpPPC64MOVWload:
                return rewriteValuePPC64_OpPPC64MOVWload(v, config)
+       case OpPPC64MOVWreg:
+               return rewriteValuePPC64_OpPPC64MOVWreg(v, config)
        case OpPPC64MOVWstore:
                return rewriteValuePPC64_OpPPC64MOVWstore(v, config)
        case OpPPC64MOVWstorezero:
                return rewriteValuePPC64_OpPPC64MOVWstorezero(v, config)
+       case OpPPC64MaskIfNotCarry:
+               return rewriteValuePPC64_OpPPC64MaskIfNotCarry(v, config)
        case OpPPC64NotEqual:
                return rewriteValuePPC64_OpPPC64NotEqual(v, config)
+       case OpPPC64OR:
+               return rewriteValuePPC64_OpPPC64OR(v, config)
+       case OpPPC64ORN:
+               return rewriteValuePPC64_OpPPC64ORN(v, config)
+       case OpPPC64ORconst:
+               return rewriteValuePPC64_OpPPC64ORconst(v, config)
+       case OpPPC64SUB:
+               return rewriteValuePPC64_OpPPC64SUB(v, config)
        case OpPPC64XOR:
                return rewriteValuePPC64_OpPPC64XOR(v, config)
        case OpPPC64XORconst:
@@ -4395,40 +4411,6 @@ func rewriteValuePPC64_OpPPC64ADD(v *Value, config *Config) bool {
                v.AddArg(x)
                return true
        }
-       // match: (ADD (MOVDconst [0]) x)
-       // cond:
-       // result: x
-       for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpPPC64MOVDconst {
-                       break
-               }
-               if v_0.AuxInt != 0 {
-                       break
-               }
-               x := v.Args[1]
-               v.reset(OpCopy)
-               v.Type = x.Type
-               v.AddArg(x)
-               return true
-       }
-       // match: (ADD x (MOVDconst [0]))
-       // cond:
-       // result: x
-       for {
-               x := v.Args[0]
-               v_1 := v.Args[1]
-               if v_1.Op != OpPPC64MOVDconst {
-                       break
-               }
-               if v_1.AuxInt != 0 {
-                       break
-               }
-               v.reset(OpCopy)
-               v.Type = x.Type
-               v.AddArg(x)
-               return true
-       }
        return false
 }
 func rewriteValuePPC64_OpPPC64ADDconst(v *Value, config *Config) bool {
@@ -4453,6 +4435,19 @@ func rewriteValuePPC64_OpPPC64ADDconst(v *Value, config *Config) bool {
                v.AddArg(x)
                return true
        }
+       // match: (ADDconst [0] x)
+       // cond:
+       // result: x
+       for {
+               if v.AuxInt != 0 {
+                       break
+               }
+               x := v.Args[0]
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
        // match: (ADDconst [c] (MOVDaddr [d] {sym} x))
        // cond:
        // result: (MOVDaddr [c+d] {sym} x)
@@ -4471,16 +4466,98 @@ func rewriteValuePPC64_OpPPC64ADDconst(v *Value, config *Config) bool {
                v.AddArg(x)
                return true
        }
-       // match: (ADDconst [0] x)
+       return false
+}
+func rewriteValuePPC64_OpPPC64AND(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (AND (MOVDconst [c]) (MOVDconst [d]))
        // cond:
-       // result: x
+       // result: (MOVDconst [c&d])
        for {
-               if v.AuxInt != 0 {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
                        break
                }
+               d := v_1.AuxInt
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = c & d
+               return true
+       }
+       // match: (AND x (MOVDconst [c]))
+       // cond: isU16Bit(c)
+       // result: (ANDconst [c] x)
+       for {
                x := v.Args[0]
-               v.reset(OpCopy)
-               v.Type = x.Type
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               if !(isU16Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c
+               v.AddArg(x)
+               return true
+       }
+       // match: (AND (MOVDconst [c]) x)
+       // cond: isU16Bit(c)
+       // result: (ANDconst [c] x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               x := v.Args[1]
+               if !(isU16Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c
+               v.AddArg(x)
+               return true
+       }
+       // match: (AND (MOVDconst [c]) x:(MOVBZload _ _))
+       // cond:
+       // result: (ANDconst [c&0xFF] x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               x := v.Args[1]
+               if x.Op != OpPPC64MOVBZload {
+                       break
+               }
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & 0xFF
+               v.AddArg(x)
+               return true
+       }
+       // match: (AND x:(MOVBZload _ _) (MOVDconst [c]))
+       // cond:
+       // result: (ANDconst [c&0xFF] x)
+       for {
+               x := v.Args[0]
+               if x.Op != OpPPC64MOVBZload {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & 0xFF
                v.AddArg(x)
                return true
        }
@@ -4489,6 +4566,22 @@ func rewriteValuePPC64_OpPPC64ADDconst(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64ANDconst(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (ANDconst [c] (ANDconst [d] x))
+       // cond:
+       // result: (ANDconst [c&d] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64ANDconst {
+                       break
+               }
+               d := v_0.AuxInt
+               x := v_0.Args[0]
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & d
+               v.AddArg(x)
+               return true
+       }
        // match: (ANDconst [-1] x)
        // cond:
        // result: x
@@ -4513,6 +4606,102 @@ func rewriteValuePPC64_OpPPC64ANDconst(v *Value, config *Config) bool {
                v.AuxInt = 0
                return true
        }
+       // match: (ANDconst [c] y:(MOVBZreg _))
+       // cond: c&0xFF == 0xFF
+       // result: y
+       for {
+               c := v.AuxInt
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBZreg {
+                       break
+               }
+               if !(c&0xFF == 0xFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (ANDconst [c] y:(MOVHZreg _))
+       // cond: c&0xFFFF == 0xFFFF
+       // result: y
+       for {
+               c := v.AuxInt
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHZreg {
+                       break
+               }
+               if !(c&0xFFFF == 0xFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (ANDconst [c] y:(MOVWZreg _))
+       // cond: c&0xFFFFFFFF == 0xFFFFFFFF
+       // result: y
+       for {
+               c := v.AuxInt
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               if !(c&0xFFFFFFFF == 0xFFFFFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (ANDconst [c] (MOVBZreg x))
+       // cond:
+       // result: (ANDconst [c&0xFF] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVBZreg {
+                       break
+               }
+               x := v_0.Args[0]
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & 0xFF
+               v.AddArg(x)
+               return true
+       }
+       // match: (ANDconst [c] (MOVHZreg x))
+       // cond:
+       // result: (ANDconst [c&0xFFFF] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVHZreg {
+                       break
+               }
+               x := v_0.Args[0]
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & 0xFFFF
+               v.AddArg(x)
+               return true
+       }
+       // match: (ANDconst [c] (MOVWZreg x))
+       // cond:
+       // result: (ANDconst [c&0xFFFFFFFF] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               x := v_0.Args[0]
+               v.reset(OpPPC64ANDconst)
+               v.AuxInt = c & 0xFFFFFFFF
+               v.AddArg(x)
+               return true
+       }
        return false
 }
 func rewriteValuePPC64_OpPPC64CMP(v *Value, config *Config) bool {
@@ -4657,6 +4846,36 @@ func rewriteValuePPC64_OpPPC64CMPUconst(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64CMPW(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (CMPW x (MOVWreg y))
+       // cond:
+       // result: (CMPW x y)
+       for {
+               x := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVWreg {
+                       break
+               }
+               y := v_1.Args[0]
+               v.reset(OpPPC64CMPW)
+               v.AddArg(x)
+               v.AddArg(y)
+               return true
+       }
+       // match: (CMPW (MOVWreg x) y)
+       // cond:
+       // result: (CMPW x y)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVWreg {
+                       break
+               }
+               x := v_0.Args[0]
+               y := v.Args[1]
+               v.reset(OpPPC64CMPW)
+               v.AddArg(x)
+               v.AddArg(y)
+               return true
+       }
        // match: (CMPW x (MOVDconst [c]))
        // cond: is16Bit(c)
        // result: (CMPWconst x [c])
@@ -4700,6 +4919,36 @@ func rewriteValuePPC64_OpPPC64CMPW(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64CMPWU(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (CMPWU x (MOVWZreg y))
+       // cond:
+       // result: (CMPWU x y)
+       for {
+               x := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               y := v_1.Args[0]
+               v.reset(OpPPC64CMPWU)
+               v.AddArg(x)
+               v.AddArg(y)
+               return true
+       }
+       // match: (CMPWU (MOVWZreg x) y)
+       // cond:
+       // result: (CMPWU x y)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               x := v_0.Args[0]
+               y := v.Args[1]
+               v.reset(OpPPC64CMPWU)
+               v.AddArg(x)
+               v.AddArg(y)
+               return true
+       }
        // match: (CMPWU x (MOVDconst [c]))
        // cond: isU16Bit(c)
        // result: (CMPWUconst x [c])
@@ -5440,30 +5689,73 @@ func rewriteValuePPC64_OpPPC64MOVBZload(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64MOVBZreg(v *Value, config *Config) bool {
        b := v.Block
        _ = b
-       // match: (MOVBZreg x:(MOVBZload _ _))
-       // cond:
-       // result: x
+       // match: (MOVBZreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0xFF
+       // result: y
        for {
-               x := v.Args[0]
-               if x.Op != OpPPC64MOVBZload {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0xFF) {
                        break
                }
                v.reset(OpCopy)
-               v.Type = x.Type
-               v.AddArg(x)
+               v.Type = y.Type
+               v.AddArg(y)
                return true
        }
-       // match: (MOVBZreg (MOVDconst [c]))
+       // match: (MOVBZreg y:(MOVBZreg _))
        // cond:
-       // result: (MOVDconst [int64(uint8(c))])
+       // result: y
        for {
-               v_0 := v.Args[0]
-               if v_0.Op != OpPPC64MOVDconst {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBZreg {
                        break
                }
-               c := v_0.AuxInt
-               v.reset(OpPPC64MOVDconst)
-               v.AuxInt = int64(uint8(c))
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVBZreg (MOVBreg x))
+       // cond:
+       // result: (MOVBZreg x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVBreg {
+                       break
+               }
+               x := v_0.Args[0]
+               v.reset(OpPPC64MOVBZreg)
+               v.AddArg(x)
+               return true
+       }
+       // match: (MOVBZreg x:(MOVBZload _ _))
+       // cond:
+       // result: x
+       for {
+               x := v.Args[0]
+               if x.Op != OpPPC64MOVBZload {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               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 != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = int64(uint8(c))
                return true
        }
        return false
@@ -5471,6 +5763,49 @@ func rewriteValuePPC64_OpPPC64MOVBZreg(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64MOVBreg(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (MOVBreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0x7F
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0x7F) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVBreg y:(MOVBreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVBreg (MOVBZreg x))
+       // cond:
+       // result: (MOVBreg x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVBZreg {
+                       break
+               }
+               x := v_0.Args[0]
+               v.reset(OpPPC64MOVBreg)
+               v.AddArg(x)
+               return true
+       }
        // match: (MOVBreg (MOVDconst [c]))
        // cond:
        // result: (MOVDconst [int64(int8(c))])
@@ -5897,6 +6232,62 @@ func rewriteValuePPC64_OpPPC64MOVHZload(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64MOVHZreg(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (MOVHZreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0xFFFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0xFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHZreg y:(MOVHZreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHZreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHZreg y:(MOVBZreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBZreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHZreg y:(MOVHreg x))
+       // cond:
+       // result: (MOVHZreg x)
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHreg {
+                       break
+               }
+               x := y.Args[0]
+               v.reset(OpPPC64MOVHZreg)
+               v.AddArg(x)
+               return true
+       }
        // match: (MOVHZreg x:(MOVHZload _ _))
        // cond:
        // result: x
@@ -5980,6 +6371,62 @@ func rewriteValuePPC64_OpPPC64MOVHload(v *Value, config *Config) bool {
 func rewriteValuePPC64_OpPPC64MOVHreg(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (MOVHreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0x7FFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0x7FFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHreg y:(MOVHreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHreg y:(MOVBreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVHreg y:(MOVHZreg x))
+       // cond:
+       // result: (MOVHreg x)
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHZreg {
+                       break
+               }
+               x := y.Args[0]
+               v.reset(OpPPC64MOVHreg)
+               v.AddArg(x)
+               return true
+       }
        // match: (MOVHreg x:(MOVHload _ _))
        // cond:
        // result: x
@@ -6233,6 +6680,101 @@ func rewriteValuePPC64_OpPPC64MOVWZload(v *Value, config *Config) bool {
        }
        return false
 }
+func rewriteValuePPC64_OpPPC64MOVWZreg(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (MOVWZreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0xFFFFFFFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0xFFFFFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWZreg y:(AND (MOVDconst [c]) _))
+       // cond: uint64(c) <= 0xFFFFFFFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64AND {
+                       break
+               }
+               y_0 := y.Args[0]
+               if y_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := y_0.AuxInt
+               if !(uint64(c) <= 0xFFFFFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWZreg y:(MOVWZreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWZreg y:(MOVHZreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHZreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWZreg y:(MOVBZreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBZreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWZreg y:(MOVWreg x))
+       // cond:
+       // result: (MOVWZreg x)
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVWreg {
+                       break
+               }
+               x := y.Args[0]
+               v.reset(OpPPC64MOVWZreg)
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
 func rewriteValuePPC64_OpPPC64MOVWload(v *Value, config *Config) bool {
        b := v.Block
        _ = b
@@ -6285,6 +6827,101 @@ func rewriteValuePPC64_OpPPC64MOVWload(v *Value, config *Config) bool {
        }
        return false
 }
+func rewriteValuePPC64_OpPPC64MOVWreg(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (MOVWreg y:(ANDconst [c] _))
+       // cond: uint64(c) <= 0xFFFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64ANDconst {
+                       break
+               }
+               c := y.AuxInt
+               if !(uint64(c) <= 0xFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWreg y:(AND (MOVDconst [c]) _))
+       // cond: uint64(c) <= 0x7FFFFFFF
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64AND {
+                       break
+               }
+               y_0 := y.Args[0]
+               if y_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := y_0.AuxInt
+               if !(uint64(c) <= 0x7FFFFFFF) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWreg y:(MOVWreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVWreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWreg y:(MOVHreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVHreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWreg y:(MOVBreg _))
+       // cond:
+       // result: y
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVBreg {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = y.Type
+               v.AddArg(y)
+               return true
+       }
+       // match: (MOVWreg y:(MOVWZreg x))
+       // cond:
+       // result: (MOVWreg x)
+       for {
+               y := v.Args[0]
+               if y.Op != OpPPC64MOVWZreg {
+                       break
+               }
+               x := y.Args[0]
+               v.reset(OpPPC64MOVWreg)
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
 func rewriteValuePPC64_OpPPC64MOVWstore(v *Value, config *Config) bool {
        b := v.Block
        _ = b
@@ -6339,26 +6976,68 @@ func rewriteValuePPC64_OpPPC64MOVWstore(v *Value, config *Config) bool {
                v.AddArg(mem)
                return true
        }
-       // match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
-       // cond: c == 0
-       // result: (MOVWstorezero [off] {sym} ptr mem)
+       // match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
+       // cond: c == 0
+       // result: (MOVWstorezero [off] {sym} ptr mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               mem := v.Args[2]
+               if !(c == 0) {
+                       break
+               }
+               v.reset(OpPPC64MOVWstorezero)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg(ptr)
+               v.AddArg(mem)
+               return true
+       }
+       // match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
+       // cond:
+       // result: (MOVWstore [off] {sym} ptr x mem)
+       for {
+               off := v.AuxInt
+               sym := v.Aux
+               ptr := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVWreg {
+                       break
+               }
+               x := v_1.Args[0]
+               mem := v.Args[2]
+               v.reset(OpPPC64MOVWstore)
+               v.AuxInt = off
+               v.Aux = sym
+               v.AddArg(ptr)
+               v.AddArg(x)
+               v.AddArg(mem)
+               return true
+       }
+       // match: (MOVWstore [off] {sym} ptr (MOVWZreg x) mem)
+       // cond:
+       // result: (MOVWstore [off] {sym} ptr x mem)
        for {
                off := v.AuxInt
                sym := v.Aux
                ptr := v.Args[0]
                v_1 := v.Args[1]
-               if v_1.Op != OpPPC64MOVDconst {
+               if v_1.Op != OpPPC64MOVWZreg {
                        break
                }
-               c := v_1.AuxInt
+               x := v_1.Args[0]
                mem := v.Args[2]
-               if !(c == 0) {
-                       break
-               }
-               v.reset(OpPPC64MOVWstorezero)
+               v.reset(OpPPC64MOVWstore)
                v.AuxInt = off
                v.Aux = sym
                v.AddArg(ptr)
+               v.AddArg(x)
                v.AddArg(mem)
                return true
        }
@@ -6416,6 +7095,32 @@ func rewriteValuePPC64_OpPPC64MOVWstorezero(v *Value, config *Config) bool {
        }
        return false
 }
+func rewriteValuePPC64_OpPPC64MaskIfNotCarry(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (MaskIfNotCarry (ADDconstForCarry [c] (ANDconst [d] _)))
+       // cond: c < 0 && d > 0 && c + d < 0
+       // result: (MOVDconst [-1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64ADDconstForCarry {
+                       break
+               }
+               c := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpPPC64ANDconst {
+                       break
+               }
+               d := v_0_0.AuxInt
+               if !(c < 0 && d > 0 && c+d < 0) {
+                       break
+               }
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = -1
+               return true
+       }
+       return false
+}
 func rewriteValuePPC64_OpPPC64NotEqual(v *Value, config *Config) bool {
        b := v.Block
        _ = b
@@ -6470,27 +7175,69 @@ func rewriteValuePPC64_OpPPC64NotEqual(v *Value, config *Config) bool {
        }
        return false
 }
-func rewriteValuePPC64_OpPPC64XOR(v *Value, config *Config) bool {
+func rewriteValuePPC64_OpPPC64OR(v *Value, config *Config) bool {
        b := v.Block
        _ = b
-       // match: (XOR (MOVDconst [0]) x)
+       // match: (OR (MOVDconst [c]) (MOVDconst [d]))
        // cond:
-       // result: x
+       // result: (MOVDconst [c|d])
        for {
                v_0 := v.Args[0]
                if v_0.Op != OpPPC64MOVDconst {
                        break
                }
-               if v_0.AuxInt != 0 {
+               c := v_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               d := v_1.AuxInt
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = c | d
+               return true
+       }
+       // match: (OR x (MOVDconst [c]))
+       // cond: isU32Bit(c)
+       // result: (ORconst [c] x)
+       for {
+               x := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               if !(isU32Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64ORconst)
+               v.AuxInt = c
+               v.AddArg(x)
+               return true
+       }
+       // match: (OR (MOVDconst [c]) x)
+       // cond: isU32Bit(c)
+       // result: (ORconst [c] x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
                        break
                }
+               c := v_0.AuxInt
                x := v.Args[1]
-               v.reset(OpCopy)
-               v.Type = x.Type
+               if !(isU32Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64ORconst)
+               v.AuxInt = c
                v.AddArg(x)
                return true
        }
-       // match: (XOR x (MOVDconst [0]))
+       return false
+}
+func rewriteValuePPC64_OpPPC64ORN(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (ORN x (MOVDconst [-1]))
        // cond:
        // result: x
        for {
@@ -6499,9 +7246,54 @@ func rewriteValuePPC64_OpPPC64XOR(v *Value, config *Config) bool {
                if v_1.Op != OpPPC64MOVDconst {
                        break
                }
-               if v_1.AuxInt != 0 {
+               if v_1.AuxInt != -1 {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
+func rewriteValuePPC64_OpPPC64ORconst(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (ORconst [c] (ORconst [d] x))
+       // cond:
+       // result: (ORconst [c|d] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64ORconst {
+                       break
+               }
+               d := v_0.AuxInt
+               x := v_0.Args[0]
+               v.reset(OpPPC64ORconst)
+               v.AuxInt = c | d
+               v.AddArg(x)
+               return true
+       }
+       // match: (ORconst [-1] _)
+       // cond:
+       // result: (MOVDconst [-1])
+       for {
+               if v.AuxInt != -1 {
+                       break
+               }
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = -1
+               return true
+       }
+       // match: (ORconst [0] x)
+       // cond:
+       // result: x
+       for {
+               if v.AuxInt != 0 {
                        break
                }
+               x := v.Args[0]
                v.reset(OpCopy)
                v.Type = x.Type
                v.AddArg(x)
@@ -6509,9 +7301,107 @@ func rewriteValuePPC64_OpPPC64XOR(v *Value, config *Config) bool {
        }
        return false
 }
+func rewriteValuePPC64_OpPPC64SUB(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (SUB x (MOVDconst [c]))
+       // cond: is32Bit(-c)
+       // result: (ADDconst [-c] x)
+       for {
+               x := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               if !(is32Bit(-c)) {
+                       break
+               }
+               v.reset(OpPPC64ADDconst)
+               v.AuxInt = -c
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
+func rewriteValuePPC64_OpPPC64XOR(v *Value, config *Config) bool {
+       b := v.Block
+       _ = b
+       // match: (XOR (MOVDconst [c]) (MOVDconst [d]))
+       // cond:
+       // result: (MOVDconst [c^d])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               d := v_1.AuxInt
+               v.reset(OpPPC64MOVDconst)
+               v.AuxInt = c ^ d
+               return true
+       }
+       // match: (XOR x (MOVDconst [c]))
+       // cond: isU32Bit(c)
+       // result: (XORconst [c] x)
+       for {
+               x := v.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_1.AuxInt
+               if !(isU32Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64XORconst)
+               v.AuxInt = c
+               v.AddArg(x)
+               return true
+       }
+       // match: (XOR (MOVDconst [c]) x)
+       // cond: isU32Bit(c)
+       // result: (XORconst [c] x)
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64MOVDconst {
+                       break
+               }
+               c := v_0.AuxInt
+               x := v.Args[1]
+               if !(isU32Bit(c)) {
+                       break
+               }
+               v.reset(OpPPC64XORconst)
+               v.AuxInt = c
+               v.AddArg(x)
+               return true
+       }
+       return false
+}
 func rewriteValuePPC64_OpPPC64XORconst(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (XORconst [c] (XORconst [d] x))
+       // cond:
+       // result: (XORconst [c^d] x)
+       for {
+               c := v.AuxInt
+               v_0 := v.Args[0]
+               if v_0.Op != OpPPC64XORconst {
+                       break
+               }
+               d := v_0.AuxInt
+               x := v_0.Args[0]
+               v.reset(OpPPC64XORconst)
+               v.AuxInt = c ^ d
+               v.AddArg(x)
+               return true
+       }
        // match: (XORconst [0] x)
        // cond:
        // result: x
@@ -8967,6 +9857,62 @@ func rewriteValuePPC64_OpZeroExt8to64(v *Value, config *Config) bool {
 func rewriteBlockPPC64(b *Block, config *Config) bool {
        switch b.Kind {
        case BlockPPC64EQ:
+               // match: (EQ (CMPconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (EQ (ANDCCconst [c] x) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       v_0 := v.Args[0]
+                       if v_0.Op != OpPPC64ANDconst {
+                               break
+                       }
+                       c := v_0.AuxInt
+                       x := v_0.Args[0]
+                       yes := b.Succs[0]
+                       no := b.Succs[1]
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Line, OpPPC64ANDCCconst, TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       _ = yes
+                       _ = no
+                       return true
+               }
+               // match: (EQ (CMPWconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (EQ (ANDCCconst [c] x) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPWconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       v_0 := v.Args[0]
+                       if v_0.Op != OpPPC64ANDconst {
+                               break
+                       }
+                       c := v_0.AuxInt
+                       x := v_0.Args[0]
+                       yes := b.Succs[0]
+                       no := b.Succs[1]
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Line, OpPPC64ANDCCconst, TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       _ = yes
+                       _ = no
+                       return true
+               }
                // match: (EQ (FlagEQ) yes no)
                // cond:
                // result: (First nil yes no)
@@ -9638,6 +10584,62 @@ func rewriteBlockPPC64(b *Block, config *Config) bool {
                        _ = no
                        return true
                }
+               // match: (NE (CMPconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (NE (ANDCCconst [c] x) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       v_0 := v.Args[0]
+                       if v_0.Op != OpPPC64ANDconst {
+                               break
+                       }
+                       c := v_0.AuxInt
+                       x := v_0.Args[0]
+                       yes := b.Succs[0]
+                       no := b.Succs[1]
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Line, OpPPC64ANDCCconst, TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       _ = yes
+                       _ = no
+                       return true
+               }
+               // match: (NE (CMPWconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (NE (ANDCCconst [c] x) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPWconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       v_0 := v.Args[0]
+                       if v_0.Op != OpPPC64ANDconst {
+                               break
+                       }
+                       c := v_0.AuxInt
+                       x := v_0.Args[0]
+                       yes := b.Succs[0]
+                       no := b.Succs[1]
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Line, OpPPC64ANDCCconst, TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       _ = yes
+                       _ = no
+                       return true
+               }
                // match: (NE (FlagEQ) yes no)
                // cond:
                // result: (First nil no yes)