]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: ensure constant folding of pointer arithmetic remains a pointer
authorKeith Randall <khr@golang.org>
Wed, 15 Feb 2023 18:21:52 +0000 (10:21 -0800)
committerKeith Randall <khr@golang.org>
Fri, 17 Feb 2023 03:56:57 +0000 (03:56 +0000)
For c + nil, we want the result to still be of pointer type.

Fixes ppc64le build failure with CL 468455, in issue33724.go.

The problem in that test is that it requires a nil check to be
scheduled before the corresponding load. This normally happens fine
because we prioritize nil checks. If we have nilcheck(p) and load(p),
once p is scheduled the nil check will always go before the load.

The issue we saw in 33724 is that when p is a nil pointer, we ended up
with two different p's, an int64(0) as the argument to the nil check
and an (*Outer)(0) as the argument to the load. Those two zeroes don't
get CSEd, so if the (*Outer)(0) happens to get scheduled first, the
load can end up before the nilcheck.

Fix this by always having constant arithmetic preserve the pointerness
of the value, so that both zeroes are of type *Outer and get CSEd.

Update #58482
Update #33724

Change-Id: Ib9b8c0446f1690b574e0f3c0afb9934efbaf3513
Reviewed-on: https://go-review.googlesource.com/c/go/+/468615
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Bypass: Keith Randall <khr@golang.org>

22 files changed:
src/cmd/compile/internal/ssa/_gen/386.rules
src/cmd/compile/internal/ssa/_gen/AMD64.rules
src/cmd/compile/internal/ssa/_gen/ARM.rules
src/cmd/compile/internal/ssa/_gen/ARM64.rules
src/cmd/compile/internal/ssa/_gen/LOONG64.rules
src/cmd/compile/internal/ssa/_gen/MIPS.rules
src/cmd/compile/internal/ssa/_gen/MIPS64.rules
src/cmd/compile/internal/ssa/_gen/PPC64.rules
src/cmd/compile/internal/ssa/_gen/RISCV64.rules
src/cmd/compile/internal/ssa/_gen/S390X.rules
src/cmd/compile/internal/ssa/_gen/Wasm.rules
src/cmd/compile/internal/ssa/rewrite386.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/cmd/compile/internal/ssa/rewriteARM.go
src/cmd/compile/internal/ssa/rewriteARM64.go
src/cmd/compile/internal/ssa/rewriteLOONG64.go
src/cmd/compile/internal/ssa/rewriteMIPS.go
src/cmd/compile/internal/ssa/rewriteMIPS64.go
src/cmd/compile/internal/ssa/rewritePPC64.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go
src/cmd/compile/internal/ssa/rewriteS390X.go
src/cmd/compile/internal/ssa/rewriteWasm.go

index 88074e5fd081301115be1fbb14f7a1cf72ccb5ca..db16ab0961face035adda4f07fca004b932fbb7b 100644 (file)
 (NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no) => (NEF  cmp yes no)
 
 // fold constants into instructions
-(ADDL x (MOVLconst [c])) => (ADDLconst [c] x)
+(ADDL x (MOVLconst <t> [c])) && !t.IsPtr() => (ADDLconst [c] x)
 (ADDLcarry x (MOVLconst [c])) => (ADDLconstcarry [c] x)
 (ADCL x (MOVLconst [c]) f) => (ADCLconst [c] x f)
 
index d58a34630b33744c479027202d4930d25a32fc57..06e48a18589ccd698a2f29cc4d17ea9af359a0e6 100644 (file)
 // (SETEQF x) => (ANDQ (SETEQ <typ.Int8> x) (SETORD <typ.Int8> x))
 
 // fold constants into instructions
-(ADDQ x (MOVQconst [c])) && is32Bit(c) => (ADDQconst [int32(c)] x)
+(ADDQ x (MOVQconst <t> [c])) && is32Bit(c) && !t.IsPtr() => (ADDQconst [int32(c)] x)
 (ADDQ x (MOVLconst [c])) => (ADDQconst [c] x)
 (ADDL x (MOVLconst [c])) => (ADDLconst [c] x)
 
