]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimize more pointer comparisons
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 6 Jun 2019 18:40:47 +0000 (11:40 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 29 Aug 2019 19:35:18 +0000 (19:35 +0000)
The existing pointer comparison optimizations
don't include pointer arithmetic. Add them.

These rules trigger a few times in std cmd, while compiling:

time.Duration.String
cmd/go/internal/tlog.NodeHash
crypto/tls.ticketKeyFromBytes (3 times)
crypto/elliptic.(*p256Point).p256ScalarMult (15 times!)
crypto/elliptic.initTable

These weird comparisons occur when using the copy builtin,
which does a pointer comparison between src and dst.

This also happens to fix #32454, by optimizing enough
early on that all values can be eliminated.

Fixes #32454

Change-Id: I799d45743350bddd15a295dc1e12f8d03c11d1c6
Reviewed-on: https://go-review.googlesource.com/c/go/+/180940
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/fixedbugs/issue32454.go [new file with mode: 0644]

index 8f2ff28879ed65275c4e5aab7e8e9dfb11c8461c..089acc38a1df19f64912363165a5b1f4ce17e9f6 100644 (file)
 (EqPtr  x x) -> (ConstBool [1])
 (NeqPtr x x) -> (ConstBool [0])
 (EqPtr  (Addr {a} _) (Addr {b} _)) -> (ConstBool [b2i(a == b)])
+(EqPtr  (Addr {a} _) (OffPtr [o] (Addr {b} _))) -> (ConstBool [b2i(a == b && o == 0)])
+(EqPtr  (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _))) -> (ConstBool [b2i(a == b && o1 == o2)])
 (NeqPtr (Addr {a} _) (Addr {b} _)) -> (ConstBool [b2i(a != b)])
+(NeqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _))) -> (ConstBool [b2i(a != b || o != 0)])
+(NeqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _))) -> (ConstBool [b2i(a != b || o1 != o2)])
 (EqPtr  (LocalAddr {a} _ _) (LocalAddr {b} _ _)) -> (ConstBool [b2i(a == b)])
+(EqPtr  (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _))) -> (ConstBool [b2i(a == b && o == 0)])
+(EqPtr  (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _))) -> (ConstBool [b2i(a == b && o1 == o2)])
 (NeqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _)) -> (ConstBool [b2i(a != b)])
+(NeqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _))) -> (ConstBool [b2i(a != b || o != 0)])
+(NeqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _))) -> (ConstBool [b2i(a != b || o1 != o2)])
 (EqPtr  (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 == 0)])
 (NeqPtr (OffPtr [o1] p1) p2) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 != 0)])
 (EqPtr  (OffPtr [o1] p1) (OffPtr [o2] p2)) && isSamePtr(p1, p2) -> (ConstBool [b2i(o1 == o2)])
 (NeqPtr (Const(32|64) [c]) (Const(32|64) [d])) -> (ConstBool [b2i(c != d)])
 
 (EqPtr  (LocalAddr _ _) (Addr _)) -> (ConstBool [0])
+(EqPtr  (OffPtr (LocalAddr _ _)) (Addr _)) -> (ConstBool [0])
+(EqPtr  (LocalAddr _ _) (OffPtr (Addr _))) -> (ConstBool [0])
+(EqPtr  (OffPtr (LocalAddr _ _)) (OffPtr (Addr _))) -> (ConstBool [0])
 (NeqPtr (LocalAddr _ _) (Addr _)) -> (ConstBool [1])
+(NeqPtr (OffPtr (LocalAddr _ _)) (Addr _)) -> (ConstBool [1])
+(NeqPtr (LocalAddr _ _) (OffPtr (Addr _))) -> (ConstBool [1])
+(NeqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _))) -> (ConstBool [1])
 
 // Simplify address comparisons.
 (EqPtr  (AddPtr p1 o1) p2) && isSamePtr(p1, p2) -> (Not (IsNonNil o1))
index e3a123e1d23f0333620e73a0949fd3a6d47254a0..d25a62e36c2dd995b5f014c3f158e4ff740deac9 100644 (file)
@@ -105,7 +105,7 @@ func rewriteValuegeneric(v *Value) bool {
        case OpEqInter:
                return rewriteValuegeneric_OpEqInter_0(v)
        case OpEqPtr:
-               return rewriteValuegeneric_OpEqPtr_0(v) || rewriteValuegeneric_OpEqPtr_10(v) || rewriteValuegeneric_OpEqPtr_20(v)
+               return rewriteValuegeneric_OpEqPtr_0(v) || rewriteValuegeneric_OpEqPtr_10(v) || rewriteValuegeneric_OpEqPtr_20(v) || rewriteValuegeneric_OpEqPtr_30(v)
        case OpEqSlice:
                return rewriteValuegeneric_OpEqSlice_0(v)
        case OpGeq16:
@@ -291,7 +291,7 @@ func rewriteValuegeneric(v *Value) bool {
        case OpNeqInter:
                return rewriteValuegeneric_OpNeqInter_0(v)
        case OpNeqPtr:
-               return rewriteValuegeneric_OpNeqPtr_0(v) || rewriteValuegeneric_OpNeqPtr_10(v) || rewriteValuegeneric_OpNeqPtr_20(v)
+               return rewriteValuegeneric_OpNeqPtr_0(v) || rewriteValuegeneric_OpNeqPtr_10(v) || rewriteValuegeneric_OpNeqPtr_20(v) || rewriteValuegeneric_OpNeqPtr_30(v)
        case OpNeqSlice:
                return rewriteValuegeneric_OpNeqSlice_0(v)
        case OpNilCheck:
@@ -27075,6 +27075,112 @@ func rewriteValuegeneric_OpEqPtr_0(v *Value) bool {
                v.AuxInt = b2i(a == b)
                return true
        }
+       // match: (EqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o == 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               a := v_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o == 0)
+               return true
+       }
+       // match: (EqPtr (OffPtr [o] (Addr {b} _)) (Addr {a} _))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o == 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               a := v_1.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o == 0)
+               return true
+       }
+       // match: (EqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o1 == o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               a := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o1 == o2)
+               return true
+       }
+       // match: (EqPtr (OffPtr [o2] (Addr {b} _)) (OffPtr [o1] (Addr {a} _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o1 == o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               a := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o1 == o2)
+               return true
+       }
        // match: (EqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _))
        // cond:
        // result: (ConstBool [b2i(a == b)])
@@ -27117,6 +27223,123 @@ func rewriteValuegeneric_OpEqPtr_0(v *Value) bool {
                v.AuxInt = b2i(a == b)
                return true
        }
+       // match: (EqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o == 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_0.Aux
+               _ = v_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o == 0)
+               return true
+       }
+       return false
+}
+func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
+       // match: (EqPtr (OffPtr [o] (LocalAddr {b} _ _)) (LocalAddr {a} _ _))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o == 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpLocalAddr {
+                       break
+               }
+               a := v_1.Aux
+               _ = v_1.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o == 0)
+               return true
+       }
+       // match: (EqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o1 == o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o1 == o2)
+               return true
+       }
+       // match: (EqPtr (OffPtr [o2] (LocalAddr {b} _ _)) (OffPtr [o1] (LocalAddr {a} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a == b && o1 == o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a == b && o1 == o2)
+               return true
+       }
        // match: (EqPtr (OffPtr [o1] p1) p2)
        // cond: isSamePtr(p1, p2)
        // result: (ConstBool [b2i(o1 == 0)])
@@ -27221,11 +27444,6 @@ func rewriteValuegeneric_OpEqPtr_0(v *Value) bool {
                v.AuxInt = b2i(c == d)
                return true
        }
-       return false
-}
-func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
        // match: (EqPtr (Const32 [d]) (Const32 [c]))
        // cond:
        // result: (ConstBool [b2i(c == d)])
@@ -27264,6 +27482,11 @@ func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
                v.AuxInt = b2i(c == d)
                return true
        }
+       return false
+}
+func rewriteValuegeneric_OpEqPtr_20(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
        // match: (EqPtr (Const64 [d]) (Const64 [c]))
        // cond:
        // result: (ConstBool [b2i(c == d)])
@@ -27319,6 +27542,146 @@ func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
                v.AuxInt = 0
                return true
        }
+       // match: (EqPtr (OffPtr (LocalAddr _ _)) (Addr _))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (EqPtr (Addr _) (OffPtr (LocalAddr _ _)))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (EqPtr (LocalAddr _ _) (OffPtr (Addr _)))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (EqPtr (OffPtr (Addr _)) (LocalAddr _ _))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (EqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _)))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (EqPtr (OffPtr (Addr _)) (OffPtr (LocalAddr _ _)))
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
        // match: (EqPtr (AddPtr p1 o1) p2)
        // cond: isSamePtr(p1, p2)
        // result: (Not (IsNonNil o1))
@@ -27339,6 +27702,11 @@ func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
                v.AddArg(v0)
                return true
        }
+       return false
+}
+func rewriteValuegeneric_OpEqPtr_30(v *Value) bool {
+       b := v.Block
+       typ := &b.Func.Config.Types
        // match: (EqPtr p2 (AddPtr p1 o1))
        // cond: isSamePtr(p1, p2)
        // result: (Not (IsNonNil o1))
@@ -27415,11 +27783,6 @@ func rewriteValuegeneric_OpEqPtr_10(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       return false
-}
-func rewriteValuegeneric_OpEqPtr_20(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
        // match: (EqPtr p (Const64 [0]))
        // cond:
        // result: (Not (IsNonNil p))
@@ -38384,6 +38747,112 @@ func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
                v.AuxInt = b2i(a != b)
                return true
        }
+       // match: (NeqPtr (Addr {a} _) (OffPtr [o] (Addr {b} _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o != 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               a := v_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o != 0)
+               return true
+       }
+       // match: (NeqPtr (OffPtr [o] (Addr {b} _)) (Addr {a} _))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o != 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               a := v_1.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o != 0)
+               return true
+       }
+       // match: (NeqPtr (OffPtr [o1] (Addr {a} _)) (OffPtr [o2] (Addr {b} _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o1 != o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               a := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o1 != o2)
+               return true
+       }
+       // match: (NeqPtr (OffPtr [o2] (Addr {b} _)) (OffPtr [o1] (Addr {a} _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o1 != o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               a := v_1_0.Aux
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o1 != o2)
+               return true
+       }
        // match: (NeqPtr (LocalAddr {a} _ _) (LocalAddr {b} _ _))
        // cond:
        // result: (ConstBool [b2i(a != b)])
@@ -38426,6 +38895,123 @@ func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
                v.AuxInt = b2i(a != b)
                return true
        }
+       // match: (NeqPtr (LocalAddr {a} _ _) (OffPtr [o] (LocalAddr {b} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o != 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_0.Aux
+               _ = v_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o != 0)
+               return true
+       }
+       return false
+}
+func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
+       // match: (NeqPtr (OffPtr [o] (LocalAddr {b} _ _)) (LocalAddr {a} _ _))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o != 0)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpLocalAddr {
+                       break
+               }
+               a := v_1.Aux
+               _ = v_1.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o != 0)
+               return true
+       }
+       // match: (NeqPtr (OffPtr [o1] (LocalAddr {a} _ _)) (OffPtr [o2] (LocalAddr {b} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o1 != o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o1 != o2)
+               return true
+       }
+       // match: (NeqPtr (OffPtr [o2] (LocalAddr {b} _ _)) (OffPtr [o1] (LocalAddr {a} _ _)))
+       // cond:
+       // result: (ConstBool [b2i(a != b || o1 != o2)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               o2 := v_0.AuxInt
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               b := v_0_0.Aux
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               o1 := v_1.AuxInt
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               a := v_1_0.Aux
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b || o1 != o2)
+               return true
+       }
        // match: (NeqPtr (OffPtr [o1] p1) p2)
        // cond: isSamePtr(p1, p2)
        // result: (ConstBool [b2i(o1 != 0)])
@@ -38530,9 +39116,6 @@ func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
                v.AuxInt = b2i(c != d)
                return true
        }
-       return false
-}
-func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
        // match: (NeqPtr (Const32 [d]) (Const32 [c]))
        // cond:
        // result: (ConstBool [b2i(c != d)])
@@ -38571,6 +39154,9 @@ func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
                v.AuxInt = b2i(c != d)
                return true
        }
+       return false
+}
+func rewriteValuegeneric_OpNeqPtr_20(v *Value) bool {
        // match: (NeqPtr (Const64 [d]) (Const64 [c]))
        // cond:
        // result: (ConstBool [b2i(c != d)])
@@ -38626,6 +39212,146 @@ func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
                v.AuxInt = 1
                return true
        }
+       // match: (NeqPtr (OffPtr (LocalAddr _ _)) (Addr _))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (NeqPtr (Addr _) (OffPtr (LocalAddr _ _)))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (NeqPtr (LocalAddr _ _) (OffPtr (Addr _)))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (NeqPtr (OffPtr (Addr _)) (LocalAddr _ _))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (NeqPtr (OffPtr (LocalAddr _ _)) (OffPtr (Addr _)))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpAddr {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (NeqPtr (OffPtr (Addr _)) (OffPtr (LocalAddr _ _)))
+       // cond:
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpOffPtr {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAddr {
+                       break
+               }
+               v_1 := v.Args[1]
+               if v_1.Op != OpOffPtr {
+                       break
+               }
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpLocalAddr {
+                       break
+               }
+               _ = v_1_0.Args[1]
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
        // match: (NeqPtr (AddPtr p1 o1) p2)
        // cond: isSamePtr(p1, p2)
        // result: (IsNonNil o1)
@@ -38644,6 +39370,9 @@ func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
                v.AddArg(o1)
                return true
        }
+       return false
+}
+func rewriteValuegeneric_OpNeqPtr_30(v *Value) bool {
        // match: (NeqPtr p2 (AddPtr p1 o1))
        // cond: isSamePtr(p1, p2)
        // result: (IsNonNil o1)
@@ -38712,9 +39441,6 @@ func rewriteValuegeneric_OpNeqPtr_10(v *Value) bool {
                v.AddArg(p)
                return true
        }
-       return false
-}
-func rewriteValuegeneric_OpNeqPtr_20(v *Value) bool {
        // match: (NeqPtr p (Const64 [0]))
        // cond:
        // result: (IsNonNil p)
diff --git a/test/fixedbugs/issue32454.go b/test/fixedbugs/issue32454.go
new file mode 100644 (file)
index 0000000..70895c9
--- /dev/null
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2019 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 p
+
+type T struct {
+       s string
+       f float64
+}
+
+func f() {
+       var f float64
+       var st T
+       for {
+               switch &st.f {
+               case &f:
+                       f = 1
+               }
+       }
+}