1
0
mirror of https://github.com/golang/go synced 2024-09-23 17:20:13 -06:00

cmd/compile: restrict bit test rewrite rules

The {AND,OR,XOR}const ops can only take an int32 as an argument.
Make sure that when rewriting a BTx op to one of these, the result
has no high-order bits.

Fixes #38746

Change-Id: Ia7c5f76952329f60974bc033c29a5433610f3b28
Reviewed-on: https://go-review.googlesource.com/c/go/+/231977
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Keith Randall 2020-05-04 09:50:20 -07:00
parent 9b189686a5
commit b4ecafc986
3 changed files with 155 additions and 87 deletions

View File

@ -735,18 +735,33 @@
(ANDQ x (MOVQconst [c])) && is32Bit(c) -> (ANDQconst [c] x)
(ANDL x (MOVLconst [c])) -> (ANDLconst [c] x)
(AND(L|Q)const [c] (AND(L|Q)const [d] x)) -> (AND(L|Q)const [c & d] x)
(BTR(L|Q)const [c] (AND(L|Q)const [d] x)) -> (AND(L|Q)const [d &^ (1<<uint32(c))] x)
(AND(L|Q)const [c] (BTR(L|Q)const [d] x)) -> (AND(L|Q)const [c &^ (1<<uint32(d))] x)
(BTR(L|Q)const [c] (BTR(L|Q)const [d] x)) -> (AND(L|Q)const [^(1<<uint32(c) | 1<<uint32(d))] x)
(XOR(L|Q)const [c] (XOR(L|Q)const [d] x)) -> (XOR(L|Q)const [c ^ d] x)
(BTC(L|Q)const [c] (XOR(L|Q)const [d] x)) -> (XOR(L|Q)const [d ^ 1<<uint32(c)] x)
(XOR(L|Q)const [c] (BTC(L|Q)const [d] x)) -> (XOR(L|Q)const [c ^ 1<<uint32(d)] x)
(BTC(L|Q)const [c] (BTC(L|Q)const [d] x)) -> (XOR(L|Q)const [1<<uint32(c) ^ 1<<uint32(d)] x)
(OR(L|Q)const [c] (OR(L|Q)const [d] x)) -> (OR(L|Q)const [c | d] x)
(OR(L|Q)const [c] (BTS(L|Q)const [d] x)) -> (OR(L|Q)const [c | 1<<uint32(d)] x)
(BTS(L|Q)const [c] (OR(L|Q)const [d] x)) -> (OR(L|Q)const [d | 1<<uint32(c)] x)
(BTS(L|Q)const [c] (BTS(L|Q)const [d] x)) -> (OR(L|Q)const [1<<uint32(d) | 1<<uint32(c)] x)
(AND(L|Q)const [c] (AND(L|Q)const [d] x)) => (AND(L|Q)const [c & d] x)
(XOR(L|Q)const [c] (XOR(L|Q)const [d] x)) => (XOR(L|Q)const [c ^ d] x)
(OR(L|Q)const [c] (OR(L|Q)const [d] x)) => (OR(L|Q)const [c | d] x)
(BTRLconst [c] (ANDLconst [d] x)) => (ANDLconst [d &^ (1<<uint32(c))] x)
(ANDLconst [c] (BTRLconst [d] x)) => (ANDLconst [c &^ (1<<uint32(d))] x)
(BTRLconst [c] (BTRLconst [d] x)) => (ANDLconst [^(1<<uint32(c) | 1<<uint32(d))] x)
(BTCLconst [c] (XORLconst [d] x)) => (XORLconst [d ^ 1<<uint32(c)] x)
(XORLconst [c] (BTCLconst [d] x)) => (XORLconst [c ^ 1<<uint32(d)] x)
(BTCLconst [c] (BTCLconst [d] x)) => (XORLconst [1<<uint32(c) | 1<<uint32(d)] x)
(BTSLconst [c] (ORLconst [d] x)) => (ORLconst [d | 1<<uint32(c)] x)
(ORLconst [c] (BTSLconst [d] x)) => (ORLconst [c | 1<<uint32(d)] x)
(BTSLconst [c] (BTSLconst [d] x)) => (ORLconst [1<<uint32(c) | 1<<uint32(d)] x)
(BTRQconst [c] (ANDQconst [d] x)) && is32Bit(int64(d) &^ (1<<uint32(c))) => (ANDQconst [d &^ (1<<uint32(c))] x)
(ANDQconst [c] (BTRQconst [d] x)) && is32Bit(int64(c) &^ (1<<uint32(d))) => (ANDQconst [c &^ (1<<uint32(d))] x)
(BTRQconst [c] (BTRQconst [d] x)) && is32Bit(^(1<<uint32(c) | 1<<uint32(d))) => (ANDQconst [^(1<<uint32(c) | 1<<uint32(d))] x)
(BTCQconst [c] (XORQconst [d] x)) && is32Bit(int64(d) ^ 1<<uint32(c)) => (XORQconst [d ^ 1<<uint32(c)] x)
(XORQconst [c] (BTCQconst [d] x)) && is32Bit(int64(c) ^ 1<<uint32(d)) => (XORQconst [c ^ 1<<uint32(d)] x)
(BTCQconst [c] (BTCQconst [d] x)) && is32Bit(1<<uint32(c) ^ 1<<uint32(d)) => (XORQconst [1<<uint32(c) ^ 1<<uint32(d)] x)
(BTSQconst [c] (ORQconst [d] x)) && is32Bit(int64(d) | 1<<uint32(c)) => (ORQconst [d | 1<<uint32(c)] x)
(ORQconst [c] (BTSQconst [d] x)) && is32Bit(int64(c) | 1<<uint32(d)) => (ORQconst [c | 1<<uint32(d)] x)
(BTSQconst [c] (BTSQconst [d] x)) && is32Bit(1<<uint32(c) | 1<<uint32(d)) => (ORQconst [1<<uint32(c) | 1<<uint32(d)] x)
(MULLconst [c] (MULLconst [d] x)) -> (MULLconst [int64(int32(c * d))] x)
(MULQconst [c] (MULQconst [d] x)) && is32Bit(c*d) -> (MULQconst [c * d] x)