index d8fbf41754e74f1dfaf8f15e39d90263ef1a9716..9ea9f9674a29771584c124c878ad9d38579781a6 100644 (file)
 (MOVHloadidx ptr idx (MOVHstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) => (MOVHreg x)
 
 // fold constant into arithmetic ops
-(ADD x (MOVWconst [c])) => (ADDconst [c] x)
+(ADD x (MOVWconst <t> [c])) && !t.IsPtr() => (ADDconst [c] x)
 (SUB (MOVWconst [c]) x) => (RSBconst [c] x)
 (SUB x (MOVWconst [c])) => (SUBconst [c] x)
 (RSB (MOVWconst [c]) x) => (SUBconst [c] x)
index 0ae02f5de370c88874cdf491561908fd178df407..cf43542615cf70a26e12e9de7008542bfae5f948 100644 (file)
 (MOVDnop (MOVDconst [c])) => (MOVDconst [c])
 
 // fold constant into arithmetic ops
-(ADD x (MOVDconst [c])) => (ADDconst [c] x)
+(ADD x (MOVDconst <t> [c])) && !t.IsPtr() => (ADDconst [c] x)
 (SUB x (MOVDconst [c])) => (SUBconst [c] x)
 (AND x (MOVDconst [c])) => (ANDconst [c] x)
 (OR  x (MOVDconst [c])) => (ORconst  [c] x)
index 7e445e506e55480e227f90a021a39d699b1e4b6e..08b94b7c07376ad48e2620ea130dd9850a15346a 100644 (file)
 (MOVVreg x) && x.Uses == 1 => (MOVVnop x)
 
 // fold constant into arithmetic ops
-(ADDV x (MOVVconst [c])) && is32Bit(c) => (ADDVconst [c] x)
+(ADDV x (MOVVconst <t> [c])) && is32Bit(c) && !t.IsPtr() => (ADDVconst [c] x)
 (SUBV x (MOVVconst [c])) && is32Bit(c) => (SUBVconst [c] x)
 (AND x (MOVVconst [c])) && is32Bit(c) => (ANDconst [c] x)
 (OR  x (MOVVconst [c])) && is32Bit(c) => (ORconst  [c] x)
index 9cd5a1618e0b03e4fba9ee6d868ec6a3697d678e..b74ab7b609744e9e9c3490af403824bc8d3c8858 100644 (file)
 (MOVWnop (MOVWconst [c])) => (MOVWconst [c])
 
 // fold constant into arithmetic ops
-(ADD x (MOVWconst [c])) => (ADDconst [c] x)
+(ADD x (MOVWconst <t> [c])) && !t.IsPtr() => (ADDconst [c] x)
 (SUB x (MOVWconst [c])) => (SUBconst [c] x)
 (AND x (MOVWconst [c])) => (ANDconst [c] x)
 (OR  x (MOVWconst [c])) => (ORconst  [c] x)
index b0d0dd8e665dbc9e35fcf31f24d0911cc8f655d9..e5cfd90e82f4ad071b9ce8bfb01fd6da69f009b0 100644 (file)
 (MOVVnop (MOVVconst [c])) => (MOVVconst [c])
 
 // fold constant into arithmetic ops
-(ADDV x (MOVVconst [c])) && is32Bit(c) => (ADDVconst [c] x)
+(ADDV x (MOVVconst <t> [c])) && is32Bit(c) && !t.IsPtr() => (ADDVconst [c] x)
 (SUBV x (MOVVconst [c])) && is32Bit(c) => (SUBVconst [c] x)
 (AND x (MOVVconst [c])) && is32Bit(c) => (ANDconst [c] x)
 (OR  x (MOVVconst [c])) && is32Bit(c) => (ORconst  [c] x)
index 16cf91c7b6a4d2d0d23aab1711147f75fda28a01..ba7347f31da4fbb6eb689565eb321f3b031af8e8 100644 (file)
 
 // Arithmetic constant ops
 
-(ADD x (MOVDconst [c])) && is32Bit(c) => (ADDconst [c] x)
+(ADD x (MOVDconst <t> [c])) && is32Bit(c) && !t.IsPtr() => (ADDconst [c] x)
 (ADDconst [c] (ADDconst [d] x)) && is32Bit(c+d) => (ADDconst [c+d] x)
 (ADDconst [0] x) => x
 (SUB x (MOVDconst [c])) && is32Bit(-c) => (ADDconst [-c] x)
index 802b1dd1fd64393e3e327b92e52976884772fce4..378b8c06f86266032fa206e4fb0de14eb450344d 100644 (file)
 (MOVDnop (MOVDconst [c])) => (MOVDconst [c])
 
 // Fold constant into immediate instructions where possible.
-(ADD (MOVDconst [val]) x) && is32Bit(val) => (ADDI [val] x)
+(ADD (MOVDconst <t> [val]) x) && is32Bit(val) && !t.IsPtr() => (ADDI [val] x)
 (AND (MOVDconst [val]) x) && is32Bit(val) => (ANDI [val] x)
 (OR  (MOVDconst [val]) x) && is32Bit(val) => (ORI  [val] x)
 (XOR (MOVDconst [val]) x) && is32Bit(val) => (XORI [val] x)
index 9495010a736bad75f909c2cc95f57b2bb7f5974a..4502a57384237330d49c022f68870dcad83cbfa5 100644 (file)
 (BRC {c} (CMPWUconst x [y]) yes no) && y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) => (CIJ   {c} x [ int8(y)] yes no)
 
 // Fold constants into instructions.
