]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: recognize constant pointer comparison
authorphilhofer <phofer@umich.edu>
Wed, 15 Mar 2017 22:34:52 +0000 (15:34 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 20 Mar 2017 21:04:44 +0000 (21:04 +0000)
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>

src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go

index ee825acb0c8def52e7586d3e89008b1ec8fb37cc..ac5afbbad3c1a748ada28762dd8c171b749266c0 100644 (file)
@@ -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 {
index 5bb5610c25827abcd42d3719e5b2826d698ad80e..86d0fcab324be5aab06a41588caf10b9555bd750 100644 (file)
        && 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,
index 81f48b48ff296b69ad6a00b694b7042bd8884b7c..8ab751797b493127c61e0d9e3f0718947dd2e9a2 100644 (file)
@@ -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 {