diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64.rules b/src/cmd/compile/internal/ssa/_gen/AMD64.rules index 1a32c26ae2..ba7f181f5e 100644 --- a/src/cmd/compile/internal/ssa/_gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/_gen/AMD64.rules @@ -664,9 +664,11 @@ // Handle bit-testing in the form (a>>b)&1 != 0 by building the above rules // and further combining shifts. (BT(Q|L)const [c] (SHRQconst [d] x)) && (c+d)<64 => (BTQconst [c+d] x) +(BT(Q|L)const [c] (ADDQ x x)) && c>1 => (BT(Q|L)const [c-1] x) (BT(Q|L)const [c] (SHLQconst [d] x)) && c>d => (BT(Q|L)const [c-d] x) (BT(Q|L)const [0] s:(SHRQ x y)) => (BTQ y x) (BTLconst [c] (SHRLconst [d] x)) && (c+d)<32 => (BTLconst [c+d] x) +(BTLconst [c] (ADDL x x)) && c>1 => (BTLconst [c-1] x) (BTLconst [c] (SHLLconst [d] x)) && c>d => (BTLconst [c-d] x) (BTLconst [0] s:(SHR(L|XL) x y)) => (BTL y x) @@ -702,11 +704,11 @@ // We thus special-case them, by detecting the shift patterns. // Special case resetting first/last bit -(SHL(L|Q)const [1] (SHR(L|Q)const [1] x)) +(ADD(L|Q) (SHR(L|Q)const [1] x) (SHR(L|Q)const [1] x)) => (AND(L|Q)const [-2] x) -(SHRLconst [1] (SHLLconst [1] x)) +(SHRLconst [1] (ADDL x x)) => (ANDLconst [0x7fffffff] x) -(SHRQconst [1] (SHLQconst [1] x)) +(SHRQconst [1] (ADDQ x x)) => (BTRQconst [63] x) // Special case testing first/last bit (with double-shift generated by generic.rules) @@ -933,17 +935,19 @@ (MUL(Q|L)const [c] x) && c%5 == 0 && isPowerOfTwo(c/5) => (SHL(Q|L)const [int8(log32(c/5))] (LEA(Q|L)4 x x)) (MUL(Q|L)const [c] x) && c%9 == 0 && isPowerOfTwo(c/9) => (SHL(Q|L)const [int8(log32(c/9))] (LEA(Q|L)8 x x)) +// Prefer addition when shifting left by one +(SHL(Q|L)const [1] x) => (ADD(Q|L) x x) + // combine add/shift into LEAQ/LEAL (ADD(L|Q) x (SHL(L|Q)const [3] y)) => (LEA(L|Q)8 x y) (ADD(L|Q) x (SHL(L|Q)const [2] y)) => (LEA(L|Q)4 x y) -(ADD(L|Q) x (SHL(L|Q)const [1] y)) => (LEA(L|Q)2 x y) (ADD(L|Q) x (ADD(L|Q) y y)) => (LEA(L|Q)2 x y) (ADD(L|Q) x (ADD(L|Q) x y)) => (LEA(L|Q)2 y x) // combine ADDQ/ADDQconst into LEAQ1/LEAL1 (ADD(Q|L)const [c] (ADD(Q|L) x y)) => (LEA(Q|L)1 [c] x y) (ADD(Q|L) (ADD(Q|L)const [c] x) y) => (LEA(Q|L)1 [c] x y) -(ADD(Q|L)const [c] (SHL(Q|L)const [1] x)) => (LEA(Q|L)1 [c] x x) +(ADD(Q|L)const [c] (ADD(Q|L) x x)) => (LEA(Q|L)1 [c] x x) // fold ADDQ/ADDL into LEAQ/LEAL (ADD(Q|L)const [c] (LEA(Q|L) [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEA(Q|L) [c+d] {s} x) @@ -965,12 +969,18 @@ (LEA(Q|L)8 [c] {s} x (ADD(Q|L)const [d] y)) && is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB => (LEA(Q|L)8 [c+8*d] {s} x y) // fold shifts into LEAQx/LEALx -(LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)2 [c] {s} x y) +(LEA(Q|L)1 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)2 [c] {s} x y) (LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)4 [c] {s} x y) (LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [3] y)) => (LEA(Q|L)8 [c] {s} x y) -(LEA(Q|L)2 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)4 [c] {s} x y) +(LEA(Q|L)2 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)4 [c] {s} x y) (LEA(Q|L)2 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)8 [c] {s} x y) -(LEA(Q|L)4 [c] {s} x (SHL(Q|L)const [1] y)) => (LEA(Q|L)8 [c] {s} x y) +(LEA(Q|L)4 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)8 [c] {s} x y) + +// (x + x) << 1 -> x << 2 +(LEA(Q|L)2 [0] {s} (ADD(Q|L) x x) x) && s == nil => (SHL(Q|L)const [2] x) + +// (x + x) << 2 -> x << 3 and similar +(SHL(Q|L)const [c] (ADD(Q|L) x x)) => (SHL(Q|L)const [c+1] x) // reverse ordering of compare instruction (SETL (InvertFlags x)) => (SETG x) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 7dc0a7bdc2..28041ea76d 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1261,6 +1261,21 @@ func rewriteValueAMD64_OpAMD64ADCQconst(v *Value) bool { func rewriteValueAMD64_OpAMD64ADDL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + // match: (ADDL (SHRLconst [1] x) (SHRLconst [1] x)) + // result: (ANDLconst [-2] x) + for { + if v_0.Op != OpAMD64SHRLconst || auxIntToInt8(v_0.AuxInt) != 1 { + break + } + x := v_0.Args[0] + if v_1.Op != OpAMD64SHRLconst || auxIntToInt8(v_1.AuxInt) != 1 || x != v_1.Args[0] { + break + } + v.reset(OpAMD64ANDLconst) + v.AuxInt = int32ToAuxInt(-2) + v.AddArg(x) + return true + } // match: (ADDL x (MOVLconst [c])) // result: (ADDLconst [c] x) for { @@ -1307,21 +1322,6 @@ func rewriteValueAMD64_OpAMD64ADDL(v *Value) bool { } break } - // match: (ADDL x (SHLLconst [1] y)) - // result: (LEAL2 x y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 { - continue - } - y := v_1.Args[0] - v.reset(OpAMD64LEAL2) - v.AddArg2(x, y) - return true - } - break - } // match: (ADDL x (ADDL y y)) // result: (LEAL2 x y) for { @@ -1461,14 +1461,17 @@ func rewriteValueAMD64_OpAMD64ADDLconst(v *Value) bool { v.AddArg2(x, y) return true } - // match: (ADDLconst [c] (SHLLconst [1] x)) + // match: (ADDLconst [c] (ADDL x x)) // result: (LEAL1 [c] x x) for { c := auxIntToInt32(v.AuxInt) - if v_0.Op != OpAMD64SHLLconst || auxIntToInt8(v_0.AuxInt) != 1 { + if v_0.Op != OpAMD64ADDL { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { break } - x := v_0.Args[0] v.reset(OpAMD64LEAL1) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, x) @@ -1806,6 +1809,21 @@ func rewriteValueAMD64_OpAMD64ADDLmodify(v *Value) bool { func rewriteValueAMD64_OpAMD64ADDQ(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + // match: (ADDQ (SHRQconst [1] x) (SHRQconst [1] x)) + // result: (ANDQconst [-2] x) + for { + if v_0.Op != OpAMD64SHRQconst || auxIntToInt8(v_0.AuxInt) != 1 { + break + } + x := v_0.Args[0] + if v_1.Op != OpAMD64SHRQconst || auxIntToInt8(v_1.AuxInt) != 1 || x != v_1.Args[0] { + break + } + v.reset(OpAMD64ANDQconst) + v.AuxInt = int32ToAuxInt(-2) + v.AddArg(x) + return true + } // match: (ADDQ x (MOVQconst [c])) // cond: is32Bit(c) && !t.IsPtr() // result: (ADDQconst [int32(c)] x) @@ -1873,21 +1891,6 @@ func rewriteValueAMD64_OpAMD64ADDQ(v *Value) bool { } break } - // match: (ADDQ x (SHLQconst [1] y)) - // result: (LEAQ2 x y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 { - continue - } - y := v_1.Args[0] - v.reset(OpAMD64LEAQ2) - v.AddArg2(x, y) - return true - } - break - } // match: (ADDQ x (ADDQ y y)) // result: (LEAQ2 x y) for { @@ -2052,14 +2055,17 @@ func rewriteValueAMD64_OpAMD64ADDQconst(v *Value) bool { v.AddArg2(x, y) return true } - // match: (ADDQconst [c] (SHLQconst [1] x)) + // match: (ADDQconst [c] (ADDQ x x)) // result: (LEAQ1 [c] x x) for { c := auxIntToInt32(v.AuxInt) - if v_0.Op != OpAMD64SHLQconst || auxIntToInt8(v_0.AuxInt) != 1 { + if v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { break } - x := v_0.Args[0] v.reset(OpAMD64LEAQ1) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, x) @@ -3637,6 +3643,23 @@ func rewriteValueAMD64_OpAMD64BTLconst(v *Value) bool { v.AddArg(x) return true } + // match: (BTLconst [c] (ADDQ x x)) + // cond: c>1 + // result: (BTLconst [c-1] x) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] || !(c > 1) { + break + } + v.reset(OpAMD64BTLconst) + v.AuxInt = int8ToAuxInt(c - 1) + v.AddArg(x) + return true + } // match: (BTLconst [c] (SHLQconst [d] x)) // cond: c>d // result: (BTLconst [c-d] x) @@ -3689,6 +3712,23 @@ func rewriteValueAMD64_OpAMD64BTLconst(v *Value) bool { v.AddArg(x) return true } + // match: (BTLconst [c] (ADDL x x)) + // cond: c>1 + // result: (BTLconst [c-1] x) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpAMD64ADDL { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] || !(c > 1) { + break + } + v.reset(OpAMD64BTLconst) + v.AuxInt = int8ToAuxInt(c - 1) + v.AddArg(x) + return true + } // match: (BTLconst [c] (SHLLconst [d] x)) // cond: c>d // result: (BTLconst [c-d] x) @@ -3761,6 +3801,23 @@ func rewriteValueAMD64_OpAMD64BTQconst(v *Value) bool { v.AddArg(x) return true } + // match: (BTQconst [c] (ADDQ x x)) + // cond: c>1 + // result: (BTQconst [c-1] x) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] || !(c > 1) { + break + } + v.reset(OpAMD64BTQconst) + v.AuxInt = int8ToAuxInt(c - 1) + v.AddArg(x) + return true + } // match: (BTQconst [c] (SHLQconst [d] x)) // cond: c>d // result: (BTQconst [c-d] x) @@ -8287,17 +8344,20 @@ func rewriteValueAMD64_OpAMD64LEAL1(v *Value) bool { } break } - // match: (LEAL1 [c] {s} x (SHLLconst [1] y)) + // match: (LEAL1 [c] {s} x (ADDL y y)) // result: (LEAL2 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDL { + continue + } + y := v_1.Args[1] + if y != v_1.Args[0] { continue } - y := v_1.Args[0] v.reset(OpAMD64LEAL2) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -8391,16 +8451,19 @@ func rewriteValueAMD64_OpAMD64LEAL2(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAL2 [c] {s} x (SHLLconst [1] y)) + // match: (LEAL2 [c] {s} x (ADDL y y)) // result: (LEAL4 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDL { + break + } + y := v_1.Args[1] + if y != v_1.Args[0] { break } - y := v_1.Args[0] v.reset(OpAMD64LEAL4) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -8423,6 +8486,26 @@ func rewriteValueAMD64_OpAMD64LEAL2(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAL2 [0] {s} (ADDL x x) x) + // cond: s == nil + // result: (SHLLconst [2] x) + for { + if auxIntToInt32(v.AuxInt) != 0 { + break + } + s := auxToSym(v.Aux) + if v_0.Op != OpAMD64ADDL { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] || x != v_1 || !(s == nil) { + break + } + v.reset(OpAMD64SHLLconst) + v.AuxInt = int8ToAuxInt(2) + v.AddArg(x) + return true + } return false } func rewriteValueAMD64_OpAMD64LEAL4(v *Value) bool { @@ -8470,16 +8553,19 @@ func rewriteValueAMD64_OpAMD64LEAL4(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAL4 [c] {s} x (SHLLconst [1] y)) + // match: (LEAL4 [c] {s} x (ADDL y y)) // result: (LEAL8 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - if v_1.Op != OpAMD64SHLLconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDL { + break + } + y := v_1.Args[1] + if y != v_1.Args[0] { break } - y := v_1.Args[0] v.reset(OpAMD64LEAL8) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -8721,17 +8807,20 @@ func rewriteValueAMD64_OpAMD64LEAQ1(v *Value) bool { } break } - // match: (LEAQ1 [c] {s} x (SHLQconst [1] y)) + // match: (LEAQ1 [c] {s} x (ADDQ y y)) // result: (LEAQ2 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDQ { + continue + } + y := v_1.Args[1] + if y != v_1.Args[0] { continue } - y := v_1.Args[0] v.reset(OpAMD64LEAQ2) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -8924,16 +9013,19 @@ func rewriteValueAMD64_OpAMD64LEAQ2(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAQ2 [c] {s} x (SHLQconst [1] y)) + // match: (LEAQ2 [c] {s} x (ADDQ y y)) // result: (LEAQ4 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDQ { + break + } + y := v_1.Args[1] + if y != v_1.Args[0] { break } - y := v_1.Args[0] v.reset(OpAMD64LEAQ4) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -8956,6 +9048,26 @@ func rewriteValueAMD64_OpAMD64LEAQ2(v *Value) bool { v.AddArg2(x, y) return true } + // match: (LEAQ2 [0] {s} (ADDQ x x) x) + // cond: s == nil + // result: (SHLQconst [2] x) + for { + if auxIntToInt32(v.AuxInt) != 0 { + break + } + s := auxToSym(v.Aux) + if v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] || x != v_1 || !(s == nil) { + break + } + v.reset(OpAMD64SHLQconst) + v.AuxInt = int8ToAuxInt(2) + v.AddArg(x) + return true + } // match: (LEAQ2 [off1] {sym1} (LEAQ [off2] {sym2} x) y) // cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && x.Op != OpSB // result: (LEAQ2 [off1+off2] {mergeSym(sym1,sym2)} x y) @@ -9087,16 +9199,19 @@ func rewriteValueAMD64_OpAMD64LEAQ4(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAQ4 [c] {s} x (SHLQconst [1] y)) + // match: (LEAQ4 [c] {s} x (ADDQ y y)) // result: (LEAQ8 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - if v_1.Op != OpAMD64SHLQconst || auxIntToInt8(v_1.AuxInt) != 1 { + if v_1.Op != OpAMD64ADDQ { + break + } + y := v_1.Args[1] + if y != v_1.Args[0] { break } - y := v_1.Args[0] v.reset(OpAMD64LEAQ8) v.AuxInt = int32ToAuxInt(c) v.Aux = symToAux(s) @@ -20736,18 +20851,6 @@ func rewriteValueAMD64_OpAMD64SHLL(v *Value) bool { } func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool { v_0 := v.Args[0] - // match: (SHLLconst [1] (SHRLconst [1] x)) - // result: (ANDLconst [-2] x) - for { - if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHRLconst || auxIntToInt8(v_0.AuxInt) != 1 { - break - } - x := v_0.Args[0] - v.reset(OpAMD64ANDLconst) - v.AuxInt = int32ToAuxInt(-2) - v.AddArg(x) - return true - } // match: (SHLLconst x [0]) // result: x for { @@ -20758,6 +20861,33 @@ func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool { v.copyOf(x) return true } + // match: (SHLLconst [1] x) + // result: (ADDL x x) + for { + if auxIntToInt8(v.AuxInt) != 1 { + break + } + x := v_0 + v.reset(OpAMD64ADDL) + v.AddArg2(x, x) + return true + } + // match: (SHLLconst [c] (ADDL x x)) + // result: (SHLLconst [c+1] x) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpAMD64ADDL { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { + break + } + v.reset(OpAMD64SHLLconst) + v.AuxInt = int8ToAuxInt(c + 1) + v.AddArg(x) + return true + } // match: (SHLLconst [d] (MOVLconst [c])) // result: (MOVLconst [c << uint64(d)]) for { @@ -20992,18 +21122,6 @@ func rewriteValueAMD64_OpAMD64SHLQ(v *Value) bool { } func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool { v_0 := v.Args[0] - // match: (SHLQconst [1] (SHRQconst [1] x)) - // result: (ANDQconst [-2] x) - for { - if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHRQconst || auxIntToInt8(v_0.AuxInt) != 1 { - break - } - x := v_0.Args[0] - v.reset(OpAMD64ANDQconst) - v.AuxInt = int32ToAuxInt(-2) - v.AddArg(x) - return true - } // match: (SHLQconst x [0]) // result: x for { @@ -21014,6 +21132,33 @@ func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool { v.copyOf(x) return true } + // match: (SHLQconst [1] x) + // result: (ADDQ x x) + for { + if auxIntToInt8(v.AuxInt) != 1 { + break + } + x := v_0 + v.reset(OpAMD64ADDQ) + v.AddArg2(x, x) + return true + } + // match: (SHLQconst [c] (ADDQ x x)) + // result: (SHLQconst [c+1] x) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { + break + } + v.reset(OpAMD64SHLQconst) + v.AuxInt = int8ToAuxInt(c + 1) + v.AddArg(x) + return true + } // match: (SHLQconst [d] (MOVQconst [c])) // result: (MOVQconst [c << uint64(d)]) for { @@ -21419,13 +21564,16 @@ func rewriteValueAMD64_OpAMD64SHRL(v *Value) bool { } func rewriteValueAMD64_OpAMD64SHRLconst(v *Value) bool { v_0 := v.Args[0] - // match: (SHRLconst [1] (SHLLconst [1] x)) + // match: (SHRLconst [1] (ADDL x x)) // result: (ANDLconst [0x7fffffff] x) for { - if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHLLconst || auxIntToInt8(v_0.AuxInt) != 1 { + if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64ADDL { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { break } - x := v_0.Args[0] v.reset(OpAMD64ANDLconst) v.AuxInt = int32ToAuxInt(0x7fffffff) v.AddArg(x) @@ -21663,13 +21811,16 @@ func rewriteValueAMD64_OpAMD64SHRQ(v *Value) bool { } func rewriteValueAMD64_OpAMD64SHRQconst(v *Value) bool { v_0 := v.Args[0] - // match: (SHRQconst [1] (SHLQconst [1] x)) + // match: (SHRQconst [1] (ADDQ x x)) // result: (BTRQconst [63] x) for { - if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64SHLQconst || auxIntToInt8(v_0.AuxInt) != 1 { + if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpAMD64ADDQ { + break + } + x := v_0.Args[1] + if x != v_0.Args[0] { break } - x := v_0.Args[0] v.reset(OpAMD64BTRQconst) v.AuxInt = int8ToAuxInt(63) v.AddArg(x) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 4b47f6c13d..063055053e 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -185,6 +185,15 @@ func Pow2Muls(n1, n2 int) (int, int) { return a, b } +func Mul_2(n1 int32, n2 int64) (int32, int64) { + // amd64:"ADDL", -"SHLL" + a := n1 * 2 + // amd64:"ADDQ", -"SHLQ" + b := n2 * 2 + + return a, b +} + func Mul_96(n int) int { // amd64:`SHLQ\t[$]5`,`LEAQ\t\(.*\)\(.*\*2\),`,-`IMULQ` // 386:`SHLL\t[$]5`,`LEAL\t\(.*\)\(.*\*2\),`,-`IMULL` diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 354dbf407a..c20e4d6733 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -120,6 +120,16 @@ func bitoff64(a, b uint64) (n uint64) { return n } +func clearLastBit(x int64, y int32) (int64, int32) { + // amd64:"ANDQ\t[$]-2" + a := (x >> 1) << 1 + + // amd64:"ANDL\t[$]-2" + b := (y >> 1) << 1 + + return a, b +} + func bitcompl64(a, b uint64) (n uint64) { // amd64:"BTCQ" n += b ^ (1 << (a & 63)) diff --git a/test/codegen/shift.go b/test/codegen/shift.go index 2d8cf86857..52efefb0ed 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -58,6 +58,16 @@ func rshConst64x64Overflow8(v int8) int64 { return int64(v) >> 8 } +func lshConst32x1(v int32) int32 { + // amd64:"ADDL", -"SHLL" + return v << 1 +} + +func lshConst64x1(v int64) int64 { + // amd64:"ADDQ", -"SHLQ" + return v << 1 +} + func lshConst32x64(v int32) int32 { // ppc64x:"SLW" // riscv64:"SLLI",-"AND",-"SLTIU", -"MOVW" @@ -94,6 +104,26 @@ func rshConst64x32(v int64) int64 { return v >> uint32(33) } +func lshConst32x1Add(x int32) int32 { + // amd64:"SHLL\t[$]2" + return (x + x) << 1 +} + +func lshConst64x1Add(x int64) int64 { + // amd64:"SHLQ\t[$]2" + return (x + x) << 1 +} + +func lshConst32x2Add(x int32) int32 { + // amd64:"SHLL\t[$]3" + return (x + x) << 2 +} + +func lshConst64x2Add(x int64) int64 { + // amd64:"SHLQ\t[$]3" + return (x + x) << 2 +} + // ------------------ // // masked shifts // // ------------------ //