-(ADD x (MOVDconst [c])) && is32Bit(c) => (ADDconst [int32(c)] x)
+(ADD x (MOVDconst <t> [c])) && is32Bit(c) && !t.IsPtr() => (ADDconst [int32(c)] x)
 (ADDW x (MOVDconst [c])) => (ADDWconst [int32(c)] x)
 
 (SUB x (MOVDconst [c])) && is32Bit(c) => (SUBconst x [int32(c)])
index e31808ebe175a3ac37f0ce7c7a83613483481193..91a9fc5e4a9772b3e5e337c5c1078170700a1dd7 100644 (file)
 (I64LeU (I64Const [1]) x) => (I64Eqz (I64Eqz x))
 (I64Ne x (I64Const [0])) => (I64Eqz (I64Eqz x))
 
-(I64Add x (I64Const [y])) => (I64AddConst [y] x)
+(I64Add x (I64Const <t> [y])) && !t.IsPtr() => (I64AddConst [y] x)
 (I64AddConst [0] x) => x
 (I64Eqz (I64Eqz (I64Eqz x))) => (I64Eqz x)
 
index 064173a946bbf97c5e3e4d18232774ef188ceb8b..f658d9380a29d703c7874d2429f6d930839e0dc5 100644 (file)
@@ -726,7 +726,8 @@ func rewriteValue386_Op386ADCL(v *Value) bool {
 func rewriteValue386_Op386ADDL(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADDL x (MOVLconst [c]))
+       // match: (ADDL x (MOVLconst <t> [c]))
+       // cond: !t.IsPtr()
        // result: (ADDLconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -734,7 +735,11 @@ func rewriteValue386_Op386ADDL(v *Value) bool {
                        if v_1.Op != Op386MOVLconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt32(v_1.AuxInt)
+                       if !(!t.IsPtr()) {
+                               continue
+                       }
                        v.reset(Op386ADDLconst)
                        v.AuxInt = int32ToAuxInt(c)
                        v.AddArg(x)
index d0982ce17bd67eab22370e1d60b6923d76f1c8c6..41cf6b93525ce5673239b9082252725e707c7f2a 100644 (file)
@@ -1792,8 +1792,8 @@ func rewriteValueAMD64_OpAMD64ADDLmodify(v *Value) bool {
 func rewriteValueAMD64_OpAMD64ADDQ(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADDQ x (MOVQconst [c]))
-       // cond: is32Bit(c)
+       // match: (ADDQ x (MOVQconst <t> [c]))
+       // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDQconst [int32(c)] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -1801,8 +1801,9 @@ func rewriteValueAMD64_OpAMD64ADDQ(v *Value) bool {
                        if v_1.Op != OpAMD64MOVQconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
-                       if !(is32Bit(c)) {
+                       if !(is32Bit(c) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpAMD64ADDQconst)
index 6ea1a7e4b26afaad386d53b9223d68f91d324ddf..896ea50223384353842b518be03f8da6f36695d8 100644 (file)
@@ -1315,7 +1315,8 @@ func rewriteValueARM_OpARMADD(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        b := v.Block
-       // match: (ADD x (MOVWconst [c]))
+       // match: (ADD x (MOVWconst <t> [c]))
+       // cond: !t.IsPtr()
        // result: (ADDconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -1323,7 +1324,11 @@ func rewriteValueARM_OpARMADD(v *Value) bool {
                        if v_1.Op != OpARMMOVWconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt32(v_1.AuxInt)
+                       if !(!t.IsPtr()) {
+                               continue
+                       }
                        v.reset(OpARMADDconst)
                        v.AuxInt = int32ToAuxInt(c)
                        v.AddArg(x)
index 6f02b507e823f8d6f32a1b72733896fc77943f18..7cc7a2a42427614d1666e72d5d23bb26ae055c4c 100644 (file)
@@ -1178,7 +1178,8 @@ func rewriteValueARM64_OpARM64ADCSflags(v *Value) bool {
 func rewriteValueARM64_OpARM64ADD(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADD x (MOVDconst [c]))
+       // match: (ADD x (MOVDconst <t> [c]))
+       // cond: !t.IsPtr()
        // result: (ADDconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -1186,7 +1187,11 @@ func rewriteValueARM64_OpARM64ADD(v *Value) bool {
                        if v_1.Op != OpARM64MOVDconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
+                       if !(!t.IsPtr()) {
+                               continue
+                       }
                        v.reset(OpARM64ADDconst)
                        v.AuxInt = int64ToAuxInt(c)
                        v.AddArg(x)
index 3c783a3037bbded85c1aeb6f433cada31b133adb..9008923c80b92e04b7b98a5d0590d7cd1687fccf 100644 (file)
@@ -1354,8 +1354,8 @@ func rewriteValueLOONG64_OpIsSliceInBounds(v *Value) bool {
 func rewriteValueLOONG64_OpLOONG64ADDV(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADDV x (MOVVconst [c]))
-       // cond: is32Bit(c)
+       // match: (ADDV x (MOVVconst <t> [c]))
+       // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDVconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -1363,8 +1363,9 @@ func rewriteValueLOONG64_OpLOONG64ADDV(v *Value) bool {
                        if v_1.Op != OpLOONG64MOVVconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
-                       if !(is32Bit(c)) {
+                       if !(is32Bit(c) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpLOONG64ADDVconst)
index a8cda7644a7c1fff0faa1efe2f334f74d324c0d9..4d56908b30f8e9848e4a6c35f4da700ed311a908 100644 (file)
@@ -2025,7 +2025,8 @@ func rewriteValueMIPS_OpLsh8x8(v *Value) bool {
 func rewriteValueMIPS_OpMIPSADD(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADD x (MOVWconst [c]))
+       // match: (ADD x (MOVWconst <t> [c]))
+       // cond: !t.IsPtr()
        // result: (ADDconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -2033,7 +2034,11 @@ func rewriteValueMIPS_OpMIPSADD(v *Value) bool {
                        if v_1.Op != OpMIPSMOVWconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt32(v_1.AuxInt)
+                       if !(!t.IsPtr()) {
+                               continue
+                       }
                        v.reset(OpMIPSADDconst)
                        v.AuxInt = int32ToAuxInt(c)
                        v.AddArg(x)
index 82d52f0b3f3479b03b8f0f06fb9f4c4d06c5db07..8b01407e01b3dcbe04b444e6ed63cc2225450b97 100644 (file)
@@ -2298,8 +2298,8 @@ func rewriteValueMIPS64_OpLsh8x8(v *Value) bool {
 func rewriteValueMIPS64_OpMIPS64ADDV(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADDV x (MOVVconst [c]))
-       // cond: is32Bit(c)
+       // match: (ADDV x (MOVVconst <t> [c]))
+       // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDVconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -2307,8 +2307,9 @@ func rewriteValueMIPS64_OpMIPS64ADDV(v *Value) bool {
                        if v_1.Op != OpMIPS64MOVVconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
-                       if !(is32Bit(c)) {
+                       if !(is32Bit(c) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpMIPS64ADDVconst)
index a0d4b54c7ab0f0fd1676e8d20f518b21c9ac08bd..bcd0a9ab4ebc180de121b4b91cdd32d11fcd5956 100644 (file)
@@ -3811,8 +3811,8 @@ func rewriteValuePPC64_OpPPC64ADD(v *Value) bool {
                }
                break
        }
-       // match: (ADD x (MOVDconst [c]))
-       // cond: is32Bit(c)
+       // match: (ADD x (MOVDconst <t> [c]))
+       // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDconst [c] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -3820,8 +3820,9 @@ func rewriteValuePPC64_OpPPC64ADD(v *Value) bool {
                        if v_1.Op != OpPPC64MOVDconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
-                       if !(is32Bit(c)) {
+                       if !(is32Bit(c) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpPPC64ADDconst)
index 66a6967db4cd0aa78f37524a95af1eaca09c8633..68851272166e20ca60002649642ad71dce6f8f54 100644 (file)
@@ -3150,17 +3150,18 @@ func rewriteValueRISCV64_OpPanicBounds(v *Value) bool {
 func rewriteValueRISCV64_OpRISCV64ADD(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADD (MOVDconst [val]) x)
-       // cond: is32Bit(val)
+       // match: (ADD (MOVDconst <t> [val]) x)
+       // cond: is32Bit(val) && !t.IsPtr()
        // result: (ADDI [val] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
                        if v_0.Op != OpRISCV64MOVDconst {
                                continue
                        }
+                       t := v_0.Type
                        val := auxIntToInt64(v_0.AuxInt)
                        x := v_1
-                       if !(is32Bit(val)) {
+                       if !(is32Bit(val) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpRISCV64ADDI)
index b766156b437051f747a3a2d7e3ad958ee8b34bff..e8cc88d655faf0b8e2cc7b22c8d6400a0b693f8c 100644 (file)
@@ -5286,8 +5286,8 @@ func rewriteValueS390X_OpRsh8x8(v *Value) bool {
 func rewriteValueS390X_OpS390XADD(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (ADD x (MOVDconst [c]))
-       // cond: is32Bit(c)
+       // match: (ADD x (MOVDconst <t> [c]))
+       // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDconst [int32(c)] x)
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -5295,8 +5295,9 @@ func rewriteValueS390X_OpS390XADD(v *Value) bool {
                        if v_1.Op != OpS390XMOVDconst {
                                continue
                        }
+                       t := v_1.Type
                        c := auxIntToInt64(v_1.AuxInt)
-                       if !(is32Bit(c)) {
+                       if !(is32Bit(c) && !t.IsPtr()) {
                                continue
                        }
                        v.reset(OpS390XADDconst)
index bb35d8e663ce93d6de66cd9674dc66f609f3822f..6f83aea13afc5a656c5f98136cae6a0f7ce2b2b1 100644 (file)
@@ -3620,14 +3620,19 @@ func rewriteValueWasm_OpWasmI64Add(v *Value) bool {
                v.AddArg2(y, v0)
                return true
        }
-       // match: (I64Add x (I64Const [y]))
+       // match: (I64Add x (I64Const <t> [y]))
+       // cond: !t.IsPtr()
        // result: (I64AddConst [y] x)
        for {
                x := v_0
                if v_1.Op != OpWasmI64Const {
                        break
                }
+               t := v_1.Type
                y := auxIntToInt64(v_1.AuxInt)
+               if !(!t.IsPtr()) {
+                       break
+               }
                v.reset(OpWasmI64AddConst)
                v.AuxInt = int64ToAuxInt(y)
                v.AddArg(x)