Account for CPE alignment when searching for new water.

Constant pool entries with different alignment may cause more alignment
padding to be inserted. Compute the amount of padding needed, and try to
pick the location that requires the least amount of padding.

Also take the extra padding into account when the water is above the
use.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146458 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-12-13 00:44:30 +00:00
parent e97b4990e1
commit 2e29024d2e

View File

@ -293,7 +293,7 @@ namespace {
MachineInstr *CPEMI, unsigned Disp, bool NegOk, MachineInstr *CPEMI, unsigned Disp, bool NegOk,
bool DoDump = false); bool DoDump = false);
bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water, bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water,
CPUser &U); CPUser &U, unsigned &Growth);
bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
bool FixUpImmediateBr(ImmBranch &Br); bool FixUpImmediateBr(ImmBranch &Br);
bool FixUpConditionalBr(ImmBranch &Br); bool FixUpConditionalBr(ImmBranch &Br);
@ -967,15 +967,42 @@ bool ARMConstantIslands::OffsetIsInRange(unsigned UserOffset,
/// WaterIsInRange - Returns true if a CPE placed after the specified /// WaterIsInRange - Returns true if a CPE placed after the specified
/// Water (a basic block) will be in range for the specific MI. /// Water (a basic block) will be in range for the specific MI.
///
/// Compute how much the function will grow by inserting a CPE after Water.
bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset, bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset,
MachineBasicBlock* Water, CPUser &U) { MachineBasicBlock* Water, CPUser &U,
unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(); unsigned &Growth) {
unsigned CPELogAlign = getCPELogAlign(U.CPEMI);
unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPELogAlign);
unsigned NextBlockOffset, NextBlockAlignment;
MachineFunction::const_iterator NextBlock = Water;
if (++NextBlock == MF->end()) {
NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
NextBlockAlignment = 0;
} else {
NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
NextBlockAlignment = NextBlock->getAlignment();
}
unsigned Size = U.CPEMI->getOperand(2).getImm();
unsigned CPEEnd = CPEOffset + Size;
// If the CPE is to be inserted before the instruction, that will raise // The CPE may be able to hide in the alignment padding before the next
// the offset of the instruction. // block. It may also cause more padding to be required if it is more aligned
if (CPEOffset < UserOffset) // that the next block.
UserOffset += U.CPEMI->getOperand(2).getImm(); if (CPEEnd > NextBlockOffset) {
Growth = CPEEnd - NextBlockOffset;
// Compute the padding that would go at the end of the CPE to align the next
// block.
Growth += OffsetToAlignment(CPEEnd, 1u << NextBlockAlignment);
// If the CPE is to be inserted before the instruction, that will raise
// the offset of the instruction. Also account for unknown alignment padding
// in blocks between CPE and the user.
if (CPEOffset < UserOffset)
UserOffset += Growth + UnknownPadding(MF->getAlignment(), CPELogAlign);
} else
// CPE fits in existing padding.
Growth = 0;
return OffsetIsInRange(UserOffset, CPEOffset, U); return OffsetIsInRange(UserOffset, CPEOffset, U);
} }
@ -1130,10 +1157,9 @@ bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset,
if (WaterList.empty()) if (WaterList.empty())
return false; return false;
bool FoundWaterThatWouldPad = false; unsigned BestGrowth = ~0u;
water_iterator IPThatWouldPad; for (water_iterator IP = prior(WaterList.end()), B = WaterList.begin();;
for (water_iterator IP = prior(WaterList.end()), --IP) {
B = WaterList.begin();; --IP) {
MachineBasicBlock* WaterBB = *IP; MachineBasicBlock* WaterBB = *IP;
// Check if water is in range and is either at a lower address than the // Check if water is in range and is either at a lower address than the
// current "high water mark" or a new water block that was created since // current "high water mark" or a new water block that was created since
@ -1143,30 +1169,24 @@ bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset,
// should be relatively uncommon and when it does happen, we want to be // should be relatively uncommon and when it does happen, we want to be
// sure to take advantage of it for all the CPEs near that block, so that // sure to take advantage of it for all the CPEs near that block, so that
// we don't insert more branches than necessary. // we don't insert more branches than necessary.
if (WaterIsInRange(UserOffset, WaterBB, U) && unsigned Growth;
if (WaterIsInRange(UserOffset, WaterBB, U, Growth) &&
(WaterBB->getNumber() < U.HighWaterMark->getNumber() || (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
NewWaterList.count(WaterBB))) { NewWaterList.count(WaterBB)) && Growth < BestGrowth) {
unsigned WBBId = WaterBB->getNumber(); // This is the least amount of required padding seen so far.
if (isThumb && BBInfo[WBBId].postOffset()%4 != 0) { BestGrowth = Growth;
// This is valid Water, but would introduce padding. Remember WaterIter = IP;
// it in case we don't find any Water that doesn't do this. DEBUG(dbgs() << "Found water after BB#" << WaterBB->getNumber()
if (!FoundWaterThatWouldPad) { << " Growth=" << Growth << '\n');
FoundWaterThatWouldPad = true;
IPThatWouldPad = IP; // Keep looking unless it is perfect.
} if (BestGrowth == 0)
} else {
WaterIter = IP;
return true; return true;
}
} }
if (IP == B) if (IP == B)
break; break;
} }
if (FoundWaterThatWouldPad) { return BestGrowth != ~0u;
WaterIter = IPThatWouldPad;
return true;
}
return false;
} }
/// CreateNewWater - No existing WaterList entry will work for /// CreateNewWater - No existing WaterList entry will work for