From: NAKAMURA Takumi Date: Mon, 4 Nov 2013 23:14:36 +0000 (+0000) Subject: Revert r194019 to r194021, "Submit the basic port of the rest of ARM constant islands... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=225f35a87ceb12adc29c4232749f3d44d86a1765;p=oota-llvm.git Revert r194019 to r194021, "Submit the basic port of the rest of ARM constant islands code to Mips." It broke -Asserts build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194026 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index 9ce0139f42f..725a3a76a61 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -60,11 +60,6 @@ class FRI16_ins op, string asmstr, InstrItinClass itin>: FRI16_ins_base; -class FRI16_TCP_ins _op, string asmstr, - InstrItinClass itin>: - FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size), - !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>; - class FRI16R_ins_base op, string asmstr, string asmstr2, InstrItinClass itin>: FRI16 _op, string asmstr, class FEXT_RI16_TCP_ins _op, string asmstr, InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size), + FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm), !strconcat(asmstr, "\t$rx, $imm"), [], itin>; class FEXT_2RI16_ins _op, string asmstr, @@ -807,8 +802,6 @@ def LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10010, "lw", IILoad>, MayLoad{ let Uses = [SP]; } -def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad; - def LwRxPcTcpX16: FEXT_RI16_TCP_ins<0b10110, "lw", IILoad>, MayLoad; // // Format: MOVE r32, rz MIPS16e @@ -1876,4 +1869,3 @@ let neverHasSideEffects = 1, isNotDuplicable = 1 in def CONSTPOOL_ENTRY : MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), "foo", []>; - diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index 8fb4538edf2..3209c0c55f2 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -27,7 +27,6 @@ #include "Mips.h" #include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsMachineFunction.h" #include "MipsTargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -43,197 +42,30 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Format.h" #include using namespace llvm; STATISTIC(NumCPEs, "Number of constpool entries"); -STATISTIC(NumSplit, "Number of uncond branches inserted"); -#ifdef IN_PROGRESS -STATISTIC(NumCBrFixed, "Number of cond branches fixed"); -#endif -STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); // FIXME: This option should be removed once it has received sufficient testing. static cl::opt AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), cl::desc("Align constant islands in code")); - -// Rather than do make check tests with huge amounts of code, we force -// the test to use this amount. -// -static cl::opt ConstantIslandsSmallOffset( - "mips-constant-islands-small-offset", - cl::init(0), - cl::desc("Make small offsets be this amount for testing purposes"), - cl::Hidden); - -/// UnknownPadding - Return the worst case padding that could result from -/// unknown offset bits. This does not include alignment padding caused by -/// known offset bits. -/// -/// @param LogAlign log2(alignment) -/// @param KnownBits Number of known low offset bits. -static inline unsigned UnknownPadding(unsigned LogAlign, unsigned KnownBits) { - if (KnownBits < LogAlign) - return (1u << LogAlign) - (1u << KnownBits); - return 0; -} - namespace { - - typedef MachineBasicBlock::iterator Iter; typedef MachineBasicBlock::reverse_iterator ReverseIter; - /// MipsConstantIslands - Due to limited PC-relative displacements, Mips - /// requires constant pool entries to be scattered among the instructions - /// inside a function. To do this, it completely ignores the normal LLVM - /// constant pool; instead, it places constants wherever it feels like with - /// special instructions. - /// - /// The terminology used in this pass includes: - /// Islands - Clumps of constants placed in the function. - /// Water - Potential places where an island could be formed. - /// CPE - A constant pool entry that has been placed somewhere, which - /// tracks a list of users. - class MipsConstantIslands : public MachineFunctionPass { - /// BasicBlockInfo - Information about the offset and size of a single - /// basic block. - struct BasicBlockInfo { - /// Offset - Distance from the beginning of the function to the beginning - /// of this basic block. - /// - /// Offsets are computed assuming worst case padding before an aligned - /// block. This means that subtracting basic block offsets always gives a - /// conservative estimate of the real distance which may be smaller. - /// - /// Because worst case padding is used, the computed offset of an aligned - /// block may not actually be aligned. - unsigned Offset; - - /// Size - Size of the basic block in bytes. If the block contains - /// inline assembly, this is a worst case estimate. - /// - /// The size does not include any alignment padding whether from the - /// beginning of the block, or from an aligned jump table at the end. - unsigned Size; - - /// KnownBits - The number of low bits in Offset that are known to be - /// exact. The remaining bits of Offset are an upper bound. - uint8_t KnownBits; - - /// Unalign - When non-zero, the block contains instructions (inline asm) - /// of unknown size. The real size may be smaller than Size bytes by a - /// multiple of 1 << Unalign. - uint8_t Unalign; - - /// PostAlign - When non-zero, the block terminator contains a .align - /// directive, so the end of the block is aligned to 1 << PostAlign - /// bytes. - uint8_t PostAlign; - - BasicBlockInfo() : Offset(0), Size(0), KnownBits(0), Unalign(0), - PostAlign(0) {} - - /// Compute the number of known offset bits internally to this block. - /// This number should be used to predict worst case padding when - /// splitting the block. - unsigned internalKnownBits() const { - unsigned Bits = Unalign ? Unalign : KnownBits; - // If the block size isn't a multiple of the known bits, assume the - // worst case padding. - if (Size & ((1u << Bits) - 1)) - Bits = countTrailingZeros(Size); - return Bits; - } - - /// Compute the offset immediately following this block. If LogAlign is - /// specified, return the offset the successor block will get if it has - /// this alignment. - unsigned postOffset(unsigned LogAlign = 0) const { - unsigned PO = Offset + Size; - return PO; - } - - /// Compute the number of known low bits of postOffset. If this block - /// contains inline asm, the number of known bits drops to the - /// instruction alignment. An aligned terminator may increase the number - /// of know bits. - /// If LogAlign is given, also consider the alignment of the next block. - unsigned postKnownBits(unsigned LogAlign = 0) const { - return std::max(std::max(unsigned(PostAlign), LogAlign), - internalKnownBits()); - } - }; - - std::vector BBInfo; - - /// WaterList - A sorted list of basic blocks where islands could be placed - /// (i.e. blocks that don't fall through to the following block, due - /// to a return, unreachable, or unconditional branch). - std::vector WaterList; - - /// NewWaterList - The subset of WaterList that was created since the - /// previous iteration by inserting unconditional branches. - SmallSet NewWaterList; - - typedef std::vector::iterator water_iterator; - - /// CPUser - One user of a constant pool, keeping the machine instruction - /// pointer, the constant pool being referenced, and the max displacement - /// allowed from the instruction to the CP. The HighWaterMark records the - /// highest basic block where a new CPEntry can be placed. To ensure this - /// pass terminates, the CP entries are initially placed at the end of the - /// function and then move monotonically to lower addresses. The - /// exception to this rule is when the current CP entry for a particular - /// CPUser is out of range, but there is another CP entry for the same - /// constant value in range. We want to use the existing in-range CP - /// entry, but if it later moves out of range, the search for new water - /// should resume where it left off. The HighWaterMark is used to record - /// that point. - struct CPUser { - MachineInstr *MI; - MachineInstr *CPEMI; - MachineBasicBlock *HighWaterMark; - private: - unsigned MaxDisp; - unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions - // with different displacements - unsigned LongFormOpcode; - public: - bool NegOk; - bool IsSoImm; - bool KnownAlignment; - CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, - bool neg, bool soimm, unsigned longformmaxdisp, unsigned longformopcode) - : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), - LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode), - NegOk(neg), IsSoImm(soimm), KnownAlignment(false) { - HighWaterMark = CPEMI->getParent(); - } - /// getMaxDisp - Returns the maximum displacement supported by MI. - /// Correct for unknown alignment. - /// Conservatively subtract 2 bytes to handle weird alignment effects. - unsigned getMaxDisp() const { - unsigned xMaxDisp = ConstantIslandsSmallOffset? ConstantIslandsSmallOffset: MaxDisp; - return (KnownAlignment ? xMaxDisp : xMaxDisp - 2) - 2; - } - unsigned getLongFormMaxDisp() const { - return (KnownAlignment ? LongFormMaxDisp : LongFormMaxDisp - 2) - 2; - } - unsigned getLongFormOpcode() const { - return LongFormOpcode; - } - }; - - /// CPUsers - Keep track of all of the machine instructions that use various - /// constant pools and their max displacement. - std::vector CPUsers; + const TargetMachine &TM; + bool IsPIC; + unsigned ABI; + const MipsSubtarget *STI; + const MipsInstrInfo *TII; + MachineFunction *MF; + MachineConstantPool *MCP; /// CPEntry - One per constant pool entry, keeping the machine instruction /// pointer, the constpool index, and the number of CPUser's which @@ -253,55 +85,13 @@ namespace { /// put in the vector of the original element, but have distinct CPIs. std::vector > CPEntries; - /// 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; - unsigned MaxDisp : 31; - bool isCond : 1; - int UncondBr; - ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) - : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} - }; - - /// ImmBranches - Keep track of all the immediate branch instructions. - /// - std::vector ImmBranches; - - /// HasFarJump - True if any far jump instruction has been emitted during - /// the branch fix up pass. - bool HasFarJump; - - const TargetMachine &TM; - bool IsPIC; - unsigned ABI; - const MipsSubtarget *STI; - const MipsInstrInfo *TII; - MipsFunctionInfo *MFI; - MachineFunction *MF; - MachineConstantPool *MCP; - - unsigned PICLabelUId; - bool PrescannedForConstants; - - void initPICLabelUId(unsigned UId) { - PICLabelUId = UId; - } - - - unsigned createPICLabelUId() { - return PICLabelUId++; - } - public: static char ID; MipsConstantIslands(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm), IsPIC(TM.getRelocationModel() == Reloc::PIC_), ABI(TM.getSubtarget().getTargetABI()), - STI(&TM.getSubtarget()), MF(0), MCP(0), PrescannedForConstants(false){} + STI(&TM.getSubtarget()), MF(0), MCP(0){} virtual const char *getPassName() const { return "Mips Constant Islands"; @@ -310,49 +100,6 @@ namespace { bool runOnMachineFunction(MachineFunction &F); void doInitialPlacement(std::vector &CPEMIs); - CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); - unsigned getCPELogAlign(const MachineInstr *CPEMI); - void initializeFunctionInfo(const std::vector &CPEMIs); - unsigned getOffsetOf(MachineInstr *MI) const; - unsigned getUserOffset(CPUser&) const; - void dumpBBs(); - void verify(); - - bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, - unsigned Disp, bool NegativeOK, bool IsSoImm = false); - bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, - const CPUser &U) { - return isOffsetInRange(UserOffset, TrialOffset, - U.getMaxDisp(), U.NegOk, U.IsSoImm); - } - bool isLongFormOffsetInRange(unsigned UserOffset, unsigned TrialOffset, - const CPUser &U) { - return isOffsetInRange(UserOffset, TrialOffset, - U.getLongFormMaxDisp(), U.NegOk, U.IsSoImm); - } - void computeBlockSize(MachineBasicBlock *MBB); - MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI); - void updateForInsertedWaterBlock(MachineBasicBlock *NewBB); - void adjustBBOffsetsAfter(MachineBasicBlock *BB); - bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI); - int findInRangeCPEntry(CPUser& U, unsigned UserOffset); - int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset); - bool findAvailableWater(CPUser&U, unsigned UserOffset, - water_iterator &WaterIter); - void createNewWater(unsigned CPUserIndex, unsigned UserOffset, - MachineBasicBlock *&NewMBB); - bool handleConstantPoolUser(unsigned CPUserIndex); - void removeDeadCPEMI(MachineInstr *CPEMI); - bool removeUnusedCPEntries(); - bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset, - MachineInstr *CPEMI, unsigned Disp, bool NegOk, - bool DoDump = false); - bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, - CPUser &U, unsigned &Growth); - bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); - bool fixupImmediateBr(ImmBranch &Br); - bool fixupConditionalBr(ImmBranch &Br); - bool fixupUnconditionalBr(ImmBranch &Br); void prescanForConstants(); @@ -363,19 +110,6 @@ namespace { char MipsConstantIslands::ID = 0; } // end of anonymous namespace -/// print block size and offset information - debugging -void MipsConstantIslands::dumpBBs() { - DEBUG({ - for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) { - const BasicBlockInfo &BBI = BBInfo[J]; - dbgs() << format("%08x BB#%u\t", BBI.Offset, J) - << " kb=" << unsigned(BBI.KnownBits) - << " ua=" << unsigned(BBI.Unalign) - << " pa=" << unsigned(BBI.PostAlign) - << format(" size=%#x\n", BBInfo[J].Size); - } - }); -} /// createMipsLongBranchPass - Returns a pass that converts branches to long /// branches. FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) { @@ -393,15 +127,13 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { return false; } TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo(); - MFI = MF->getInfo(); DEBUG(dbgs() << "constant island processing " << "\n"); // // will need to make predermination if there is any constants we need to // put in constant islands. TBD. // - if (!PrescannedForConstants) prescanForConstants(); + prescanForConstants(); - HasFarJump = false; // This pass invalidates liveness information when it splits basic blocks. MF->getRegInfo().invalidateLiveness(); @@ -409,66 +141,13 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { // the numbers agree with the position of the block in the function. MF->RenumberBlocks(); - bool MadeChange = false; - // Perform the initial placement of the constant pool entries. To start with, // we put them all at the end of the function. std::vector CPEMIs; if (!MCP->isEmpty()) doInitialPlacement(CPEMIs); - /// The next UID to take is the first unused one. - initPICLabelUId(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 - // constant pool users. - initializeFunctionInfo(CPEMIs); - CPEMIs.clear(); - DEBUG(dumpBBs()); - - /// Remove dead constant pool entries. - MadeChange |= removeUnusedCPEntries(); - - // Iteratively place constant pool entries and fix up branches until there - // is no change. - unsigned NoCPIters = 0, NoBRIters = 0; - (void)NoBRIters; - while (true) { - DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); - bool CPChange = false; - for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) - CPChange |= handleConstantPoolUser(i); - if (CPChange && ++NoCPIters > 30) - report_fatal_error("Constant Island pass failed to converge!"); - DEBUG(dumpBBs()); - - // Clear NewWaterList now. If we split a block for branches, it should - // appear as "new water" for the next iteration of constant pool placement. - NewWaterList.clear(); - - DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); - bool BRChange = false; -#ifdef IN_PROGRESS - for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) - BRChange |= fixupImmediateBr(ImmBranches[i]); - if (BRChange && ++NoBRIters > 30) - report_fatal_error("Branch Fix Up pass failed to converge!"); - DEBUG(dumpBBs()); -#endif - if (!CPChange && !BRChange) - break; - MadeChange = true; - } - - DEBUG(dbgs() << '\n'; dumpBBs()); - - BBInfo.clear(); - WaterList.clear(); - CPUsers.clear(); - CPEntries.clear(); - ImmBranches.clear(); - return MadeChange; + return true; } /// doInitialPlacement - Perform the initial placement of the constant pool @@ -537,1165 +216,9 @@ MipsConstantIslands::doInitialPlacement(std::vector &CPEMIs) { DEBUG(BB->dump()); } -/// BBHasFallthrough - Return true if the specified basic block can fallthrough -/// into the block immediately after it. -static bool BBHasFallthrough(MachineBasicBlock *MBB) { - // Get the next machine basic block in the function. - MachineFunction::iterator MBBI = MBB; - // Can't fall off end of function. - if (llvm::next(MBBI) == MBB->getParent()->end()) - return false; - - MachineBasicBlock *NextBB = llvm::next(MBBI); - for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), - E = MBB->succ_end(); I != E; ++I) - if (*I == NextBB) - return true; - - return false; -} - -/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, -/// look up the corresponding CPEntry. -MipsConstantIslands::CPEntry -*MipsConstantIslands::findConstPoolEntry(unsigned CPI, - const MachineInstr *CPEMI) { - std::vector &CPEs = CPEntries[CPI]; - // Number of entries per constpool index should be small, just do a - // linear search. - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - if (CPEs[i].CPEMI == CPEMI) - return &CPEs[i]; - } - return NULL; -} - -/// getCPELogAlign - Returns the required alignment of the constant pool entry -/// represented by CPEMI. Alignment is measured in log2(bytes) units. -unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) { - assert(CPEMI && CPEMI->getOpcode() == Mips::CONSTPOOL_ENTRY); - - // Everything is 4-byte aligned unless AlignConstantIslands is set. - if (!AlignConstantIslands) - return 2; - - 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"); - return Log2_32(Align); -} - -/// initializeFunctionInfo - 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 constant pool users. -void MipsConstantIslands:: -initializeFunctionInfo(const std::vector &CPEMIs) { - BBInfo.clear(); - BBInfo.resize(MF->getNumBlockIDs()); - - // First thing, compute the size of all basic blocks, and see if the function - // has any inline assembly in it. If so, we have to be conservative about - // alignment assumptions, as we don't know for sure the size of any - // instructions in the inline assembly. - for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) - computeBlockSize(I); - - // The known bits of the entry block offset are determined by the function - // alignment. - BBInfo.front().KnownBits = MF->getAlignment(); - - // Compute block offsets. - adjustBBOffsetsAfter(MF->begin()); - - // Now go back through the instructions and build up our data structures. - for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end(); - MBBI != E; ++MBBI) { - MachineBasicBlock &MBB = *MBBI; - - // If this block doesn't fall through into the next MBB, then this is - // 'water' that a constant pool island could be placed. - if (!BBHasFallthrough(&MBB)) - WaterList.push_back(&MBB); - for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); - I != E; ++I) { - if (I->isDebugValue()) - continue; - - int Opc = I->getOpcode(); - if (I->isBranch()) { - bool isCond = false; - unsigned Bits = 0; - unsigned Scale = 1; - int UOpc = Opc; - - switch (Opc) { - default: - continue; // Ignore other JT branches -#ifdef IN_PROGRESS - case ARM::t2BR_JT: - T2JumpTables.push_back(I); - continue; // Does not get an entry in ImmBranches - 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; - case ARM::t2Bcc: - isCond = true; - UOpc = ARM::t2B; - Bits = 20; - Scale = 2; - break; - case ARM::t2B: - Bits = 24; - Scale = 2; - break; -#endif - } - // Record this immediate branch. - unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; - ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc)); - - } - - - if (Opc == Mips::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()) { - - // 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; - bool NegOk = false; - bool IsSoImm = false; - unsigned LongFormBits = 0; - unsigned LongFormScale = 0; - unsigned LongFormOpcode = 0; - switch (Opc) { - default: - llvm_unreachable("Unknown addressing mode for CP reference!"); - case Mips::LwRxPcTcp16: - Bits = 8; - Scale = 2; - LongFormOpcode = Mips::LwRxPcTcpX16; - break; - case Mips::LwRxPcTcpX16: - Bits = 16; - Scale = 2; - break; -#ifdef IN_PROGRESS - // Taking the address of a CP entry. - case ARM::LEApcrel: - // 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 - // displacements that fits in a SoImm as well. - Bits = 8; - Scale = 4; - NegOk = true; - IsSoImm = true; - break; - case ARM::t2LEApcrel: - Bits = 12; - NegOk = true; - break; - case ARM::tLEApcrel: - Bits = 8; - Scale = 4; - break; - - case ARM::LDRBi12: - case ARM::LDRi12: - case ARM::LDRcp: - case ARM::t2LDRpci: - Bits = 12; // +-offset_12 - NegOk = true; - break; - - case ARM::tLDRpci: - Bits = 8; - Scale = 4; // +(offset_8*4) - break; - - case ARM::VLDRD: - case ARM::VLDRS: - Bits = 8; - Scale = 4; // +-(offset_8*4) - NegOk = true; - break; -#endif - } - // Remember that this is a user of a CP entry. - unsigned CPI = I->getOperand(op).getIndex(); - MachineInstr *CPEMI = CPEMIs[CPI]; - unsigned MaxOffs = ((1 << Bits)-1) * Scale; - unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale; - CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, IsSoImm, LongFormMaxOffs, - LongFormOpcode)); - - // Increment corresponding CPEntry reference count. - CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); - assert(CPE && "Cannot find a corresponding CPEntry!"); - CPE->RefCount++; - - // Instructions can only use one CP entry, don't bother scanning the - // rest of the operands. - break; - - } - - } - } - -} - -/// computeBlockSize - Compute the size and some alignment information for MBB. -/// This function updates BBInfo directly. -void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) { - BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; - BBI.Size = 0; - BBI.Unalign = 0; - BBI.PostAlign = 0; - - for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; - ++I) - BBI.Size += TII->GetInstSizeInBytes(I); - -} - -/// getOffsetOf - Return the current offset of the specified machine instruction -/// from the start of the function. This offset changes as stuff is moved -/// around inside the function. -unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const { - MachineBasicBlock *MBB = MI->getParent(); - - // The offset is composed of two things: the sum of the sizes of all MBB's - // before this instruction's block, and the offset from the start of the block - // it is in. - unsigned Offset = BBInfo[MBB->getNumber()].Offset; - - // Sum instructions before MI in MBB. - for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { - assert(I != MBB->end() && "Didn't find MI in its own basic block?"); - Offset += TII->GetInstSizeInBytes(I); - } - return Offset; -} - -/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB -/// ID. -static bool CompareMBBNumbers(const MachineBasicBlock *LHS, - const MachineBasicBlock *RHS) { - return LHS->getNumber() < RHS->getNumber(); -} - -/// updateForInsertedWaterBlock - When a block is newly inserted into the -/// machine function, it upsets all of the block numbers. Renumber the blocks -/// and update the arrays that parallel this numbering. -void MipsConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) { - // Renumber the MBB's to keep them consecutive. - NewBB->getParent()->RenumberBlocks(NewBB); - - // Insert an entry into BBInfo to align it properly with the (newly - // renumbered) block numbers. - BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); - - // Next, update WaterList. Specifically, we need to add NewMBB as having - // available water after it. - water_iterator IP = - std::lower_bound(WaterList.begin(), WaterList.end(), NewBB, - CompareMBBNumbers); - WaterList.insert(IP, NewBB); -} - -/// getUserOffset - Compute the offset of U.MI as seen by the hardware -/// displacement computation. Update U.KnownAlignment to match its current -/// basic block location. -unsigned MipsConstantIslands::getUserOffset(CPUser &U) const { - unsigned UserOffset = getOffsetOf(U.MI); - const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()]; - unsigned KnownBits = BBI.internalKnownBits(); - - // The value read from PC is offset from the actual instruction address. -#ifdef IN_PROGRESS - UserOffset += (isThumb ? 4 : 8); -#endif - - // Because of inline assembly, we may not know the alignment (mod 4) of U.MI. - // Make sure U.getMaxDisp() returns a constrained range. - U.KnownAlignment = (KnownBits >= 2); - - // On Thumb, offsets==2 mod 4 are rounded down by the hardware for - // purposes of the displacement computation; compensate for that here. - // For unknown alignments, getMaxDisp() constrains the range instead. -#ifdef IN_PROGRESS - if (isThumb && U.KnownAlignment) - UserOffset &= ~3u; -#endif - - return UserOffset; -} - -/// Split the basic block containing MI into two blocks, which are joined by -/// an unconditional branch. Update data structures and renumber blocks to -/// account for this change and returns the newly created block. -MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) { - MachineBasicBlock *OrigBB = MI->getParent(); - - // Create a new MBB for the code after the OrigBB. - MachineBasicBlock *NewBB = - MF->CreateMachineBasicBlock(OrigBB->getBasicBlock()); - MachineFunction::iterator MBBI = OrigBB; ++MBBI; - MF->insert(MBBI, NewBB); - - // Splice the instructions starting with MI over to NewBB. - NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); - - // Add an unconditional branch from OrigBB to NewBB. - // Note the new unconditional branch is not being recorded. - // There doesn't seem to be meaningful DebugInfo available; this doesn't - // correspond to anything in the source. - BuildMI(OrigBB, DebugLoc(), TII->get(Mips::BimmX16)).addMBB(NewBB); -#ifdef IN_PROGRESS - unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B; - if (!isThumb) - BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB); - else - BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB) - .addImm(ARMCC::AL).addReg(0); -#endif - ++NumSplit; - - // Update the CFG. All succs of OrigBB are now succs of NewBB. - NewBB->transferSuccessors(OrigBB); - - // OrigBB branches to NewBB. - OrigBB->addSuccessor(NewBB); - - // 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. - MF->RenumberBlocks(NewBB); - - // Insert an entry into BBInfo to align it properly with the (newly - // renumbered) block numbers. - BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); - - // Next, update WaterList. Specifically, we need to add OrigMBB as having - // available water after it (but not if it's already there, which happens - // when splitting before a conditional branch that is followed by an - // unconditional branch - in that case we want to insert NewBB). - water_iterator IP = - std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB, - CompareMBBNumbers); - MachineBasicBlock* WaterBB = *IP; - if (WaterBB == OrigBB) - WaterList.insert(llvm::next(IP), NewBB); - else - WaterList.insert(IP, OrigBB); - NewWaterList.insert(OrigBB); - - // Figure out how large the OrigBB is. As the first half of the original - // block, it cannot contain a tablejump. The size includes - // the new jump we added. (It should be possible to do this without - // recounting everything, but it's very confusing, and this is rarely - // executed.) - computeBlockSize(OrigBB); - - // Figure out how large the NewMBB is. As the second half of the original - // block, it may contain a tablejump. - computeBlockSize(NewBB); - - // All BBOffsets following these blocks must be modified. - adjustBBOffsetsAfter(OrigBB); - - return NewBB; -} - -#ifndef NDEBUG - - -/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool -/// reference) is within MaxDisp of TrialOffset (a proposed location of a -/// constant pool entry). -/// UserOffset is computed by getUserOffset above to include PC adjustments. If -/// the mod 4 alignment of UserOffset is not known, the uncertainty must be -/// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that. -bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset, - unsigned TrialOffset, unsigned MaxDisp, - bool NegativeOK, bool IsSoImm) { - if (UserOffset <= TrialOffset) { - // User before the Trial. - if (TrialOffset - UserOffset <= MaxDisp) - return true; - // FIXME: Make use full range of soimm values. - } else if (NegativeOK) { - if (UserOffset - TrialOffset <= MaxDisp) - return true; - // FIXME: Make use full range of soimm values. - } - return false; -} - -/// isWaterInRange - Returns true if a CPE placed after the specified -/// 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 MipsConstantIslands::isWaterInRange(unsigned UserOffset, - MachineBasicBlock* Water, CPUser &U, - 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; - - // The CPE may be able to hide in the alignment padding before the next - // block. It may also cause more padding to be required if it is more aligned - // that the next block. - 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 isOffsetInRange(UserOffset, CPEOffset, U); -} - -/// isCPEntryInRange - Returns true if the distance between specific MI and -/// specific ConstPool entry instruction can fit in MI's displacement field. -bool MipsConstantIslands::isCPEntryInRange(MachineInstr *MI, unsigned UserOffset, - MachineInstr *CPEMI, unsigned MaxDisp, - bool NegOk, bool DoDump) { - unsigned CPEOffset = getOffsetOf(CPEMI); - - if (DoDump) { - DEBUG({ - unsigned Block = MI->getParent()->getNumber(); - const BasicBlockInfo &BBI = BBInfo[Block]; - dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm() - << " max delta=" << MaxDisp - << format(" insn address=%#x", UserOffset) - << " in BB#" << Block << ": " - << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI - << format("CPE address=%#x offset=%+d: ", CPEOffset, - int(CPEOffset-UserOffset)); - }); - } - - return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk); -} - -/// BBIsJumpedOver - Return true of the specified basic block's only predecessor -/// unconditionally branches to its only successor. -static bool BBIsJumpedOver(MachineBasicBlock *MBB) { - if (MBB->pred_size() != 1 || MBB->succ_size() != 1) - return false; - -#ifdef IN_PROGRESS - MachineBasicBlock *Succ = *MBB->succ_begin(); - MachineBasicBlock *Pred = *MBB->pred_begin(); - MachineInstr *PredMI = &Pred->back(); - if (PredMI->getOpcode() == ARM::B || PredMI->getOpcode() == ARM::tB - || PredMI->getOpcode() == ARM::t2B) - return PredMI->getOperand(0).getMBB() == Succ; -#endif - return false; -} -#endif // NDEBUG - -void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) { - unsigned BBNum = BB->getNumber(); - for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) { - // Get the offset and known bits at the end of the layout predecessor. - // Include the alignment of the current block. - unsigned Offset = BBInfo[i - 1].postOffset(); - BBInfo[i].Offset = Offset; - } -} - -/// decrementCPEReferenceCount - find the constant pool entry with index CPI -/// and instruction CPEMI, and decrement its refcount. If the refcount -/// becomes 0 remove the entry and instruction. Returns true if we removed -/// the entry, false if we didn't. - -bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI, - MachineInstr *CPEMI) { - // Find the old entry. Eliminate it if it is no longer used. - CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); - assert(CPE && "Unexpected!"); - if (--CPE->RefCount == 0) { - removeDeadCPEMI(CPEMI); - CPE->CPEMI = NULL; - --NumCPEs; - return true; - } - return false; -} - -/// 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: -/// 0 = no existing entry found -/// 1 = entry found, and there were no code insertions or deletions -/// 2 = entry found, and there were code insertions or deletions -int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) -{ - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - - // Check to see if the CPE is already in-range. - if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk, - true)) { - DEBUG(dbgs() << "In range\n"); - return 1; - } - - // No. Look for previously created clones of the CPE that are in range. - unsigned CPI = CPEMI->getOperand(1).getIndex(); - std::vector &CPEs = CPEntries[CPI]; - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - // We already tried this one - if (CPEs[i].CPEMI == CPEMI) - continue; - // Removing CPEs can leave empty entries, skip - if (CPEs[i].CPEMI == NULL) - continue; - if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(), - U.NegOk)) { - DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); - // Point the CPUser node to the replacement - 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).isCPI()) { - UserMI->getOperand(j).setIndex(CPEs[i].CPI); - break; - } - // Adjust the refcount of the clone... - CPEs[i].RefCount++; - // ...and the original. If we didn't remove the old entry, none of the - // addresses changed, so we don't need another pass. - return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; - } - } - return 0; -} - -/// LookForCPEntryInRange - see if the currently referenced CPE is in range; -/// This version checks if the longer form of the instruction can be used to -/// to satisfy things. -/// 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: -/// 0 = no existing entry found -/// 1 = entry found, and there were no code insertions or deletions -/// 2 = entry found, and there were code insertions or deletions -int MipsConstantIslands::findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset) -{ - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - - // Check to see if the CPE is already in-range. - if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getLongFormMaxDisp(), U.NegOk, - true)) { - DEBUG(dbgs() << "In range\n"); - UserMI->setDesc(TII->get(U.getLongFormOpcode())); - return 2; // instruction is longer length now - } - - // No. Look for previously created clones of the CPE that are in range. - unsigned CPI = CPEMI->getOperand(1).getIndex(); - std::vector &CPEs = CPEntries[CPI]; - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - // We already tried this one - if (CPEs[i].CPEMI == CPEMI) - continue; - // Removing CPEs can leave empty entries, skip - if (CPEs[i].CPEMI == NULL) - continue; - if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getLongFormMaxDisp(), - U.NegOk)) { - DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); - // Point the CPUser node to the replacement - 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).isCPI()) { - UserMI->getOperand(j).setIndex(CPEs[i].CPI); - break; - } - // Adjust the refcount of the clone... - CPEs[i].RefCount++; - // ...and the original. If we didn't remove the old entry, none of the - // addresses changed, so we don't need another pass. - return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; - } - } - return 0; -} - -/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in -/// the specific unconditional branch instruction. -static inline unsigned getUnconditionalBrDisp(int Opc) { -#ifdef IN_PROGRESS - switch (Opc) { - case ARM::tB: - return ((1<<10)-1)*2; - case ARM::t2B: - return ((1<<23)-1)*2; - default: - break; - } -#endif - return ((1<<23)-1)*4; -} - -/// findAvailableWater - Look for an existing entry in the WaterList in which -/// we can place the CPE referenced from U so it's within range of U's MI. -/// Returns true if found, false if not. If it returns true, WaterIter -/// is set to the WaterList entry. For Thumb, prefer water that will not -/// introduce padding to water that will. To ensure that this pass -/// terminates, the CPE location for a particular CPUser is only allowed to -/// move to a lower address, so search backward from the end of the list and -/// prefer the first water that is in range. -bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset, - water_iterator &WaterIter) { - if (WaterList.empty()) - return false; - - unsigned BestGrowth = ~0u; - for (water_iterator IP = prior(WaterList.end()), B = WaterList.begin();; - --IP) { - MachineBasicBlock* WaterBB = *IP; - // 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 - // the previous iteration by inserting an unconditional branch. In the - // latter case, we want to allow resetting the high water mark back to - // this new water since we haven't seen it before. Inserting branches - // 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 - // we don't insert more branches than necessary. - unsigned Growth; - if (isWaterInRange(UserOffset, WaterBB, U, Growth) && - (WaterBB->getNumber() < U.HighWaterMark->getNumber() || - NewWaterList.count(WaterBB)) && Growth < BestGrowth) { - // This is the least amount of required padding seen so far. - BestGrowth = Growth; - WaterIter = IP; - DEBUG(dbgs() << "Found water after BB#" << WaterBB->getNumber() - << " Growth=" << Growth << '\n'); - - // Keep looking unless it is perfect. - if (BestGrowth == 0) - return true; - } - if (IP == B) - break; - } - return BestGrowth != ~0u; -} - -/// createNewWater - No existing WaterList entry will work for -/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the -/// block is used if in range, and the conditional branch munged so control -/// flow is correct. Otherwise the block is split to create a hole with an -/// unconditional branch around it. In either case NewMBB is set to a -/// block following which the new island can be inserted (the WaterList -/// is not adjusted). -void MipsConstantIslands::createNewWater(unsigned CPUserIndex, - unsigned UserOffset, - MachineBasicBlock *&NewMBB) { - CPUser &U = CPUsers[CPUserIndex]; - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - unsigned CPELogAlign = getCPELogAlign(CPEMI); - MachineBasicBlock *UserMBB = UserMI->getParent(); - const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()]; - - // If the block does not end in an unconditional branch already, and if the - // end of the block is within range, make new water there. (The addition - // below is for the unconditional branch we will be adding: 4 bytes on ARM + - // Thumb2, 2 on Thumb1. - if (BBHasFallthrough(UserMBB)) { - // Size of branch to insert. -#ifdef IN_PROGRESS - unsigned Delta = isThumb1 ? 2 : 4; -#else - unsigned Delta = 4; -#endif - // Compute the offset where the CPE will begin. - unsigned CPEOffset = UserBBI.postOffset(CPELogAlign) + Delta; - - if (isOffsetInRange(UserOffset, CPEOffset, U)) { - DEBUG(dbgs() << "Split at end of BB#" << UserMBB->getNumber() - << format(", expected CPE offset %#x\n", CPEOffset)); - NewMBB = llvm::next(MachineFunction::iterator(UserMBB)); - // Add an unconditional branch from UserMBB to fallthrough block. Record - // it for branch lengthening; this new branch will not get out of range, - // but if the preceding conditional branch is out of range, the targets - // will be exchanged, and the altered branch may be out of range, so the - // machinery has to know about it. -#ifdef IN_PROGRESS - int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B; - if (!isThumb) - BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); - else - BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB) - .addImm(ARMCC::AL).addReg(0); -#else - int UncondBr = 1; -#endif - unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); - ImmBranches.push_back(ImmBranch(&UserMBB->back(), - MaxDisp, false, UncondBr)); - BBInfo[UserMBB->getNumber()].Size += Delta; - adjustBBOffsetsAfter(UserMBB); - return; - } - } - - // What a big block. Find a place within the block to split it. This is a - // little tricky on Thumb1 since instructions are 2 bytes and constant pool - // entries are 4 bytes: if instruction I references island CPE, and - // instruction I+1 references CPE', it will not work well to put CPE as far - // forward as possible, since then CPE' cannot immediately follow it (that - // location is 2 bytes farther away from I+1 than CPE was from I) and we'd - // need to create a new island. So, we make a first guess, then walk through - // the instructions between the one currently being looked at and the - // possible insertion point, and make sure any other instructions that - // reference CPEs will be able to use the same island area; if not, we back - // up the insertion point. - - // Try to split the block so it's fully aligned. Compute the latest split - // point where we can add a 4-byte branch instruction, and then align to - // LogAlign which is the largest possible alignment in the function. - unsigned LogAlign = MF->getAlignment(); - assert(LogAlign >= CPELogAlign && "Over-aligned constant pool entry"); - unsigned KnownBits = UserBBI.internalKnownBits(); - unsigned UPad = UnknownPadding(LogAlign, KnownBits); - unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad; - DEBUG(dbgs() << format("Split in middle of big block before %#x", - BaseInsertOffset)); - - // The 4 in the following is for the unconditional branch we'll be inserting - // (allows for long branch on Thumb1). Alignment of the island is handled - // inside isOffsetInRange. - BaseInsertOffset -= 4; - - DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) - << " la=" << LogAlign - << " kb=" << KnownBits - << " up=" << UPad << '\n'); - - // This could point off the end of the block if we've already got constant - // pool entries following this block; only the last one is in the water list. - // Back past any possible branches (allow for a conditional and a maximally - // long unconditional). - if (BaseInsertOffset + 8 >= UserBBI.postOffset()) { - BaseInsertOffset = UserBBI.postOffset() - UPad - 8; - DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); - } - unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad + - CPEMI->getOperand(2).getImm(); - MachineBasicBlock::iterator MI = UserMI; - ++MI; - unsigned CPUIndex = CPUserIndex+1; - unsigned NumCPUsers = CPUsers.size(); - MachineInstr *LastIT = 0; - for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI); - Offset < BaseInsertOffset; - Offset += TII->GetInstSizeInBytes(MI), - MI = llvm::next(MI)) { - assert(MI != UserMBB->end() && "Fell off end of block"); - if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { - CPUser &U = CPUsers[CPUIndex]; - if (!isOffsetInRange(Offset, EndInsertOffset, U)) { - // Shift intertion point by one unit of alignment so it is within reach. - BaseInsertOffset -= 1u << LogAlign; - EndInsertOffset -= 1u << LogAlign; - } - // This is overly conservative, as we don't account for CPEMIs being - // reused within the block, but it doesn't matter much. Also assume CPEs - // are added in order with alignment padding. We may eventually be able - // to pack the aligned CPEs better. - EndInsertOffset += U.CPEMI->getOperand(2).getImm(); - CPUIndex++; - } -#ifdef IN_PROGRESS - // Remember the last IT instruction. - if (MI->getOpcode() == ARM::t2IT) - LastIT = MI; -#endif - } - - --MI; - - // Avoid splitting an IT block. - if (LastIT) { -#ifdef IN_PROGRESS - unsigned PredReg = 0; - ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg); - if (CC != ARMCC::AL) - MI = LastIT; -#endif - } - NewMBB = splitBlockBeforeInstr(MI); -} - -/// handleConstantPoolUser - Analyze the specified user, checking to see if it -/// is out-of-range. If so, pick up the constant pool value and move it some -/// place in-range. Return true if we changed any addresses (thus must run -/// another pass of branch lengthening), false otherwise. -bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { - CPUser &U = CPUsers[CPUserIndex]; - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - unsigned CPI = CPEMI->getOperand(1).getIndex(); - unsigned Size = CPEMI->getOperand(2).getImm(); - // Compute this only once, it's expensive. - unsigned UserOffset = getUserOffset(U); - - // See if the current entry is within range, or there is a clone of it - // in range. - int result = findInRangeCPEntry(U, UserOffset); - if (result==1) return false; - else if (result==2) return true; - - - // Look for water where we can place this CPE. - MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock(); - MachineBasicBlock *NewMBB; - water_iterator IP; - if (findAvailableWater(U, UserOffset, IP)) { - DEBUG(dbgs() << "Found water in range\n"); - MachineBasicBlock *WaterBB = *IP; - - // If the original WaterList entry was "new water" on this iteration, - // propagate that to the new island. This is just keeping NewWaterList - // updated to match the WaterList, which will be updated below. - if (NewWaterList.erase(WaterBB)) - NewWaterList.insert(NewIsland); - - // The new CPE goes before the following block (NewMBB). - NewMBB = llvm::next(MachineFunction::iterator(WaterBB)); - - } else { - // No water found. - // we first see if a longer form of the instrucion could have reached the constant. - // in that case we won't bother to split -#ifdef IN_PROGRESS - result = findLongFormInRangeCPEntry(U, UserOffset); -#endif - DEBUG(dbgs() << "No water found\n"); - createNewWater(CPUserIndex, UserOffset, NewMBB); - - // splitBlockBeforeInstr adds to WaterList, which is important when it is - // called while handling branches so that the water will be seen on the - // next iteration for constant pools, but in this context, we don't want - // it. Check for this so it will be removed from the WaterList. - // Also remove any entry from NewWaterList. - MachineBasicBlock *WaterBB = prior(MachineFunction::iterator(NewMBB)); - IP = std::find(WaterList.begin(), WaterList.end(), WaterBB); - if (IP != WaterList.end()) - NewWaterList.erase(WaterBB); - - // We are adding new water. Update NewWaterList. - NewWaterList.insert(NewIsland); - } - - // Remove the original WaterList entry; we want subsequent insertions in - // this vicinity to go after the one we're about to insert. This - // considerably reduces the number of times we have to move the same CPE - // more than once and is also important to ensure the algorithm terminates. - if (IP != WaterList.end()) - WaterList.erase(IP); - - // Okay, we know we can put an island before NewMBB now, do it! - MF->insert(NewMBB, NewIsland); - - // 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(), TII->get(Mips::CONSTPOOL_ENTRY)) - .addImm(ID).addConstantPoolIndex(CPI).addImm(Size); - CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); - ++NumCPEs; - - // Mark the basic block as aligned as required by the const-pool entry. - NewIsland->setAlignment(getCPELogAlign(U.CPEMI)); - - // Increase the size of the island block to account for the new entry. - BBInfo[NewIsland->getNumber()].Size += Size; - adjustBBOffsetsAfter(llvm::prior(MachineFunction::iterator(NewIsland))); - - // No existing clone of this CPE is within range. - // We will be generating a new clone. Get a UID for it. - unsigned ID = createPICLabelUId(); - - // 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).isCPI()) { - UserMI->getOperand(i).setIndex(ID); - break; - } - - DEBUG(dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI - << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); - - return true; -} - -/// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update -/// sizes and offsets of impacted basic blocks. -void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) { - MachineBasicBlock *CPEBB = CPEMI->getParent(); - unsigned Size = CPEMI->getOperand(2).getImm(); - CPEMI->eraseFromParent(); - BBInfo[CPEBB->getNumber()].Size -= Size; - // All succeeding offsets have the current size value added in, fix this. - if (CPEBB->empty()) { - BBInfo[CPEBB->getNumber()].Size = 0; - - // This block no longer needs to be aligned. - CPEBB->setAlignment(0); - } else - // Entries are sorted by descending alignment, so realign from the front. - CPEBB->setAlignment(getCPELogAlign(CPEBB->begin())); - - adjustBBOffsetsAfter(CPEBB); - // An island has only one predecessor BB and one successor BB. Check if - // this BB's predecessor jumps directly to this BB's successor. This - // shouldn't happen currently. - assert(!BBIsJumpedOver(CPEBB) && "How did this happen?"); - // FIXME: remove the empty blocks after all the work is done? -} - -/// removeUnusedCPEntries - Remove constant pool entries whose refcounts -/// are zero. -bool MipsConstantIslands::removeUnusedCPEntries() { - unsigned MadeChange = false; - for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { - std::vector &CPEs = CPEntries[i]; - for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) { - if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) { - removeDeadCPEMI(CPEs[j].CPEMI); - CPEs[j].CPEMI = NULL; - MadeChange = true; - } - } - } - return MadeChange; -} - -/// isBBInRange - Returns true if the distance between specific MI and -/// specific BB can fit in MI's displacement field. -bool MipsConstantIslands::isBBInRange(MachineInstr *MI,MachineBasicBlock *DestBB, - unsigned MaxDisp) { -#ifdef IN_PROGRESS - unsigned PCAdj = isThumb ? 4 : 8; -#else - unsigned PCAdj = 4; -#endif - unsigned BrOffset = getOffsetOf(MI) + PCAdj; - unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; - - DEBUG(dbgs() << "Branch of destination BB#" << DestBB->getNumber() - << " from BB#" << MI->getParent()->getNumber() - << " max delta=" << MaxDisp - << " from " << getOffsetOf(MI) << " to " << DestOffset - << " offset " << int(DestOffset-BrOffset) << "\t" << *MI); - - if (BrOffset <= DestOffset) { - // Branch before the Dest. - if (DestOffset-BrOffset <= MaxDisp) - return true; - } else { - if (BrOffset-DestOffset <= MaxDisp) - return true; - } - return false; -} - -/// fixupImmediateBr - Fix up an immediate branch whose destination is too far -/// away to fit in its displacement field. -bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) { - MachineInstr *MI = Br.MI; - MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); - - // Check to see if the DestBB is already in-range. - if (isBBInRange(MI, DestBB, Br.MaxDisp)) - return false; - - if (!Br.isCond) - return fixupUnconditionalBr(Br); - return fixupConditionalBr(Br); -} - -/// fixupUnconditionalBr - Fix up an unconditional branch whose destination is -/// too far away to fit in its displacement field. If the LR register has been -/// spilled in the epilogue, then we can use BL to implement a far jump. -/// Otherwise, add an intermediate branch instruction to a branch. -bool -MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { - MachineInstr *MI = Br.MI; - MachineBasicBlock *MBB = MI->getParent(); -#ifdef IN_PROGRESS - if (!isThumb1) - llvm_unreachable("fixupUnconditionalBr is Thumb1 only!"); -#endif - // Use BL to implement far jump. - Br.MaxDisp = (1 << 21) * 2; -#ifdef IN_PROGRESS - MI->setDesc(TII->get(ARM::tBfar)); -#endif - BBInfo[MBB->getNumber()].Size += 2; - adjustBBOffsetsAfter(MBB); - HasFarJump = true; - ++NumUBrFixed; - - DEBUG(dbgs() << " Changed B to long jump " << *MI); - - return true; -} - -/// fixupConditionalBr - Fix up a conditional branch whose destination is too -/// far away to fit in its displacement field. It is converted to an inverse -/// conditional branch + an unconditional branch to the destination. -bool -MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { -#ifdef IN_PROGRESS - MachineInstr *MI = Br.MI; - MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); - - // Add an 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).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, - // split the MBB before the next instruction. - MachineBasicBlock *MBB = MI->getParent(); - MachineInstr *BMI = &MBB->back(); - bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); - - ++NumCBrFixed; - if (BMI != MI) { - if (llvm::next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) && - BMI->getOpcode() == Br.UncondBr) { - // Last MI in the BB is an unconditional branch. Can we simply invert the - // condition and swap destinations: - // beq L1 - // b L2 - // => - // bne L2 - // b L1 - MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB(); - if (isBBInRange(MI, NewDest, Br.MaxDisp)) { - DEBUG(dbgs() << " Invert Bcc condition and swap its destination with " - << *BMI); - BMI->getOperand(0).setMBB(DestBB); - MI->getOperand(0).setMBB(NewDest); - MI->getOperand(1).setImm(CC); - return true; - } - } - } - - if (NeedSplit) { - splitBlockBeforeInstr(MI); - // No need for the branch to the next block. We're adding an unconditional - // branch to the destination. - int delta = TII->GetInstSizeInBytes(&MBB->back()); - BBInfo[MBB->getNumber()].Size -= delta; - MBB->back().eraseFromParent(); - // BBInfo[SplitBB].Offset is wrong temporarily, fixed below - } - MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(MBB)); - - DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber() - << " also invert condition and change dest. to BB#" - << NextBB->getNumber() << "\n"); - - // 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, DebugLoc(), TII->get(MI->getOpcode())) - .addMBB(NextBB).addImm(CC).addReg(CCReg); - Br.MI = &MBB->back(); - BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); - if (isThumb) - BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB) - .addImm(ARMCC::AL).addReg(0); - else - BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); - BBInfo[MBB->getNumber()].Size += 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. - BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI); - MI->eraseFromParent(); - adjustBBOffsetsAfter(MBB); -#endif - return true; -} - void MipsConstantIslands::prescanForConstants() { unsigned int J; - PrescannedForConstants = true; for (MachineFunction::iterator B = MF->begin(), E = MF->end(); B != E; ++B) { for (MachineBasicBlock::instr_iterator I = @@ -1715,11 +238,10 @@ void MipsConstantIslands::prescanForConstants() { unsigned index = MCP->getConstantPoolIndex(C, 4); I->getOperand(2).ChangeToImmediate(index); DEBUG(dbgs() << "constant island constant " << *I << "\n"); - I->setDesc(TII->get(Mips::LwRxPcTcp16)); + I->setDesc(TII->get(Mips::LwRxPcTcpX16)); I->RemoveOperand(1); I->RemoveOperand(1); I->addOperand(MachineOperand::CreateCPI(index, 0)); - I->addOperand(MachineOperand::CreateImm(4)); } break; } @@ -1729,4 +251,3 @@ void MipsConstantIslands::prescanForConstants() { } } } - diff --git a/test/CodeGen/Mips/const4.ll b/test/CodeGen/Mips/const4.ll deleted file mode 100644 index 04da7318590..00000000000 --- a/test/CodeGen/Mips/const4.ll +++ /dev/null @@ -1,64 +0,0 @@ -; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static -mips16-constant-islands -mips-constant-islands-small-offset=20 < %s | FileCheck %s -check-prefix=offset20 - -; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static -mips16-constant-islands -mips-constant-islands-small-offset=40 < %s | FileCheck %s -check-prefix=offset40 - - -@i = common global i32 0, align 4 -@b = common global i32 0, align 4 - -; Function Attrs: nounwind -define void @t() #0 { -entry: - store i32 -559023410, i32* @i, align 4 - %0 = load i32* @b, align 4 - %tobool = icmp ne i32 %0, 0 - br i1 %tobool, label %if.then, label %if.else -; offset20: lw ${{[0-9]+}}, $CPI0_1 # 16 bit inst -; offset20: b $BB0_2 -; offset20: .align 2 -; offset20: $CPI0_0: -; offset20: .4byte 3735943886 -; offset20: $BB0_2: - -; offset40: beqz ${{[0-9]+}}, $BB0_3 -; offset40: jal foo -; offset40: nop -; offset40: b $BB0_4 -; offset40: .align 2 -; offset40: $CPI0_0: -; offset40: .4byte 3735943886 -; offset40: $BB0_3: -; offset40: jal goo - -if.then: ; preds = %entry - call void bitcast (void (...)* @foo to void ()*)() - br label %if.end - -if.else: ; preds = %entry - call void bitcast (void (...)* @goo to void ()*)() - br label %if.end - -if.end: ; preds = %if.else, %if.then - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - call void bitcast (void (...)* @hoo to void ()*)() - ret void -} - -declare void @foo(...) #1 - -declare void @goo(...) #1 - -declare void @hoo(...) #1 - -attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } - -!llvm.ident = !{!0} - -!0 = metadata !{metadata !"clang version 3.4 (gitosis@dmz-portal.mips.com:clang.git 3a50d847e098f36e3bf8bc14eea07a6cc35f7803) (gitosis@dmz-portal.mips.com:llvm.git f52db0b69f0c888bdc98bb2f13aaecc1e83288a9)"}