From: philhofer Date: Wed, 15 Mar 2017 22:34:52 +0000 (-0700) Subject: cmd/compile/internal/ssa: recognize constant pointer comparison X-Git-Tag: go1.9beta1~1088 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d68bb16b1e2f2fb55b347bdb6d1374103b5cb6a0;p=gostls13.git 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 Reviewed-by: Keith Randall Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot --- diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index ee825acb0c..ac5afbbad3 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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 { diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 5bb5610c25..86d0fcab32 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -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, diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 81f48b48ff..8ab751797b 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -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 {