mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-13 01:15:32 +00:00
Add intelligence about where to break large blocks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34755 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eac6607d7c
commit
f1b214d3ca
@ -140,7 +140,7 @@ namespace {
|
||||
void AdjustBBOffsetsAfter(MachineBasicBlock *BB, int delta);
|
||||
bool DecrementOldEntry(unsigned CPI, MachineInstr* CPEMI, unsigned Size);
|
||||
int LookForExistingCPEntry(CPUser& U, unsigned UserOffset);
|
||||
bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
|
||||
bool HandleConstantPoolUser(MachineFunction &Fn, unsigned CPUserIndex);
|
||||
bool CPEIsInRange(MachineInstr *MI, unsigned UserOffset,
|
||||
MachineInstr *CPEMI, unsigned Disp,
|
||||
bool DoDump);
|
||||
@ -197,7 +197,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &Fn) {
|
||||
while (true) {
|
||||
bool Change = false;
|
||||
for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
|
||||
Change |= HandleConstantPoolUser(Fn, CPUsers[i]);
|
||||
Change |= HandleConstantPoolUser(Fn, i);
|
||||
for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
|
||||
Change |= FixUpImmediateBr(Fn, ImmBranches[i]);
|
||||
if (!Change)
|
||||
@ -722,11 +722,19 @@ int ARMConstantIslands::LookForExistingCPEntry(CPUser& U, unsigned UserOffset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in
|
||||
/// the specific unconditional branch instruction.
|
||||
static inline unsigned getUnconditionalBrDisp(int Opc) {
|
||||
return (Opc == ARM::tB) ? ((1<<10)-1)*2 : ((1<<23)-1)*4;
|
||||
}
|
||||
|
||||
/// HandleConstantPoolUser - Analyze the specified user, checking to see if it
|
||||
/// is out-of-range. If so, pick it up the constant pool value and move it some
|
||||
/// place in-range. Return true if we changed any addresses (thus must run
|
||||
/// another pass of branch lengthening), false otherwise.
|
||||
bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn,
|
||||
unsigned CPUserIndex){
|
||||
CPUser &U = CPUsers[CPUserIndex];
|
||||
MachineInstr *UserMI = U.MI;
|
||||
MachineInstr *CPEMI = U.CPEMI;
|
||||
unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
|
||||
@ -750,6 +758,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
// away that will work. Forward references only for now (although later
|
||||
// we might find some that are backwards).
|
||||
bool WaterFound = false;
|
||||
bool PadNewWater = true;
|
||||
if (!WaterList.empty()) {
|
||||
for (std::vector<MachineBasicBlock*>::iterator IP = prior(WaterList.end()),
|
||||
B = WaterList.begin();; --IP) {
|
||||
@ -759,6 +768,17 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
DOUT << "found water in range\n";
|
||||
// CPE goes before following block (NewMBB).
|
||||
NewMBB = next(MachineFunction::iterator(WaterBB));
|
||||
// If WaterBB is an island, don't pad the new island.
|
||||
// If WaterBB is empty, go backwards until we find something that
|
||||
// isn't. WaterBB may become empty if it's an island whose
|
||||
// contents were moved farther back.
|
||||
if (isThumb) {
|
||||
MachineBasicBlock* BB = WaterBB;
|
||||
while (BB->empty())
|
||||
BB = BB->Prev;
|
||||
if (BB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY)
|
||||
PadNewWater = false;
|
||||
}
|
||||
// Remove the original WaterList entry; we want subsequent
|
||||
// insertions in this vicinity to go after the one we're
|
||||
// about to insert. This considerably reduces the number
|
||||
@ -776,22 +796,32 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
|
||||
DOUT << "No water found\n";
|
||||
MachineBasicBlock *UserMBB = UserMI->getParent();
|
||||
unsigned TrialOffset = BBOffsets[UserMBB->getNumber()] +
|
||||
BBSizes[UserMBB->getNumber()] +
|
||||
isThumb ? 2 : 4; /* for branch to be added */
|
||||
unsigned OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()] +
|
||||
BBSizes[UserMBB->getNumber()];
|
||||
assert(OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()+1]);
|
||||
|
||||
// If the use is at the end of the block, or the end of the block
|
||||
// is within range, make new water there. (If the block ends in
|
||||
// is within range, make new water there. (The +2 or 4 below is
|
||||
// for the unconditional branch we will be adding. If the block ends in
|
||||
// an unconditional branch already, it is water, and is known to
|
||||
// be out of range; so it's OK to assume above we'll be adding a Br.)
|
||||
// be out of range, so we'll always be adding one.)
|
||||
if (&UserMBB->back() == UserMI ||
|
||||
OffsetIsInRange(UserOffset, TrialOffset, U.MaxDisp, !isThumb)) {
|
||||
OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb ? 2 : 4),
|
||||
U.MaxDisp, !isThumb)) {
|
||||
DOUT << "Split at end of block\n";
|
||||
if (&UserMBB->back() == UserMI)
|
||||
assert(BBHasFallthrough(UserMBB) && "Expected a fallthrough BB!");
|
||||
NewMBB = next(MachineFunction::iterator(UserMBB));
|
||||
// Add an unconditional branch from UserMBB to fallthrough block.
|
||||
// Note the new unconditional branch is not being recorded.
|
||||
BuildMI(UserMBB, TII->get(isThumb ? ARM::tB : ARM::B)).addMBB(NewMBB);
|
||||
// Record it for branch lengthening; this new branch will not get out of
|
||||
// range, but if the preceding conditional branch is out of range, the
|
||||
// targets will be exchanged, and the altered branch may be out of
|
||||
// range, so the machinery has to know about it.
|
||||
int UncondBr = isThumb ? ARM::tB : ARM::B;
|
||||
BuildMI(UserMBB, TII->get(UncondBr)).addMBB(NewMBB);
|
||||
unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
|
||||
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
|
||||
MaxDisp, false, UncondBr));
|
||||
int delta = isThumb ? 2 : 4;
|
||||
BBSizes[UserMBB->getNumber()] += delta;
|
||||
AdjustBBOffsetsAfter(UserMBB, delta);
|
||||
@ -804,11 +834,37 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
// CPE' cannot immediately follow it (that location is 2 bytes
|
||||
// farther away from I+1 than CPE was from I) and we'd need to create
|
||||
// a new island.
|
||||
|
||||
// Solution of last resort: split the user's MBB right after the user
|
||||
// and insert a clone of the CPE into the newly created water.
|
||||
MachineInstr *NextMI = next(MachineBasicBlock::iterator(UserMI));
|
||||
NewMBB = SplitBlockBeforeInstr(NextMI);
|
||||
// The 4 in the following is for the unconditional branch we'll be
|
||||
// inserting (allows for long branch on Thumb). The 2 or 0 is for
|
||||
// alignment of the island.
|
||||
unsigned BaseInsertOffset = UserOffset + U.MaxDisp -4 + (isThumb ? 2 : 0);
|
||||
// This could point off the end of the block if we've already got
|
||||
// constant pool entries following this block; only the last one is
|
||||
// in the water list. Back past any possible branches.
|
||||
if (BaseInsertOffset >= BBOffsets[UserMBB->getNumber()+1])
|
||||
BaseInsertOffset = BBOffsets[UserMBB->getNumber()+1] - 6;
|
||||
unsigned EndInsertOffset = BaseInsertOffset +
|
||||
CPEMI->getOperand(2).getImm();
|
||||
MachineBasicBlock::iterator MI = UserMI; ++MI;
|
||||
unsigned CPUIndex = CPUserIndex+1;
|
||||
for (unsigned Offset = UserOffset+ARM::GetInstSize(UserMI);
|
||||
Offset < BaseInsertOffset;
|
||||
Offset += ARM::GetInstSize(MI),
|
||||
MI = next(MI)) {
|
||||
if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) {
|
||||
if (!OffsetIsInRange(Offset, EndInsertOffset,
|
||||
CPUsers[CPUIndex].MaxDisp, !isThumb)) {
|
||||
BaseInsertOffset -= (isThumb ? 2 : 4);
|
||||
EndInsertOffset -= (isThumb ? 2 : 4);
|
||||
}
|
||||
// This is overly conservative, as we don't account for CPEMIs
|
||||
// being reused within the block, but it doesn't matter much.
|
||||
EndInsertOffset += CPUsers[CPUIndex].CPEMI->getOperand(2).getImm();
|
||||
CPUIndex++;
|
||||
}
|
||||
}
|
||||
DOUT << "Split in middle of big block\n";
|
||||
NewMBB = SplitBlockBeforeInstr(prior(MI));
|
||||
}
|
||||
}
|
||||
|
||||
@ -830,7 +886,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
|
||||
NumCPEs++;
|
||||
|
||||
// Compensate for .align 2 in thumb mode.
|
||||
if (isThumb) Size += 2;
|
||||
if (isThumb && PadNewWater) Size += 2;
|
||||
// Increase the size of the island block to account for the new entry.
|
||||
BBSizes[NewIsland->getNumber()] += Size;
|
||||
BBOffsets[NewIsland->getNumber()] = BBOffsets[NewMBB->getNumber()];
|
||||
@ -902,12 +958,6 @@ ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in
|
||||
/// the specific unconditional branch instruction.
|
||||
static inline unsigned getUnconditionalBrDisp(int Opc) {
|
||||
return (Opc == ARM::tB) ? (1<<10)*2 : (1<<23)*4;
|
||||
}
|
||||
|
||||
/// FixUpConditionalBr - Fix up a conditional branch whose destination is too
|
||||
/// far away to fit in its displacement field. It is converted to an inverse
|
||||
/// conditional branch + an unconditional branch to the destination.
|
||||
|
@ -17,24 +17,19 @@ Reimplement 'select' in terms of 'SEL'.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
The constant island pass has been much improved; all the todo items in the
|
||||
previous version of this document have been addressed. However, there are still
|
||||
things that can be done:
|
||||
The constant island pass is in good shape. Some cleanups might be desirable,
|
||||
but there is unlikely to be much improvement in the generated code.
|
||||
|
||||
1. When there isn't an existing water, the current MBB is split right after
|
||||
the use. It would be profitable to look farther forward, especially on Thumb,
|
||||
where negative offsets won't work.
|
||||
(Partially fixed: it will put the island at the end of the block if that is
|
||||
in range. If it is not in range things still work as above, which is poor on
|
||||
Thumb.)
|
||||
|
||||
2. There may be some advantage to trying to be smarter about the initial
|
||||
1. There may be some advantage to trying to be smarter about the initial
|
||||
placement, rather than putting everything at the end.
|
||||
|
||||
3. The handling of 2-byte padding for Thumb is overly conservative. There
|
||||
2. The handling of 2-byte padding for Thumb is overly conservative. There
|
||||
would be a small gain to keeping accurate track of the padding (which would
|
||||
require aligning functions containing constant pools to 4-byte boundaries).
|
||||
|
||||
3. There might be some compile-time efficiency to be had by representing
|
||||
consecutive islands as a single block rather than multiple blocks.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
We need to start generating predicated instructions. The .td files have a way
|
||||
|
Loading…
x
Reference in New Issue
Block a user