From 396688af7ee121d478e9b8d2cc9d06999ba7fc6e Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 26 Jun 2020 18:19:01 -0400 Subject: [PATCH] cmd/compile: make translation to calls for SSA look more "value-oriented" 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 Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 44 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 75fdbbae045..c59945f2066 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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 {