Added (preliminary) branch shortening capability to constantpool island pass.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33497 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2007-01-25 03:12:46 +00:00
parent 6318ffd736
commit af5cbcb809

View File

@ -15,6 +15,7 @@
#define DEBUG_TYPE "arm-cp-islands" #define DEBUG_TYPE "arm-cp-islands"
#include "ARM.h" #include "ARM.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMInstrInfo.h" #include "ARMInstrInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
@ -72,13 +73,30 @@ namespace {
/// constant pools and their max displacement. /// constant pools and their max displacement.
std::vector<CPUser> CPUsers; std::vector<CPUser> CPUsers;
/// ImmBranch - One per immediate branch, keeping the machine instruction
/// pointer, conditional or unconditional, the max displacement,
/// and (if isCond is true) the corresponding unconditional branch
/// opcode.
struct ImmBranch {
MachineInstr *MI;
bool isCond;
int UncondBr;
unsigned MaxDisp;
ImmBranch(MachineInstr *mi, bool cond, int ubr, unsigned maxdisp)
: MI(mi), isCond(cond), UncondBr(ubr), MaxDisp(maxdisp) {}
};
/// Branches - Keep track of all the immediate branche instructions.
///
std::vector<ImmBranch> ImmBranches;
const TargetInstrInfo *TII; const TargetInstrInfo *TII;
const TargetAsmInfo *TAI; const TargetAsmInfo *TAI;
public: public:
virtual bool runOnMachineFunction(MachineFunction &Fn); virtual bool runOnMachineFunction(MachineFunction &Fn);
virtual const char *getPassName() const { virtual const char *getPassName() const {
return "ARM constant island placement pass"; return "ARM constant island placement and branch shortening pass";
} }
private: private:
@ -87,16 +105,18 @@ namespace {
void InitialFunctionScan(MachineFunction &Fn, void InitialFunctionScan(MachineFunction &Fn,
const std::vector<MachineInstr*> &CPEMIs); const std::vector<MachineInstr*> &CPEMIs);
void SplitBlockBeforeInstr(MachineInstr *MI); void SplitBlockBeforeInstr(MachineInstr *MI);
bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB); void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB);
bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
bool ShortenImmediateBranch(MachineFunction &Fn, ImmBranch &Br);
unsigned GetInstSize(MachineInstr *MI) const; unsigned GetInstSize(MachineInstr *MI) const;
unsigned GetOffsetOf(MachineInstr *MI) const; unsigned GetOffsetOf(MachineInstr *MI) const;
unsigned GetOffsetOf(MachineBasicBlock *MBB) const;
}; };
} }
/// createARMLoadStoreOptimizationPass - returns an instance of the load / store /// createARMConstantIslandPass - returns an instance of the constpool
/// optimization pass. /// island pass.
FunctionPass *llvm::createARMConstantIslandPass() { FunctionPass *llvm::createARMConstantIslandPass() {
return new ARMConstantIslands(); return new ARMConstantIslands();
} }
@ -133,11 +153,14 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &Fn) {
MadeChange = false; MadeChange = false;
for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
MadeChange |= HandleConstantPoolUser(Fn, CPUsers[i]); MadeChange |= HandleConstantPoolUser(Fn, CPUsers[i]);
for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
MadeChange |= ShortenImmediateBranch(Fn, ImmBranches[i]);
} while (MadeChange); } while (MadeChange);
BBSizes.clear(); BBSizes.clear();
WaterList.clear(); WaterList.clear();
CPUsers.clear(); CPUsers.clear();
ImmBranches.clear();
return true; return true;
} }
@ -208,6 +231,37 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
// Add instruction size to MBBSize. // Add instruction size to MBBSize.
MBBSize += GetInstSize(I); MBBSize += GetInstSize(I);
int Opc = I->getOpcode();
if (TII->isBranch(Opc)) {
bool isCond = false;
unsigned Bits = 0;
unsigned Scale = 1;
int UOpc = Opc;
switch (Opc) {
default: break; // Ignore JT branches
case ARM::Bcc:
isCond = true;
UOpc = ARM::B;
// Fallthrough
case ARM::B:
Bits = 24;
Scale = 4;
break;
case ARM::tBcc:
isCond = true;
UOpc = ARM::tB;
Bits = 8;
Scale = 2;
break;
case ARM::tB:
Bits = 11;
Scale = 2;
break;
}
unsigned MaxDisp = (1 << (Bits-1)) * Scale;
ImmBranches.push_back(ImmBranch(I, isCond, UOpc, MaxDisp));
}
// Scan the instructions for constant pool operands. // Scan the instructions for constant pool operands.
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
if (I->getOperand(op).isConstantPoolIndex()) { if (I->getOperand(op).isConstantPoolIndex()) {
@ -336,6 +390,18 @@ unsigned ARMConstantIslands::GetOffsetOf(MachineInstr *MI) const {
} }
} }
/// GetOffsetOf - Return the current offset of the specified machine BB
/// from the start of the function. This offset changes as stuff is moved
/// around inside the function.
unsigned ARMConstantIslands::GetOffsetOf(MachineBasicBlock *MBB) const {
// Sum block sizes before MBB.
unsigned Offset = 0;
for (unsigned BB = 0, e = MBB->getNumber(); BB != e; ++BB)
Offset += BBSizes[BB];
return Offset;
}
/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB /// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB
/// ID. /// ID.
static bool CompareMBBNumbers(const MachineBasicBlock *LHS, static bool CompareMBBNumbers(const MachineBasicBlock *LHS,
@ -368,6 +434,8 @@ void ARMConstantIslands::UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
/// account for this change. /// account for this change.
void ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) { void ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
MachineBasicBlock *OrigBB = MI->getParent(); MachineBasicBlock *OrigBB = MI->getParent();
const ARMFunctionInfo *AFI = OrigBB->getParent()->getInfo<ARMFunctionInfo>();
bool isThumb = AFI->isThumbFunction();
// Create a new MBB for the code after the OrigBB. // Create a new MBB for the code after the OrigBB.
MachineBasicBlock *NewBB = new MachineBasicBlock(OrigBB->getBasicBlock()); MachineBasicBlock *NewBB = new MachineBasicBlock(OrigBB->getBasicBlock());
@ -378,7 +446,7 @@ void ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
// Add an unconditional branch from OrigBB to NewBB. // Add an unconditional branch from OrigBB to NewBB.
BuildMI(OrigBB, TII->get(ARM::B)).addMBB(NewBB); BuildMI(OrigBB, TII->get(isThumb ? ARM::tB : ARM::B)).addMBB(NewBB);
NumSplit++; NumSplit++;
// Update the CFG. All succs of OrigBB are now succs of NewBB. // Update the CFG. All succs of OrigBB are now succs of NewBB.
@ -409,8 +477,8 @@ void ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
BBSizes[NewBB->getNumber()] = NewBBSize; BBSizes[NewBB->getNumber()] = NewBBSize;
// We removed instructions from UserMBB, subtract that off from its size. // We removed instructions from UserMBB, subtract that off from its size.
// Add 4 to the block to count the unconditional branch we added to it. // Add 2 or 4 to the block to count the unconditional branch we added to it.
BBSizes[OrigBB->getNumber()] -= NewBBSize-4; BBSizes[OrigBB->getNumber()] -= NewBBSize - (isThumb ? 2 : 4);
} }
/// HandleConstantPoolUser - Analyze the specified user, checking to see if it /// HandleConstantPoolUser - Analyze the specified user, checking to see if it
@ -491,3 +559,58 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
return true; return true;
} }
bool
ARMConstantIslands::ShortenImmediateBranch(MachineFunction &Fn, ImmBranch &Br) {
MachineInstr *MI = Br.MI;
MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
unsigned BrOffset = GetOffsetOf(MI);
unsigned DestOffset = GetOffsetOf(DestBB);
// Check to see if the destination BB is in range.
if (BrOffset < DestOffset) {
if (DestOffset - BrOffset < Br.MaxDisp)
return false;
} else {
if (BrOffset - DestOffset <= Br.MaxDisp)
return false;
}
if (!Br.isCond) {
// Unconditional branch. We have to insert a branch somewhere to perform
// a two level branch (branch to branch). FIXME: not yet implemented.
assert(false && "Can't handle unconditional branch yet!");
return false;
}
// Otherwise, add a unconditional branch to the destination and
// invert the branch condition to jump over it:
// blt L1
// =>
// bge L2
// b L1
// L2:
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImmedValue();
CC = ARMCC::getOppositeCondition(CC);
// If the branch is at the end of its MBB and that has a fall-through block,
// direct the updated conditional branch to the fall-through block. Otherwise,
// split the MBB before the next instruction.
MachineBasicBlock *MBB = MI->getParent();
if (&MBB->back() != MI || !BBHasFallthrough(MBB))
SplitBlockBeforeInstr(MI);
MachineBasicBlock *NextBB = next(MachineFunction::iterator(MBB));
// Insert a unconditional branch and replace the conditional branch.
// Also update the ImmBranch as well as adding a new entry for the new branch.
BuildMI(MBB, TII->get(MI->getOpcode())).addMBB(NextBB).addImm((unsigned)CC);
Br.MI = &MBB->back();
BuildMI(MBB, TII->get(Br.UncondBr)).addMBB(DestBB);
unsigned MaxDisp = (Br.UncondBr == ARM::tB) ? (1<<10)*2 : (1<<23)*4;
ImmBranches.push_back(ImmBranch(&MBB->back(), false, Br.UncondBr, MaxDisp));
MI->eraseFromParent();
// Increase the size of MBB to account for the new unconditional branch.
BBSizes[MBB->getNumber()] += GetInstSize(&MBB->back());
return true;
}