]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use ANDCC, ORCC, XORCC to avoid CMP on ppc64x
authorLynn Boger <laboger@linux.vnet.ibm.com>
Wed, 10 Oct 2018 17:47:18 +0000 (13:47 -0400)
committerLynn Boger <laboger@linux.vnet.ibm.com>
Fri, 9 Nov 2018 19:40:52 +0000 (19:40 +0000)
This change makes use of the cc versions of the AND, OR, XOR
instructions, omitting the need for a CMP instruction.

In many test programs and in the go binary, this reduces the
size of 20-30 functions by at least 1 instruction, many in
runtime.

Testcase added to test/codegen/comparisons.go

Change-Id: I6cc1ca8b80b065d7390749c625bc9784b0039adb
Reviewed-on: https://go-review.googlesource.com/c/143059
Reviewed-by: Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
Reviewed-by: Michael Munday <mike.munday@ibm.com>
Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gobot Gobot <gobot@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/rewritePPC64.go
test/codegen/comparisons.go

index a3f8b67177d56504ae677661f1f0aa182de77f1b..a6dd8cab5f50229507cb223c1ef85f95741a8d9b 100644 (file)
@@ -569,7 +569,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                ssa.OpPPC64ROTL, ssa.OpPPC64ROTLW,
                ssa.OpPPC64MULHD, ssa.OpPPC64MULHW, ssa.OpPPC64MULHDU, ssa.OpPPC64MULHWU,
                ssa.OpPPC64FMUL, ssa.OpPPC64FMULS, ssa.OpPPC64FDIV, ssa.OpPPC64FDIVS, ssa.OpPPC64FCPSGN,
-               ssa.OpPPC64AND, ssa.OpPPC64OR, ssa.OpPPC64ANDN, ssa.OpPPC64ORN, ssa.OpPPC64NOR, ssa.OpPPC64XOR, ssa.OpPPC64EQV:
+               ssa.OpPPC64AND, ssa.OpPPC64ANDCC, ssa.OpPPC64OR, ssa.OpPPC64ORCC, ssa.OpPPC64ANDN, ssa.OpPPC64ORN, ssa.OpPPC64NOR, ssa.OpPPC64XOR, ssa.OpPPC64XORCC, ssa.OpPPC64EQV:
                r := v.Reg()
                r1 := v.Args[0].Reg()
                r2 := v.Args[1].Reg()
index 0eaa88596ba96b5ba4def326a00f14752ffca49b..24cee6f0a3a02107316602b805661dffb6e37019 100644 (file)
 (LessEqual (InvertFlags x)) -> (GreaterEqual x)
 (GreaterEqual (InvertFlags x)) -> (LessEqual x)
 
+// Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] (ANDconst [c] x)) yes no) -> ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPWconst [0] (ANDconst [c] x)) yes no) -> ((EQ|NE|LT|LE|GT|GE) (ANDCCconst [c] x) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (ANDCC x y) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(OR x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (ORCC x y) yes no)
+((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 -> ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no)
+
 // Lowering loads
 (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
 (Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
index ef0db69fb71303cb16b2f966a735a22d0d3079ae..d6638b1ec72e644ba5eaec5b48e4e9e2d7611974 100644 (file)
@@ -241,24 +241,27 @@ func init() {
                {name: "MFVSRD", argLength: 1, reg: fpgp, asm: "MFVSRD", typ: "Int64"},   // move 64 bits of F register into G register
                {name: "MTVSRD", argLength: 1, reg: gpfp, asm: "MTVSRD", typ: "Float64"}, // move 64 bits of G register into F register
 
-               {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true},               // arg0&arg1
-               {name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"},                                // arg0&^arg1
-               {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true},                 // arg0|arg1
-               {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"},                                  // arg0|^arg1
-               {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true},               // ^(arg0|arg1)
-               {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true}, // arg0^arg1
-               {name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1
-               {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"},                                  // -arg0 (integer)
-               {name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"},                                // -arg0 (floating point)
-               {name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"},                              // sqrt(arg0) (floating point)
-               {name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"},                            // sqrt(arg0) (floating point, single precision)
-               {name: "FFLOOR", argLength: 1, reg: fp11, asm: "FRIM"},                              // floor(arg0), float64
-               {name: "FCEIL", argLength: 1, reg: fp11, asm: "FRIP"},                               // ceil(arg0), float64
-               {name: "FTRUNC", argLength: 1, reg: fp11, asm: "FRIZ"},                              // trunc(arg0), float64
-               {name: "FROUND", argLength: 1, reg: fp11, asm: "FRIN"},                              // round(arg0), float64
-               {name: "FABS", argLength: 1, reg: fp11, asm: "FABS"},                                // abs(arg0), float64
-               {name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"},                              // -abs(arg0), float64
-               {name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"},                            // copysign arg0 -> arg1, float64
+               {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true},                   // arg0&arg1
+               {name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"},                                    // arg0&^arg1
+               {name: "ANDCC", argLength: 2, reg: gp21, asm: "ANDCC", commutative: true, typ: "Flags"}, // arg0&arg1 sets CC
+               {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true},                     // arg0|arg1
+               {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"},                                      // arg0|^arg1
+               {name: "ORCC", argLength: 2, reg: gp21, asm: "ORCC", commutative: true, typ: "Flags"},   // arg0|arg1 sets CC
+               {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true},                   // ^(arg0|arg1)
+               {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true},     // arg0^arg1
+               {name: "XORCC", argLength: 2, reg: gp21, asm: "XORCC", commutative: true, typ: "Flags"}, // arg0^arg1 sets CC
+               {name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true},     // arg0^^arg1
+               {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"},                                      // -arg0 (integer)
+               {name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"},                                    // -arg0 (floating point)
+               {name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"},                                  // sqrt(arg0) (floating point)
+               {name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"},                                // sqrt(arg0) (floating point, single precision)
+               {name: "FFLOOR", argLength: 1, reg: fp11, asm: "FRIM"},                                  // floor(arg0), float64
+               {name: "FCEIL", argLength: 1, reg: fp11, asm: "FRIP"},                                   // ceil(arg0), float64
+               {name: "FTRUNC", argLength: 1, reg: fp11, asm: "FRIZ"},                                  // trunc(arg0), float64
+               {name: "FROUND", argLength: 1, reg: fp11, asm: "FRIN"},                                  // round(arg0), float64
+               {name: "FABS", argLength: 1, reg: fp11, asm: "FABS"},                                    // abs(arg0), float64
+               {name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"},                                  // -abs(arg0), float64
+               {name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"},                                // copysign arg0 -> arg1, float64
 
                {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"},                                                                                     // arg0|aux
                {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"},                                                                                   // arg0^aux
index 03837b5f63e82464bf4a7e63a21d46a8f482597e..f6568be660f4e043087196fed2c6fed01fd7a424 100644 (file)
@@ -1663,10 +1663,13 @@ const (
        OpPPC64MTVSRD
        OpPPC64AND
        OpPPC64ANDN
+       OpPPC64ANDCC
        OpPPC64OR
        OpPPC64ORN
+       OpPPC64ORCC
        OpPPC64NOR
        OpPPC64XOR
+       OpPPC64XORCC
        OpPPC64EQV
        OpPPC64NEG
        OpPPC64FNEG
@@ -22202,6 +22205,21 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:        "ANDCC",
+               argLen:      2,
+               commutative: true,
+               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
+                               {1, 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
+                       },
+                       outputs: []outputInfo{
+                               {0, 1073733624}, // 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:        "OR",
                argLen:      2,
@@ -22231,6 +22249,21 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:        "ORCC",
+               argLen:      2,
+               commutative: true,
+               asm:         ppc64.AORCC,
+               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
+                               {1, 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
+                       },
+                       outputs: []outputInfo{
+                               {0, 1073733624}, // 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:        "NOR",
                argLen:      2,
@@ -22261,6 +22294,21 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:        "XORCC",
+               argLen:      2,
+               commutative: true,
+               asm:         ppc64.AXORCC,
+               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
+                               {1, 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
+                       },
+                       outputs: []outputInfo{
+                               {0, 1073733624}, // 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:        "EQV",
                argLen:      2,
index abad10a2d1a93193b1b6212b939b191015ebd1c0..9c89e0e674a4f12416decc19a18d3994d4884f2d 100644 (file)
@@ -30996,6 +30996,143 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        return true
                }
+               // 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]
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       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]
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (EQ (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (EQ (ANDCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (EQ (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (EQ (ORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (EQ (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (EQ (XORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64EQ
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
        case BlockPPC64GE:
                // match: (GE (FlagEQ) yes no)
                // cond:
@@ -31051,6 +31188,143 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        return true
                }
+               // match: (GE (CMPconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (GE (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]
+                       b.Kind = BlockPPC64GE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GE (CMPWconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (GE (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]
+                       b.Kind = BlockPPC64GE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GE (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GE (ANDCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GE (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GE (ORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GE (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GE (XORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GE
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
        case BlockPPC64GT:
                // match: (GT (FlagEQ) yes no)
                // cond:
@@ -31107,6 +31381,143 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        return true
                }
+               // match: (GT (CMPconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (GT (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]
+                       b.Kind = BlockPPC64GT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GT (CMPWconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (GT (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]
+                       b.Kind = BlockPPC64GT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GT (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GT (ANDCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GT (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GT (ORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (GT (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (GT (XORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64GT
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
        case BlockIf:
                // match: (If (Equal cc) yes no)
                // cond:
@@ -31234,39 +31645,231 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        return true
                }
-               // match: (If (FGreaterEqual cc) yes no)
-               // cond:
-               // result: (FGE cc yes no)
+               // match: (If (FGreaterEqual cc) yes no)
+               // cond:
+               // result: (FGE cc yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64FGreaterEqual {
+                               break
+                       }
+                       cc := v.Args[0]
+                       b.Kind = BlockPPC64FGE
+                       b.SetControl(cc)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (If cond yes no)
+               // cond:
+               // result: (NE (CMPWconst [0] cond) yes no)
+               for {
+                       v := b.Control
+                       _ = v
+                       cond := b.Control
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags)
+                       v0.AuxInt = 0
+                       v0.AddArg(cond)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+       case BlockPPC64LE:
+               // match: (LE (FlagEQ) yes no)
+               // cond:
+               // result: (First nil yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64FlagEQ {
+                               break
+                       }
+                       b.Kind = BlockFirst
+                       b.SetControl(nil)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (FlagLT) yes no)
+               // cond:
+               // result: (First nil yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64FlagLT {
+                               break
+                       }
+                       b.Kind = BlockFirst
+                       b.SetControl(nil)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (FlagGT) yes no)
+               // cond:
+               // result: (First nil no yes)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64FlagGT {
+                               break
+                       }
+                       b.Kind = BlockFirst
+                       b.SetControl(nil)
+                       b.Aux = nil
+                       b.swapSuccessors()
+                       return true
+               }
+               // match: (LE (InvertFlags cmp) yes no)
+               // cond:
+               // result: (GE cmp yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64InvertFlags {
+                               break
+                       }
+                       cmp := v.Args[0]
+                       b.Kind = BlockPPC64GE
+                       b.SetControl(cmp)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (CMPconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (LE (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]
+                       b.Kind = BlockPPC64LE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (CMPWconst [0] (ANDconst [c] x)) yes no)
+               // cond:
+               // result: (LE (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]
+                       b.Kind = BlockPPC64LE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LE (ANDCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LE (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LE (ORCC x y) yes no)
                for {
                        v := b.Control
-                       if v.Op != OpPPC64FGreaterEqual {
+                       if v.Op != OpPPC64CMPconst {
                                break
                        }
-                       cc := v.Args[0]
-                       b.Kind = BlockPPC64FGE
-                       b.SetControl(cc)
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
                        b.Aux = nil
                        return true
                }
-               // match: (If cond yes no)
-               // cond:
-               // result: (NE (CMPWconst [0] cond) yes no)
+               // match: (LE (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LE (XORCC x y) yes no)
                for {
                        v := b.Control
-                       _ = v
-                       cond := b.Control
-                       b.Kind = BlockPPC64NE
-                       v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags)
-                       v0.AuxInt = 0
-                       v0.AddArg(cond)
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LE
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
                        b.SetControl(v0)
                        b.Aux = nil
                        return true
                }
-       case BlockPPC64LE:
-               // match: (LE (FlagEQ) yes no)
+       case BlockPPC64LT:
+               // match: (LT (FlagEQ) yes no)
                // cond:
-               // result: (First nil yes no)
+               // result: (First nil no yes)
                for {
                        v := b.Control
                        if v.Op != OpPPC64FlagEQ {
@@ -31275,9 +31878,10 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Kind = BlockFirst
                        b.SetControl(nil)
                        b.Aux = nil
+                       b.swapSuccessors()
                        return true
                }
-               // match: (LE (FlagLT) yes no)
+               // match: (LT (FlagLT) yes no)
                // cond:
                // result: (First nil yes no)
                for {
@@ -31290,7 +31894,7 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        return true
                }
-               // match: (LE (FlagGT) yes no)
+               // match: (LT (FlagGT) yes no)
                // cond:
                // result: (First nil no yes)
                for {
@@ -31304,73 +31908,154 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.swapSuccessors()
                        return true
                }
-               // match: (LE (InvertFlags cmp) yes no)
+               // match: (LT (InvertFlags cmp) yes no)
                // cond:
-               // result: (GE cmp yes no)
+               // result: (GT cmp yes no)
                for {
                        v := b.Control
                        if v.Op != OpPPC64InvertFlags {
                                break
                        }
                        cmp := v.Args[0]
-                       b.Kind = BlockPPC64GE
+                       b.Kind = BlockPPC64GT
                        b.SetControl(cmp)
                        b.Aux = nil
                        return true
                }
-       case BlockPPC64LT:
-               // match: (LT (FlagEQ) yes no)
+               // match: (LT (CMPconst [0] (ANDconst [c] x)) yes no)
                // cond:
-               // result: (First nil no yes)
+               // result: (LT (ANDCCconst [c] x) yes no)
                for {
                        v := b.Control
-                       if v.Op != OpPPC64FlagEQ {
+                       if v.Op != OpPPC64CMPconst {
                                break
                        }
-                       b.Kind = BlockFirst
-                       b.SetControl(nil)
+                       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]
+                       b.Kind = BlockPPC64LT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
                        b.Aux = nil
-                       b.swapSuccessors()
                        return true
                }
-               // match: (LT (FlagLT) yes no)
+               // match: (LT (CMPWconst [0] (ANDconst [c] x)) yes no)
                // cond:
-               // result: (First nil yes no)
+               // result: (LT (ANDCCconst [c] x) yes no)
                for {
                        v := b.Control
-                       if v.Op != OpPPC64FlagLT {
+                       if v.Op != OpPPC64CMPWconst {
                                break
                        }
-                       b.Kind = BlockFirst
-                       b.SetControl(nil)
+                       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]
+                       b.Kind = BlockPPC64LT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
                        b.Aux = nil
                        return true
                }
-               // match: (LT (FlagGT) yes no)
-               // cond:
-               // result: (First nil no yes)
+               // match: (LT (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LT (ANDCC x y) yes no)
                for {
                        v := b.Control
-                       if v.Op != OpPPC64FlagGT {
+                       if v.Op != OpPPC64CMPconst {
                                break
                        }
-                       b.Kind = BlockFirst
-                       b.SetControl(nil)
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
                        b.Aux = nil
-                       b.swapSuccessors()
                        return true
                }
-               // match: (LT (InvertFlags cmp) yes no)
-               // cond:
-               // result: (GT cmp yes no)
+               // match: (LT (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LT (ORCC x y) yes no)
                for {
                        v := b.Control
-                       if v.Op != OpPPC64InvertFlags {
+                       if v.Op != OpPPC64CMPconst {
                                break
                        }
-                       cmp := v.Args[0]
-                       b.Kind = BlockPPC64GT
-                       b.SetControl(cmp)
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LT
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (LT (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (LT (XORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64LT
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
                        b.Aux = nil
                        return true
                }
@@ -31689,6 +32374,143 @@ func rewriteBlockPPC64(b *Block) bool {
                        b.Aux = nil
                        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]
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       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]
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.TypeFlags)
+                       v0.AuxInt = c
+                       v0.AddArg(x)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (NE (CMPconst [0] z:(AND x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (NE (ANDCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64AND {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ANDCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (NE (CMPconst [0] z:(OR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (NE (ORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64OR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64ORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
+               // match: (NE (CMPconst [0] z:(XOR x y)) yes no)
+               // cond: z.Uses == 1
+               // result: (NE (XORCC x y) yes no)
+               for {
+                       v := b.Control
+                       if v.Op != OpPPC64CMPconst {
+                               break
+                       }
+                       if v.AuxInt != 0 {
+                               break
+                       }
+                       z := v.Args[0]
+                       if z.Op != OpPPC64XOR {
+                               break
+                       }
+                       _ = z.Args[1]
+                       x := z.Args[0]
+                       y := z.Args[1]
+                       if !(z.Uses == 1) {
+                               break
+                       }
+                       b.Kind = BlockPPC64NE
+                       v0 := b.NewValue0(v.Pos, OpPPC64XORCC, types.TypeFlags)
+                       v0.AddArg(x)
+                       v0.AddArg(y)
+                       b.SetControl(v0)
+                       b.Aux = nil
+                       return true
+               }
        }
        return false
 }
index fb17d3ca5dd13afc031ab503e118e0ac32ed0869..f14918e9dfdda5e4ce993e1495034cfa51c9bf8e 100644 (file)
@@ -210,3 +210,36 @@ func CmpToZero(a, b, d int32, e, f int64) int32 {
                return 0
        }
 }
+
+func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
+
+       // ppc64:"ANDCC",-"CMPW"
+       // ppc64le:"ANDCC",-"CMPW"
+       if a & 63 == 0 {
+               return 1
+       }
+
+       // ppc64:"ANDCC",-"CMP"
+       // ppc64le:"ANDCC",-"CMP"
+       if d & 255 == 0 {
+               return 1
+       }
+
+       // ppc64:"ANDCC",-"CMP"
+       // ppc64le:"ANDCC",-"CMP"
+       if d & e == 0 {
+               return 1
+       }
+       // ppc64:"ORCC",-"CMP"
+       // ppc64le:"ORCC",-"CMP"
+       if d | e == 0 {
+               return 1
+       }
+
+       // ppc64:"XORCC",-"CMP"
+       // ppc64le:"XORCC",-"CMP"
+       if e ^ d == 0 {
+               return 1
+       }
+       return 0
+}