OutStreamer->EmitValue(Expr, Size);
}
-void ARMAsmPrinter::EmitJumpTableAddrs(const MachineInstr *MI) {
- const MachineOperand &MO1 = MI->getOperand(1);
+void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
+ unsigned Opcode = MI->getOpcode();
+ int OpNum = 1;
+ if (Opcode == ARM::BR_JTadd)
+ OpNum = 2;
+ else if (Opcode == ARM::BR_JTm)
+ OpNum = 3;
+
+ const MachineOperand &MO1 = MI->getOperand(OpNum);
unsigned JTI = MO1.getIndex();
- // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
- // ARM mode tables.
- EmitAlignment(2);
-
// Emit a label for the jump table.
MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
OutStreamer->EmitLabel(JTISymbol);
OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
}
-void ARMAsmPrinter::EmitJumpTableInsts(const MachineInstr *MI) {
- const MachineOperand &MO1 = MI->getOperand(1);
+void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
+ unsigned Opcode = MI->getOpcode();
+ int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
+ const MachineOperand &MO1 = MI->getOperand(OpNum);
unsigned JTI = MO1.getIndex();
MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+ unsigned OffsetWidth = 4;
+ if (MI->getOpcode() == ARM::t2TBB_JT) {
+ OffsetWidth = 1;
+ // Mark the jump table as data-in-code.
+ OutStreamer->EmitDataRegion(MCDR_DataRegionJT8);
+ } else if (MI->getOpcode() == ARM::t2TBH_JT) {
+ OffsetWidth = 2;
+ // Mark the jump table as data-in-code.
+ OutStreamer->EmitDataRegion(MCDR_DataRegionJT16);
+ }
for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
MachineBasicBlock *MBB = JTBBs[i];
const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
OutContext);
// If this isn't a TBB or TBH, the entries are direct branch instructions.
- EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B)
+ if (OffsetWidth == 4) {
+ EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B)
.addExpr(MBBSymbolExpr)
.addImm(ARMCC::AL)
.addReg(0));
- }
-}
-
-void ARMAsmPrinter::EmitJumpTableTBInst(const MachineInstr *MI,
- unsigned OffsetWidth) {
- assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
- const MachineOperand &MO1 = MI->getOperand(1);
- unsigned JTI = MO1.getIndex();
-
- MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
- OutStreamer->EmitLabel(JTISymbol);
-
- // Emit each entry of the table.
- const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
- const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
- const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
-
- // Mark the jump table as data-in-code.
- OutStreamer->EmitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8
- : MCDR_DataRegionJT16);
-
- for (auto MBB : JTBBs) {
- const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
- OutContext);
+ continue;
+ }
// Otherwise it's an offset from the dispatch instruction. Construct an
// MCExpr for the entry. We want a value of the form:
- // (BasicBlockAddr - TBBInstAddr + 4) / 2
+ // (BasicBlockAddr - TableBeginAddr) / 2
//
// For example, a TBB table with entries jumping to basic blocks BB0 and BB1
// would look like:
// LJTI_0_0:
- // .byte (LBB0 - (LCPI0_0 + 4)) / 2
- // .byte (LBB1 - (LCPI0_0 + 4)) / 2
- // where LCPI0_0 is a label defined just before the TBB instruction using
- // this table.
- MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());
- const MCExpr *Expr = MCBinaryExpr::CreateAdd(
- MCSymbolRefExpr::Create(TBInstPC, OutContext),
- MCConstantExpr::Create(4, OutContext), OutContext);
- Expr = MCBinaryExpr::CreateSub(MBBSymbolExpr, Expr, OutContext);
+ // .byte (LBB0 - LJTI_0_0) / 2
+ // .byte (LBB1 - LJTI_0_0) / 2
+ const MCExpr *Expr =
+ MCBinaryExpr::CreateSub(MBBSymbolExpr,
+ MCSymbolRefExpr::Create(JTISymbol, OutContext),
+ OutContext);
Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
OutContext);
OutStreamer->EmitValue(Expr, OffsetWidth);
// Mark the end of jump table data-in-code region. 32-bit offsets use
// actual branch instructions here, so we don't mark those as a data-region
// at all.
- OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
-
- // Make sure the next instruction is 2-byte aligned.
- EmitAlignment(1);
+ if (OffsetWidth != 4)
+ OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
}
void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
EmitGlobalConstant(MCPE.Val.ConstVal);
return;
}
- case ARM::JUMPTABLE_ADDRS:
- EmitJumpTableAddrs(MI);
- return;
- case ARM::JUMPTABLE_INSTS:
- EmitJumpTableInsts(MI);
- return;
- case ARM::JUMPTABLE_TBB:
- case ARM::JUMPTABLE_TBH:
- EmitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
- return;
case ARM::t2BR_JT: {
// Lower and emit the instruction itself, then the jump table following it.
EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
// Add predicate operands.
.addImm(ARMCC::AL)
.addReg(0));
+
+ // Output the data for the jump table itself
+ EmitJump2Table(MI);
+ return;
+ }
+ case ARM::t2TBB_JT: {
+ // Lower and emit the instruction itself, then the jump table following it.
+ EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2TBB)
+ .addReg(ARM::PC)
+ .addReg(MI->getOperand(0).getReg())
+ // Add predicate operands.
+ .addImm(ARMCC::AL)
+ .addReg(0));
+
+ // Output the data for the jump table itself
+ EmitJump2Table(MI);
+ // Make sure the next instruction is 2-byte aligned.
+ EmitAlignment(1);
return;
}
- case ARM::t2TBB_JT:
case ARM::t2TBH_JT: {
- unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
- // Lower and emit the PC label, then the instruction itself.
- OutStreamer->EmitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
- EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)
- .addReg(MI->getOperand(0).getReg())
- .addReg(MI->getOperand(1).getReg())
- // Add predicate operands.
- .addImm(ARMCC::AL)
- .addReg(0));
+ // Lower and emit the instruction itself, then the jump table following it.
+ EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2TBH)
+ .addReg(ARM::PC)
+ .addReg(MI->getOperand(0).getReg())
+ // Add predicate operands.
+ .addImm(ARMCC::AL)
+ .addReg(0));
+
+ // Output the data for the jump table itself
+ EmitJump2Table(MI);
return;
}
case ARM::tBR_JTr:
if (Opc == ARM::MOVr)
TmpInst.addOperand(MCOperand::createReg(0));
EmitToStreamer(*OutStreamer, TmpInst);
+
+ // Make sure the Thumb jump table is 4-byte aligned.
+ if (Opc == ARM::tMOVr)
+ EmitAlignment(2);
+
+ // Output the data for the jump table itself
+ EmitJumpTable(MI);
return;
}
case ARM::BR_JTm: {
TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
TmpInst.addOperand(MCOperand::createReg(0));
EmitToStreamer(*OutStreamer, TmpInst);
+
+ // Output the data for the jump table itself
+ EmitJumpTable(MI);
return;
}
case ARM::BR_JTadd: {
.addReg(0)
// Add 's' bit operand (always reg0 for this)
.addReg(0));
+
+ // Output the data for the jump table itself
+ EmitJumpTable(MI);
return;
}
case ARM::SPACE:
MachineInstr *MI;
MachineInstr *CPEMI;
MachineBasicBlock *HighWaterMark;
+ private:
unsigned MaxDisp;
+ public:
bool NegOk;
bool IsSoImm;
bool KnownAlignment;
};
/// CPEntries - Keep track of all of the constant pool entry machine
- /// instructions. For each original constpool index (i.e. those that existed
- /// upon entry to this pass), it keeps a vector of entries. Original
- /// elements are cloned as we go along; the clones are put in the vector of
- /// the original element, but have distinct CPIs.
- ///
- /// The first half of CPEntries contains generic constants, the second half
- /// contains jump tables. Use getCombinedIndex on a generic CPEMI to look up
- /// which vector it will be in here.
+ /// instructions. For each original constpool index (i.e. those that
+ /// existed upon entry to this pass), it keeps a vector of entries.
+ /// Original elements are cloned as we go along; the clones are
+ /// put in the vector of the original element, but have distinct CPIs.
std::vector<std::vector<CPEntry> > CPEntries;
- /// Maps a JT index to the offset in CPEntries containing copies of that
- /// table. The equivalent map for a CONSTPOOL_ENTRY is the identity.
- DenseMap<int, int> JumpTableEntryIndices;
-
- /// Maps a JT index to the LEA that actually uses the index to calculate its
- /// base address.
- DenseMap<int, int> JumpTableUserIndices;
-
/// 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
}
private:
- void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
- void doInitialJumpTablePlacement(std::vector<MachineInstr *> &CPEMIs);
+ void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
bool BBHasFallthrough(MachineBasicBlock *MBB);
CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
unsigned getCPELogAlign(const MachineInstr *CPEMI);
void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
void adjustBBOffsetsAfter(MachineBasicBlock *BB);
bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
- unsigned getCombinedIndex(const MachineInstr *CPEMI);
int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
bool findAvailableWater(CPUser&U, unsigned UserOffset,
water_iterator &WaterIter);
// we put them all at the end of the function.
std::vector<MachineInstr*> CPEMIs;
if (!MCP->isEmpty())
- doInitialConstPlacement(CPEMIs);
-
- if (MF->getJumpTableInfo())
- doInitialJumpTablePlacement(CPEMIs);
+ doInitialPlacement(CPEMIs);
/// The next UID to take is the first unused one.
AFI->initPICLabelUId(CPEMIs.size());
for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) {
for (unsigned j = 0, je = CPEntries[i].size(); j != je; ++j) {
const CPEntry & CPE = CPEntries[i][j];
- if (CPE.CPEMI && CPE.CPEMI->getOperand(1).isCPI())
- AFI->recordCPEClone(i, CPE.CPI);
+ AFI->recordCPEClone(i, CPE.CPI);
}
}
WaterList.clear();
CPUsers.clear();
CPEntries.clear();
- JumpTableEntryIndices.clear();
- JumpTableUserIndices.clear();
ImmBranches.clear();
PushPopMIs.clear();
T2JumpTables.clear();
return MadeChange;
}
-/// \brief Perform the initial placement of the regular constant pool entries.
-/// To start with, we put them all at the end of the function.
+/// doInitialPlacement - Perform the initial placement of the constant pool
+/// entries. To start with, we put them all at the end of the function.
void
-ARMConstantIslands::doInitialConstPlacement(std::vector<MachineInstr*> &CPEMIs) {
+ARMConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) {
// Create the basic block to hold the CPE's.
MachineBasicBlock *BB = MF->CreateMachineBasicBlock();
MF->push_back(BB);
DEBUG(BB->dump());
}
-/// \brief Do initial placement of the jump tables. Because Thumb2's TBB and TBH
-/// instructions can be made more efficient if the jump table immediately
-/// follows the instruction, it's best to place them immediately next to their
-/// jumps to begin with. In almost all cases they'll never be moved from that
-/// position.
-void ARMConstantIslands::doInitialJumpTablePlacement(
- std::vector<MachineInstr *> &CPEMIs) {
- unsigned i = CPEntries.size();
- auto MJTI = MF->getJumpTableInfo();
- const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
-
- MachineBasicBlock *LastCorrectlyNumberedBB = nullptr;
- for (MachineBasicBlock &MBB : *MF) {
- auto MI = MBB.getLastNonDebugInstr();
-
- unsigned JTOpcode;
- switch (MI->getOpcode()) {
- default:
- continue;
- case ARM::BR_JTadd:
- case ARM::BR_JTr:
- case ARM::tBR_JTr:
- case ARM::BR_JTm:
- JTOpcode = ARM::JUMPTABLE_ADDRS;
- break;
- case ARM::t2BR_JT:
- JTOpcode = ARM::JUMPTABLE_INSTS;
- break;
- case ARM::t2TBB_JT:
- JTOpcode = ARM::JUMPTABLE_TBB;
- break;
- case ARM::t2TBH_JT:
- JTOpcode = ARM::JUMPTABLE_TBH;
- break;
- }
-
- unsigned NumOps = MI->getDesc().getNumOperands();
- MachineOperand JTOp =
- MI->getOperand(NumOps - (MI->isPredicable() ? 2 : 1));
- unsigned JTI = JTOp.getIndex();
- unsigned Size = JT[JTI].MBBs.size() * sizeof(uint32_t);
- MachineBasicBlock *JumpTableBB = MF->CreateMachineBasicBlock();
- MF->insert(std::next(MachineFunction::iterator(MBB)), JumpTableBB);
- MachineInstr *CPEMI = BuildMI(*JumpTableBB, JumpTableBB->begin(),
- DebugLoc(), TII->get(JTOpcode))
- .addImm(i++)
- .addJumpTableIndex(JTI)
- .addImm(Size);
- CPEMIs.push_back(CPEMI);
- CPEntries.emplace_back(1, CPEntry(CPEMI, JTI));
- JumpTableEntryIndices.insert(std::make_pair(JTI, CPEntries.size() - 1));
- if (!LastCorrectlyNumberedBB)
- LastCorrectlyNumberedBB = &MBB;
- }
-
- // If we did anything then we need to renumber the subsequent blocks.
- if (LastCorrectlyNumberedBB)
- MF->RenumberBlocks(LastCorrectlyNumberedBB);
-}
-
/// BBHasFallthrough - Return true if the specified basic block can fallthrough
/// into the block immediately after it.
bool ARMConstantIslands::BBHasFallthrough(MachineBasicBlock *MBB) {
/// getCPELogAlign - Returns the required alignment of the constant pool entry
/// represented by CPEMI. Alignment is measured in log2(bytes) units.
unsigned ARMConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) {
- switch (CPEMI->getOpcode()) {
- case ARM::CONSTPOOL_ENTRY:
- break;
- case ARM::JUMPTABLE_TBB:
- return 0;
- case ARM::JUMPTABLE_TBH:
- case ARM::JUMPTABLE_INSTS:
- return 1;
- case ARM::JUMPTABLE_ADDRS:
- return 2;
- default:
- llvm_unreachable("unknown constpool entry kind");
- }
+ assert(CPEMI && CPEMI->getOpcode() == ARM::CONSTPOOL_ENTRY);
- unsigned CPI = getCombinedIndex(CPEMI);
+ unsigned CPI = CPEMI->getOperand(1).getIndex();
assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
unsigned Align = MCP->getConstants()[CPI].getAlignment();
assert(isPowerOf2_32(Align) && "Invalid CPE alignment");
if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET)
PushPopMIs.push_back(I);
- if (Opc == ARM::CONSTPOOL_ENTRY || Opc == ARM::JUMPTABLE_ADDRS ||
- Opc == ARM::JUMPTABLE_INSTS || Opc == ARM::JUMPTABLE_TBB ||
- Opc == ARM::JUMPTABLE_TBH)
+ if (Opc == ARM::CONSTPOOL_ENTRY)
continue;
// Scan the instructions for constant pool operands.
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (I->getOperand(op).isCPI() || I->getOperand(op).isJTI()) {
+ if (I->getOperand(op).isCPI()) {
// We found one. The addressing mode tells us the max displacement
// from the PC that this instruction permits.
// Taking the address of a CP entry.
case ARM::LEApcrel:
- case ARM::LEApcrelJT:
// This takes a SoImm, which is 8 bit immediate rotated. We'll
// pretend the maximum offset is 255 * 4. Since each instruction
// 4 byte wide, this is always correct. We'll check for other
IsSoImm = true;
break;
case ARM::t2LEApcrel:
- case ARM::t2LEApcrelJT:
Bits = 12;
NegOk = true;
break;
case ARM::tLEApcrel:
- case ARM::tLEApcrelJT:
Bits = 8;
Scale = 4;
break;
// Remember that this is a user of a CP entry.
unsigned CPI = I->getOperand(op).getIndex();
- if (I->getOperand(op).isJTI()) {
- JumpTableUserIndices.insert(std::make_pair(CPI, CPUsers.size()));
- CPI = JumpTableEntryIndices[CPI];
- }
-
MachineInstr *CPEMI = CPEMIs[CPI];
unsigned MaxOffs = ((1 << Bits)-1) * Scale;
CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, IsSoImm));
return false;
}
-unsigned ARMConstantIslands::getCombinedIndex(const MachineInstr *CPEMI) {
- if (CPEMI->getOperand(1).isCPI())
- return CPEMI->getOperand(1).getIndex();
-
- return JumpTableEntryIndices[CPEMI->getOperand(1).getIndex()];
-}
-
/// LookForCPEntryInRange - see if the currently referenced CPE is in range;
/// if not, see if an in-range clone of the CPE is in range, and if so,
/// change the data structures so the user references the clone. Returns:
}
// No. Look for previously created clones of the CPE that are in range.
- unsigned CPI = getCombinedIndex(CPEMI);
+ 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
CPUser &U = CPUsers[CPUserIndex];
MachineInstr *UserMI = U.MI;
MachineInstr *CPEMI = U.CPEMI;
- unsigned CPI = getCombinedIndex(CPEMI);
+ unsigned CPI = CPEMI->getOperand(1).getIndex();
unsigned Size = CPEMI->getOperand(2).getImm();
// Compute this only once, it's expensive.
unsigned UserOffset = getUserOffset(U);
// Update internal data structures to account for the newly inserted MBB.
updateForInsertedWaterBlock(NewIsland);
+ // Decrement the old entry, and remove it if refcount becomes 0.
+ decrementCPEReferenceCount(CPI, CPEMI);
+
// Now that we have an island to add the CPE to, clone the original CPE and
// add it to the island.
U.HighWaterMark = NewIsland;
- U.CPEMI = BuildMI(NewIsland, DebugLoc(), CPEMI->getDesc())
- .addImm(ID).addOperand(CPEMI->getOperand(1)).addImm(Size);
+ U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(ARM::CONSTPOOL_ENTRY))
+ .addImm(ID).addConstantPoolIndex(CPI).addImm(Size);
CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
++NumCPEs;
- // Decrement the old entry, and remove it if refcount becomes 0.
- decrementCPEReferenceCount(CPI, CPEMI);
-
// Mark the basic block as aligned as required by the const-pool entry.
NewIsland->setAlignment(getCPELogAlign(U.CPEMI));
return BytesRemoved;
}
-/// \brief Returns whether CPEMI is the first instruction in the block
-/// immediately following JTMI (assumed to be a TBB or TBH terminator). If so,
-/// we can switch the first register to PC and usually remove the address
-/// calculation that preceeded it.
-static bool jumpTableFollowsTB(MachineInstr *JTMI, MachineInstr *CPEMI) {
- MachineFunction::iterator MBB = JTMI->getParent();
- MachineFunction *MF = MBB->getParent();
- ++MBB;
-
- return MBB != MF->end() && MBB->begin() != MBB->end() &&
- &*MBB->begin() == CPEMI;
-}
-
/// optimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller
/// jumptables when it's possible.
bool ARMConstantIslands::optimizeThumb2JumpTables() {
break;
}
- if (!ByteOk && !HalfWordOk)
- continue;
+ if (ByteOk || HalfWordOk) {
+ MachineBasicBlock *MBB = MI->getParent();
+ unsigned BaseReg = MI->getOperand(0).getReg();
+ bool BaseRegKill = MI->getOperand(0).isKill();
+ if (!BaseRegKill)
+ continue;
+ unsigned IdxReg = MI->getOperand(1).getReg();
+ bool IdxRegKill = MI->getOperand(1).isKill();
- MachineBasicBlock *MBB = MI->getParent();
- unsigned BaseReg = MI->getOperand(0).getReg();
- bool BaseRegKill = MI->getOperand(0).isKill();
- if (!BaseRegKill)
- continue;
- unsigned IdxReg = MI->getOperand(1).getReg();
- bool IdxRegKill = MI->getOperand(1).isKill();
-
- DEBUG(dbgs() << "Shrink JT: " << *MI);
- CPUser &User = CPUsers[JumpTableUserIndices[JTI]];
- MachineInstr *CPEMI = User.CPEMI;
- unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
- MachineBasicBlock::iterator MI_JT = MI;
- MachineInstr *NewJTMI =
+ DEBUG(dbgs() << "Shrink JT: " << *MI);
+ unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
+ MachineBasicBlock::iterator MI_JT = MI;
+ MachineInstr *NewJTMI =
BuildMI(*MBB, MI_JT, MI->getDebugLoc(), TII->get(Opc))
- .addReg(BaseReg, getKillRegState(BaseRegKill))
- .addReg(IdxReg, getKillRegState(IdxRegKill))
- .addJumpTableIndex(JTI, JTOP.getTargetFlags())
- .addImm(CPEMI->getOperand(0).getImm());
- DEBUG(dbgs() << "BB#" << MBB->getNumber() << ": " << *NewJTMI);
-
- unsigned JTOpc = ByteOk ? ARM::JUMPTABLE_TBB : ARM::JUMPTABLE_TBH;
- CPEMI->setDesc(TII->get(JTOpc));
-
- // Now we need to determine whether the actual jump table has been moved
- // from immediately after this instruction. If not, we can replace BaseReg
- // with PC and probably eliminate the BaseReg calculations.
- unsigned DeadSize = 0;
- if (jumpTableFollowsTB(NewJTMI, User.CPEMI)) {
- NewJTMI->getOperand(0).setReg(ARM::PC);
- NewJTMI->getOperand(0).setIsKill(false);
-
- DeadSize = removeDeadDefinitions(MI, BaseReg, IdxReg);
- if (!User.MI->getParent()) {
- // The LEA was eliminated, the TBB instruction becomes the only new user
- // of the jump table.
- User.MI = NewJTMI;
- User.MaxDisp = 4;
- User.NegOk = false;
- User.IsSoImm = false;
- User.KnownAlignment = false;
- } else {
- // The LEA couldn't be eliminated, so we must add another CPUser to
- // record the TBB or TBH use.
- int CPEntryIdx = JumpTableEntryIndices[JTI];
- auto &CPEs = CPEntries[CPEntryIdx];
- auto Entry = std::find_if(CPEs.begin(), CPEs.end(), [&](CPEntry &E) {
- return E.CPEMI == User.CPEMI;
- });
- ++Entry->RefCount;
- CPUsers.emplace_back(CPUser(NewJTMI, User.CPEMI, 4, false, false));
- }
- }
-
- unsigned NewSize = TII->GetInstSizeInBytes(NewJTMI);
- unsigned OrigSize = TII->GetInstSizeInBytes(MI);
- MI->eraseFromParent();
+ .addReg(IdxReg, getKillRegState(IdxRegKill))
+ .addJumpTableIndex(JTI, JTOP.getTargetFlags());
+ DEBUG(dbgs() << "BB#" << MBB->getNumber() << ": " << *NewJTMI);
+ // FIXME: Insert an "ALIGN" instruction to ensure the next instruction
+ // is 2-byte aligned. For now, asm printer will fix it up.
+ unsigned NewSize = TII->GetInstSizeInBytes(NewJTMI);
+ unsigned OrigSize = TII->GetInstSizeInBytes(MI);
+ unsigned DeadSize = removeDeadDefinitions(MI, BaseReg, IdxReg);
+ MI->eraseFromParent();
- int Delta = OrigSize - NewSize + DeadSize;
- BBInfo[MBB->getNumber()].Size -= Delta;
- adjustBBOffsetsAfter(MBB);
+ int delta = OrigSize - NewSize + DeadSize;
+ BBInfo[MBB->getNumber()].Size -= delta;
+ adjustBBOffsetsAfter(MBB);
- ++NumTBs;
- MadeChange = true;
+ ++NumTBs;
+ MadeChange = true;
+ }
}
return MadeChange;