Commit 3202aa78 authored by Michael Munday's avatar Michael Munday

cmd/compile: improve s390x SSA rules for logical ops

This CL introduces some minor changes to match rules more closely
to the instructions they are targeting. s390x logical operation
with immediate instructions typically leave some bits in the
target register unchanged. This means for example that an XOR
with -1 requires 2 instructions. It is better in cases such as
this to create a constant and leave it visible to the compiler
so that it can be reused rather than hiding it in the assembler.

This CL also tweaks the rules a bit to ensure that constants are
folded when possible.

Change-Id: I1c6dee31ece00fc3c5fdf6a24f1abbc91dd2db2a
Reviewed-on: https://go-review.googlesource.com/31754Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent 2481481f
......@@ -88,7 +88,7 @@
(Com32 x) -> (NOTW x)
(Com16 x) -> (NOTW x)
(Com8 x) -> (NOTW x)
(NOT x) && true -> (XORconst [-1] x)
(NOT x) && true -> (XOR (MOVDconst [-1]) x)
(NOTW x) && true -> (XORWconst [-1] x)
// Lowering boolean ops
......@@ -480,21 +480,25 @@
(MULLW x (MOVDconst [c])) -> (MULLWconst [c] x)
(MULLW (MOVDconst [c]) x) -> (MULLWconst [c] x)
(AND x (MOVDconst [c])) && is32Bit(c) -> (ANDconst [c] x)
(AND (MOVDconst [c]) x) && is32Bit(c) -> (ANDconst [c] x)
// NILF instructions leave the high 32 bits unchanged which is
// equivalent to the leftmost 32 bits being set.
// TODO(mundaym): modify the assembler to accept 64-bit values
// and use isU32Bit(^c).
(AND x (MOVDconst [c])) && is32Bit(c) && c < 0 -> (ANDconst [c] x)
(AND (MOVDconst [c]) x) && is32Bit(c) && c < 0 -> (ANDconst [c] x)
(ANDW x (MOVDconst [c])) -> (ANDWconst [c] x)
(ANDW (MOVDconst [c]) x) -> (ANDWconst [c] x)
(ANDWconst [c] (ANDWconst [d] x)) -> (ANDWconst [c & d] x)
(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c & d] x)
(OR x (MOVDconst [c])) && is32Bit(c) -> (ORconst [c] x)
(OR (MOVDconst [c]) x) && is32Bit(c) -> (ORconst [c] x)
(OR x (MOVDconst [c])) && isU32Bit(c) -> (ORconst [c] x)
(OR (MOVDconst [c]) x) && isU32Bit(c) -> (ORconst [c] x)
(ORW x (MOVDconst [c])) -> (ORWconst [c] x)
(ORW (MOVDconst [c]) x) -> (ORWconst [c] x)
(XOR x (MOVDconst [c])) && is32Bit(c) -> (XORconst [c] x)
(XOR (MOVDconst [c]) x) && is32Bit(c) -> (XORconst [c] x)
(XOR x (MOVDconst [c])) && isU32Bit(c) -> (XORconst [c] x)
(XOR (MOVDconst [c]) x) && isU32Bit(c) -> (XORconst [c] x)
(XORW x (MOVDconst [c])) -> (XORWconst [c] x)
(XORW (MOVDconst [c]) x) -> (XORWconst [c] x)
......@@ -521,10 +525,15 @@
(CMPWU x (MOVDconst [c])) -> (CMPWUconst x [int64(uint32(c))])
(CMPWU (MOVDconst [c]) x) -> (InvertFlags (CMPWUconst x [int64(uint32(c))]))
// Using MOVBZreg instead of AND is cheaper.
(ANDconst [0xFF] x) -> (MOVBZreg x)
(ANDconst [0xFFFF] x) -> (MOVHZreg x)
(ANDconst [0xFFFFFFFF] x) -> (MOVWZreg x)
// Using MOV{W,H,B}Zreg instead of AND is cheaper.
(AND (MOVDconst [0xFF]) x) -> (MOVBZreg x)
(AND x (MOVDconst [0xFF])) -> (MOVBZreg x)
(AND (MOVDconst [0xFFFF]) x) -> (MOVHZreg x)
(AND x (MOVDconst [0xFFFF])) -> (MOVHZreg x)
(AND (MOVDconst [0xFFFFFFFF]) x) -> (MOVWZreg x)
(AND x (MOVDconst [0xFFFFFFFF])) -> (MOVWZreg x)
(ANDWconst [0xFF] x) -> (MOVBZreg x)
(ANDWconst [0xFFFF] x) -> (MOVHZreg x)
// strength reduction
(MULLDconst [-1] x) -> (NEG x)
......@@ -638,21 +647,6 @@
(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
// Fold extensions and ANDs together.
(MOVBZreg (ANDWconst [c] x)) -> (ANDconst [c & 0xff] x)
(MOVHZreg (ANDWconst [c] x)) -> (ANDconst [c & 0xffff] x)
(MOVWZreg (ANDWconst [c] x)) -> (ANDconst [c & 0xffffffff] x)
(MOVBreg (ANDWconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c & 0x7f] x)
(MOVHreg (ANDWconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c & 0x7fff] x)
(MOVWreg (ANDWconst [c] x)) && c & 0x80000000 == 0 -> (ANDconst [c & 0x7fffffff] x)
(MOVBZreg (ANDconst [c] x)) -> (ANDconst [c & 0xff] x)
(MOVHZreg (ANDconst [c] x)) -> (ANDconst [c & 0xffff] x)
(MOVWZreg (ANDconst [c] x)) -> (ANDconst [c & 0xffffffff] x)
(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c & 0x7f] x)
(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c & 0x7fff] x)
(MOVWreg (ANDconst [c] x)) && c & 0x80000000 == 0 -> (ANDconst [c & 0x7fffffff] x)
// Don't extend before storing
(MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
(MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
......@@ -951,14 +945,15 @@
(NEGW (MOVDconst [c])) -> (MOVDconst [int64(int32(-c))])
(MULLDconst [c] (MOVDconst [d])) -> (MOVDconst [c*d])
(MULLWconst [c] (MOVDconst [d])) -> (MOVDconst [int64(int32(c*d))])
(AND (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c&d])
(ANDconst [c] (MOVDconst [d])) -> (MOVDconst [c&d])
(ANDWconst [c] (MOVDconst [d])) -> (MOVDconst [c&d])
(OR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c|d])
(ORconst [c] (MOVDconst [d])) -> (MOVDconst [c|d])
(ORWconst [c] (MOVDconst [d])) -> (MOVDconst [c|d])
(XOR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c^d])
(XORconst [c] (MOVDconst [d])) -> (MOVDconst [c^d])
(XORWconst [c] (MOVDconst [d])) -> (MOVDconst [c^d])
(NOT (MOVDconst [c])) -> (MOVDconst [^c])
(NOTW (MOVDconst [c])) -> (MOVDconst [^c])
// generic simplifications
// TODO: more of this
......
......@@ -6173,7 +6173,7 @@ func rewriteValueS390X_OpS390XAND(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (AND x (MOVDconst [c]))
// cond: is32Bit(c)
// cond: is32Bit(c) && c < 0
// result: (ANDconst [c] x)
for {
x := v.Args[0]
......@@ -6182,7 +6182,7 @@ func rewriteValueS390X_OpS390XAND(v *Value, config *Config) bool {
break
}
c := v_1.AuxInt
if !(is32Bit(c)) {
if !(is32Bit(c) && c < 0) {
break
}
v.reset(OpS390XANDconst)
......@@ -6191,7 +6191,7 @@ func rewriteValueS390X_OpS390XAND(v *Value, config *Config) bool {
return true
}
// match: (AND (MOVDconst [c]) x)
// cond: is32Bit(c)
// cond: is32Bit(c) && c < 0
// result: (ANDconst [c] x)
for {
v_0 := v.Args[0]
......@@ -6200,7 +6200,7 @@ func rewriteValueS390X_OpS390XAND(v *Value, config *Config) bool {
}
c := v_0.AuxInt
x := v.Args[1]
if !(is32Bit(c)) {
if !(is32Bit(c) && c < 0) {
break
}
v.reset(OpS390XANDconst)
......@@ -6208,6 +6208,120 @@ func rewriteValueS390X_OpS390XAND(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (AND (MOVDconst [0xFF]) x)
// cond:
// result: (MOVBZreg x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
if v_0.AuxInt != 0xFF {
break
}
x := v.Args[1]
v.reset(OpS390XMOVBZreg)
v.AddArg(x)
return true
}
// match: (AND x (MOVDconst [0xFF]))
// cond:
// result: (MOVBZreg x)
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
if v_1.AuxInt != 0xFF {
break
}
v.reset(OpS390XMOVBZreg)
v.AddArg(x)
return true
}
// match: (AND (MOVDconst [0xFFFF]) x)
// cond:
// result: (MOVHZreg x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
if v_0.AuxInt != 0xFFFF {
break
}
x := v.Args[1]
v.reset(OpS390XMOVHZreg)
v.AddArg(x)
return true
}
// match: (AND x (MOVDconst [0xFFFF]))
// cond:
// result: (MOVHZreg x)
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
if v_1.AuxInt != 0xFFFF {
break
}
v.reset(OpS390XMOVHZreg)
v.AddArg(x)
return true
}
// match: (AND (MOVDconst [0xFFFFFFFF]) x)
// cond:
// result: (MOVWZreg x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
if v_0.AuxInt != 0xFFFFFFFF {
break
}
x := v.Args[1]
v.reset(OpS390XMOVWZreg)
v.AddArg(x)
return true
}
// match: (AND x (MOVDconst [0xFFFFFFFF]))
// cond:
// result: (MOVWZreg x)
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
if v_1.AuxInt != 0xFFFFFFFF {
break
}
v.reset(OpS390XMOVWZreg)
v.AddArg(x)
return true
}
// match: (AND (MOVDconst [c]) (MOVDconst [d]))
// cond:
// result: (MOVDconst [c&d])
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
d := v_1.AuxInt
v.reset(OpS390XMOVDconst)
v.AuxInt = c & d
return true
}
// match: (AND x x)
// cond:
// result: x
......@@ -6446,6 +6560,30 @@ func rewriteValueS390X_OpS390XANDWconst(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (ANDWconst [0xFF] x)
// cond:
// result: (MOVBZreg x)
for {
if v.AuxInt != 0xFF {
break
}
x := v.Args[0]
v.reset(OpS390XMOVBZreg)
v.AddArg(x)
return true
}
// match: (ANDWconst [0xFFFF] x)
// cond:
// result: (MOVHZreg x)
for {
if v.AuxInt != 0xFFFF {
break
}
x := v.Args[0]
v.reset(OpS390XMOVHZreg)
v.AddArg(x)
return true
}
// match: (ANDWconst [c] _)
// cond: int32(c)==0
// result: (MOVDconst [0])
......@@ -6507,42 +6645,6 @@ func rewriteValueS390X_OpS390XANDconst(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (ANDconst [0xFF] x)
// cond:
// result: (MOVBZreg x)
for {
if v.AuxInt != 0xFF {
break
}
x := v.Args[0]
v.reset(OpS390XMOVBZreg)
v.AddArg(x)
return true
}
// match: (ANDconst [0xFFFF] x)
// cond:
// result: (MOVHZreg x)
for {
if v.AuxInt != 0xFFFF {
break
}
x := v.Args[0]
v.reset(OpS390XMOVHZreg)
v.AddArg(x)
return true
}
// match: (ANDconst [0xFFFFFFFF] x)
// cond:
// result: (MOVWZreg x)
for {
if v.AuxInt != 0xFFFFFFFF {
break
}
x := v.Args[0]
v.reset(OpS390XMOVWZreg)
v.AddArg(x)
return true
}
// match: (ANDconst [0] _)
// cond:
// result: (MOVDconst [0])
......@@ -8185,36 +8287,6 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVBZreg (ANDWconst [c] x))
// cond:
// result: (ANDconst [c & 0xff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xff
v.AddArg(x)
return true
}
// match: (MOVBZreg (ANDconst [c] x))
// cond:
// result: (ANDconst [c & 0xff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xff
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVBload(v *Value, config *Config) bool {
......@@ -8330,42 +8402,6 @@ func rewriteValueS390X_OpS390XMOVBreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVBreg (ANDWconst [c] x))
// cond: c & 0x80 == 0
// result: (ANDconst [c & 0x7f] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x80 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7f
v.AddArg(x)
return true
}
// match: (MOVBreg (ANDconst [c] x))
// cond: c & 0x80 == 0
// result: (ANDconst [c & 0x7f] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x80 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7f
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVBstore(v *Value, config *Config) bool {
......@@ -11271,36 +11307,6 @@ func rewriteValueS390X_OpS390XMOVHZreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVHZreg (ANDWconst [c] x))
// cond:
// result: (ANDconst [c & 0xffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xffff
v.AddArg(x)
return true
}
// match: (MOVHZreg (ANDconst [c] x))
// cond:
// result: (ANDconst [c & 0xffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xffff
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVHload(v *Value, config *Config) bool {
......@@ -11468,42 +11474,6 @@ func rewriteValueS390X_OpS390XMOVHreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVHreg (ANDWconst [c] x))
// cond: c & 0x8000 == 0
// result: (ANDconst [c & 0x7fff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x8000 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7fff
v.AddArg(x)
return true
}
// match: (MOVHreg (ANDconst [c] x))
// cond: c & 0x8000 == 0
// result: (ANDconst [c & 0x7fff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x8000 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7fff
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVHstore(v *Value, config *Config) bool {
......@@ -12738,36 +12708,6 @@ func rewriteValueS390X_OpS390XMOVWZreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVWZreg (ANDWconst [c] x))
// cond:
// result: (ANDconst [c & 0xffffffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xffffffff
v.AddArg(x)
return true
}
// match: (MOVWZreg (ANDconst [c] x))
// cond:
// result: (ANDconst [c & 0xffffffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
v.reset(OpS390XANDconst)
v.AuxInt = c & 0xffffffff
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVWload(v *Value, config *Config) bool {
......@@ -12987,42 +12927,6 @@ func rewriteValueS390X_OpS390XMOVWreg(v *Value, config *Config) bool {
v0.AddArg(mem)
return true
}
// match: (MOVWreg (ANDWconst [c] x))
// cond: c & 0x80000000 == 0
// result: (ANDconst [c & 0x7fffffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDWconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x80000000 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7fffffff
v.AddArg(x)
return true
}
// match: (MOVWreg (ANDconst [c] x))
// cond: c & 0x80000000 == 0
// result: (ANDconst [c & 0x7fffffff] x)
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XANDconst {
break
}
c := v_0.AuxInt
x := v_0.Args[0]
if !(c&0x80000000 == 0) {
break
}
v.reset(OpS390XANDconst)
v.AuxInt = c & 0x7fffffff
v.AddArg(x)
return true
}
return false
}
func rewriteValueS390X_OpS390XMOVWstore(v *Value, config *Config) bool {
......@@ -14119,30 +14023,19 @@ func rewriteValueS390X_OpS390XNOT(v *Value, config *Config) bool {
_ = b
// match: (NOT x)
// cond: true
// result: (XORconst [-1] x)
// result: (XOR (MOVDconst [-1]) x)
for {
x := v.Args[0]
if !(true) {
break
}
v.reset(OpS390XXORconst)
v.AuxInt = -1
v.reset(OpS390XXOR)
v0 := b.NewValue0(v.Line, OpS390XMOVDconst, config.fe.TypeUInt64())
v0.AuxInt = -1
v.AddArg(v0)
v.AddArg(x)
return true
}
// match: (NOT (MOVDconst [c]))
// cond:
// result: (MOVDconst [^c])
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v.reset(OpS390XMOVDconst)
v.AuxInt = ^c
return true
}
return false
}
func rewriteValueS390X_OpS390XNOTW(v *Value, config *Config) bool {
......@@ -14161,26 +14054,13 @@ func rewriteValueS390X_OpS390XNOTW(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (NOTW (MOVDconst [c]))
// cond:
// result: (MOVDconst [^c])
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v.reset(OpS390XMOVDconst)
v.AuxInt = ^c
return true
}
return false
}
func rewriteValueS390X_OpS390XOR(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (OR x (MOVDconst [c]))
// cond: is32Bit(c)
// cond: isU32Bit(c)
// result: (ORconst [c] x)
for {
x := v.Args[0]
......@@ -14189,7 +14069,7 @@ func rewriteValueS390X_OpS390XOR(v *Value, config *Config) bool {
break
}
c := v_1.AuxInt
if !(is32Bit(c)) {
if !(isU32Bit(c)) {
break
}
v.reset(OpS390XORconst)
......@@ -14198,7 +14078,7 @@ func rewriteValueS390X_OpS390XOR(v *Value, config *Config) bool {
return true
}
// match: (OR (MOVDconst [c]) x)
// cond: is32Bit(c)
// cond: isU32Bit(c)
// result: (ORconst [c] x)
for {
v_0 := v.Args[0]
......@@ -14207,7 +14087,7 @@ func rewriteValueS390X_OpS390XOR(v *Value, config *Config) bool {
}
c := v_0.AuxInt
x := v.Args[1]
if !(is32Bit(c)) {
if !(isU32Bit(c)) {
break
}
v.reset(OpS390XORconst)
......@@ -14215,6 +14095,24 @@ func rewriteValueS390X_OpS390XOR(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (OR (MOVDconst [c]) (MOVDconst [d]))
// cond:
// result: (MOVDconst [c|d])
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
d := v_1.AuxInt
v.reset(OpS390XMOVDconst)
v.AuxInt = c | d
return true
}
// match: (OR x x)
// cond:
// result: x
......@@ -16683,7 +16581,7 @@ func rewriteValueS390X_OpS390XXOR(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (XOR x (MOVDconst [c]))
// cond: is32Bit(c)
// cond: isU32Bit(c)
// result: (XORconst [c] x)
for {
x := v.Args[0]
......@@ -16692,7 +16590,7 @@ func rewriteValueS390X_OpS390XXOR(v *Value, config *Config) bool {
break
}
c := v_1.AuxInt
if !(is32Bit(c)) {
if !(isU32Bit(c)) {
break
}
v.reset(OpS390XXORconst)
......@@ -16701,7 +16599,7 @@ func rewriteValueS390X_OpS390XXOR(v *Value, config *Config) bool {
return true
}
// match: (XOR (MOVDconst [c]) x)
// cond: is32Bit(c)
// cond: isU32Bit(c)
// result: (XORconst [c] x)
for {
v_0 := v.Args[0]
......@@ -16710,7 +16608,7 @@ func rewriteValueS390X_OpS390XXOR(v *Value, config *Config) bool {
}
c := v_0.AuxInt
x := v.Args[1]
if !(is32Bit(c)) {
if !(isU32Bit(c)) {
break
}
v.reset(OpS390XXORconst)
......@@ -16718,6 +16616,24 @@ func rewriteValueS390X_OpS390XXOR(v *Value, config *Config) bool {
v.AddArg(x)
return true
}
// match: (XOR (MOVDconst [c]) (MOVDconst [d]))
// cond:
// result: (MOVDconst [c^d])
for {
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
d := v_1.AuxInt
v.reset(OpS390XMOVDconst)
v.AuxInt = c ^ d
return true
}
// match: (XOR x x)
// cond:
// result: (MOVDconst [0])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment