mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/loong64: recheck jump offset boundary after auto-aligning loop heads
After the alignment of the loop header is performed, the offset of the checked conditional branch instruction may overflow, so it needs to be checked again. When checking whether the offset of the branch jump instruction overflows, it can be classified and processed according to the range of the immediate field of the specific instruction, which can reduce the introduction of unnecessary jump instructions. Fixes #61819 Change-Id: I772a5b5b8b8de21c78d7566be30be8ff65fdbce8 Reviewed-on: https://go-review.googlesource.com/c/go/+/519915 Reviewed-by: sophie zhao <zhaoxiaolin@loongson.cn> Reviewed-by: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Meidan Li <limeidan@loongson.cn> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Run-TryBot: qiu laidongfeng2 <2645477756@qq.com> Reviewed-by: WANG Xuerui <git@xen0n.name>
This commit is contained in:
parent
59209c4b35
commit
f7f56ded01
2 changed files with 112 additions and 14 deletions
|
|
@ -449,11 +449,8 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
}
|
||||
|
||||
// Run these passes until convergence.
|
||||
bflag := 1
|
||||
var otxt int64
|
||||
var q *obj.Prog
|
||||
for bflag != 0 {
|
||||
bflag = 0
|
||||
for {
|
||||
rescan := false
|
||||
pc = 0
|
||||
prev := c.cursym.Func().Text
|
||||
for p = prev.Link; p != nil; prev, p = p, p.Link {
|
||||
|
|
@ -468,7 +465,7 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
// because pc will be adjusted if padding happens.
|
||||
if p.Mark&branchLoopHead != 0 && pc&(loopAlign-1) != 0 &&
|
||||
!(prev.As == obj.APCALIGN && prev.From.Offset >= loopAlign) {
|
||||
q = c.newprog()
|
||||
q := c.newprog()
|
||||
prev.Link = q
|
||||
q.Link = p
|
||||
q.Pc = pc
|
||||
|
|
@ -484,18 +481,29 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
// since this loop iteration is for p.
|
||||
pc += int64(pcAlignPadLength(ctxt, pc, loopAlign))
|
||||
p.Pc = pc
|
||||
rescan = true
|
||||
}
|
||||
|
||||
// very large conditional branches
|
||||
//
|
||||
// if any procedure is large enough to
|
||||
// generate a large SBRA branch, then
|
||||
// generate extra passes putting branches
|
||||
// around jmps to fix. this is rare.
|
||||
// if any procedure is large enough to generate a large SBRA branch, then
|
||||
// generate extra passes putting branches around jmps to fix. this is rare.
|
||||
if o.type_ == 6 && p.To.Target() != nil {
|
||||
otxt = p.To.Target().Pc - pc
|
||||
if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
|
||||
q = c.newprog()
|
||||
otxt := p.To.Target().Pc - pc
|
||||
|
||||
// On loong64, the immediate value field of the conditional branch instructions
|
||||
// BFPT and BFPT is 21 bits, and the others are 16 bits. The jump target address
|
||||
// is to logically shift the immediate value in the instruction code to the left
|
||||
// by 2 bits and then sign extend.
|
||||
bound := int64(1 << (18 - 1))
|
||||
|
||||
switch p.As {
|
||||
case ABFPT, ABFPF:
|
||||
bound = int64(1 << (23 - 1))
|
||||
}
|
||||
|
||||
if otxt < -bound || otxt >= bound {
|
||||
q := c.newprog()
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
q.As = AJMP
|
||||
|
|
@ -510,7 +518,7 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
q.Pos = p.Pos
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(q.Link.Link)
|
||||
bflag = 1
|
||||
rescan = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -532,7 +540,12 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
}
|
||||
|
||||
c.cursym.Size = pc
|
||||
|
||||
if !rescan {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
pc += -pc & (FuncAlign - 1)
|
||||
c.cursym.Size = pc
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue