From 3f483e6520ff2d4be6a4a3eeb7a5b485ba0c2d96 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 5 Apr 2018 10:20:05 -0700 Subject: [PATCH] cmd/compile: rewrite a & 1 != 1 into a & 1 == 0 on amd64 These rules trigger 190 times during make.bash. Change-Id: I20d1688db5d8c904a7237c08635c6c9d8bd58b1c Reviewed-on: https://go-review.googlesource.com/105037 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Giovanni Bajo --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 7 + src/cmd/compile/internal/ssa/rewriteAMD64.go | 336 ++++++++++++++++--- 2 files changed, 299 insertions(+), 44 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 4006c5cd7e..10afb2152e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -684,6 +684,13 @@ (BTLconst [c] (SHLLconst [d] x)) && c>d -> (BTLconst [c-d] x) (BTLconst [0] s:(SHRL x y)) -> (BTL y x) +// Rewrite a & 1 != 1 into a & 1 == 0. +// Among other things, this lets us turn (a>>b)&1 != 1 into a bit test. +(SET(NE|EQ) (CMPLconst [1] s:(ANDLconst [1] _))) -> (SET(EQ|NE) (CMPLconst [0] s)) +(SET(NE|EQ)mem [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem) -> (SET(EQ|NE)mem [off] {sym} ptr (CMPLconst [0] s) mem) +(SET(NE|EQ) (CMPQconst [1] s:(ANDQconst [1] _))) -> (SET(EQ|NE) (CMPQconst [0] s)) +(SET(NE|EQ)mem [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem) -> (SET(EQ|NE)mem [off] {sym} ptr (CMPQconst [0] s) mem) + // Recognize bit setting (a |= 1< (BTS(Q|L) x y) (XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) && !config.nacl -> (BTC(Q|L) x y) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 3d781db6f6..5d446b6c45 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -42452,6 +42452,63 @@ func rewriteValueAMD64_OpAMD64SETEQ_0(v *Value) bool { v.AddArg(v0) return true } + // match: (SETEQ (CMPLconst [1] s:(ANDLconst [1] _))) + // cond: + // result: (SETNE (CMPLconst [0] s)) + for { + v_0 := v.Args[0] + if v_0.Op != OpAMD64CMPLconst { + break + } + if v_0.AuxInt != 1 { + break + } + s := v_0.Args[0] + if s.Op != OpAMD64ANDLconst { + break + } + if s.AuxInt != 1 { + break + } + v.reset(OpAMD64SETNE) + v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + return true + } + // match: (SETEQ (CMPQconst [1] s:(ANDQconst [1] _))) + // cond: + // result: (SETNE (CMPQconst [0] s)) + for { + v_0 := v.Args[0] + if v_0.Op != OpAMD64CMPQconst { + break + } + if v_0.AuxInt != 1 { + break + } + s := v_0.Args[0] + if s.Op != OpAMD64ANDQconst { + break + } + if s.AuxInt != 1 { + break + } + v.reset(OpAMD64SETNE) + v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64SETEQ_10(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETEQ (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2)) // cond: z1==z2 && !config.nacl // result: (SETAE (BTQconst [63] x)) @@ -42522,13 +42579,6 @@ func rewriteValueAMD64_OpAMD64SETEQ_0(v *Value) bool { v.AddArg(v0) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETEQ_10(v *Value) bool { - b := v.Block - _ = b - config := b.Func.Config - _ = config // match: (SETEQ (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2)) // cond: z1==z2 && !config.nacl // result: (SETAE (BTQconst [31] x)) @@ -42795,6 +42845,13 @@ func rewriteValueAMD64_OpAMD64SETEQ_10(v *Value) bool { v.AddArg(v0) return true } + return false +} +func rewriteValueAMD64_OpAMD64SETEQ_20(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETEQ (TESTL z1:(SHRLconst [31] x) z2)) // cond: z1==z2 && !config.nacl // result: (SETAE (BTLconst [31] x)) @@ -42851,9 +42908,6 @@ func rewriteValueAMD64_OpAMD64SETEQ_10(v *Value) bool { v.AddArg(v0) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETEQ_20(v *Value) bool { // match: (SETEQ (InvertFlags x)) // cond: // result: (SETEQ x) @@ -43228,6 +43282,81 @@ func rewriteValueAMD64_OpAMD64SETEQmem_0(v *Value) bool { v.AddArg(mem) return true } + // match: (SETEQmem [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem) + // cond: + // result: (SETNEmem [off] {sym} ptr (CMPLconst [0] s) mem) + for { + off := v.AuxInt + sym := v.Aux + _ = v.Args[2] + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAMD64CMPLconst { + break + } + if v_1.AuxInt != 1 { + break + } + s := v_1.Args[0] + if s.Op != OpAMD64ANDLconst { + break + } + if s.AuxInt != 1 { + break + } + mem := v.Args[2] + v.reset(OpAMD64SETNEmem) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (SETEQmem [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem) + // cond: + // result: (SETNEmem [off] {sym} ptr (CMPQconst [0] s) mem) + for { + off := v.AuxInt + sym := v.Aux + _ = v.Args[2] + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAMD64CMPQconst { + break + } + if v_1.AuxInt != 1 { + break + } + s := v_1.Args[0] + if s.Op != OpAMD64ANDQconst { + break + } + if s.AuxInt != 1 { + break + } + mem := v.Args[2] + v.reset(OpAMD64SETNEmem) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64SETEQmem_10(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETEQmem [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETAEmem [off] {sym} ptr (BTQconst [63] x) mem) @@ -43316,13 +43445,6 @@ func rewriteValueAMD64_OpAMD64SETEQmem_0(v *Value) bool { v.AddArg(mem) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETEQmem_10(v *Value) bool { - b := v.Block - _ = b - config := b.Func.Config - _ = config // match: (SETEQmem [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETAEmem [off] {sym} ptr (BTLconst [31] x) mem) @@ -43661,6 +43783,13 @@ func rewriteValueAMD64_OpAMD64SETEQmem_10(v *Value) bool { v.AddArg(mem) return true } + return false +} +func rewriteValueAMD64_OpAMD64SETEQmem_20(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETEQmem [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETAEmem [off] {sym} ptr (BTLconst [31] x) mem) @@ -43735,11 +43864,6 @@ func rewriteValueAMD64_OpAMD64SETEQmem_10(v *Value) bool { v.AddArg(mem) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETEQmem_20(v *Value) bool { - b := v.Block - _ = b // match: (SETEQmem [off] {sym} ptr (InvertFlags x) mem) // cond: // result: (SETEQmem [off] {sym} ptr x mem) @@ -45243,6 +45367,63 @@ func rewriteValueAMD64_OpAMD64SETNE_0(v *Value) bool { v.AddArg(v0) return true } + // match: (SETNE (CMPLconst [1] s:(ANDLconst [1] _))) + // cond: + // result: (SETEQ (CMPLconst [0] s)) + for { + v_0 := v.Args[0] + if v_0.Op != OpAMD64CMPLconst { + break + } + if v_0.AuxInt != 1 { + break + } + s := v_0.Args[0] + if s.Op != OpAMD64ANDLconst { + break + } + if s.AuxInt != 1 { + break + } + v.reset(OpAMD64SETEQ) + v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + return true + } + // match: (SETNE (CMPQconst [1] s:(ANDQconst [1] _))) + // cond: + // result: (SETEQ (CMPQconst [0] s)) + for { + v_0 := v.Args[0] + if v_0.Op != OpAMD64CMPQconst { + break + } + if v_0.AuxInt != 1 { + break + } + s := v_0.Args[0] + if s.Op != OpAMD64ANDQconst { + break + } + if s.AuxInt != 1 { + break + } + v.reset(OpAMD64SETEQ) + v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64SETNE_10(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETNE (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2)) // cond: z1==z2 && !config.nacl // result: (SETB (BTQconst [63] x)) @@ -45313,13 +45494,6 @@ func rewriteValueAMD64_OpAMD64SETNE_0(v *Value) bool { v.AddArg(v0) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETNE_10(v *Value) bool { - b := v.Block - _ = b - config := b.Func.Config - _ = config // match: (SETNE (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2)) // cond: z1==z2 && !config.nacl // result: (SETB (BTQconst [31] x)) @@ -45586,6 +45760,13 @@ func rewriteValueAMD64_OpAMD64SETNE_10(v *Value) bool { v.AddArg(v0) return true } + return false +} +func rewriteValueAMD64_OpAMD64SETNE_20(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETNE (TESTL z1:(SHRLconst [31] x) z2)) // cond: z1==z2 && !config.nacl // result: (SETB (BTLconst [31] x)) @@ -45642,9 +45823,6 @@ func rewriteValueAMD64_OpAMD64SETNE_10(v *Value) bool { v.AddArg(v0) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETNE_20(v *Value) bool { // match: (SETNE (InvertFlags x)) // cond: // result: (SETNE x) @@ -46019,6 +46197,81 @@ func rewriteValueAMD64_OpAMD64SETNEmem_0(v *Value) bool { v.AddArg(mem) return true } + // match: (SETNEmem [off] {sym} ptr (CMPLconst [1] s:(ANDLconst [1] _)) mem) + // cond: + // result: (SETEQmem [off] {sym} ptr (CMPLconst [0] s) mem) + for { + off := v.AuxInt + sym := v.Aux + _ = v.Args[2] + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAMD64CMPLconst { + break + } + if v_1.AuxInt != 1 { + break + } + s := v_1.Args[0] + if s.Op != OpAMD64ANDLconst { + break + } + if s.AuxInt != 1 { + break + } + mem := v.Args[2] + v.reset(OpAMD64SETEQmem) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (SETNEmem [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem) + // cond: + // result: (SETEQmem [off] {sym} ptr (CMPQconst [0] s) mem) + for { + off := v.AuxInt + sym := v.Aux + _ = v.Args[2] + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAMD64CMPQconst { + break + } + if v_1.AuxInt != 1 { + break + } + s := v_1.Args[0] + if s.Op != OpAMD64ANDQconst { + break + } + if s.AuxInt != 1 { + break + } + mem := v.Args[2] + v.reset(OpAMD64SETEQmem) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags) + v0.AuxInt = 0 + v0.AddArg(s) + v.AddArg(v0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64SETNEmem_10(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETNEmem [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETBmem [off] {sym} ptr (BTQconst [63] x) mem) @@ -46107,13 +46360,6 @@ func rewriteValueAMD64_OpAMD64SETNEmem_0(v *Value) bool { v.AddArg(mem) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETNEmem_10(v *Value) bool { - b := v.Block - _ = b - config := b.Func.Config - _ = config // match: (SETNEmem [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETBmem [off] {sym} ptr (BTLconst [31] x) mem) @@ -46452,6 +46698,13 @@ func rewriteValueAMD64_OpAMD64SETNEmem_10(v *Value) bool { v.AddArg(mem) return true } + return false +} +func rewriteValueAMD64_OpAMD64SETNEmem_20(v *Value) bool { + b := v.Block + _ = b + config := b.Func.Config + _ = config // match: (SETNEmem [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem) // cond: z1==z2 && !config.nacl // result: (SETBmem [off] {sym} ptr (BTLconst [31] x) mem) @@ -46526,11 +46779,6 @@ func rewriteValueAMD64_OpAMD64SETNEmem_10(v *Value) bool { v.AddArg(mem) return true } - return false -} -func rewriteValueAMD64_OpAMD64SETNEmem_20(v *Value) bool { - b := v.Block - _ = b // match: (SETNEmem [off] {sym} ptr (InvertFlags x) mem) // cond: // result: (SETNEmem [off] {sym} ptr x mem) -- 2.50.0