Reed Kotler | 5bf8020 | 2013-02-27 04:20:14 +0000 | [diff] [blame] | 1 | //===-- MipsConstantIslandPass.cpp - Emit Pc Relative loads----------------===// |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // |
| 11 | // This pass is used to make Pc relative loads of constants. |
| 12 | // For now, only Mips16 will use this. While it has the same name and |
| 13 | // uses many ideas from the LLVM ARM Constant Island Pass, it's not intended |
| 14 | // to reuse any of the code from the ARM version. |
| 15 | // |
| 16 | // Loading constants inline is expensive on Mips16 and it's in general better |
| 17 | // to place the constant nearby in code space and then it can be loaded with a |
| 18 | // simple 16 bit load instruction. |
| 19 | // |
| 20 | // The constants can be not just numbers but addresses of functions and labels. |
| 21 | // This can be particularly helpful in static relocation mode for embedded |
| 22 | // non linux targets. |
| 23 | // |
| 24 | // |
| 25 | |
| 26 | #define DEBUG_TYPE "mips-constant-islands" |
| 27 | |
| 28 | #include "Mips.h" |
| 29 | #include "MCTargetDesc/MipsBaseInfo.h" |
| 30 | #include "MipsTargetMachine.h" |
| 31 | #include "llvm/ADT/Statistic.h" |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 32 | #include "llvm/CodeGen/MachineBasicBlock.h" |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 33 | #include "llvm/CodeGen/MachineFunctionPass.h" |
| 34 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 35 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 36 | #include "llvm/IR/Function.h" |
| 37 | #include "llvm/Support/CommandLine.h" |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 38 | #include "llvm/Support/Debug.h" |
| 39 | #include "llvm/Support/InstIterator.h" |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 40 | #include "llvm/Support/MathExtras.h" |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 41 | #include "llvm/Support/raw_ostream.h" |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 42 | #include "llvm/Target/TargetInstrInfo.h" |
| 43 | #include "llvm/Target/TargetMachine.h" |
| 44 | #include "llvm/Target/TargetRegisterInfo.h" |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 45 | #include <algorithm> |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 46 | |
| 47 | using namespace llvm; |
| 48 | |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 49 | STATISTIC(NumCPEs, "Number of constpool entries"); |
| 50 | |
| 51 | // FIXME: This option should be removed once it has received sufficient testing. |
| 52 | static cl::opt<bool> |
| 53 | AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), |
| 54 | cl::desc("Align constant islands in code")); |
| 55 | |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 56 | namespace { |
| 57 | typedef MachineBasicBlock::iterator Iter; |
| 58 | typedef MachineBasicBlock::reverse_iterator ReverseIter; |
| 59 | |
| 60 | class MipsConstantIslands : public MachineFunctionPass { |
| 61 | |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 62 | const TargetMachine &TM; |
| 63 | bool IsPIC; |
| 64 | unsigned ABI; |
| 65 | const MipsSubtarget *STI; |
| 66 | const MipsInstrInfo *TII; |
| 67 | MachineFunction *MF; |
| 68 | MachineConstantPool *MCP; |
| 69 | |
| 70 | /// CPEntry - One per constant pool entry, keeping the machine instruction |
| 71 | /// pointer, the constpool index, and the number of CPUser's which |
| 72 | /// reference this entry. |
| 73 | struct CPEntry { |
| 74 | MachineInstr *CPEMI; |
| 75 | unsigned CPI; |
| 76 | unsigned RefCount; |
| 77 | CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) |
| 78 | : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} |
| 79 | }; |
| 80 | |
| 81 | /// CPEntries - Keep track of all of the constant pool entry machine |
| 82 | /// instructions. For each original constpool index (i.e. those that |
| 83 | /// existed upon entry to this pass), it keeps a vector of entries. |
| 84 | /// Original elements are cloned as we go along; the clones are |
| 85 | /// put in the vector of the original element, but have distinct CPIs. |
| 86 | std::vector<std::vector<CPEntry> > CPEntries; |
| 87 | |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 88 | public: |
| 89 | static char ID; |
| 90 | MipsConstantIslands(TargetMachine &tm) |
| 91 | : MachineFunctionPass(ID), TM(tm), |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 92 | IsPIC(TM.getRelocationModel() == Reloc::PIC_), |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 93 | ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()), |
| 94 | STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0){} |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 95 | |
| 96 | virtual const char *getPassName() const { |
| 97 | return "Mips Constant Islands"; |
| 98 | } |
| 99 | |
| 100 | bool runOnMachineFunction(MachineFunction &F); |
| 101 | |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 102 | void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs); |
| 103 | |
| 104 | void prescanForConstants(); |
| 105 | |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 106 | private: |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 107 | |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 108 | }; |
| 109 | |
| 110 | char MipsConstantIslands::ID = 0; |
| 111 | } // end of anonymous namespace |
| 112 | |
| 113 | /// createMipsLongBranchPass - Returns a pass that converts branches to long |
| 114 | /// branches. |
| 115 | FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) { |
| 116 | return new MipsConstantIslands(tm); |
| 117 | } |
| 118 | |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 119 | bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { |
Reed Kotler | 1595f36 | 2013-04-09 19:46:01 +0000 | [diff] [blame] | 120 | // The intention is for this to be a mips16 only pass for now |
| 121 | // FIXME: |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 122 | MF = &mf; |
| 123 | MCP = mf.getConstantPool(); |
| 124 | DEBUG(dbgs() << "constant island machine function " << "\n"); |
| 125 | if (!TM.getSubtarget<MipsSubtarget>().inMips16Mode() || |
| 126 | !MipsSubtarget::useConstantIslands()) { |
| 127 | return false; |
| 128 | } |
| 129 | TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo(); |
| 130 | DEBUG(dbgs() << "constant island processing " << "\n"); |
| 131 | // |
| 132 | // will need to make predermination if there is any constants we need to |
| 133 | // put in constant islands. TBD. |
| 134 | // |
| 135 | prescanForConstants(); |
| 136 | |
| 137 | // This pass invalidates liveness information when it splits basic blocks. |
| 138 | MF->getRegInfo().invalidateLiveness(); |
| 139 | |
| 140 | // Renumber all of the machine basic blocks in the function, guaranteeing that |
| 141 | // the numbers agree with the position of the block in the function. |
| 142 | MF->RenumberBlocks(); |
| 143 | |
| 144 | // Perform the initial placement of the constant pool entries. To start with, |
| 145 | // we put them all at the end of the function. |
| 146 | std::vector<MachineInstr*> CPEMIs; |
| 147 | if (!MCP->isEmpty()) |
| 148 | doInitialPlacement(CPEMIs); |
| 149 | |
| 150 | return true; |
Reed Kotler | bb3094a | 2013-02-27 03:33:58 +0000 | [diff] [blame] | 151 | } |
| 152 | |
Reed Kotler | 91ae982 | 2013-10-27 21:57:36 +0000 | [diff] [blame^] | 153 | /// doInitialPlacement - Perform the initial placement of the constant pool |
| 154 | /// entries. To start with, we put them all at the end of the function. |
| 155 | void |
| 156 | MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { |
| 157 | // Create the basic block to hold the CPE's. |
| 158 | MachineBasicBlock *BB = MF->CreateMachineBasicBlock(); |
| 159 | MF->push_back(BB); |
| 160 | |
| 161 | |
| 162 | // MachineConstantPool measures alignment in bytes. We measure in log2(bytes). |
| 163 | unsigned MaxAlign = Log2_32(MCP->getConstantPoolAlignment()); |
| 164 | |
| 165 | // Mark the basic block as required by the const-pool. |
| 166 | // If AlignConstantIslands isn't set, use 4-byte alignment for everything. |
| 167 | BB->setAlignment(AlignConstantIslands ? MaxAlign : 2); |
| 168 | |
| 169 | // The function needs to be as aligned as the basic blocks. The linker may |
| 170 | // move functions around based on their alignment. |
| 171 | MF->ensureAlignment(BB->getAlignment()); |
| 172 | |
| 173 | // Order the entries in BB by descending alignment. That ensures correct |
| 174 | // alignment of all entries as long as BB is sufficiently aligned. Keep |
| 175 | // track of the insertion point for each alignment. We are going to bucket |
| 176 | // sort the entries as they are created. |
| 177 | SmallVector<MachineBasicBlock::iterator, 8> InsPoint(MaxAlign + 1, BB->end()); |
| 178 | |
| 179 | // Add all of the constants from the constant pool to the end block, use an |
| 180 | // identity mapping of CPI's to CPE's. |
| 181 | const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); |
| 182 | |
| 183 | const DataLayout &TD = *MF->getTarget().getDataLayout(); |
| 184 | for (unsigned i = 0, e = CPs.size(); i != e; ++i) { |
| 185 | unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); |
| 186 | assert(Size >= 4 && "Too small constant pool entry"); |
| 187 | unsigned Align = CPs[i].getAlignment(); |
| 188 | assert(isPowerOf2_32(Align) && "Invalid alignment"); |
| 189 | // Verify that all constant pool entries are a multiple of their alignment. |
| 190 | // If not, we would have to pad them out so that instructions stay aligned. |
| 191 | assert((Size % Align) == 0 && "CP Entry not multiple of 4 bytes!"); |
| 192 | |
| 193 | // Insert CONSTPOOL_ENTRY before entries with a smaller alignment. |
| 194 | unsigned LogAlign = Log2_32(Align); |
| 195 | MachineBasicBlock::iterator InsAt = InsPoint[LogAlign]; |
| 196 | |
| 197 | MachineInstr *CPEMI = |
| 198 | BuildMI(*BB, InsAt, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY)) |
| 199 | .addImm(i).addConstantPoolIndex(i).addImm(Size); |
| 200 | |
| 201 | CPEMIs.push_back(CPEMI); |
| 202 | |
| 203 | // Ensure that future entries with higher alignment get inserted before |
| 204 | // CPEMI. This is bucket sort with iterators. |
| 205 | for (unsigned a = LogAlign + 1; a <= MaxAlign; ++a) |
| 206 | if (InsPoint[a] == InsAt) |
| 207 | InsPoint[a] = CPEMI; |
| 208 | // Add a new CPEntry, but no corresponding CPUser yet. |
| 209 | std::vector<CPEntry> CPEs; |
| 210 | CPEs.push_back(CPEntry(CPEMI, i)); |
| 211 | CPEntries.push_back(CPEs); |
| 212 | ++NumCPEs; |
| 213 | DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " |
| 214 | << Size << ", align = " << Align <<'\n'); |
| 215 | } |
| 216 | DEBUG(BB->dump()); |
| 217 | } |
| 218 | |
| 219 | |
| 220 | void MipsConstantIslands::prescanForConstants() { |
| 221 | unsigned int J; |
| 222 | for (MachineFunction::iterator B = |
| 223 | MF->begin(), E = MF->end(); B != E; ++B) { |
| 224 | for (MachineBasicBlock::instr_iterator I = |
| 225 | B->instr_begin(), EB = B->instr_end(); I != EB; ++I) { |
| 226 | switch(I->getDesc().getOpcode()) { |
| 227 | case Mips::LwConstant32: { |
| 228 | DEBUG(dbgs() << "constant island constant " << *I << "\n"); |
| 229 | J = I->getNumOperands(); |
| 230 | DEBUG(dbgs() << "num operands " << J << "\n"); |
| 231 | MachineOperand& Literal = I->getOperand(1); |
| 232 | if (Literal.isImm()) { |
| 233 | int64_t V = Literal.getImm(); |
| 234 | DEBUG(dbgs() << "literal " << V << "\n"); |
| 235 | Type *Int32Ty = |
| 236 | Type::getInt32Ty(MF->getFunction()->getContext()); |
| 237 | const Constant *C = ConstantInt::get(Int32Ty, V); |
| 238 | unsigned index = MCP->getConstantPoolIndex(C, 4); |
| 239 | I->getOperand(2).ChangeToImmediate(index); |
| 240 | DEBUG(dbgs() << "constant island constant " << *I << "\n"); |
| 241 | I->setDesc(TII->get(Mips::LwRxPcTcpX16)); |
| 242 | I->RemoveOperand(1); |
| 243 | I->RemoveOperand(1); |
| 244 | I->addOperand(MachineOperand::CreateCPI(index, 0)); |
| 245 | } |
| 246 | break; |
| 247 | } |
| 248 | default: |
| 249 | break; |
| 250 | } |
| 251 | } |
| 252 | } |
| 253 | } |