]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: remove self copies in tail-call wrappers
authorCherry Mui <cherryyz@google.com>
Thu, 16 Sep 2021 17:55:45 +0000 (13:55 -0400)
committerCherry Mui <cherryyz@google.com>
Fri, 17 Sep 2021 23:21:29 +0000 (23:21 +0000)
The previous CL re-enables tail calls for method wrappers. But
with the changed IR and SSA representation, for stack arguments
it generates self copies. This CL makes the compiler detect the
self copies and remove them.

Change-Id: I7252572a1a47834f28b6706e45906e2356408e02
Reviewed-on: https://go-review.googlesource.com/c/go/+/350349
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/ssa/expand_calls.go

index 79434f33d39246edb76de232f003d81464edefbe..a0f0e653aa41041dda93ecc88ac43a9e26b91fe5 100644 (file)
@@ -1098,6 +1098,17 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) {
                        if a.MemoryArg() != m0 {
                                x.f.Fatalf("Op...LECall and OpDereference have mismatched mem, %s and %s", v.LongString(), a.LongString())
                        }
+                       if v.Op == OpTailLECall {
+                               // It's common for a tail call passing the same arguments (e.g. method wrapper),
+                               // so this would be a self copy. Detect this and optimize it out.
+                               a0 := a.Args[0]
+                               if a0.Op == OpLocalAddr {
+                                       n := a0.Aux.(*ir.Name)
+                                       if n.Class == ir.PPARAM && n.FrameOffset()+x.f.Config.ctxt.FixedFrameSize() == aOffset {
+                                               continue
+                                       }
+                               }
+                       }
                        // "Dereference" of addressed (probably not-SSA-eligible) value becomes Move
                        // TODO(register args) this will be more complicated with registers in the picture.
                        mem = x.rewriteDereference(v.Block, sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos)
@@ -1110,6 +1121,14 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) {
                        } else {
                                aOffset = aux.OffsetOfArg(auxI)
                        }
+                       if v.Op == OpTailLECall && a.Op == OpArg && a.AuxInt == 0 {
+                               // It's common for a tail call passing the same arguments (e.g. method wrapper),
+                               // so this would be a self copy. Detect this and optimize it out.
+                               n := a.Aux.(*ir.Name)
+                               if n.Class == ir.PPARAM && n.FrameOffset()+x.f.Config.ctxt.FixedFrameSize() == aOffset {
+                                       continue
+                               }
+                       }
                        if x.debug > 1 {
                                x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
                        }