When determining whether a pc relative branch / load displacement fits in the

instruction field, adjust it for PC value (4 for thumb, 8 for arm).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33711 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2007-01-31 19:57:44 +00:00
parent 4c3d3a99d5
commit c0dbec7e10

View File

@@ -115,7 +115,8 @@ namespace {
MachineBasicBlock *SplitBlockBeforeInstr(MachineInstr *MI); MachineBasicBlock *SplitBlockBeforeInstr(MachineInstr *MI);
void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB); void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB);
bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U); bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
bool BBIsInBranchRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned D); bool CPEIsInRange(MachineInstr *MI, MachineInstr *CPEMI, unsigned Disp);
bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
bool FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br); bool FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br);
bool FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br); bool FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br);
bool FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br); bool FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br);
@@ -458,33 +459,41 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
return NewBB; return NewBB;
} }
/// CPEIsInRange - Returns true is the distance between specific MI and
/// specific ConstPool entry instruction can fit in MI's displacement field.
bool ARMConstantIslands::CPEIsInRange(MachineInstr *MI, MachineInstr *CPEMI,
unsigned MaxDisp) {
unsigned PCAdj = AFI->isThumbFunction() ? 4 : 8;
unsigned UserOffset = GetOffsetOf(MI) + PCAdj;
unsigned CPEOffset = GetOffsetOf(CPEMI);
DEBUG(std::cerr << "User of CPE#" << CPEMI->getOperand(0).getImm()
<< " max delta=" << MaxDisp
<< " at offset " << int(UserOffset-CPEOffset) << "\t"
<< *MI);
if (UserOffset < CPEOffset) {
// User before the CPE.
if (CPEOffset-UserOffset <= MaxDisp)
return true;
} else if (!AFI->isThumbFunction()) {
// Thumb LDR cannot encode negative offset.
if (UserOffset-CPEOffset <= MaxDisp)
return true;
}
return false;
}
/// HandleConstantPoolUser - Analyze the specified user, checking to see if it /// 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 /// is out-of-range. If so, pick it up the constant pool value and move it some
/// place in-range. /// place in-range.
bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
bool isThumb = AFI->isThumbFunction();
MachineInstr *UserMI = U.MI; MachineInstr *UserMI = U.MI;
MachineInstr *CPEMI = U.CPEMI; MachineInstr *CPEMI = U.CPEMI;
unsigned UserOffset = GetOffsetOf(UserMI);
unsigned CPEOffset = GetOffsetOf(CPEMI);
DEBUG(std::cerr << "User of CPE#" << CPEMI->getOperand(0).getImm()
<< " max delta=" << U.MaxDisp
<< " at offset " << int(UserOffset-CPEOffset) << "\t"
<< *UserMI);
// Check to see if the CPE is already in-range. // Check to see if the CPE is already in-range.
if (UserOffset < CPEOffset) { if (CPEIsInRange(UserMI, CPEMI, U.MaxDisp))
// User before the CPE. return false;
if (CPEOffset-UserOffset <= U.MaxDisp)
return false;
} else if (!isThumb) {
// Thumb LDR cannot encode negative offset.
if (UserOffset-CPEOffset <= U.MaxDisp)
return false;
}
// Solution guaranteed to work: split the user's MBB right after the user and // Solution guaranteed to work: split the user's MBB right after the user and
// insert a clone the CPE into the newly created water. // insert a clone the CPE into the newly created water.
@@ -500,6 +509,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
NewMBB = next(MachineFunction::iterator(UserMBB)); NewMBB = next(MachineFunction::iterator(UserMBB));
// Add an unconditional branch from UserMBB to fallthrough block. // Add an unconditional branch from UserMBB to fallthrough block.
// Note the new unconditional branch is not being recorded. // Note the new unconditional branch is not being recorded.
bool isThumb = AFI->isThumbFunction();
BuildMI(UserMBB, TII->get(isThumb ? ARM::tB : ARM::B)).addMBB(NewMBB); BuildMI(UserMBB, TII->get(isThumb ? ARM::tB : ARM::B)).addMBB(NewMBB);
BBSizes[UserMBB->getNumber()] += isThumb ? 2 : 4; BBSizes[UserMBB->getNumber()] += isThumb ? 2 : 4;
} else { } else {
@@ -540,15 +550,19 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
return true; return true;
} }
/// BBIsInBranchRange - Returns true is the distance between specific MI and /// BBIsInRange - Returns true is the distance between specific MI and
/// specific BB can fit in MI's displacement field. /// specific BB can fit in MI's displacement field.
bool ARMConstantIslands::BBIsInBranchRange(MachineInstr *MI, bool ARMConstantIslands::BBIsInRange(MachineInstr *MI,MachineBasicBlock *DestBB,
MachineBasicBlock *DestBB, unsigned MaxDisp) {
unsigned MaxDisp) { unsigned PCAdj = AFI->isThumbFunction() ? 4 : 8;
unsigned BrOffset = GetOffsetOf(MI); unsigned BrOffset = GetOffsetOf(MI) + PCAdj;
unsigned DestOffset = GetOffsetOf(DestBB); unsigned DestOffset = GetOffsetOf(DestBB);
// Check to see if the destination BB is in range. DEBUG(std::cerr << "Branch of destination BB#" << DestBB->getNumber()
<< " max delta=" << MaxDisp
<< " at offset " << int(BrOffset-DestOffset) << "\t"
<< *MI);
if (BrOffset < DestOffset) { if (BrOffset < DestOffset) {
if (DestOffset - BrOffset < MaxDisp) if (DestOffset - BrOffset < MaxDisp)
return true; return true;
@@ -565,7 +579,8 @@ bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br) {
MachineInstr *MI = Br.MI; MachineInstr *MI = Br.MI;
MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock(); MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
if (BBIsInBranchRange(MI, DestBB, Br.MaxDisp)) // Check to see if the DestBB is already in-range.
if (BBIsInRange(MI, DestBB, Br.MaxDisp))
return false; return false;
if (!Br.isCond) if (!Br.isCond)
@@ -635,7 +650,7 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
// bne L2 // bne L2
// b L1 // b L1
MachineBasicBlock *NewDest = BackMI->getOperand(0).getMachineBasicBlock(); MachineBasicBlock *NewDest = BackMI->getOperand(0).getMachineBasicBlock();
if (BBIsInBranchRange(MI, NewDest, Br.MaxDisp)) { if (BBIsInRange(MI, NewDest, Br.MaxDisp)) {
BackMI->getOperand(0).setMachineBasicBlock(DestBB); BackMI->getOperand(0).setMachineBasicBlock(DestBB);
MI->getOperand(0).setMachineBasicBlock(NewDest); MI->getOperand(0).setMachineBasicBlock(NewDest);
MI->getOperand(1).setImm(CC); MI->getOperand(1).setImm(CC);