]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/ssa/rewrite.go
cmd/compile/internal/ssa: on PPC64, merge (CMPconst [0] (op ...)) more aggressively
[gostls13.git] / src / cmd / compile / internal / ssa / rewrite.go
index eebedea68c9ed310545dad3dfc40af3be9cb5bfd..fa4208228e78cbb49c16ecf5704b04d19ee068e5 100644 (file)
@@ -859,6 +859,9 @@ func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool {
                        offset += base.AuxInt
                        base = base.Args[0]
                }
+               if opcodeTable[base.Op].nilCheck {
+                       base = base.Args[0]
+               }
                return base, offset
        }
        p1, off1 := baseAndOffset(p1)
@@ -1183,6 +1186,12 @@ func min(x, y int64) int64 {
        }
        return y
 }
+func max(x, y int64) int64 {
+       if x > y {
+               return x
+       }
+       return y
+}
 
 func isConstZero(v *Value) bool {
        switch v.Op {
@@ -1621,6 +1630,52 @@ func mergePPC64SldiSrw(sld, srw int64) int64 {
        return encodePPC64RotateMask((32-srw+sld)&31, int64(mask), 32)
 }
 
+// Convert a PPC64 opcode from the Op to OpCC form. This converts (op x y)
+// to (Select0 (opCC x y)) without having to explicitly fixup every user
+// of op.
+//
+// E.g consider the case:
+// a = (ADD x y)
+// b = (CMPconst [0] a)
+// c = (OR a z)
+//
+// A rule like (CMPconst [0] (ADD x y)) => (CMPconst [0] (Select0 (ADDCC x y)))
+// would produce:
+// a  = (ADD x y)
+// a' = (ADDCC x y)
+// a” = (Select0 a')
+// b  = (CMPconst [0] a”)
+// c  = (OR a z)
+//
+// which makes it impossible to rewrite the second user. Instead the result
+// of this conversion is:
+// a' = (ADDCC x y)
+// a  = (Select0 a')
+// b  = (CMPconst [0] a)
+// c  = (OR a z)
+//
+// Which makes it trivial to rewrite b using a lowering rule.
+func convertPPC64OpToOpCC(op *Value) *Value {
+       ccOpMap := map[Op]Op{
+               OpPPC64ADD:      OpPPC64ADDCC,
+               OpPPC64ADDconst: OpPPC64ADDCCconst,
+               OpPPC64AND:      OpPPC64ANDCC,
+               OpPPC64ANDN:     OpPPC64ANDNCC,
+               OpPPC64CNTLZD:   OpPPC64CNTLZDCC,
+               OpPPC64OR:       OpPPC64ORCC,
+               OpPPC64SUB:      OpPPC64SUBCC,
+               OpPPC64NEG:      OpPPC64NEGCC,
+               OpPPC64NOR:      OpPPC64NORCC,
+               OpPPC64XOR:      OpPPC64XORCC,
+       }
+       b := op.Block
+       opCC := b.NewValue0I(op.Pos, ccOpMap[op.Op], types.NewTuple(op.Type, types.TypeFlags), op.AuxInt)
+       opCC.AddArgs(op.Args...)
+       op.reset(OpSelect0)
+       op.AddArgs(opCC)
+       return op
+}
+
 // Convenience function to rotate a 32 bit constant value by another constant.
 func rotateLeft32(v, rotate int64) int64 {
        return int64(bits.RotateLeft32(uint32(v), int(rotate)))
@@ -2146,3 +2201,11 @@ func isARM64addcon(v int64) bool {
        }
        return v <= 0xFFF
 }
+
+// setPos sets the position of v to pos, then returns true.
+// Useful for setting the result of a rewrite's position to
+// something other than the default.
+func setPos(v *Value, pos src.XPos) bool {
+       v.Pos = pos
+       return true
+}