mirror of
https://github.com/golang/go
synced 2024-11-23 10:50:09 -07:00
cmd/compile/internal/ssa: recognize constant pointer comparison
Teach the backend to recognize that the address of a symbol is equal with itself, and that the addresses of two different symbols are different. Some examples of where this rule hits in the standard library: - inlined uses of (*time.Time).setLoc (e.g. time.UTC) - inlined uses of bufio.NewReader (via type assertion) Change-Id: I23dcb068c2ec333655c1292917bec13bbd908c24 Reviewed-on: https://go-review.googlesource.com/38338 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
f8b0231639
commit
d68bb16b1e
@ -1366,7 +1366,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
if n.Class == PFUNC {
|
||||
// "value" of a function is the address of the function's closure
|
||||
sym := Linksym(funcsym(n.Sym))
|
||||
aux := &ssa.ExternSymbol{Typ: n.Type, Sym: sym}
|
||||
aux := s.lookupSymbol(n, &ssa.ExternSymbol{Typ: n.Type, Sym: sym})
|
||||
return s.entryNewValue1A(ssa.OpAddr, typPtr(n.Type), aux, s.sb)
|
||||
}
|
||||
if s.canSSA(n) {
|
||||
@ -2137,7 +2137,8 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
|
||||
|
||||
// Call growslice
|
||||
s.startBlock(grow)
|
||||
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: Linksym(typenamesym(n.Type.Elem()))}, s.sb)
|
||||
sym := s.lookupSymbol(n, &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: Linksym(typenamesym(n.Type.Elem()))})
|
||||
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], sym, s.sb)
|
||||
|
||||
r := s.rtcall(growslice, true, []*Type{pt, Types[TINT], Types[TINT]}, taddr, p, l, c, nl)
|
||||
|
||||
@ -4087,7 +4088,8 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
|
||||
if !commaok {
|
||||
// on failure, panic by calling panicdottype
|
||||
s.startBlock(bFail)
|
||||
taddr := s.newValue1A(ssa.OpAddr, byteptr, &ssa.ExternSymbol{Typ: byteptr, Sym: Linksym(typenamesym(n.Left.Type))}, s.sb)
|
||||
sym := s.lookupSymbol(n, &ssa.ExternSymbol{Typ: byteptr, Sym: Linksym(typenamesym(n.Left.Type))})
|
||||
taddr := s.newValue1A(ssa.OpAddr, byteptr, sym, s.sb)
|
||||
if n.Left.Type.IsEmptyInterface() {
|
||||
s.rtcall(panicdottypeE, false, nil, itab, target, taddr)
|
||||
} else {
|
||||
|
@ -1432,6 +1432,10 @@
|
||||
&& warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
|
||||
-> (Invalid)
|
||||
|
||||
// Address comparison shows up in type assertions.
|
||||
(EqPtr x x) -> (ConstBool [1])
|
||||
(EqPtr (Addr {a} x) (Addr {b} x)) -> (ConstBool [b2i(a == b)])
|
||||
|
||||
// De-virtualize interface calls into static calls.
|
||||
// Note that (ITab (IMake)) doesn't get
|
||||
// rewritten until after the first opt pass,
|
||||
|
@ -5332,6 +5332,40 @@ func rewriteValuegeneric_OpEqPtr(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr x x)
|
||||
// cond:
|
||||
// result: (ConstBool [1])
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x != v.Args[1] {
|
||||
break
|
||||
}
|
||||
v.reset(OpConstBool)
|
||||
v.AuxInt = 1
|
||||
return true
|
||||
}
|
||||
// match: (EqPtr (Addr {a} x) (Addr {b} x))
|
||||
// cond:
|
||||
// result: (ConstBool [b2i(a == b)])
|
||||
for {
|
||||
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
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpEqSlice(v *Value) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user