Commit 625f2dcc authored by Bryan Chan's avatar Bryan Chan Committed by Brad Fitzpatrick

cmd/compile/internal/ssa: handle symbol address comparisons consistently

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/102275Reviewed-by: 's avatarKeith Randall <khr@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent ec60e4a0
......@@ -1244,6 +1244,8 @@
// 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))))
......
......@@ -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 {
......
// 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'")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment