]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make translation to calls for SSA look more "value-oriented"
authorDavid Chase <drchase@google.com>
Fri, 26 Jun 2020 22:19:01 +0000 (18:19 -0400)
committerDavid Chase <drchase@google.com>
Wed, 16 Sep 2020 21:02:46 +0000 (21:02 +0000)
The existing translation assumes an in-memory return values, thus it returns
the address of the result(s).  Most consumers immediately load from the
address to get the value, and in late call expansion that is the favored idiom,
and it is also the favored idiom when arguments and results use registers
instead of memory.

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

index 75fdbbae045d8b56d1fcc761a2c933e517a30096..c59945f2066d9b46ad78571f50f15bf52d1cbccf 100644 (file)
@@ -1076,7 +1076,7 @@ func (s *state) stmt(n *Node) {
                fallthrough
 
        case OCALLMETH, OCALLINTER:
-               s.call(n, callNormal)
+               s.callAddr(n, callNormal)
                if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class() == PFUNC {
                        if fn := n.Left.Sym.Name; compiling_runtime && fn == "throw" ||
                                n.Left.Sym.Pkg == Runtimepkg && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") {
@@ -1108,10 +1108,10 @@ func (s *state) stmt(n *Node) {
                        if n.Esc == EscNever {
                                d = callDeferStack
                        }
-                       s.call(n.Left, d)
+                       s.callAddr(n.Left, d)
                }
        case OGO:
-               s.call(n.Left, callGo)
+               s.callAddr(n.Left, callGo)
 
        case OAS2DOTTYPE:
                res, resok := s.dottype(n.Right, true)
@@ -2715,8 +2715,7 @@ func (s *state) expr(n *Node) *ssa.Value {
                fallthrough
 
        case OCALLINTER, OCALLMETH:
-               a := s.call(n, callNormal)
-               return s.load(n.Type, a)
+               return s.callResult(n, callNormal)
 
        case OGETG:
                return s.newValue1(ssa.OpGetG, n.Type, s.mem())
@@ -3589,8 +3588,7 @@ func init() {
        addF("math", "FMA",
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
                        if !s.config.UseFMA {
-                               a := s.call(n, callNormal)
-                               s.vars[n] = s.load(types.Types[TFLOAT64], a)
+                               s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
                                return s.variable(n, types.Types[TFLOAT64])
                        }
                        v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[TBOOL], x86HasFMA)
@@ -3611,8 +3609,7 @@ func init() {
 
                        // Call the pure Go version.
                        s.startBlock(bFalse)
-                       a := s.call(n, callNormal)
-                       s.vars[n] = s.load(types.Types[TFLOAT64], a)
+                       s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
                        s.endBlock().AddEdgeTo(bEnd)
 
                        // Merge results.
@@ -3623,8 +3620,7 @@ func init() {
        addF("math", "FMA",
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
                        if !s.config.UseFMA {
-                               a := s.call(n, callNormal)
-                               s.vars[n] = s.load(types.Types[TFLOAT64], a)
+                               s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
                                return s.variable(n, types.Types[TFLOAT64])
                        }
                        addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), armHasVFPv4, s.sb)
@@ -3646,8 +3642,7 @@ func init() {
 
                        // Call the pure Go version.
                        s.startBlock(bFalse)
-                       a := s.call(n, callNormal)
-                       s.vars[n] = s.load(types.Types[TFLOAT64], a)
+                       s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
                        s.endBlock().AddEdgeTo(bEnd)
 
                        // Merge results.
@@ -3676,8 +3671,7 @@ func init() {
 
                        // Call the pure Go version.
                        s.startBlock(bFalse)
-                       a := s.call(n, callNormal)
-                       s.vars[n] = s.load(types.Types[TFLOAT64], a)
+                       s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
                        s.endBlock().AddEdgeTo(bEnd)
 
                        // Merge results.
@@ -3887,8 +3881,7 @@ func init() {
 
                        // Call the pure Go version.
                        s.startBlock(bFalse)
-                       a := s.call(n, callNormal)
-                       s.vars[n] = s.load(types.Types[TINT], a)
+                       s.vars[n] = s.callResult(n, callNormal) // types.Types[TINT]
                        s.endBlock().AddEdgeTo(bEnd)
 
                        // Merge results.
@@ -4336,9 +4329,17 @@ func (s *state) openDeferExit() {
        }
 }
 
+func (s *state) callResult(n *Node, k callKind) *ssa.Value {
+       return s.call(n, k, false)
+}
+
+func (s *state) callAddr(n *Node, k callKind) *ssa.Value {
+       return s.call(n, k, true)
+}
+
 // Calls the function n using the specified call type.
 // Returns the address of the return value (or nil if none).
-func (s *state) call(n *Node, k callKind) *ssa.Value {
+func (s *state) call(n *Node, k callKind, returnResultAddr bool) *ssa.Value {
        var sym *types.Sym     // target symbol (if static)
        var closure *ssa.Value // ptr to closure to run (if dynamic)
        var codeptr *ssa.Value // ptr to target code (if dynamic)
@@ -4547,7 +4548,10 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
                return nil
        }
        fp := res.Field(0)
-       return s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize())
+       if returnResultAddr {
+               return s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize())
+       }
+       return s.load(n.Type, s.constOffPtrSP(types.NewPtr(fp.Type), fp.Offset+Ctxt.FixedFrameSize()))
 }
 
 // maybeNilCheckClosure checks if a nil check of a closure is needed in some
@@ -4676,7 +4680,7 @@ func (s *state) addr(n *Node) *ssa.Value {
                addr := s.addr(n.Left)
                return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
        case OCALLFUNC, OCALLINTER, OCALLMETH:
-               return s.call(n, callNormal)
+               return s.callAddr(n, callNormal)
        case ODOTTYPE:
                v, _ := s.dottype(n, false)
                if v.Op != ssa.OpLoad {