mirror of
https://github.com/golang/go
synced 2024-11-07 00:16:10 -07:00
cmd/compile, cmd/internal/obj/ppc64: use LR for indirect calls
On PPC64, indirect calls can be made through LR or CTR. Currently both are used. This CL changes it to always use LR. For async preemption, to return from the injected call, we need an indirect jump back to the PC we preeempted. This jump can be made through LR or CTR. So we'll have to clobber either LR or CTR. Currently, LR is used more frequently. In particular, for a leaf function, LR is live throughout the function. We don't want to make leaf functions nonpreemptible. So we choose CTR for the call injection. For code sequences that use CTR, if it is ok to use another register, change it to. Plus, it is a call so it will clobber LR anyway. It doesn't need to also clobber CTR (even without preemption). Change-Id: I07bd0e93b94a1a3aa2be2cd465801136165d8ab8 Reviewed-on: https://go-review.googlesource.com/c/go/+/203822 Run-TryBot: Cherry Zhang <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
a96cfa75c6
commit
24e549a717
@ -1239,14 +1239,14 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_REG
|
||||||
p.From.Reg = v.Args[0].Reg()
|
p.From.Reg = v.Args[0].Reg()
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = ppc64.REG_CTR
|
p.To.Reg = ppc64.REG_LR
|
||||||
|
|
||||||
if v.Args[0].Reg() != ppc64.REG_R12 {
|
if v.Args[0].Reg() != ppc64.REG_R12 {
|
||||||
v.Fatalf("Function address for %v should be in R12 %d but is in %d", v.LongString(), ppc64.REG_R12, p.From.Reg)
|
v.Fatalf("Function address for %v should be in R12 %d but is in %d", v.LongString(), ppc64.REG_R12, p.From.Reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pp := s.Call(v)
|
pp := s.Call(v)
|
||||||
pp.To.Reg = ppc64.REG_CTR
|
pp.To.Reg = ppc64.REG_LR
|
||||||
|
|
||||||
if gc.Ctxt.Flag_shared {
|
if gc.Ctxt.Flag_shared {
|
||||||
// When compiling Go into PIC, the function we just
|
// When compiling Go into PIC, the function we just
|
||||||
|
@ -130,8 +130,8 @@ func (c *ctxt9) rewriteToUseTOC(p *obj.Prog) {
|
|||||||
// becomes
|
// becomes
|
||||||
// MOVD runtime.duffxxx@TOC, R12
|
// MOVD runtime.duffxxx@TOC, R12
|
||||||
// ADD $offset, R12
|
// ADD $offset, R12
|
||||||
// MOVD R12, CTR
|
// MOVD R12, LR
|
||||||
// BL (CTR)
|
// BL (LR)
|
||||||
var sym *obj.LSym
|
var sym *obj.LSym
|
||||||
if p.As == obj.ADUFFZERO {
|
if p.As == obj.ADUFFZERO {
|
||||||
sym = c.ctxt.Lookup("runtime.duffzero")
|
sym = c.ctxt.Lookup("runtime.duffzero")
|
||||||
@ -167,13 +167,11 @@ func (c *ctxt9) rewriteToUseTOC(p *obj.Prog) {
|
|||||||
p2.From.Type = obj.TYPE_REG
|
p2.From.Type = obj.TYPE_REG
|
||||||
p2.From.Reg = REG_R12
|
p2.From.Reg = REG_R12
|
||||||
p2.To.Type = obj.TYPE_REG
|
p2.To.Type = obj.TYPE_REG
|
||||||
p2.To.Reg = REG_CTR
|
p2.To.Reg = REG_LR
|
||||||
p3 := obj.Appendp(p2, c.newprog)
|
p3 := obj.Appendp(p2, c.newprog)
|
||||||
p3.As = obj.ACALL
|
p3.As = obj.ACALL
|
||||||
p3.From.Type = obj.TYPE_REG
|
|
||||||
p3.From.Reg = REG_R12
|
|
||||||
p3.To.Type = obj.TYPE_REG
|
p3.To.Type = obj.TYPE_REG
|
||||||
p3.To.Reg = REG_CTR
|
p3.To.Reg = REG_LR
|
||||||
}
|
}
|
||||||
|
|
||||||
var source *obj.Addr
|
var source *obj.Addr
|
||||||
@ -288,8 +286,8 @@ func (c *ctxt9) rewriteToUseGot(p *obj.Prog) {
|
|||||||
// becomes
|
// becomes
|
||||||
// MOVD runtime.duffxxx@GOT, R12
|
// MOVD runtime.duffxxx@GOT, R12
|
||||||
// ADD $offset, R12
|
// ADD $offset, R12
|
||||||
// MOVD R12, CTR
|
// MOVD R12, LR
|
||||||
// BL (CTR)
|
// BL (LR)
|
||||||
var sym *obj.LSym
|
var sym *obj.LSym
|
||||||
if p.As == obj.ADUFFZERO {
|
if p.As == obj.ADUFFZERO {
|
||||||
sym = c.ctxt.Lookup("runtime.duffzero")
|
sym = c.ctxt.Lookup("runtime.duffzero")
|
||||||
@ -317,13 +315,11 @@ func (c *ctxt9) rewriteToUseGot(p *obj.Prog) {
|
|||||||
p2.From.Type = obj.TYPE_REG
|
p2.From.Type = obj.TYPE_REG
|
||||||
p2.From.Reg = REG_R12
|
p2.From.Reg = REG_R12
|
||||||
p2.To.Type = obj.TYPE_REG
|
p2.To.Type = obj.TYPE_REG
|
||||||
p2.To.Reg = REG_CTR
|
p2.To.Reg = REG_LR
|
||||||
p3 := obj.Appendp(p2, c.newprog)
|
p3 := obj.Appendp(p2, c.newprog)
|
||||||
p3.As = obj.ACALL
|
p3.As = obj.ACALL
|
||||||
p3.From.Type = obj.TYPE_REG
|
|
||||||
p3.From.Reg = REG_R12
|
|
||||||
p3.To.Type = obj.TYPE_REG
|
p3.To.Type = obj.TYPE_REG
|
||||||
p3.To.Reg = REG_CTR
|
p3.To.Reg = REG_LR
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only care about global data: NAME_EXTERN means a global
|
// We only care about global data: NAME_EXTERN means a global
|
||||||
@ -1196,21 +1192,19 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = REG_R12
|
p.To.Reg = REG_R12
|
||||||
|
|
||||||
// MOVD R12, CTR
|
// MOVD R12, LR
|
||||||
p = obj.Appendp(p, c.newprog)
|
p = obj.Appendp(p, c.newprog)
|
||||||
p.As = AMOVD
|
p.As = AMOVD
|
||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_REG
|
||||||
p.From.Reg = REG_R12
|
p.From.Reg = REG_R12
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = REG_CTR
|
p.To.Reg = REG_LR
|
||||||
|
|
||||||
// BL CTR
|
// BL LR
|
||||||
p = obj.Appendp(p, c.newprog)
|
p = obj.Appendp(p, c.newprog)
|
||||||
p.As = obj.ACALL
|
p.As = obj.ACALL
|
||||||
p.From.Type = obj.TYPE_REG
|
|
||||||
p.From.Reg = REG_R12
|
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = REG_CTR
|
p.To.Reg = REG_LR
|
||||||
} else {
|
} else {
|
||||||
// BL runtime.morestack(SB)
|
// BL runtime.morestack(SB)
|
||||||
p = obj.Appendp(p, c.newprog)
|
p = obj.Appendp(p, c.newprog)
|
||||||
|
Loading…
Reference in New Issue
Block a user