]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: handle symbol address comparisons consistently
authorBryan Chan <bryanpkc@gmail.com>
Fri, 23 Mar 2018 08:14:25 +0000 (04:14 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sat, 31 Mar 2018 21:37:13 +0000 (21:37 +0000)
CL 38338 introduced SSA rules to optimize two types of pointer equality
tests: a pointer compared with itself, and comparison of addresses taken
of two symbols which may have the same base. This patch adds rules to
apply the same optimization to pointer inequality tests, which also ensures
that two pointers to zero-width types cannot be both equal and unequal
at the same time.

Fixes #24503.

Change-Id: Ic828aeb86ae2e680caf66c35f4c247674768a9ba
Reviewed-on: https://go-review.googlesource.com/102275
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/fixedbugs/issue24503.go [new file with mode: 0644]

index 24fb52c8925b39aed8600de4a68911f5d835f4fa..06f32490d29c149a5f0f1347b8ace38c18027fcc 100644 (file)
 // Address comparison shows up in type assertions.
 (EqPtr x x) -> (ConstBool [1])
 (EqPtr (Addr {a} x) (Addr {b} x)) -> (ConstBool [b2i(a == b)])
+(NeqPtr x x) -> (ConstBool [0])
+(NeqPtr (Addr {a} x) (Addr {b} x)) -> (ConstBool [b2i(a != b)])
 
 // Inline small runtime.memmove calls with constant length.
 (StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store  _ src s3:(Store {t} _ dst mem))))
index 542c669848b4910a590bb9b8f2f5273bd6f6738f..add2f0d97b89507787e3d3b15a84ebc6e03dae4d 100644 (file)
@@ -18048,6 +18048,65 @@ func rewriteValuegeneric_OpNeqPtr_0(v *Value) bool {
                v.AddArg(p)
                return true
        }
+       // match: (NeqPtr x x)
+       // cond:
+       // result: (ConstBool [0])
+       for {
+               _ = v.Args[1]
+               x := v.Args[0]
+               if x != v.Args[1] {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 0
+               return true
+       }
+       // match: (NeqPtr (Addr {a} x) (Addr {b} x))
+       // cond:
+       // result: (ConstBool [b2i(a != b)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               a := v_0.Aux
+               x := v_0.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               b := v_1.Aux
+               if x != v_1.Args[0] {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b)
+               return true
+       }
+       // match: (NeqPtr (Addr {b} x) (Addr {a} x))
+       // cond:
+       // result: (ConstBool [b2i(a != b)])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpAddr {
+                       break
+               }
+               b := v_0.Aux
+               x := v_0.Args[0]
+               v_1 := v.Args[1]
+               if v_1.Op != OpAddr {
+                       break
+               }
+               a := v_1.Aux
+               if x != v_1.Args[0] {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = b2i(a != b)
+               return true
+       }
        return false
 }
 func rewriteValuegeneric_OpNeqSlice_0(v *Value) bool {
diff --git a/test/fixedbugs/issue24503.go b/test/fixedbugs/issue24503.go
new file mode 100644 (file)
index 0000000..933ce70
--- /dev/null
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2018 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.
+
+// Issue 24503: Handle == and != of addresses taken of symbols consistently.
+
+package main
+
+func test() string {
+       type test struct{}
+       o1 := test{}
+       o2 := test{}
+       if &o1 == &o2 {
+               return "equal"
+       }
+       if &o1 != &o2 {
+               return "unequal"
+       }
+       return "failed"
+}
+
+func main() {
+       if test() == "failed" {
+               panic("expected either 'equal' or 'unequal'")
+       }
+}