mirror of
https://github.com/golang/go
synced 2024-11-22 16:04:40 -07:00
cmd/internal/obj/ppc64: improve long conditional branch fixup
Improve the code which fixes up conditional branches which exceed the range of a single instruction by inserting one extra jump when possible instead of two. Change-Id: Ib0eb5b0f47f7d0e0ccd55471307a5f73fbda88a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342930 Run-TryBot: Paul Murphy <murp@ibm.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
5670ff4ae5
commit
8f397bc118
@ -329,18 +329,13 @@ const (
|
||||
BI_OVF = 3
|
||||
)
|
||||
|
||||
// Values for the BO field. Add the branch type to
|
||||
// the likely bits, if a likely setting is known.
|
||||
// If branch likely or unlikely is not known, don't set it.
|
||||
// e.g. branch on cr+likely = 15
|
||||
// Common values for the BO field.
|
||||
|
||||
const (
|
||||
BO_BCTR = 16 // branch on ctr value
|
||||
BO_BCR = 12 // branch on cr value
|
||||
BO_BCRBCTR = 8 // branch on ctr and cr value
|
||||
BO_NOTBCR = 4 // branch on not cr value
|
||||
BO_UNLIKELY = 2 // value for unlikely
|
||||
BO_LIKELY = 3 // value for likely
|
||||
BO_BCTR = 16 // decrement ctr, branch on ctr != 0
|
||||
BO_BCR = 12 // branch on cr value
|
||||
BO_BCRBCTR = 8 // decrement ctr, branch on ctr != 0 and cr value
|
||||
BO_NOTBCR = 4 // branch on not cr value
|
||||
)
|
||||
|
||||
// Bit settings from the CR
|
||||
|
@ -642,6 +642,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
|
||||
var otxt int64
|
||||
var q *obj.Prog
|
||||
var out [6]uint32
|
||||
for bflag != 0 {
|
||||
bflag = 0
|
||||
pc = 0
|
||||
@ -653,22 +654,74 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
if (o.type_ == 16 || o.type_ == 17) && p.To.Target() != nil {
|
||||
otxt = p.To.Target().Pc - pc
|
||||
if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
|
||||
q = c.newprog()
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
q.As = ABR
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(p.To.Target())
|
||||
p.To.SetTarget(q)
|
||||
q = c.newprog()
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
q.As = ABR
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(q.Link.Link)
|
||||
// Assemble the instruction with a target not too far to figure out BI and BO fields.
|
||||
// If only the CTR or BI (the CR bit) are tested, the conditional branch can be inverted,
|
||||
// and only one extra branch is needed to reach the target.
|
||||
tgt := p.To.Target()
|
||||
p.To.SetTarget(p.Link)
|
||||
c.asmout(p, o, out[:])
|
||||
p.To.SetTarget(tgt)
|
||||
|
||||
//addnop(p->link);
|
||||
//addnop(p);
|
||||
bo := int64(out[0]>>21) & 31
|
||||
bi := int16((out[0] >> 16) & 31)
|
||||
invertible := false
|
||||
|
||||
if bo&0x14 == 0x14 {
|
||||
// A conditional branch that is unconditionally taken. This cannot be inverted.
|
||||
} else if bo&0x10 == 0x10 {
|
||||
// A branch based on the value of CTR. Invert the CTR comparison against zero bit.
|
||||
bo ^= 0x2
|
||||
invertible = true
|
||||
} else if bo&0x04 == 0x04 {
|
||||
// A branch based on CR bit. Invert the BI comparison bit.
|
||||
bo ^= 0x8
|
||||
invertible = true
|
||||
}
|
||||
|
||||
if invertible {
|
||||
// Rewrite
|
||||
// BC bo,...,far_away_target
|
||||
// NEXT_INSN
|
||||
// to:
|
||||
// BC invert(bo),next_insn
|
||||
// JMP far_away_target
|
||||
// next_insn:
|
||||
// NEXT_INSN
|
||||
p.As = ABC
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: bo}
|
||||
q = c.newprog()
|
||||
q.As = ABR
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(p.To.Target())
|
||||
q.Link = p.Link
|
||||
p.To.SetTarget(p.Link)
|
||||
p.Link = q
|
||||
p.Reg = bi // TODO: This is a hack since BI bits are not enumerated as registers
|
||||
} else {
|
||||
// Rewrite
|
||||
// BC ...,far_away_target
|
||||
// NEXT_INSN
|
||||
// to
|
||||
// BC ...,tmp
|
||||
// JMP next_insn
|
||||
// tmp:
|
||||
// JMP far_away_target
|
||||
// next_insn:
|
||||
// NEXT_INSN
|
||||
q = c.newprog()
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
q.As = ABR
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(p.To.Target())
|
||||
p.To.SetTarget(q)
|
||||
q = c.newprog()
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
q.As = ABR
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(q.Link.Link)
|
||||
}
|
||||
bflag = 1
|
||||
}
|
||||
}
|
||||
@ -706,7 +759,6 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
|
||||
bp := c.cursym.P
|
||||
var i int32
|
||||
var out [6]uint32
|
||||
for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
|
||||
c.pc = p.Pc
|
||||
o = c.oplook(p)
|
||||
|
Loading…
Reference in New Issue
Block a user