Same as BSFQ, if the input is known to be nonzero we don't need a CMOV
to correct for the weird all-zero behavior of the BSRQ instruction.
Fixes #51964
Change-Id: Ic1d14fdf3e7e698ff2f47efecfd761d8a036012a
Reviewed-on: https://go-review.googlesource.com/c/go/+/396034
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
(CMPXCHGLlock [off1+off2] {sym} ptr old new_ mem)
// We don't need the conditional move if we know the arg of BSF is not zero.
-(CMOVQEQ x _ (Select1 (BSFQ (ORQconst [c] _)))) && c != 0 => x
+(CMOVQEQ x _ (Select1 (BS(F|R)Q (ORQconst [c] _)))) && c != 0 => x
// Extension is unnecessary for trailing zeros.
(BSFQ (ORQconst <t> [1<<8] (MOVBQZX x))) => (BSFQ (ORQconst <t> [1<<8] x))
(BSFQ (ORQconst <t> [1<<16] (MOVWQZX x))) => (BSFQ (ORQconst <t> [1<<16] x))
v.copyOf(x)
return true
}
+ // match: (CMOVQEQ x _ (Select1 (BSRQ (ORQconst [c] _))))
+ // cond: c != 0
+ // result: x
+ for {
+ x := v_0
+ if v_2.Op != OpSelect1 {
+ break
+ }
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpAMD64BSRQ {
+ break
+ }
+ v_2_0_0 := v_2_0.Args[0]
+ if v_2_0_0.Op != OpAMD64ORQconst {
+ break
+ }
+ c := auxIntToInt32(v_2_0_0.AuxInt)
+ if !(c != 0) {
+ break
+ }
+ v.copyOf(x)
+ return true
+ }
return false
}
func rewriteValueAMD64_OpAMD64CMOVQGE(v *Value) bool {