(XORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
-> (EXTRWconst [32-c] x2 x)
-// Generic rules rewrite certain AND to a pair of shifts.
-// However, on ARM64 the bitmask can fit into an instruction.
-// Rewrite it back to AND.
+// Rewrite special pairs of shifts to AND.
+// On ARM64 the bitmask can fit into an instruction.
(SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1<<uint(64-c)-1] x) // mask out high bits
(SLLconst [c] (SRLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [^(1<<uint(c)-1)] x) // mask out low bits
(Slicemask (Const64 [x])) && x > 0 -> (Const64 [-1])
(Slicemask (Const64 [0])) -> (Const64 [0])
-// Rewrite AND of consts as shifts if possible, slightly faster for 64 bit operands
-// leading zeros can be shifted left, then right
-(And64 <t> (Const64 [y]) x) && nlz(y) + nto(y) == 64 && nto(y) >= 32
- -> (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
-// trailing zeros can be shifted right, then left
-(And64 <t> (Const64 [y]) x) && nlo(y) + ntz(y) == 64 && ntz(y) >= 32
- -> (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
-
// simplifications often used for lengths. e.g. len(s[i:i+5])==5
(Sub(64|32|16|8) (Add(64|32|16|8) x y) x) -> y
(Sub(64|32|16|8) (Add(64|32|16|8) x y) y) -> x
v.AddArg(y)
return true
}
- // match: (And64 <t> (Const64 [y]) x)
- // cond: nlz(y) + nto(y) == 64 && nto(y) >= 32
- // result: (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
- for {
- t := v.Type
- x := v.Args[1]
- v_0 := v.Args[0]
- if v_0.Op != OpConst64 {
- break
- }
- y := v_0.AuxInt
- if !(nlz(y)+nto(y) == 64 && nto(y) >= 32) {
- break
- }
- v.reset(OpRsh64Ux64)
- v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
- v0.AddArg(x)
- v1 := b.NewValue0(v.Pos, OpConst64, t)
- v1.AuxInt = nlz(y)
- v0.AddArg(v1)
- v.AddArg(v0)
- v2 := b.NewValue0(v.Pos, OpConst64, t)
- v2.AuxInt = nlz(y)
- v.AddArg(v2)
- return true
- }
- // match: (And64 <t> x (Const64 [y]))
- // cond: nlz(y) + nto(y) == 64 && nto(y) >= 32
- // result: (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst64 {
- break
- }
- y := v_1.AuxInt
- if !(nlz(y)+nto(y) == 64 && nto(y) >= 32) {
- break
- }
- v.reset(OpRsh64Ux64)
- v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
- v0.AddArg(x)
- v1 := b.NewValue0(v.Pos, OpConst64, t)
- v1.AuxInt = nlz(y)
- v0.AddArg(v1)
- v.AddArg(v0)
- v2 := b.NewValue0(v.Pos, OpConst64, t)
- v2.AuxInt = nlz(y)
- v.AddArg(v2)
- return true
- }
- // match: (And64 <t> (Const64 [y]) x)
- // cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32
- // result: (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
- for {
- t := v.Type
- x := v.Args[1]
- v_0 := v.Args[0]
- if v_0.Op != OpConst64 {
- break
- }
- y := v_0.AuxInt
- if !(nlo(y)+ntz(y) == 64 && ntz(y) >= 32) {
- break
- }
- v.reset(OpLsh64x64)
- v0 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
- v0.AddArg(x)
- v1 := b.NewValue0(v.Pos, OpConst64, t)
- v1.AuxInt = ntz(y)
- v0.AddArg(v1)
- v.AddArg(v0)
- v2 := b.NewValue0(v.Pos, OpConst64, t)
- v2.AuxInt = ntz(y)
- v.AddArg(v2)
- return true
- }
- // match: (And64 <t> x (Const64 [y]))
- // cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32
- // result: (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst64 {
- break
- }
- y := v_1.AuxInt
- if !(nlo(y)+ntz(y) == 64 && ntz(y) >= 32) {
- break
- }
- v.reset(OpLsh64x64)
- v0 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
- v0.AddArg(x)
- v1 := b.NewValue0(v.Pos, OpConst64, t)
- v1.AuxInt = ntz(y)
- v0.AddArg(v1)
- v.AddArg(v0)
- v2 := b.NewValue0(v.Pos, OpConst64, t)
- v2.AuxInt = ntz(y)
- v.AddArg(v2)
- return true
- }
// match: (And64 (And64 i:(Const64 <t>) z) x)
// cond: (z.Op != OpConst64 && x.Op != OpConst64)
// result: (And64 i (And64 <t> z x))
v.AddArg(v0)
return true
}
- return false
-}
-func rewriteValuegeneric_OpAnd64_20(v *Value) bool {
- b := v.Block
// match: (And64 (And64 z i:(Const64 <t>)) x)
// cond: (z.Op != OpConst64 && x.Op != OpConst64)
// result: (And64 i (And64 <t> z x))
v.AddArg(x)
return true
}
+ return false
+}
+func rewriteValuegeneric_OpAnd64_20(v *Value) bool {
+ b := v.Block
// match: (And64 (Const64 <t> [c]) (And64 x (Const64 <t> [d])))
// cond:
// result: (And64 (Const64 <t> [c&d]) x)
// Check that it's using integer registers
func copysign(a, b, c float64) {
- // amd64:"BTRQ\t[$]63","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // amd64:"BTRQ\t[$]63","ANDQ","ORQ"
// s390x:"CPSDR",-"MOVD" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)
- // amd64:-"SHLQ\t[$]1",-"SHRQ\t[$]1","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // amd64:"ANDQ","ORQ"
// s390x:"CPSDR\t",-"MOVD\t" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"