//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// CPE - A constant pool entry that has been placed somewhere, which
/// tracks a list of users.
class VISIBILITY_HIDDEN ARMConstantIslands : public MachineFunctionPass {
- /// NextUID - Assign unique ID's to CPE's.
- unsigned NextUID;
-
/// BBSizes - The size of each MachineBasicBlock in bytes of code, indexed
/// by MBB Number. The two-byte pads required for Thumb alignment are
/// counted as part of the following block (i.e., the offset and size for
: MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
};
- /// Branches - Keep track of all the immediate branch instructions.
+ /// ImmBranches - Keep track of all the immediate branch instructions.
///
std::vector<ImmBranch> ImmBranches;
ARMFunctionInfo *AFI;
bool isThumb;
public:
+ static char ID;
+ ARMConstantIslands() : MachineFunctionPass(&ID) {}
+
virtual bool runOnMachineFunction(MachineFunction &Fn);
virtual const char *getPassName() const {
MachineInstr *CPEMI, unsigned Disp,
bool DoDump);
bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water,
- unsigned Disp);
+ CPUser &U);
bool OffsetIsInRange(unsigned UserOffset, unsigned TrialOffset,
unsigned Disp, bool NegativeOK);
bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
void dumpBBs();
void verify(MachineFunction &Fn);
};
+ char ARMConstantIslands::ID = 0;
}
/// verify - check BBOffsets, BBSizes, alignment of islands
/// print block size and offset information - debugging
void ARMConstantIslands::dumpBBs() {
for (unsigned J = 0, E = BBOffsets.size(); J !=E; ++J) {
- DOUT << "block" << J << " offset" << BBOffsets[J] <<
- " size" << BBSizes[J] << "\n";
+ DOUT << "block " << J << " offset " << BBOffsets[J] <<
+ " size " << BBSizes[J] << "\n";
}
}
}
/// The next UID to take is the first unused one.
- NextUID = CPEMIs.size();
+ AFI->initConstPoolEntryUId(CPEMIs.size());
// Do the initial scan of the function, building up information about the
// sizes of each block, the location of all the water, and finding all of the
void ARMConstantIslands::DoInitialPlacement(MachineFunction &Fn,
std::vector<MachineInstr*> &CPEMIs){
// Create the basic block to hold the CPE's.
- MachineBasicBlock *BB = new MachineBasicBlock();
- Fn.getBasicBlockList().push_back(BB);
+ MachineBasicBlock *BB = Fn.CreateMachineBasicBlock();
+ Fn.push_back(BB);
// Add all of the constants from the constant pool to the end block, use an
// identity mapping of CPI's to CPE's.
const TargetData &TD = *Fn.getTarget().getTargetData();
for (unsigned i = 0, e = CPs.size(); i != e; ++i) {
- unsigned Size = TD.getTypeSize(CPs[i].getType());
+ unsigned Size = TD.getABITypeSize(CPs[i].getType());
// Verify that all constant pool entries are a multiple of 4 bytes. If not,
// we would have to pad them out or something so that instructions stay
// aligned.
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
I != E; ++I) {
// Add instruction size to MBBSize.
- MBBSize += ARM::GetInstSize(I);
+ MBBSize += TII->GetInstSizeInBytes(I);
int Opc = I->getOpcode();
- if (TII->isBranch(Opc)) {
+ if (I->getDesc().isBranch()) {
bool isCond = false;
unsigned Bits = 0;
unsigned Scale = 1;
// Scan the instructions for constant pool operands.
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (I->getOperand(op).isConstantPoolIndex()) {
+ if (I->getOperand(op).isCPI()) {
// We found one. The addressing mode tells us the max displacement
// from the PC that this instruction permits.
// Basic size info comes from the TSFlags field.
unsigned Bits = 0;
unsigned Scale = 1;
- unsigned TSFlags = I->getInstrDescriptor()->TSFlags;
+ unsigned TSFlags = I->getDesc().TSFlags;
switch (TSFlags & ARMII::AddrModeMask) {
default:
// Constant pool entries can reach anything.
}
// Remember that this is a user of a CP entry.
- unsigned CPI = I->getOperand(op).getConstantPoolIndex();
+ unsigned CPI = I->getOperand(op).getIndex();
MachineInstr *CPEMI = CPEMIs[CPI];
unsigned MaxOffs = ((1 << Bits)-1) * Scale;
CPUsers.push_back(CPUser(I, CPEMI, MaxOffs));
for (MachineBasicBlock::iterator I = MBB->begin(); ; ++I) {
assert(I != MBB->end() && "Didn't find MI in its own basic block?");
if (&*I == MI) return Offset;
- Offset += ARM::GetInstSize(I);
+ Offset += TII->GetInstSizeInBytes(I);
}
}
/// account for this change and returns the newly created block.
MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
MachineBasicBlock *OrigBB = MI->getParent();
+ MachineFunction &MF = *OrigBB->getParent();
// Create a new MBB for the code after the OrigBB.
- MachineBasicBlock *NewBB = new MachineBasicBlock(OrigBB->getBasicBlock());
+ MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
MachineFunction::iterator MBBI = OrigBB; ++MBBI;
- OrigBB->getParent()->getBasicBlockList().insert(MBBI, NewBB);
+ MF.insert(MBBI, NewBB);
// Splice the instructions starting with MI over to NewBB.
NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
// Update internal data structures to account for the newly inserted MBB.
// This is almost the same as UpdateForInsertedWaterBlock, except that
// the Water goes after OrigBB, not NewBB.
- NewBB->getParent()->RenumberBlocks(NewBB);
+ MF.RenumberBlocks(NewBB);
// Insert a size into BBSizes to align it properly with the (newly
// renumbered) block numbers.
unsigned NewBBSize = 0;
for (MachineBasicBlock::iterator I = NewBB->begin(), E = NewBB->end();
I != E; ++I)
- NewBBSize += ARM::GetInstSize(I);
+ NewBBSize += TII->GetInstSizeInBytes(I);
unsigned OrigBBI = OrigBB->getNumber();
unsigned NewBBI = NewBB->getNumber();
/// Water (a basic block) will be in range for the specific MI.
bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset,
- MachineBasicBlock* Water, unsigned MaxDisp)
+ MachineBasicBlock* Water, CPUser &U)
{
+ unsigned MaxDisp = U.MaxDisp;
MachineFunction::iterator I = next(MachineFunction::iterator(Water));
unsigned CPEOffset = BBOffsets[Water->getNumber()] +
BBSizes[Water->getNumber()];
// the offset of the instruction. (Currently applies only to ARM, so
// no alignment compensation attempted here.)
if (CPEOffset < UserOffset)
- UserOffset += 4;
+ UserOffset += U.CPEMI->getOperand(2).getImm();
return OffsetIsInRange (UserOffset, CPEOffset, MaxDisp, !isThumb);
}
delta -= 2;
}
}
- // Thumb jump tables require padding. They can be at the end, or
- // followed by an unconditional branch.
+ // Thumb jump tables require padding. They should be at the end;
+ // following unconditional branches are removed by AnalyzeBranch.
MachineInstr *ThumbJTMI = NULL;
if (prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
ThumbJTMI = prior(MBB->end());
- else if (prior(MBB->end()) != MBB->begin() &&
- prior(prior(MBB->end()))->getOpcode() == ARM::tBR_JTr)
- ThumbJTMI = prior(prior(MBB->end()));
if (ThumbJTMI) {
unsigned newMIOffset = GetOffsetOf(ThumbJTMI);
unsigned oldMIOffset = newMIOffset - delta;
}
// No. Look for previously created clones of the CPE that are in range.
- unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
+ unsigned CPI = CPEMI->getOperand(1).getIndex();
std::vector<CPEntry> &CPEs = CPEntries[CPI];
for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {
// We already tried this one
U.CPEMI = CPEs[i].CPEMI;
// Change the CPI in the instruction operand to refer to the clone.
for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j)
- if (UserMI->getOperand(j).isConstantPoolIndex()) {
- UserMI->getOperand(j).setConstantPoolIndex(CPEs[i].CPI);
+ if (UserMI->getOperand(j).isCPI()) {
+ UserMI->getOperand(j).setIndex(CPEs[i].CPI);
break;
}
// Adjust the refcount of the clone...
for (std::vector<MachineBasicBlock*>::iterator IP = prior(WaterList.end()),
B = WaterList.begin();; --IP) {
MachineBasicBlock* WaterBB = *IP;
- if (WaterIsInRange(UserOffset, WaterBB, U.MaxDisp)) {
+ if (WaterIsInRange(UserOffset, WaterBB, U)) {
if (isThumb &&
(BBOffsets[WaterBB->getNumber()] +
BBSizes[WaterBB->getNumber()])%4 != 0) {
MachineBasicBlock::iterator MI = UserMI;
++MI;
unsigned CPUIndex = CPUserIndex+1;
- for (unsigned Offset = UserOffset+ARM::GetInstSize(UserMI);
+ for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI);
Offset < BaseInsertOffset;
- Offset += ARM::GetInstSize(MI),
+ Offset += TII->GetInstSizeInBytes(MI),
MI = next(MI)) {
if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) {
if (!OffsetIsInRange(Offset, EndInsertOffset,
CPUser &U = CPUsers[CPUserIndex];
MachineInstr *UserMI = U.MI;
MachineInstr *CPEMI = U.CPEMI;
- unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
+ unsigned CPI = CPEMI->getOperand(1).getIndex();
unsigned Size = CPEMI->getOperand(2).getImm();
MachineBasicBlock *NewMBB;
// Compute this only once, it's expensive. The 4 or 8 is the value the
// No existing clone of this CPE is within range.
// We will be generating a new clone. Get a UID for it.
- unsigned ID = NextUID++;
+ unsigned ID = AFI->createConstPoolEntryUId();
// Look for water where we can place this CPE. We look for the farthest one
// away that will work. Forward references only for now (although later
}
// Okay, we know we can put an island before NewMBB now, do it!
- MachineBasicBlock *NewIsland = new MachineBasicBlock();
- Fn.getBasicBlockList().insert(NewMBB, NewIsland);
+ MachineBasicBlock *NewIsland = Fn.CreateMachineBasicBlock();
+ Fn.insert(NewMBB, NewIsland);
// Update internal data structures to account for the newly inserted MBB.
UpdateForInsertedWaterBlock(NewIsland);
// Finally, change the CPI in the instruction operand to be ID.
for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i)
- if (UserMI->getOperand(i).isConstantPoolIndex()) {
- UserMI->getOperand(i).setConstantPoolIndex(ID);
+ if (UserMI->getOperand(i).isCPI()) {
+ UserMI->getOperand(i).setIndex(ID);
break;
}
/// away to fit in its displacement field.
bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br) {
MachineInstr *MI = Br.MI;
- MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
+ MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
// Check to see if the DestBB is already in-range.
if (BBIsInRange(MI, DestBB, Br.MaxDisp))
// Use BL to implement far jump.
Br.MaxDisp = (1 << 21) * 2;
- MI->setInstrDescriptor(TII->get(ARM::tBfar));
+ MI->setDesc(TII->get(ARM::tBfar));
BBSizes[MBB->getNumber()] += 2;
AdjustBBOffsetsAfter(MBB, 2);
HasFarJump = true;
bool
ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
MachineInstr *MI = Br.MI;
- MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
+ MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
// Add a unconditional branch to the destination and invert the branch
// condition to jump over it:
// bge L2
// b L1
// L2:
- ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImmedValue();
+ ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImm();
CC = ARMCC::getOppositeCondition(CC);
+ unsigned CCReg = MI->getOperand(2).getReg();
// 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,
NumCBrFixed++;
if (BMI != MI) {
- if (next(MachineBasicBlock::iterator(MI)) == MBB->back() &&
+ if (next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) &&
BMI->getOpcode() == Br.UncondBr) {
// Last MI in the BB is a unconditional branch. Can we simply invert the
// condition and swap destinations:
// =>
// bne L2
// b L1
- MachineBasicBlock *NewDest = BMI->getOperand(0).getMachineBasicBlock();
+ MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB();
if (BBIsInRange(MI, NewDest, Br.MaxDisp)) {
DOUT << " Invert Bcc condition and swap its destination with " << *BMI;
- BMI->getOperand(0).setMachineBasicBlock(DestBB);
- MI->getOperand(0).setMachineBasicBlock(NewDest);
+ BMI->getOperand(0).setMBB(DestBB);
+ MI->getOperand(0).setMBB(NewDest);
MI->getOperand(1).setImm(CC);
return true;
}
SplitBlockBeforeInstr(MI);
// No need for the branch to the next block. We're adding a unconditional
// branch to the destination.
- int delta = ARM::GetInstSize(&MBB->back());
+ int delta = TII->GetInstSizeInBytes(&MBB->back());
BBSizes[MBB->getNumber()] -= delta;
MachineBasicBlock* SplitBB = next(MachineFunction::iterator(MBB));
AdjustBBOffsetsAfter(SplitBB, -delta);
// Insert a new conditional branch and a new unconditional 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(CC);
+ BuildMI(MBB, TII->get(MI->getOpcode())).addMBB(NextBB)
+ .addImm(CC).addReg(CCReg);
Br.MI = &MBB->back();
- BBSizes[MBB->getNumber()] += ARM::GetInstSize(&MBB->back());
+ BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back());
BuildMI(MBB, TII->get(Br.UncondBr)).addMBB(DestBB);
- BBSizes[MBB->getNumber()] += ARM::GetInstSize(&MBB->back());
+ BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back());
unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr);
ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
// Remove the old conditional branch. It may or may not still be in MBB.
- BBSizes[MI->getParent()->getNumber()] -= ARM::GetInstSize(MI);
+ BBSizes[MI->getParent()->getNumber()] -= TII->GetInstSizeInBytes(MI);
MI->eraseFromParent();
// The net size change is an addition of one unconditional branch.
- int delta = ARM::GetInstSize(&MBB->back());
+ int delta = TII->GetInstSizeInBytes(&MBB->back());
AdjustBBOffsetsAfter(MBB, delta);
return true;
}
bool MadeChange = false;
for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
MachineInstr *MI = PushPopMIs[i];
- if (MI->getNumOperands() == 1) {
- if (MI->getOpcode() == ARM::tPOP_RET &&
- MI->getOperand(0).getReg() == ARM::PC)
- BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
- MI->eraseFromParent();
- MadeChange = true;
+ if (MI->getOpcode() == ARM::tPOP_RET &&
+ MI->getOperand(0).getReg() == ARM::PC &&
+ MI->getNumExplicitOperands() == 1) {
+ BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
+ MI->eraseFromParent();
+ MadeChange = true;
}
}
return MadeChange;