aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/regalloc.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc.go')
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 8309af2997..4180868932 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -460,6 +460,18 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, line
return c
}
+// isLeaf reports whether f performs any calls.
+func isLeaf(f *Func) bool {
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if opcodeTable[v.Op].call {
+ return false
+ }
+ }
+ }
+ return true
+}
+
func (s *regAllocState) init(f *Func) {
s.f = f
s.registers = f.Config.registers
@@ -510,6 +522,12 @@ func (s *regAllocState) init(f *Func) {
s.allocatable &^= 1 << 12 // R12
}
}
+ if s.f.Config.LinkReg != -1 {
+ if isLeaf(f) {
+ // Leaf functions don't save/restore the link register.
+ s.allocatable &^= 1 << uint(s.f.Config.LinkReg)
+ }
+ }
if s.f.Config.ctxt.Flag_dynlink {
switch s.f.Config.arch {
case "amd64":