Commit 3dcc424b authored by Keith Randall's avatar Keith Randall

[dev.ssa] cmd/compile/internal/ssa: compute outarg size correctly

Keep track of the outargs size needed at each call.
Compute the size of the outargs section of the stack frame.  It's just
the max of the outargs size at all the callsites in the function.

Change-Id: I3d0640f654f01307633b1a5f75bab16e211ea6c0
Reviewed-on: https://go-review.googlesource.com/12178Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
parent 8adc905a
...@@ -626,6 +626,8 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -626,6 +626,8 @@ func (s *state) expr(n *Node) *ssa.Value {
entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem()) entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem()) call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
} }
dowidth(n.Left.Type)
call.AuxInt = n.Left.Type.Argwid // call operations carry the argsize of the callee along with them
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockCall b.Kind = ssa.BlockCall
b.Control = call b.Control = call
......
...@@ -29,7 +29,6 @@ Regalloc ...@@ -29,7 +29,6 @@ Regalloc
- Make calls clobber all registers - Make calls clobber all registers
StackAlloc: StackAlloc:
- Compute size of outargs section correctly
- Sort variables so all ptr-containing ones are first (so stack - Sort variables so all ptr-containing ones are first (so stack
maps are smaller) maps are smaller)
- Reuse stack slots for noninterfering and type-compatible variables - Reuse stack slots for noninterfering and type-compatible variables
......
...@@ -88,8 +88,8 @@ ...@@ -88,8 +88,8 @@
(If (SETB cmp) yes no) -> (ULT cmp yes no) (If (SETB cmp) yes no) -> (ULT cmp yes no)
(If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB <TypeFlags> cond cond) yes no) (If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB <TypeFlags> cond cond) yes no)
(StaticCall {target} mem) -> (CALLstatic {target} mem) (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
(ClosureCall entry closure mem) -> (CALLclosure entry closure mem) (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
// Rules below here apply some simple optimizations after lowering. // Rules below here apply some simple optimizations after lowering.
// TODO: Should this be a separate pass? // TODO: Should this be a separate pass?
......
...@@ -460,10 +460,11 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -460,10 +460,11 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
endf8ca12fe79290bc82b11cfa463bc9413: endf8ca12fe79290bc82b11cfa463bc9413:
; ;
case OpClosureCall: case OpClosureCall:
// match: (ClosureCall entry closure mem) // match: (ClosureCall [argwid] entry closure mem)
// cond: // cond:
// result: (CALLclosure entry closure mem) // result: (CALLclosure [argwid] entry closure mem)
{ {
argwid := v.AuxInt
entry := v.Args[0] entry := v.Args[0]
closure := v.Args[1] closure := v.Args[1]
mem := v.Args[2] mem := v.Args[2]
...@@ -471,13 +472,14 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -471,13 +472,14 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
v.resetArgs() v.resetArgs()
v.AuxInt = argwid
v.AddArg(entry) v.AddArg(entry)
v.AddArg(closure) v.AddArg(closure)
v.AddArg(mem) v.AddArg(mem)
return true return true
} }
goto endee26da781e813a3c602ccb4f7ade98c7 goto endfd75d26316012d86cb71d0dd1214259b
endee26da781e813a3c602ccb4f7ade98c7: endfd75d26316012d86cb71d0dd1214259b:
; ;
case OpConst: case OpConst:
// match: (Const <t> [val]) // match: (Const <t> [val])
...@@ -1611,22 +1613,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ...@@ -1611,22 +1613,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool {
end78e66b6fc298684ff4ac8aec5ce873c9: end78e66b6fc298684ff4ac8aec5ce873c9:
; ;
case OpStaticCall: case OpStaticCall:
// match: (StaticCall {target} mem) // match: (StaticCall [argwid] {target} mem)
// cond: // cond:
// result: (CALLstatic {target} mem) // result: (CALLstatic [argwid] {target} mem)
{ {
argwid := v.AuxInt
target := v.Aux target := v.Aux
mem := v.Args[0] mem := v.Args[0]
v.Op = OpAMD64CALLstatic v.Op = OpAMD64CALLstatic
v.AuxInt = 0 v.AuxInt = 0
v.Aux = nil v.Aux = nil
v.resetArgs() v.resetArgs()
v.AuxInt = argwid
v.Aux = target v.Aux = target
v.AddArg(mem) v.AddArg(mem)
return true return true
} }
goto end1948857a7cfc2a4f905045e58d3b9ec1 goto end32c5cbec813d1c2ae94fc9b1090e4b2a
end1948857a7cfc2a4f905045e58d3b9ec1: end32c5cbec813d1c2ae94fc9b1090e4b2a:
; ;
case OpStore: case OpStore:
// match: (Store ptr val mem) // match: (Store ptr val mem)
......
...@@ -9,12 +9,16 @@ package ssa ...@@ -9,12 +9,16 @@ package ssa
func stackalloc(f *Func) { func stackalloc(f *Func) {
home := f.RegAlloc home := f.RegAlloc
// First compute the size of the outargs section. // Start with space for callee arguments/returns.
n := int64(16) //TODO: compute max of all callsites var n int64
for _, b := range f.Blocks {
// Include one slot for deferreturn. if b.Kind != BlockCall {
if false && n < f.Config.ptrSize { //TODO: check for deferreturn continue
n = f.Config.ptrSize }
v := b.Control
if n < v.AuxInt {
n = v.AuxInt
}
} }
// TODO: group variables by ptr/nonptr, size, etc. Emit ptr vars last // TODO: group variables by ptr/nonptr, size, etc. Emit ptr vars last
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment