mirror of
https://github.com/golang/go
synced 2024-11-26 14:56:47 -07:00
cmd/compile: get rid of BlockCall
No need for it, we can treat calls as (mostly) normal values that take a memory and return a memory. Lowers the number of basic blocks needed to represent a function. "go test -c net/http" uses 27% fewer basic blocks. Probably doesn't affect generated code much, but should help various passes whose running time and/or space depends on the number of basic blocks. Fixes #15631 Change-Id: I0bf21e123f835e2cfa382753955a4f8bce03dfa6 Reviewed-on: https://go-review.googlesource.com/28950 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
d00a3cead8
commit
c345a3913f
@ -1065,7 +1065,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.SetLineno(b.Line)
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
@ -994,7 +994,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.SetLineno(b.Line)
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
@ -890,7 +890,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.SetLineno(b.Line)
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
@ -2894,7 +2894,6 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||
}
|
||||
|
||||
// call target
|
||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||
var call *ssa.Value
|
||||
switch {
|
||||
case k == callDefer:
|
||||
@ -2912,29 +2911,29 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||
Fatalf("bad call type %v %v", n.Op, n)
|
||||
}
|
||||
call.AuxInt = stksize // Call operations carry the argsize of the callee along with them
|
||||
|
||||
// Finish call block
|
||||
s.vars[&memVar] = call
|
||||
b := s.endBlock()
|
||||
b.Kind = ssa.BlockCall
|
||||
b.SetControl(call)
|
||||
b.AddEdgeTo(bNext)
|
||||
|
||||
// Finish block for defers
|
||||
if k == callDefer {
|
||||
// Add recover edge to exit code.
|
||||
b := s.endBlock()
|
||||
b.Kind = ssa.BlockDefer
|
||||
b.SetControl(call)
|
||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||
b.AddEdgeTo(bNext)
|
||||
// Add recover edge to exit code.
|
||||
r := s.f.NewBlock(ssa.BlockPlain)
|
||||
s.startBlock(r)
|
||||
s.exit()
|
||||
b.AddEdgeTo(r)
|
||||
b.Likely = ssa.BranchLikely
|
||||
s.startBlock(bNext)
|
||||
}
|
||||
|
||||
// Start exit block, find address of result.
|
||||
s.startBlock(bNext)
|
||||
// Keep input pointer args live across calls. This is a bandaid until 1.8.
|
||||
for _, n := range s.ptrargs {
|
||||
s.vars[&memVar] = s.newValue2(ssa.OpKeepAlive, ssa.TypeMem, s.variable(n, n.Type), s.mem())
|
||||
}
|
||||
// Find address of result.
|
||||
res := n.Left.Type.Results()
|
||||
if res.NumFields() == 0 || k != callNormal {
|
||||
// call has no return value. Continue with the next statement.
|
||||
@ -3276,9 +3275,9 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
|
||||
call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, fn.Sym, s.mem())
|
||||
s.vars[&memVar] = call
|
||||
|
||||
// Finish block
|
||||
b := s.endBlock()
|
||||
if !returns {
|
||||
// Finish block
|
||||
b := s.endBlock()
|
||||
b.Kind = ssa.BlockExit
|
||||
b.SetControl(call)
|
||||
call.AuxInt = off - Ctxt.FixedFrameSize()
|
||||
@ -3287,11 +3286,6 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
b.Kind = ssa.BlockCall
|
||||
b.SetControl(call)
|
||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||
b.AddEdgeTo(bNext)
|
||||
s.startBlock(bNext)
|
||||
|
||||
// Keep input pointer args live across calls. This is a bandaid until 1.8.
|
||||
for _, n := range s.ptrargs {
|
||||
@ -4267,7 +4261,7 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) {
|
||||
}
|
||||
// Emit control flow instructions for block
|
||||
var next *ssa.Block
|
||||
if i < len(f.Blocks)-1 && (Debug['N'] == 0 || b.Kind == ssa.BlockCall) {
|
||||
if i < len(f.Blocks)-1 && Debug['N'] == 0 {
|
||||
// If -N, leave next==nil so every block with successors
|
||||
// ends in a JMP (except call blocks - plive doesn't like
|
||||
// select{send,recv} followed by a JMP call). Helps keep
|
||||
|
@ -765,7 +765,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.SetLineno(b.Line)
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
@ -972,7 +972,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
|
||||
}
|
||||
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
@ -80,16 +80,6 @@ func checkFunc(f *Func) {
|
||||
if !b.Control.Type.IsBoolean() {
|
||||
f.Fatalf("if block %s has non-bool control value %s", b, b.Control.LongString())
|
||||
}
|
||||
case BlockCall:
|
||||
if len(b.Succs) != 1 {
|
||||
f.Fatalf("call block %s len(Succs)==%d, want 1", b, len(b.Succs))
|
||||
}
|
||||
if b.Control == nil {
|
||||
f.Fatalf("call block %s has no control value", b)
|
||||
}
|
||||
if !b.Control.Type.IsMemory() {
|
||||
f.Fatalf("call block %s has non-memory control value %s", b, b.Control.LongString())
|
||||
}
|
||||
case BlockDefer:
|
||||
if len(b.Succs) != 2 {
|
||||
f.Fatalf("defer block %s len(Succs)==%d, want 2", b, len(b.Succs))
|
||||
|
@ -54,6 +54,7 @@ func liveValues(f *Func, reachable []bool) []bool {
|
||||
var q []*Value // stack-like worklist of unscanned values
|
||||
|
||||
// Starting set: all control values of reachable blocks are live.
|
||||
// Calls are live (because callee can observe the memory state).
|
||||
for _, b := range f.Blocks {
|
||||
if !reachable[b.ID] {
|
||||
continue
|
||||
@ -62,6 +63,12 @@ func liveValues(f *Func, reachable []bool) []bool {
|
||||
live[v.ID] = true
|
||||
q = append(q, v)
|
||||
}
|
||||
for _, v := range b.Values {
|
||||
if opcodeTable[v.Op].call && !live[v.ID] {
|
||||
live[v.ID] = true
|
||||
q = append(q, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute transitive closure of live values.
|
||||
|
@ -389,11 +389,11 @@ func init() {
|
||||
},
|
||||
},
|
||||
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// arg0 = destination pointer
|
||||
// arg1 = source pointer
|
||||
|
@ -436,11 +436,11 @@ func init() {
|
||||
},
|
||||
},
|
||||
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// arg0 = destination pointer
|
||||
// arg1 = source pointer
|
||||
|
@ -318,11 +318,11 @@ func init() {
|
||||
{name: "CSELULT0", argLength: 2, reg: gp1flags1, asm: "CSEL"}, // returns arg0 if flags indicates unsigned LT, 0 otherwise, arg1=flags
|
||||
|
||||
// function calls
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// pseudo-ops
|
||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}}, // panic if arg0 is nil. arg1=mem.
|
||||
|
@ -363,11 +363,11 @@ func init() {
|
||||
{name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags
|
||||
|
||||
// function calls
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// pseudo-ops
|
||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}}, // panic if arg0 is nil. arg1=mem.
|
||||
|
@ -264,11 +264,11 @@ func init() {
|
||||
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
|
||||
|
||||
// function calls
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// duffzero
|
||||
// arg0 = address of memory to zero
|
||||
|
@ -295,11 +295,11 @@ func init() {
|
||||
// Convert pointer to integer, takes a memory operand for ordering.
|
||||
{name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
|
||||
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gp | sp, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gp | sp, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||
|
||||
// large or unaligned zeroing
|
||||
// arg0 = address of memory to zero (in R3, changed as side effect)
|
||||
|
@ -313,11 +313,11 @@ var genericOps = []opData{
|
||||
// Function calls. Arguments to the call have already been written to the stack.
|
||||
// Return values appear on the stack. The method receiver, if any, is treated
|
||||
// as a phantom first argument.
|
||||
{name: "ClosureCall", argLength: 3, aux: "Int64"}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory.
|
||||
{name: "StaticCall", argLength: 1, aux: "SymOff"}, // call function aux.(*gc.Sym), arg0=memory. auxint=arg size. Returns memory.
|
||||
{name: "DeferCall", argLength: 1, aux: "Int64"}, // defer call. arg0=memory, auxint=arg size. Returns memory.
|
||||
{name: "GoCall", argLength: 1, aux: "Int64"}, // go call. arg0=memory, auxint=arg size. Returns memory.
|
||||
{name: "InterCall", argLength: 2, aux: "Int64"}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory.
|
||||
{name: "ClosureCall", argLength: 3, aux: "Int64", call: true}, // arg0=code pointer, arg1=context ptr, arg2=memory. auxint=arg size. Returns memory.
|
||||
{name: "StaticCall", argLength: 1, aux: "SymOff", call: true}, // call function aux.(*gc.Sym), arg0=memory. auxint=arg size. Returns memory.
|
||||
{name: "DeferCall", argLength: 1, aux: "Int64", call: true}, // defer call. arg0=memory, auxint=arg size. Returns memory.
|
||||
{name: "GoCall", argLength: 1, aux: "Int64", call: true}, // go call. arg0=memory, auxint=arg size. Returns memory.
|
||||
{name: "InterCall", argLength: 2, aux: "Int64", call: true}, // interface call. arg0=code pointer, arg1=memory, auxint=arg size. Returns memory.
|
||||
|
||||
// Conversions: signed extensions, zero (unsigned) extensions, truncations
|
||||
{name: "SignExt8to16", argLength: 1, typ: "Int16"},
|
||||
@ -475,7 +475,6 @@ var genericOps = []opData{
|
||||
var genericBlocks = []blockData{
|
||||
{name: "Plain"}, // a single successor
|
||||
{name: "If"}, // 2 successors, if control goto Succs[0] else goto Succs[1]
|
||||
{name: "Call"}, // 1 successor, control is call op (of memory type)
|
||||
{name: "Defer"}, // 2 successors, Succs[0]=defer queued, Succs[1]=defer recovered. control is call op (of memory type)
|
||||
{name: "Check"}, // 1 successor, control is nilcheck op (of void type)
|
||||
{name: "Ret"}, // no successors, control value is memory result
|
||||
|
@ -46,6 +46,7 @@ type opData struct {
|
||||
resultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
|
||||
resultNotInArgs bool // outputs must not be allocated to the same registers as inputs
|
||||
clobberFlags bool // this op clobbers flags register
|
||||
call bool // is a function call
|
||||
}
|
||||
|
||||
type blockData struct {
|
||||
@ -175,6 +176,9 @@ func genOp() {
|
||||
if v.clobberFlags {
|
||||
fmt.Fprintln(w, "clobberFlags: true,")
|
||||
}
|
||||
if v.call {
|
||||
fmt.Fprintln(w, "call: true,")
|
||||
}
|
||||
if a.name == "generic" {
|
||||
fmt.Fprintln(w, "generic:true,")
|
||||
fmt.Fprintln(w, "},") // close op
|
||||
|
@ -28,7 +28,7 @@ type loop struct {
|
||||
isInner bool // True if never discovered to contain a loop
|
||||
|
||||
// register allocation uses this.
|
||||
containsCall bool // if any block in this loop or any loop it contains is a BlockCall or BlockDefer
|
||||
containsCall bool // if any block in this loop or any loop it contains has a call
|
||||
}
|
||||
|
||||
// outerinner records that outer contains inner
|
||||
@ -50,8 +50,15 @@ func (l *loop) setContainsCall() {
|
||||
|
||||
}
|
||||
func (l *loop) checkContainsCall(bb *Block) {
|
||||
if bb.Kind == BlockCall || bb.Kind == BlockDefer {
|
||||
if bb.Kind == BlockDefer {
|
||||
l.setContainsCall()
|
||||
return
|
||||
}
|
||||
for _, v := range bb.Values {
|
||||
if opcodeTable[v.Op].call {
|
||||
l.setContainsCall()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,7 +139,7 @@ func likelyadjust(f *Func) {
|
||||
// Calls. TODO not all calls are equal, names give useful clues.
|
||||
// Any name-based heuristics are only relative to other calls,
|
||||
// and less influential than inferences from loop structure.
|
||||
case BlockCall, BlockDefer:
|
||||
case BlockDefer:
|
||||
local[b.ID] = blCALL
|
||||
certain[b.ID] = max8(blCALL, certain[b.Succs[0].b.ID])
|
||||
|
||||
@ -210,6 +217,13 @@ func likelyadjust(f *Func) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Look for calls in the block. If there is one, make this block unlikely.
|
||||
for _, v := range b.Values {
|
||||
if opcodeTable[v.Op].call {
|
||||
local[b.ID] = blCALL
|
||||
certain[b.ID] = max8(blCALL, certain[b.Succs[0].b.ID])
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.pass.debug > 2 {
|
||||
f.Config.Warnl(b.Line, "BP: Block %s, local=%s, certain=%s", b, bllikelies[local[b.ID]-blMin], bllikelies[certain[b.ID]-blMin])
|
||||
|
@ -29,6 +29,7 @@ type opInfo struct {
|
||||
resultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
|
||||
resultNotInArgs bool // outputs must not be allocated to the same registers as inputs
|
||||
clobberFlags bool // this op clobbers flags register
|
||||
call bool // is a function call
|
||||
}
|
||||
|
||||
type inputInfo struct {
|
||||
|
@ -89,7 +89,6 @@ const (
|
||||
|
||||
BlockPlain
|
||||
BlockIf
|
||||
BlockCall
|
||||
BlockDefer
|
||||
BlockCheck
|
||||
BlockRet
|
||||
@ -175,7 +174,6 @@ var blockString = [...]string{
|
||||
|
||||
BlockPlain: "Plain",
|
||||
BlockIf: "If",
|
||||
BlockCall: "Call",
|
||||
BlockDefer: "Defer",
|
||||
BlockCheck: "Check",
|
||||
BlockRet: "Ret",
|
||||
@ -3725,6 +3723,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
@ -3734,6 +3733,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 4}, // DX
|
||||
@ -3747,6 +3747,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
@ -3756,6 +3757,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
@ -3765,6 +3767,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 239}, // AX CX DX BX BP SI DI
|
||||
@ -6667,6 +6670,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294967279, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
|
||||
},
|
||||
@ -6676,6 +6680,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 4}, // DX
|
||||
@ -6689,6 +6694,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294967279, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
|
||||
},
|
||||
@ -6698,6 +6704,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294967279, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
|
||||
},
|
||||
@ -6707,6 +6714,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
@ -9820,6 +9828,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294907903, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
|
||||
},
|
||||
@ -9829,6 +9838,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 128}, // R7
|
||||
@ -9842,6 +9852,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294907903, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
|
||||
},
|
||||
@ -9851,6 +9862,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4294907903, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
|
||||
},
|
||||
@ -9860,6 +9872,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||
@ -11908,6 +11921,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4611686017621819391, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||
},
|
||||
@ -11917,6 +11931,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 67108864}, // R26
|
||||
@ -11930,6 +11945,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4611686017621819391, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||
},
|
||||
@ -11939,6 +11955,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 4611686017621819391, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||
},
|
||||
@ -11948,6 +11965,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 133955583}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26
|
||||
@ -13406,6 +13424,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 2305843009180139518, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
|
||||
},
|
||||
@ -13415,6 +13434,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 4194304}, // R22
|
||||
@ -13428,6 +13448,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 2305843009180139518, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
|
||||
},
|
||||
@ -13437,6 +13458,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 2305843009180139518, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
|
||||
},
|
||||
@ -13446,6 +13468,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 33554430}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25
|
||||
@ -14905,6 +14928,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 288230372930482172, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
},
|
||||
@ -14914,6 +14938,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 1024}, // R11
|
||||
@ -14927,6 +14952,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 288230372930482172, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
},
|
||||
@ -14936,6 +14962,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
clobbers: 288230372930482172, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
|
||||
},
|
||||
@ -14945,6 +14972,7 @@ var opcodeTable = [...]opInfo{
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
call: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 536866812}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||
@ -16117,30 +16145,35 @@ var opcodeTable = [...]opInfo{
|
||||
name: "ClosureCall",
|
||||
auxType: auxInt64,
|
||||
argLen: 3,
|
||||
call: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "StaticCall",
|
||||
auxType: auxSymOff,
|
||||
argLen: 1,
|
||||
call: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "DeferCall",
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
call: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "GoCall",
|
||||
auxType: auxInt64,
|
||||
argLen: 1,
|
||||
call: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "InterCall",
|
||||
auxType: auxInt64,
|
||||
argLen: 2,
|
||||
call: true,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
|
@ -698,12 +698,8 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
// Initialize liveSet and uses fields for this block.
|
||||
// Walk backwards through the block doing liveness analysis.
|
||||
liveSet.clear()
|
||||
d := int32(len(b.Values))
|
||||
if b.Kind == BlockCall || b.Kind == BlockDefer {
|
||||
d += unlikelyDistance
|
||||
}
|
||||
for _, e := range s.live[b.ID] {
|
||||
s.addUse(e.ID, d+e.dist) // pseudo-uses from beyond end of block
|
||||
s.addUse(e.ID, int32(len(b.Values))+e.dist) // pseudo-uses from beyond end of block
|
||||
liveSet.add(e.ID)
|
||||
}
|
||||
if v := b.Control; v != nil && s.values[v.ID].needReg {
|
||||
@ -2200,14 +2196,8 @@ func (s *regAllocState) computeLive() {
|
||||
// Add len(b.Values) to adjust from end-of-block distance
|
||||
// to beginning-of-block distance.
|
||||
live.clear()
|
||||
d := int32(len(b.Values))
|
||||
if b.Kind == BlockCall || b.Kind == BlockDefer {
|
||||
// Because we keep no values in registers across a call,
|
||||
// make every use past a call appear very far away.
|
||||
d += unlikelyDistance
|
||||
}
|
||||
for _, e := range s.live[b.ID] {
|
||||
live.set(e.ID, e.dist+d)
|
||||
live.set(e.ID, e.dist+int32(len(b.Values)))
|
||||
}
|
||||
|
||||
// Mark control value as live
|
||||
@ -2226,6 +2216,12 @@ func (s *regAllocState) computeLive() {
|
||||
phis = append(phis, v)
|
||||
continue
|
||||
}
|
||||
if opcodeTable[v.Op].call {
|
||||
c := live.contents()
|
||||
for i := range c {
|
||||
c[i].val += unlikelyDistance
|
||||
}
|
||||
}
|
||||
for _, a := range v.Args {
|
||||
if s.values[a.ID].needReg {
|
||||
live.set(a.ID, int32(i))
|
||||
|
@ -925,7 +925,7 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||
}
|
||||
|
||||
switch b.Kind {
|
||||
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
|
||||
case ssa.BlockPlain, ssa.BlockCheck:
|
||||
if b.Succs[0].Block() != next {
|
||||
p := gc.Prog(obj.AJMP)
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
Loading…
Reference in New Issue
Block a user