cmd/compile: enable late expansion in openDeferExit

Change-Id: I4ce9e914d22b519b00d7e19d93091f6ac0b60938
Reviewed-on: https://go-review.googlesource.com/c/go/+/248188
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>
This commit is contained in:
David Chase 2020-08-12 12:58:07 -04:00
parent 68bc950583
commit bb46b60d29

View File

@ -4251,6 +4251,7 @@ func (s *state) openDeferExit() {
s.lastDeferExit = deferExit s.lastDeferExit = deferExit
s.lastDeferCount = len(s.openDefers) s.lastDeferCount = len(s.openDefers)
zeroval := s.constInt8(types.Types[TUINT8], 0) zeroval := s.constInt8(types.Types[TUINT8], 0)
testLateExpansion := ssa.LateCallExpansionEnabledWithin(s.f)
// Test for and run defers in reverse order // Test for and run defers in reverse order
for i := len(s.openDefers) - 1; i >= 0; i-- { for i := len(s.openDefers) - 1; i >= 0; i-- {
r := s.openDefers[i] r := s.openDefers[i]
@ -4288,18 +4289,32 @@ func (s *state) openDeferExit() {
stksize := fn.Type.ArgWidth() stksize := fn.Type.ArgWidth()
var ACArgs []ssa.Param var ACArgs []ssa.Param
var ACResults []ssa.Param var ACResults []ssa.Param
var callArgs []*ssa.Value
if r.rcvr != nil { if r.rcvr != nil {
// rcvr in case of OCALLINTER // rcvr in case of OCALLINTER
v := s.load(r.rcvr.Type.Elem(), r.rcvr) v := s.load(r.rcvr.Type.Elem(), r.rcvr)
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart) addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)}) ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)})
if testLateExpansion {
callArgs = append(callArgs, v)
} else {
s.store(types.Types[TUINTPTR], addr, v) s.store(types.Types[TUINTPTR], addr, v)
} }
}
for j, argAddrVal := range r.argVals { for j, argAddrVal := range r.argVals {
f := getParam(r.n, j) f := getParam(r.n, j)
pt := types.NewPtr(f.Type) pt := types.NewPtr(f.Type)
ACArgs = append(ACArgs, ssa.Param{Type: f.Type, Offset: int32(argStart + f.Offset)})
if testLateExpansion {
var a *ssa.Value
if !canSSAType(f.Type) {
a = s.newValue2(ssa.OpDereference, f.Type, argAddrVal, s.mem())
} else {
a = s.load(f.Type, argAddrVal)
}
callArgs = append(callArgs, a)
} else {
addr := s.constOffPtrSP(pt, argStart+f.Offset) addr := s.constOffPtrSP(pt, argStart+f.Offset)
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart + f.Offset)})
if !canSSAType(f.Type) { if !canSSAType(f.Type) {
s.move(f.Type, addr, argAddrVal) s.move(f.Type, addr, argAddrVal)
} else { } else {
@ -4307,18 +4322,38 @@ func (s *state) openDeferExit() {
s.storeType(f.Type, addr, argVal, 0, false) s.storeType(f.Type, addr, argVal, 0, false)
} }
} }
}
var call *ssa.Value var call *ssa.Value
if r.closure != nil { if r.closure != nil {
v := s.load(r.closure.Type.Elem(), r.closure) v := s.load(r.closure.Type.Elem(), r.closure)
s.maybeNilCheckClosure(v, callDefer) s.maybeNilCheckClosure(v, callDefer)
codeptr := s.rawLoad(types.Types[TUINTPTR], v) codeptr := s.rawLoad(types.Types[TUINTPTR], v)
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(ACArgs, ACResults), codeptr, v, s.mem()) aux := ssa.ClosureAuxCall(ACArgs, ACResults)
if testLateExpansion {
callArgs = append(callArgs, s.mem())
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v)
call.AddArgs(callArgs...)
} else {
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, aux, codeptr, v, s.mem())
}
} else {
aux := ssa.StaticAuxCall(fn.Sym.Linksym(), ACArgs, ACResults)
if testLateExpansion {
callArgs = append(callArgs, s.mem())
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
call.AddArgs(callArgs...)
} else { } else {
// Do a static call if the original call was a static function or method // Do a static call if the original call was a static function or method
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym(), ACArgs, ACResults), s.mem()) call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, aux, s.mem())
}
} }
call.AuxInt = stksize call.AuxInt = stksize
if testLateExpansion {
s.vars[&memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
} else {
s.vars[&memVar] = call s.vars[&memVar] = call
}
// Make sure that the stack slots with pointers are kept live // Make sure that the stack slots with pointers are kept live
// through the call (which is a pre-emption point). Also, we will // through the call (which is a pre-emption point). Also, we will
// use the first call of the last defer exit to compute liveness // use the first call of the last defer exit to compute liveness