]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: restrict bit test rewrite rules
authorKeith Randall <khr@golang.org>
Mon, 4 May 2020 16:50:20 +0000 (09:50 -0700)
committerKeith Randall <khr@golang.org>
Tue, 5 May 2020 15:41:37 +0000 (15:41 +0000)
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>
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/rewriteAMD64.go
test/fixedbugs/issue38746.go [new file with mode: 0644]

index 7538ce9f721f87e182aab0f5807082819f52dfcd..9967c7b0305ea76a2a98b4f9ee54f9ddac6503fa 100644 (file)
 (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)
index 5f3d4e5b90d8a363203f17ba0a7d62905b713236..20eab05e9ca2ab02df8494eaa1c2c6b98e7bc347 100644 (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
        }
diff --git a/test/fixedbugs/issue38746.go b/test/fixedbugs/issue38746.go
new file mode 100644 (file)
index 0000000..c670349
--- /dev/null
@@ -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)
+}