View File

@ -2797,28 +2797,28 @@ func rewriteValueAMD64_OpAMD64ANDLconst(v *Value) bool {
// match: (ANDLconst [c] (ANDLconst [d] x))
// result: (ANDLconst [c & d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64ANDLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ANDLconst)
v.AuxInt = c & d
v.AuxInt = int32ToAuxInt(c & d)
v.AddArg(x)
return true
}
// match: (ANDLconst [c] (BTRLconst [d] x))
// result: (ANDLconst [c &^ (1<<uint32(d))] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTRLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ANDLconst)
v.AuxInt = c &^ (1 << uint32(d))
v.AuxInt = int32ToAuxInt(c &^ (1 << uint32(d)))
v.AddArg(x)
return true
}
@ -3176,28 +3176,32 @@ func rewriteValueAMD64_OpAMD64ANDQconst(v *Value) bool {
// match: (ANDQconst [c] (ANDQconst [d] x))
// result: (ANDQconst [c & d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64ANDQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ANDQconst)
v.AuxInt = c & d
v.AuxInt = int32ToAuxInt(c & d)
v.AddArg(x)
return true
}
// match: (ANDQconst [c] (BTRQconst [d] x))
// cond: is32Bit(int64(c) &^ (1<<uint32(d)))
// result: (ANDQconst [c &^ (1<<uint32(d))] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTRQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(c) &^ (1 << uint32(d)))) {
break
}
v.reset(OpAMD64ANDQconst)
v.AuxInt = c &^ (1 << uint32(d))
v.AuxInt = int32ToAuxInt(c &^ (1 << uint32(d)))
v.AddArg(x)
return true
}
@ -3494,28 +3498,28 @@ func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool {
// match: (BTCLconst [c] (XORLconst [d] x))
// result: (XORLconst [d ^ 1<<uint32(c)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64XORLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64XORLconst)
v.AuxInt = d ^ 1<<uint32(c)
v.AuxInt = int32ToAuxInt(d ^ 1<<uint32(c))
v.AddArg(x)
return true
}
// match: (BTCLconst [c] (BTCLconst [d] x))
// result: (XORLconst [1<<uint32(c) ^ 1<<uint32(d)] x)
// result: (XORLconst [1<<uint32(c) | 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTCLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64XORLconst)
v.AuxInt = 1<<uint32(c) ^ 1<<uint32(d)
v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
v.AddArg(x)
return true
}
@ -3635,30 +3639,38 @@ func rewriteValueAMD64_OpAMD64BTCLmodify(v *Value) bool {
func rewriteValueAMD64_OpAMD64BTCQconst(v *Value) bool {
v_0 := v.Args[0]
// match: (BTCQconst [c] (XORQconst [d] x))
// cond: is32Bit(int64(d) ^ 1<<uint32(c))
// result: (XORQconst [d ^ 1<<uint32(c)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64XORQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(d) ^ 1<<uint32(c))) {
break
}
v.reset(OpAMD64XORQconst)
v.AuxInt = d ^ 1<<uint32(c)
v.AuxInt = int32ToAuxInt(d ^ 1<<uint32(c))
v.AddArg(x)
return true
}
// match: (BTCQconst [c] (BTCQconst [d] x))
// cond: is32Bit(1<<uint32(c) ^ 1<<uint32(d))
// result: (XORQconst [1<<uint32(c) ^ 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTCQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(1<<uint32(c) ^ 1<<uint32(d))) {
break
}
v.reset(OpAMD64XORQconst)
v.AuxInt = 1<<uint32(c) ^ 1<<uint32(d)
v.AuxInt = int32ToAuxInt(1<<uint32(c) ^ 1<<uint32(d))
v.AddArg(x)
return true
}
@ -3970,28 +3982,28 @@ func rewriteValueAMD64_OpAMD64BTRLconst(v *Value) bool {
// match: (BTRLconst [c] (ANDLconst [d] x))
// result: (ANDLconst [d &^ (1<<uint32(c))] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64ANDLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ANDLconst)
v.AuxInt = d &^ (1 << uint32(c))
v.AuxInt = int32ToAuxInt(d &^ (1 << uint32(c)))
v.AddArg(x)
return true
}
// match: (BTRLconst [c] (BTRLconst [d] x))
// result: (ANDLconst [^(1<<uint32(c) | 1<<uint32(d))] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTRLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ANDLconst)
v.AuxInt = ^(1<<uint32(c) | 1<<uint32(d))
v.AuxInt = int32ToAuxInt(^(1<<uint32(c) | 1<<uint32(d)))
v.AddArg(x)
return true
}
@ -4137,30 +4149,38 @@ func rewriteValueAMD64_OpAMD64BTRQconst(v *Value) bool {
return true
}
// match: (BTRQconst [c] (ANDQconst [d] x))
// cond: is32Bit(int64(d) &^ (1<<uint32(c)))
// result: (ANDQconst [d &^ (1<<uint32(c))] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64ANDQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(d) &^ (1 << uint32(c)))) {
break
}
v.reset(OpAMD64ANDQconst)
v.AuxInt = d &^ (1 << uint32(c))
v.AuxInt = int32ToAuxInt(d &^ (1 << uint32(c)))
v.AddArg(x)
return true
}
// match: (BTRQconst [c] (BTRQconst [d] x))
// cond: is32Bit(^(1<<uint32(c) | 1<<uint32(d)))
// result: (ANDQconst [^(1<<uint32(c) | 1<<uint32(d))] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTRQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(^(1<<uint32(c) | 1<<uint32(d)))) {
break
}
v.reset(OpAMD64ANDQconst)
v.AuxInt = ^(1<<uint32(c) | 1<<uint32(d))
v.AuxInt = int32ToAuxInt(^(1<<uint32(c) | 1<<uint32(d)))
v.AddArg(x)
return true
}
@ -4308,28 +4328,28 @@ func rewriteValueAMD64_OpAMD64BTSLconst(v *Value) bool {
// match: (BTSLconst [c] (ORLconst [d] x))
// result: (ORLconst [d | 1<<uint32(c)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64ORLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ORLconst)
v.AuxInt = d | 1<<uint32(c)
v.AuxInt = int32ToAuxInt(d | 1<<uint32(c))
v.AddArg(x)
return true
}
// match: (BTSLconst [c] (BTSLconst [d] x))
// result: (ORLconst [1<<uint32(d) | 1<<uint32(c)] x)
// result: (ORLconst [1<<uint32(c) | 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTSLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ORLconst)
v.AuxInt = 1<<uint32(d) | 1<<uint32(c)
v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
v.AddArg(x)
return true
}
@ -4475,30 +4495,38 @@ func rewriteValueAMD64_OpAMD64BTSQconst(v *Value) bool {
return true
}
// match: (BTSQconst [c] (ORQconst [d] x))
// cond: is32Bit(int64(d) | 1<<uint32(c))
// result: (ORQconst [d | 1<<uint32(c)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64ORQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(d) | 1<<uint32(c))) {
break
}
v.reset(OpAMD64ORQconst)
v.AuxInt = d | 1<<uint32(c)
v.AuxInt = int32ToAuxInt(d | 1<<uint32(c))
v.AddArg(x)
return true
}
// match: (BTSQconst [c] (BTSQconst [d] x))
// result: (ORQconst [1<<uint32(d) | 1<<uint32(c)] x)
// cond: is32Bit(1<<uint32(c) | 1<<uint32(d))
// result: (ORQconst [1<<uint32(c) | 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt8(v.AuxInt)
if v_0.Op != OpAMD64BTSQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(1<<uint32(c) | 1<<uint32(d))) {
break
}
v.reset(OpAMD64ORQconst)
v.AuxInt = 1<<uint32(d) | 1<<uint32(c)
v.AuxInt = int32ToAuxInt(1<<uint32(c) | 1<<uint32(d))
v.AddArg(x)
return true
}
@ -18127,28 +18155,28 @@ func rewriteValueAMD64_OpAMD64ORLconst(v *Value) bool {
// match: (ORLconst [c] (ORLconst [d] x))
// result: (ORLconst [c | d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64ORLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ORLconst)
v.AuxInt = c | d
v.AuxInt = int32ToAuxInt(c | d)
v.AddArg(x)
return true
}
// match: (ORLconst [c] (BTSLconst [d] x))
// result: (ORLconst [c | 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTSLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ORLconst)
v.AuxInt = c | 1<<uint32(d)
v.AuxInt = int32ToAuxInt(c | 1<<uint32(d))
v.AddArg(x)
return true
}
@ -19754,28 +19782,32 @@ func rewriteValueAMD64_OpAMD64ORQconst(v *Value) bool {
// match: (ORQconst [c] (ORQconst [d] x))
// result: (ORQconst [c | d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64ORQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64ORQconst)
v.AuxInt = c | d
v.AuxInt = int32ToAuxInt(c | d)
v.AddArg(x)
return true
}
// match: (ORQconst [c] (BTSQconst [d] x))
// cond: is32Bit(int64(c) | 1<<uint32(d))
// result: (ORQconst [c | 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTSQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(c) | 1<<uint32(d))) {
break
}
v.reset(OpAMD64ORQconst)
v.AuxInt = c | 1<<uint32(d)
v.AuxInt = int32ToAuxInt(c | 1<<uint32(d))
v.AddArg(x)
return true
}
@ -27785,28 +27817,28 @@ func rewriteValueAMD64_OpAMD64XORLconst(v *Value) bool {
// match: (XORLconst [c] (XORLconst [d] x))
// result: (XORLconst [c ^ d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64XORLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64XORLconst)
v.AuxInt = c ^ d
v.AuxInt = int32ToAuxInt(c ^ d)
v.AddArg(x)
return true
}
// match: (XORLconst [c] (BTCLconst [d] x))
// result: (XORLconst [c ^ 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTCLconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64XORLconst)
v.AuxInt = c ^ 1<<uint32(d)
v.AuxInt = int32ToAuxInt(c ^ 1<<uint32(d))
v.AddArg(x)
return true
}
@ -28151,28 +28183,32 @@ func rewriteValueAMD64_OpAMD64XORQconst(v *Value) bool {
// match: (XORQconst [c] (XORQconst [d] x))
// result: (XORQconst [c ^ d] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64XORQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt32(v_0.AuxInt)
x := v_0.Args[0]
v.reset(OpAMD64XORQconst)
v.AuxInt = c ^ d
v.AuxInt = int32ToAuxInt(c ^ d)
v.AddArg(x)
return true
}
// match: (XORQconst [c] (BTCQconst [d] x))
// cond: is32Bit(int64(c) ^ 1<<uint32(d))
// result: (XORQconst [c ^ 1<<uint32(d)] x)
for {
c := v.AuxInt
c := auxIntToInt32(v.AuxInt)
if v_0.Op != OpAMD64BTCQconst {
break
}
d := v_0.AuxInt
d := auxIntToInt8(v_0.AuxInt)
x := v_0.Args[0]
if !(is32Bit(int64(c) ^ 1<<uint32(d))) {
break
}
v.reset(OpAMD64XORQconst)
v.AuxInt = c ^ 1<<uint32(d)
v.AuxInt = int32ToAuxInt(c ^ 1<<uint32(d))
v.AddArg(x)
return true
}

View File

@ -0,0 +1,17 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
var g *uint64
func main() {
var v uint64
g = &v
v &^= (1 << 31)
v |= 1 << 63
v &^= (1 << 63)
}