10b57cec5SDimitry Andric //===- MipsConstantIslandPass.cpp - Emit Pc Relative loads ----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass is used to make Pc relative loads of constants. 100b57cec5SDimitry Andric // For now, only Mips16 will use this. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // Loading constants inline is expensive on Mips16 and it's in general better 130b57cec5SDimitry Andric // to place the constant nearby in code space and then it can be loaded with a 140b57cec5SDimitry Andric // simple 16 bit load instruction. 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric // The constants can be not just numbers but addresses of functions and labels. 170b57cec5SDimitry Andric // This can be particularly helpful in static relocation mode for embedded 180b57cec5SDimitry Andric // non-linux targets. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #include "Mips.h" 230b57cec5SDimitry Andric #include "Mips16InstrInfo.h" 240b57cec5SDimitry Andric #include "MipsMachineFunction.h" 250b57cec5SDimitry Andric #include "MipsSubtarget.h" 260b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 270b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 280b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 290b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 300b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 380b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 390b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 400b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 410b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 420b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 430b57cec5SDimitry Andric #include "llvm/IR/Function.h" 440b57cec5SDimitry Andric #include "llvm/IR/Type.h" 450b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 460b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 470b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 480b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 490b57cec5SDimitry Andric #include "llvm/Support/Format.h" 500b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 520b57cec5SDimitry Andric #include <algorithm> 530b57cec5SDimitry Andric #include <cassert> 540b57cec5SDimitry Andric #include <cstdint> 550b57cec5SDimitry Andric #include <iterator> 560b57cec5SDimitry Andric #include <vector> 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric using namespace llvm; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric #define DEBUG_TYPE "mips-constant-islands" 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric STATISTIC(NumCPEs, "Number of constpool entries"); 630b57cec5SDimitry Andric STATISTIC(NumSplit, "Number of uncond branches inserted"); 640b57cec5SDimitry Andric STATISTIC(NumCBrFixed, "Number of cond branches fixed"); 650b57cec5SDimitry Andric STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // FIXME: This option should be removed once it has received sufficient testing. 680b57cec5SDimitry Andric static cl::opt<bool> 690b57cec5SDimitry Andric AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), 700b57cec5SDimitry Andric cl::desc("Align constant islands in code")); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric // Rather than do make check tests with huge amounts of code, we force 730b57cec5SDimitry Andric // the test to use this amount. 740b57cec5SDimitry Andric static cl::opt<int> ConstantIslandsSmallOffset( 750b57cec5SDimitry Andric "mips-constant-islands-small-offset", 760b57cec5SDimitry Andric cl::init(0), 770b57cec5SDimitry Andric cl::desc("Make small offsets be this amount for testing purposes"), 780b57cec5SDimitry Andric cl::Hidden); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // For testing purposes we tell it to not use relaxed load forms so that it 810b57cec5SDimitry Andric // will split blocks. 820b57cec5SDimitry Andric static cl::opt<bool> NoLoadRelaxation( 830b57cec5SDimitry Andric "mips-constant-islands-no-load-relaxation", 840b57cec5SDimitry Andric cl::init(false), 850b57cec5SDimitry Andric cl::desc("Don't relax loads to long loads - for testing purposes"), 860b57cec5SDimitry Andric cl::Hidden); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric static unsigned int branchTargetOperand(MachineInstr *MI) { 890b57cec5SDimitry Andric switch (MI->getOpcode()) { 900b57cec5SDimitry Andric case Mips::Bimm16: 910b57cec5SDimitry Andric case Mips::BimmX16: 920b57cec5SDimitry Andric case Mips::Bteqz16: 930b57cec5SDimitry Andric case Mips::BteqzX16: 940b57cec5SDimitry Andric case Mips::Btnez16: 950b57cec5SDimitry Andric case Mips::BtnezX16: 960b57cec5SDimitry Andric case Mips::JalB16: 970b57cec5SDimitry Andric return 0; 980b57cec5SDimitry Andric case Mips::BeqzRxImm16: 990b57cec5SDimitry Andric case Mips::BeqzRxImmX16: 1000b57cec5SDimitry Andric case Mips::BnezRxImm16: 1010b57cec5SDimitry Andric case Mips::BnezRxImmX16: 1020b57cec5SDimitry Andric return 1; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric llvm_unreachable("Unknown branch type"); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric static unsigned int longformBranchOpcode(unsigned int Opcode) { 1080b57cec5SDimitry Andric switch (Opcode) { 1090b57cec5SDimitry Andric case Mips::Bimm16: 1100b57cec5SDimitry Andric case Mips::BimmX16: 1110b57cec5SDimitry Andric return Mips::BimmX16; 1120b57cec5SDimitry Andric case Mips::Bteqz16: 1130b57cec5SDimitry Andric case Mips::BteqzX16: 1140b57cec5SDimitry Andric return Mips::BteqzX16; 1150b57cec5SDimitry Andric case Mips::Btnez16: 1160b57cec5SDimitry Andric case Mips::BtnezX16: 1170b57cec5SDimitry Andric return Mips::BtnezX16; 1180b57cec5SDimitry Andric case Mips::JalB16: 1190b57cec5SDimitry Andric return Mips::JalB16; 1200b57cec5SDimitry Andric case Mips::BeqzRxImm16: 1210b57cec5SDimitry Andric case Mips::BeqzRxImmX16: 1220b57cec5SDimitry Andric return Mips::BeqzRxImmX16; 1230b57cec5SDimitry Andric case Mips::BnezRxImm16: 1240b57cec5SDimitry Andric case Mips::BnezRxImmX16: 1250b57cec5SDimitry Andric return Mips::BnezRxImmX16; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric llvm_unreachable("Unknown branch type"); 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 130480093f4SDimitry Andric // FIXME: need to go through this whole constant islands port and check 131480093f4SDimitry Andric // the math for branch ranges and clean this up and make some functions 132480093f4SDimitry Andric // to calculate things that are done many times identically. 1330b57cec5SDimitry Andric // Need to refactor some of the code to call this routine. 1340b57cec5SDimitry Andric static unsigned int branchMaxOffsets(unsigned int Opcode) { 1350b57cec5SDimitry Andric unsigned Bits, Scale; 1360b57cec5SDimitry Andric switch (Opcode) { 1370b57cec5SDimitry Andric case Mips::Bimm16: 1380b57cec5SDimitry Andric Bits = 11; 1390b57cec5SDimitry Andric Scale = 2; 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric case Mips::BimmX16: 1420b57cec5SDimitry Andric Bits = 16; 1430b57cec5SDimitry Andric Scale = 2; 1440b57cec5SDimitry Andric break; 1450b57cec5SDimitry Andric case Mips::BeqzRxImm16: 1460b57cec5SDimitry Andric Bits = 8; 1470b57cec5SDimitry Andric Scale = 2; 1480b57cec5SDimitry Andric break; 1490b57cec5SDimitry Andric case Mips::BeqzRxImmX16: 1500b57cec5SDimitry Andric Bits = 16; 1510b57cec5SDimitry Andric Scale = 2; 1520b57cec5SDimitry Andric break; 1530b57cec5SDimitry Andric case Mips::BnezRxImm16: 1540b57cec5SDimitry Andric Bits = 8; 1550b57cec5SDimitry Andric Scale = 2; 1560b57cec5SDimitry Andric break; 1570b57cec5SDimitry Andric case Mips::BnezRxImmX16: 1580b57cec5SDimitry Andric Bits = 16; 1590b57cec5SDimitry Andric Scale = 2; 1600b57cec5SDimitry Andric break; 1610b57cec5SDimitry Andric case Mips::Bteqz16: 1620b57cec5SDimitry Andric Bits = 8; 1630b57cec5SDimitry Andric Scale = 2; 1640b57cec5SDimitry Andric break; 1650b57cec5SDimitry Andric case Mips::BteqzX16: 1660b57cec5SDimitry Andric Bits = 16; 1670b57cec5SDimitry Andric Scale = 2; 1680b57cec5SDimitry Andric break; 1690b57cec5SDimitry Andric case Mips::Btnez16: 1700b57cec5SDimitry Andric Bits = 8; 1710b57cec5SDimitry Andric Scale = 2; 1720b57cec5SDimitry Andric break; 1730b57cec5SDimitry Andric case Mips::BtnezX16: 1740b57cec5SDimitry Andric Bits = 16; 1750b57cec5SDimitry Andric Scale = 2; 1760b57cec5SDimitry Andric break; 1770b57cec5SDimitry Andric default: 1780b57cec5SDimitry Andric llvm_unreachable("Unknown branch type"); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; 1810b57cec5SDimitry Andric return MaxOffs; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric namespace { 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric using Iter = MachineBasicBlock::iterator; 1870b57cec5SDimitry Andric using ReverseIter = MachineBasicBlock::reverse_iterator; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// MipsConstantIslands - Due to limited PC-relative displacements, Mips 1900b57cec5SDimitry Andric /// requires constant pool entries to be scattered among the instructions 1910b57cec5SDimitry Andric /// inside a function. To do this, it completely ignores the normal LLVM 1920b57cec5SDimitry Andric /// constant pool; instead, it places constants wherever it feels like with 1930b57cec5SDimitry Andric /// special instructions. 1940b57cec5SDimitry Andric /// 1950b57cec5SDimitry Andric /// The terminology used in this pass includes: 1960b57cec5SDimitry Andric /// Islands - Clumps of constants placed in the function. 1970b57cec5SDimitry Andric /// Water - Potential places where an island could be formed. 1980b57cec5SDimitry Andric /// CPE - A constant pool entry that has been placed somewhere, which 1990b57cec5SDimitry Andric /// tracks a list of users. 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric class MipsConstantIslands : public MachineFunctionPass { 2020b57cec5SDimitry Andric /// BasicBlockInfo - Information about the offset and size of a single 2030b57cec5SDimitry Andric /// basic block. 2040b57cec5SDimitry Andric struct BasicBlockInfo { 2050b57cec5SDimitry Andric /// Offset - Distance from the beginning of the function to the beginning 2060b57cec5SDimitry Andric /// of this basic block. 2070b57cec5SDimitry Andric /// 2080b57cec5SDimitry Andric /// Offsets are computed assuming worst case padding before an aligned 2090b57cec5SDimitry Andric /// block. This means that subtracting basic block offsets always gives a 2100b57cec5SDimitry Andric /// conservative estimate of the real distance which may be smaller. 2110b57cec5SDimitry Andric /// 2120b57cec5SDimitry Andric /// Because worst case padding is used, the computed offset of an aligned 2130b57cec5SDimitry Andric /// block may not actually be aligned. 2140b57cec5SDimitry Andric unsigned Offset = 0; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric /// Size - Size of the basic block in bytes. If the block contains 2170b57cec5SDimitry Andric /// inline assembly, this is a worst case estimate. 2180b57cec5SDimitry Andric /// 2190b57cec5SDimitry Andric /// The size does not include any alignment padding whether from the 2200b57cec5SDimitry Andric /// beginning of the block, or from an aligned jump table at the end. 2210b57cec5SDimitry Andric unsigned Size = 0; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric BasicBlockInfo() = default; 2240b57cec5SDimitry Andric 2258bcb0991SDimitry Andric unsigned postOffset() const { return Offset + Size; } 2260b57cec5SDimitry Andric }; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric std::vector<BasicBlockInfo> BBInfo; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /// WaterList - A sorted list of basic blocks where islands could be placed 2310b57cec5SDimitry Andric /// (i.e. blocks that don't fall through to the following block, due 2320b57cec5SDimitry Andric /// to a return, unreachable, or unconditional branch). 2330b57cec5SDimitry Andric std::vector<MachineBasicBlock*> WaterList; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric /// NewWaterList - The subset of WaterList that was created since the 2360b57cec5SDimitry Andric /// previous iteration by inserting unconditional branches. 2370b57cec5SDimitry Andric SmallSet<MachineBasicBlock*, 4> NewWaterList; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric using water_iterator = std::vector<MachineBasicBlock *>::iterator; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric /// CPUser - One user of a constant pool, keeping the machine instruction 2420b57cec5SDimitry Andric /// pointer, the constant pool being referenced, and the max displacement 2430b57cec5SDimitry Andric /// allowed from the instruction to the CP. The HighWaterMark records the 2440b57cec5SDimitry Andric /// highest basic block where a new CPEntry can be placed. To ensure this 2450b57cec5SDimitry Andric /// pass terminates, the CP entries are initially placed at the end of the 2460b57cec5SDimitry Andric /// function and then move monotonically to lower addresses. The 2470b57cec5SDimitry Andric /// exception to this rule is when the current CP entry for a particular 2480b57cec5SDimitry Andric /// CPUser is out of range, but there is another CP entry for the same 2490b57cec5SDimitry Andric /// constant value in range. We want to use the existing in-range CP 2500b57cec5SDimitry Andric /// entry, but if it later moves out of range, the search for new water 2510b57cec5SDimitry Andric /// should resume where it left off. The HighWaterMark is used to record 2520b57cec5SDimitry Andric /// that point. 2530b57cec5SDimitry Andric struct CPUser { 2540b57cec5SDimitry Andric MachineInstr *MI; 2550b57cec5SDimitry Andric MachineInstr *CPEMI; 2560b57cec5SDimitry Andric MachineBasicBlock *HighWaterMark; 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric private: 2590b57cec5SDimitry Andric unsigned MaxDisp; 2600b57cec5SDimitry Andric unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions 2610b57cec5SDimitry Andric // with different displacements 2620b57cec5SDimitry Andric unsigned LongFormOpcode; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric public: 2650b57cec5SDimitry Andric bool NegOk; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, 2680b57cec5SDimitry Andric bool neg, 2690b57cec5SDimitry Andric unsigned longformmaxdisp, unsigned longformopcode) 2700b57cec5SDimitry Andric : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), 2710b57cec5SDimitry Andric LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode), 2720b57cec5SDimitry Andric NegOk(neg){ 2730b57cec5SDimitry Andric HighWaterMark = CPEMI->getParent(); 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric /// getMaxDisp - Returns the maximum displacement supported by MI. 2770b57cec5SDimitry Andric unsigned getMaxDisp() const { 2780b57cec5SDimitry Andric unsigned xMaxDisp = ConstantIslandsSmallOffset? 2790b57cec5SDimitry Andric ConstantIslandsSmallOffset: MaxDisp; 2800b57cec5SDimitry Andric return xMaxDisp; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric void setMaxDisp(unsigned val) { 2840b57cec5SDimitry Andric MaxDisp = val; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric unsigned getLongFormMaxDisp() const { 2880b57cec5SDimitry Andric return LongFormMaxDisp; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric unsigned getLongFormOpcode() const { 2920b57cec5SDimitry Andric return LongFormOpcode; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric }; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric /// CPUsers - Keep track of all of the machine instructions that use various 2970b57cec5SDimitry Andric /// constant pools and their max displacement. 2980b57cec5SDimitry Andric std::vector<CPUser> CPUsers; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric /// CPEntry - One per constant pool entry, keeping the machine instruction 3010b57cec5SDimitry Andric /// pointer, the constpool index, and the number of CPUser's which 3020b57cec5SDimitry Andric /// reference this entry. 3030b57cec5SDimitry Andric struct CPEntry { 3040b57cec5SDimitry Andric MachineInstr *CPEMI; 3050b57cec5SDimitry Andric unsigned CPI; 3060b57cec5SDimitry Andric unsigned RefCount; 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) 3090b57cec5SDimitry Andric : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} 3100b57cec5SDimitry Andric }; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric /// CPEntries - Keep track of all of the constant pool entry machine 3130b57cec5SDimitry Andric /// instructions. For each original constpool index (i.e. those that 3140b57cec5SDimitry Andric /// existed upon entry to this pass), it keeps a vector of entries. 3150b57cec5SDimitry Andric /// Original elements are cloned as we go along; the clones are 3160b57cec5SDimitry Andric /// put in the vector of the original element, but have distinct CPIs. 3170b57cec5SDimitry Andric std::vector<std::vector<CPEntry>> CPEntries; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric /// ImmBranch - One per immediate branch, keeping the machine instruction 3200b57cec5SDimitry Andric /// pointer, conditional or unconditional, the max displacement, 3210b57cec5SDimitry Andric /// and (if isCond is true) the corresponding unconditional branch 3220b57cec5SDimitry Andric /// opcode. 3230b57cec5SDimitry Andric struct ImmBranch { 3240b57cec5SDimitry Andric MachineInstr *MI; 3250b57cec5SDimitry Andric unsigned MaxDisp : 31; 3260b57cec5SDimitry Andric bool isCond : 1; 3270b57cec5SDimitry Andric int UncondBr; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) 3300b57cec5SDimitry Andric : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} 3310b57cec5SDimitry Andric }; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric /// ImmBranches - Keep track of all the immediate branch instructions. 3340b57cec5SDimitry Andric /// 3350b57cec5SDimitry Andric std::vector<ImmBranch> ImmBranches; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric /// HasFarJump - True if any far jump instruction has been emitted during 3380b57cec5SDimitry Andric /// the branch fix up pass. 3390b57cec5SDimitry Andric bool HasFarJump; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric const MipsSubtarget *STI = nullptr; 3420b57cec5SDimitry Andric const Mips16InstrInfo *TII; 3430b57cec5SDimitry Andric MipsFunctionInfo *MFI; 3440b57cec5SDimitry Andric MachineFunction *MF = nullptr; 3450b57cec5SDimitry Andric MachineConstantPool *MCP = nullptr; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric unsigned PICLabelUId; 3480b57cec5SDimitry Andric bool PrescannedForConstants = false; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric void initPICLabelUId(unsigned UId) { 3510b57cec5SDimitry Andric PICLabelUId = UId; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric unsigned createPICLabelUId() { 3550b57cec5SDimitry Andric return PICLabelUId++; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric public: 3590b57cec5SDimitry Andric static char ID; 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric MipsConstantIslands() : MachineFunctionPass(ID) {} 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric StringRef getPassName() const override { return "Mips Constant Islands"; } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 3680b57cec5SDimitry Andric return MachineFunctionProperties().set( 3690b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs); 3730b57cec5SDimitry Andric CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); 3748bcb0991SDimitry Andric Align getCPEAlign(const MachineInstr &CPEMI); 3750b57cec5SDimitry Andric void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs); 3760b57cec5SDimitry Andric unsigned getOffsetOf(MachineInstr *MI) const; 3770b57cec5SDimitry Andric unsigned getUserOffset(CPUser&) const; 3780b57cec5SDimitry Andric void dumpBBs(); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, 3810b57cec5SDimitry Andric unsigned Disp, bool NegativeOK); 3820b57cec5SDimitry Andric bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, 3830b57cec5SDimitry Andric const CPUser &U); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric void computeBlockSize(MachineBasicBlock *MBB); 3860b57cec5SDimitry Andric MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI); 3870b57cec5SDimitry Andric void updateForInsertedWaterBlock(MachineBasicBlock *NewBB); 3880b57cec5SDimitry Andric void adjustBBOffsetsAfter(MachineBasicBlock *BB); 3890b57cec5SDimitry Andric bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI); 3900b57cec5SDimitry Andric int findInRangeCPEntry(CPUser& U, unsigned UserOffset); 3910b57cec5SDimitry Andric int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset); 3920b57cec5SDimitry Andric bool findAvailableWater(CPUser&U, unsigned UserOffset, 3930b57cec5SDimitry Andric water_iterator &WaterIter); 3940b57cec5SDimitry Andric void createNewWater(unsigned CPUserIndex, unsigned UserOffset, 3950b57cec5SDimitry Andric MachineBasicBlock *&NewMBB); 3960b57cec5SDimitry Andric bool handleConstantPoolUser(unsigned CPUserIndex); 3970b57cec5SDimitry Andric void removeDeadCPEMI(MachineInstr *CPEMI); 3980b57cec5SDimitry Andric bool removeUnusedCPEntries(); 3990b57cec5SDimitry Andric bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset, 4000b57cec5SDimitry Andric MachineInstr *CPEMI, unsigned Disp, bool NegOk, 4010b57cec5SDimitry Andric bool DoDump = false); 4020b57cec5SDimitry Andric bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, 4030b57cec5SDimitry Andric CPUser &U, unsigned &Growth); 4040b57cec5SDimitry Andric bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); 4050b57cec5SDimitry Andric bool fixupImmediateBr(ImmBranch &Br); 4060b57cec5SDimitry Andric bool fixupConditionalBr(ImmBranch &Br); 4070b57cec5SDimitry Andric bool fixupUnconditionalBr(ImmBranch &Br); 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric void prescanForConstants(); 4100b57cec5SDimitry Andric }; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric } // end anonymous namespace 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric char MipsConstantIslands::ID = 0; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric bool MipsConstantIslands::isOffsetInRange 4170b57cec5SDimitry Andric (unsigned UserOffset, unsigned TrialOffset, 4180b57cec5SDimitry Andric const CPUser &U) { 4190b57cec5SDimitry Andric return isOffsetInRange(UserOffset, TrialOffset, 4200b57cec5SDimitry Andric U.getMaxDisp(), U.NegOk); 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4240b57cec5SDimitry Andric /// print block size and offset information - debugging 4250b57cec5SDimitry Andric LLVM_DUMP_METHOD void MipsConstantIslands::dumpBBs() { 4260b57cec5SDimitry Andric for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) { 4270b57cec5SDimitry Andric const BasicBlockInfo &BBI = BBInfo[J]; 4280b57cec5SDimitry Andric dbgs() << format("%08x %bb.%u\t", BBI.Offset, J) 4290b57cec5SDimitry Andric << format(" size=%#x\n", BBInfo[J].Size); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric #endif 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { 4350b57cec5SDimitry Andric // The intention is for this to be a mips16 only pass for now 4360b57cec5SDimitry Andric // FIXME: 4370b57cec5SDimitry Andric MF = &mf; 4380b57cec5SDimitry Andric MCP = mf.getConstantPool(); 4390b57cec5SDimitry Andric STI = &static_cast<const MipsSubtarget &>(mf.getSubtarget()); 4400b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "constant island machine function " 4410b57cec5SDimitry Andric << "\n"); 4420b57cec5SDimitry Andric if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { 4430b57cec5SDimitry Andric return false; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric TII = (const Mips16InstrInfo *)STI->getInstrInfo(); 4460b57cec5SDimitry Andric MFI = MF->getInfo<MipsFunctionInfo>(); 4470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "constant island processing " 4480b57cec5SDimitry Andric << "\n"); 4490b57cec5SDimitry Andric // 4500b57cec5SDimitry Andric // will need to make predermination if there is any constants we need to 4510b57cec5SDimitry Andric // put in constant islands. TBD. 4520b57cec5SDimitry Andric // 4530b57cec5SDimitry Andric if (!PrescannedForConstants) prescanForConstants(); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric HasFarJump = false; 4560b57cec5SDimitry Andric // This pass invalidates liveness information when it splits basic blocks. 4570b57cec5SDimitry Andric MF->getRegInfo().invalidateLiveness(); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric // Renumber all of the machine basic blocks in the function, guaranteeing that 4600b57cec5SDimitry Andric // the numbers agree with the position of the block in the function. 4610b57cec5SDimitry Andric MF->RenumberBlocks(); 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric bool MadeChange = false; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric // Perform the initial placement of the constant pool entries. To start with, 4660b57cec5SDimitry Andric // we put them all at the end of the function. 4670b57cec5SDimitry Andric std::vector<MachineInstr*> CPEMIs; 4680b57cec5SDimitry Andric if (!MCP->isEmpty()) 4690b57cec5SDimitry Andric doInitialPlacement(CPEMIs); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric /// The next UID to take is the first unused one. 4720b57cec5SDimitry Andric initPICLabelUId(CPEMIs.size()); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric // Do the initial scan of the function, building up information about the 4750b57cec5SDimitry Andric // sizes of each block, the location of all the water, and finding all of the 4760b57cec5SDimitry Andric // constant pool users. 4770b57cec5SDimitry Andric initializeFunctionInfo(CPEMIs); 4780b57cec5SDimitry Andric CPEMIs.clear(); 4790b57cec5SDimitry Andric LLVM_DEBUG(dumpBBs()); 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric /// Remove dead constant pool entries. 4820b57cec5SDimitry Andric MadeChange |= removeUnusedCPEntries(); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric // Iteratively place constant pool entries and fix up branches until there 4850b57cec5SDimitry Andric // is no change. 4860b57cec5SDimitry Andric unsigned NoCPIters = 0, NoBRIters = 0; 4870b57cec5SDimitry Andric (void)NoBRIters; 4880b57cec5SDimitry Andric while (true) { 4890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); 4900b57cec5SDimitry Andric bool CPChange = false; 4910b57cec5SDimitry Andric for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) 4920b57cec5SDimitry Andric CPChange |= handleConstantPoolUser(i); 4930b57cec5SDimitry Andric if (CPChange && ++NoCPIters > 30) 4940b57cec5SDimitry Andric report_fatal_error("Constant Island pass failed to converge!"); 4950b57cec5SDimitry Andric LLVM_DEBUG(dumpBBs()); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric // Clear NewWaterList now. If we split a block for branches, it should 4980b57cec5SDimitry Andric // appear as "new water" for the next iteration of constant pool placement. 4990b57cec5SDimitry Andric NewWaterList.clear(); 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); 5020b57cec5SDimitry Andric bool BRChange = false; 5030b57cec5SDimitry Andric for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) 5040b57cec5SDimitry Andric BRChange |= fixupImmediateBr(ImmBranches[i]); 5050b57cec5SDimitry Andric if (BRChange && ++NoBRIters > 30) 5060b57cec5SDimitry Andric report_fatal_error("Branch Fix Up pass failed to converge!"); 5070b57cec5SDimitry Andric LLVM_DEBUG(dumpBBs()); 5080b57cec5SDimitry Andric if (!CPChange && !BRChange) 5090b57cec5SDimitry Andric break; 5100b57cec5SDimitry Andric MadeChange = true; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << '\n'; dumpBBs()); 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric BBInfo.clear(); 5160b57cec5SDimitry Andric WaterList.clear(); 5170b57cec5SDimitry Andric CPUsers.clear(); 5180b57cec5SDimitry Andric CPEntries.clear(); 5190b57cec5SDimitry Andric ImmBranches.clear(); 5200b57cec5SDimitry Andric return MadeChange; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric /// doInitialPlacement - Perform the initial placement of the constant pool 5240b57cec5SDimitry Andric /// entries. To start with, we put them all at the end of the function. 5250b57cec5SDimitry Andric void 5260b57cec5SDimitry Andric MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { 5270b57cec5SDimitry Andric // Create the basic block to hold the CPE's. 5280b57cec5SDimitry Andric MachineBasicBlock *BB = MF->CreateMachineBasicBlock(); 5290b57cec5SDimitry Andric MF->push_back(BB); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric // MachineConstantPool measures alignment in bytes. We measure in log2(bytes). 532*5ffd83dbSDimitry Andric const Align MaxAlign = MCP->getConstantPoolAlign(); 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric // Mark the basic block as required by the const-pool. 5350b57cec5SDimitry Andric // If AlignConstantIslands isn't set, use 4-byte alignment for everything. 5368bcb0991SDimitry Andric BB->setAlignment(AlignConstantIslands ? MaxAlign : Align(4)); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric // The function needs to be as aligned as the basic blocks. The linker may 5390b57cec5SDimitry Andric // move functions around based on their alignment. 5400b57cec5SDimitry Andric MF->ensureAlignment(BB->getAlignment()); 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric // Order the entries in BB by descending alignment. That ensures correct 5430b57cec5SDimitry Andric // alignment of all entries as long as BB is sufficiently aligned. Keep 5440b57cec5SDimitry Andric // track of the insertion point for each alignment. We are going to bucket 5450b57cec5SDimitry Andric // sort the entries as they are created. 5468bcb0991SDimitry Andric SmallVector<MachineBasicBlock::iterator, 8> InsPoint(Log2(MaxAlign) + 1, 5478bcb0991SDimitry Andric BB->end()); 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // Add all of the constants from the constant pool to the end block, use an 5500b57cec5SDimitry Andric // identity mapping of CPI's to CPE's. 5510b57cec5SDimitry Andric const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric const DataLayout &TD = MF->getDataLayout(); 5540b57cec5SDimitry Andric for (unsigned i = 0, e = CPs.size(); i != e; ++i) { 5550b57cec5SDimitry Andric unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); 5560b57cec5SDimitry Andric assert(Size >= 4 && "Too small constant pool entry"); 557*5ffd83dbSDimitry Andric Align Alignment = CPs[i].getAlign(); 5580b57cec5SDimitry Andric // Verify that all constant pool entries are a multiple of their alignment. 5590b57cec5SDimitry Andric // If not, we would have to pad them out so that instructions stay aligned. 560*5ffd83dbSDimitry Andric assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!"); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // Insert CONSTPOOL_ENTRY before entries with a smaller alignment. 563*5ffd83dbSDimitry Andric unsigned LogAlign = Log2(Alignment); 5640b57cec5SDimitry Andric MachineBasicBlock::iterator InsAt = InsPoint[LogAlign]; 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric MachineInstr *CPEMI = 5670b57cec5SDimitry Andric BuildMI(*BB, InsAt, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY)) 5680b57cec5SDimitry Andric .addImm(i).addConstantPoolIndex(i).addImm(Size); 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric CPEMIs.push_back(CPEMI); 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric // Ensure that future entries with higher alignment get inserted before 5730b57cec5SDimitry Andric // CPEMI. This is bucket sort with iterators. 5748bcb0991SDimitry Andric for (unsigned a = LogAlign + 1; a <= Log2(MaxAlign); ++a) 5750b57cec5SDimitry Andric if (InsPoint[a] == InsAt) 5760b57cec5SDimitry Andric InsPoint[a] = CPEMI; 5770b57cec5SDimitry Andric // Add a new CPEntry, but no corresponding CPUser yet. 5780b57cec5SDimitry Andric CPEntries.emplace_back(1, CPEntry(CPEMI, i)); 5790b57cec5SDimitry Andric ++NumCPEs; 5800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " 581*5ffd83dbSDimitry Andric << Size << ", align = " << Alignment.value() << '\n'); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric LLVM_DEBUG(BB->dump()); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric /// BBHasFallthrough - Return true if the specified basic block can fallthrough 5870b57cec5SDimitry Andric /// into the block immediately after it. 5880b57cec5SDimitry Andric static bool BBHasFallthrough(MachineBasicBlock *MBB) { 5890b57cec5SDimitry Andric // Get the next machine basic block in the function. 5900b57cec5SDimitry Andric MachineFunction::iterator MBBI = MBB->getIterator(); 5910b57cec5SDimitry Andric // Can't fall off end of function. 5920b57cec5SDimitry Andric if (std::next(MBBI) == MBB->getParent()->end()) 5930b57cec5SDimitry Andric return false; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric MachineBasicBlock *NextBB = &*std::next(MBBI); 5960b57cec5SDimitry Andric for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), 5970b57cec5SDimitry Andric E = MBB->succ_end(); I != E; ++I) 5980b57cec5SDimitry Andric if (*I == NextBB) 5990b57cec5SDimitry Andric return true; 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric return false; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric /// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, 6050b57cec5SDimitry Andric /// look up the corresponding CPEntry. 6060b57cec5SDimitry Andric MipsConstantIslands::CPEntry 6070b57cec5SDimitry Andric *MipsConstantIslands::findConstPoolEntry(unsigned CPI, 6080b57cec5SDimitry Andric const MachineInstr *CPEMI) { 6090b57cec5SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[CPI]; 6100b57cec5SDimitry Andric // Number of entries per constpool index should be small, just do a 6110b57cec5SDimitry Andric // linear search. 6120b57cec5SDimitry Andric for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { 6130b57cec5SDimitry Andric if (CPEs[i].CPEMI == CPEMI) 6140b57cec5SDimitry Andric return &CPEs[i]; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric return nullptr; 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric 6198bcb0991SDimitry Andric /// getCPEAlign - Returns the required alignment of the constant pool entry 6200b57cec5SDimitry Andric /// represented by CPEMI. Alignment is measured in log2(bytes) units. 6218bcb0991SDimitry Andric Align MipsConstantIslands::getCPEAlign(const MachineInstr &CPEMI) { 6220b57cec5SDimitry Andric assert(CPEMI.getOpcode() == Mips::CONSTPOOL_ENTRY); 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric // Everything is 4-byte aligned unless AlignConstantIslands is set. 6250b57cec5SDimitry Andric if (!AlignConstantIslands) 6268bcb0991SDimitry Andric return Align(4); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric unsigned CPI = CPEMI.getOperand(1).getIndex(); 6290b57cec5SDimitry Andric assert(CPI < MCP->getConstants().size() && "Invalid constant pool index."); 630*5ffd83dbSDimitry Andric return MCP->getConstants()[CPI].getAlign(); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric /// initializeFunctionInfo - Do the initial scan of the function, building up 6340b57cec5SDimitry Andric /// information about the sizes of each block, the location of all the water, 6350b57cec5SDimitry Andric /// and finding all of the constant pool users. 6360b57cec5SDimitry Andric void MipsConstantIslands:: 6370b57cec5SDimitry Andric initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { 6380b57cec5SDimitry Andric BBInfo.clear(); 6390b57cec5SDimitry Andric BBInfo.resize(MF->getNumBlockIDs()); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric // First thing, compute the size of all basic blocks, and see if the function 6420b57cec5SDimitry Andric // has any inline assembly in it. If so, we have to be conservative about 6430b57cec5SDimitry Andric // alignment assumptions, as we don't know for sure the size of any 6440b57cec5SDimitry Andric // instructions in the inline assembly. 6450b57cec5SDimitry Andric for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) 6460b57cec5SDimitry Andric computeBlockSize(&*I); 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // Compute block offsets. 6490b57cec5SDimitry Andric adjustBBOffsetsAfter(&MF->front()); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric // Now go back through the instructions and build up our data structures. 6520b57cec5SDimitry Andric for (MachineBasicBlock &MBB : *MF) { 6530b57cec5SDimitry Andric // If this block doesn't fall through into the next MBB, then this is 6540b57cec5SDimitry Andric // 'water' that a constant pool island could be placed. 6550b57cec5SDimitry Andric if (!BBHasFallthrough(&MBB)) 6560b57cec5SDimitry Andric WaterList.push_back(&MBB); 6570b57cec5SDimitry Andric for (MachineInstr &MI : MBB) { 6580b57cec5SDimitry Andric if (MI.isDebugInstr()) 6590b57cec5SDimitry Andric continue; 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric int Opc = MI.getOpcode(); 6620b57cec5SDimitry Andric if (MI.isBranch()) { 6630b57cec5SDimitry Andric bool isCond = false; 6640b57cec5SDimitry Andric unsigned Bits = 0; 6650b57cec5SDimitry Andric unsigned Scale = 1; 6660b57cec5SDimitry Andric int UOpc = Opc; 6670b57cec5SDimitry Andric switch (Opc) { 6680b57cec5SDimitry Andric default: 6690b57cec5SDimitry Andric continue; // Ignore other branches for now 6700b57cec5SDimitry Andric case Mips::Bimm16: 6710b57cec5SDimitry Andric Bits = 11; 6720b57cec5SDimitry Andric Scale = 2; 6730b57cec5SDimitry Andric isCond = false; 6740b57cec5SDimitry Andric break; 6750b57cec5SDimitry Andric case Mips::BimmX16: 6760b57cec5SDimitry Andric Bits = 16; 6770b57cec5SDimitry Andric Scale = 2; 6780b57cec5SDimitry Andric isCond = false; 6790b57cec5SDimitry Andric break; 6800b57cec5SDimitry Andric case Mips::BeqzRxImm16: 6810b57cec5SDimitry Andric UOpc=Mips::Bimm16; 6820b57cec5SDimitry Andric Bits = 8; 6830b57cec5SDimitry Andric Scale = 2; 6840b57cec5SDimitry Andric isCond = true; 6850b57cec5SDimitry Andric break; 6860b57cec5SDimitry Andric case Mips::BeqzRxImmX16: 6870b57cec5SDimitry Andric UOpc=Mips::Bimm16; 6880b57cec5SDimitry Andric Bits = 16; 6890b57cec5SDimitry Andric Scale = 2; 6900b57cec5SDimitry Andric isCond = true; 6910b57cec5SDimitry Andric break; 6920b57cec5SDimitry Andric case Mips::BnezRxImm16: 6930b57cec5SDimitry Andric UOpc=Mips::Bimm16; 6940b57cec5SDimitry Andric Bits = 8; 6950b57cec5SDimitry Andric Scale = 2; 6960b57cec5SDimitry Andric isCond = true; 6970b57cec5SDimitry Andric break; 6980b57cec5SDimitry Andric case Mips::BnezRxImmX16: 6990b57cec5SDimitry Andric UOpc=Mips::Bimm16; 7000b57cec5SDimitry Andric Bits = 16; 7010b57cec5SDimitry Andric Scale = 2; 7020b57cec5SDimitry Andric isCond = true; 7030b57cec5SDimitry Andric break; 7040b57cec5SDimitry Andric case Mips::Bteqz16: 7050b57cec5SDimitry Andric UOpc=Mips::Bimm16; 7060b57cec5SDimitry Andric Bits = 8; 7070b57cec5SDimitry Andric Scale = 2; 7080b57cec5SDimitry Andric isCond = true; 7090b57cec5SDimitry Andric break; 7100b57cec5SDimitry Andric case Mips::BteqzX16: 7110b57cec5SDimitry Andric UOpc=Mips::Bimm16; 7120b57cec5SDimitry Andric Bits = 16; 7130b57cec5SDimitry Andric Scale = 2; 7140b57cec5SDimitry Andric isCond = true; 7150b57cec5SDimitry Andric break; 7160b57cec5SDimitry Andric case Mips::Btnez16: 7170b57cec5SDimitry Andric UOpc=Mips::Bimm16; 7180b57cec5SDimitry Andric Bits = 8; 7190b57cec5SDimitry Andric Scale = 2; 7200b57cec5SDimitry Andric isCond = true; 7210b57cec5SDimitry Andric break; 7220b57cec5SDimitry Andric case Mips::BtnezX16: 7230b57cec5SDimitry Andric UOpc=Mips::Bimm16; 7240b57cec5SDimitry Andric Bits = 16; 7250b57cec5SDimitry Andric Scale = 2; 7260b57cec5SDimitry Andric isCond = true; 7270b57cec5SDimitry Andric break; 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric // Record this immediate branch. 7300b57cec5SDimitry Andric unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; 7310b57cec5SDimitry Andric ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc)); 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric if (Opc == Mips::CONSTPOOL_ENTRY) 7350b57cec5SDimitry Andric continue; 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric // Scan the instructions for constant pool operands. 7380b57cec5SDimitry Andric for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op) 7390b57cec5SDimitry Andric if (MI.getOperand(op).isCPI()) { 7400b57cec5SDimitry Andric // We found one. The addressing mode tells us the max displacement 7410b57cec5SDimitry Andric // from the PC that this instruction permits. 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric // Basic size info comes from the TSFlags field. 7440b57cec5SDimitry Andric unsigned Bits = 0; 7450b57cec5SDimitry Andric unsigned Scale = 1; 7460b57cec5SDimitry Andric bool NegOk = false; 7470b57cec5SDimitry Andric unsigned LongFormBits = 0; 7480b57cec5SDimitry Andric unsigned LongFormScale = 0; 7490b57cec5SDimitry Andric unsigned LongFormOpcode = 0; 7500b57cec5SDimitry Andric switch (Opc) { 7510b57cec5SDimitry Andric default: 7520b57cec5SDimitry Andric llvm_unreachable("Unknown addressing mode for CP reference!"); 7530b57cec5SDimitry Andric case Mips::LwRxPcTcp16: 7540b57cec5SDimitry Andric Bits = 8; 7550b57cec5SDimitry Andric Scale = 4; 7560b57cec5SDimitry Andric LongFormOpcode = Mips::LwRxPcTcpX16; 7570b57cec5SDimitry Andric LongFormBits = 14; 7580b57cec5SDimitry Andric LongFormScale = 1; 7590b57cec5SDimitry Andric break; 7600b57cec5SDimitry Andric case Mips::LwRxPcTcpX16: 7610b57cec5SDimitry Andric Bits = 14; 7620b57cec5SDimitry Andric Scale = 1; 7630b57cec5SDimitry Andric NegOk = true; 7640b57cec5SDimitry Andric break; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric // Remember that this is a user of a CP entry. 7670b57cec5SDimitry Andric unsigned CPI = MI.getOperand(op).getIndex(); 7680b57cec5SDimitry Andric MachineInstr *CPEMI = CPEMIs[CPI]; 7690b57cec5SDimitry Andric unsigned MaxOffs = ((1 << Bits)-1) * Scale; 7700b57cec5SDimitry Andric unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale; 7710b57cec5SDimitry Andric CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs, 7720b57cec5SDimitry Andric LongFormOpcode)); 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // Increment corresponding CPEntry reference count. 7750b57cec5SDimitry Andric CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); 7760b57cec5SDimitry Andric assert(CPE && "Cannot find a corresponding CPEntry!"); 7770b57cec5SDimitry Andric CPE->RefCount++; 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric // Instructions can only use one CP entry, don't bother scanning the 7800b57cec5SDimitry Andric // rest of the operands. 7810b57cec5SDimitry Andric break; 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric /// computeBlockSize - Compute the size and some alignment information for MBB. 7880b57cec5SDimitry Andric /// This function updates BBInfo directly. 7890b57cec5SDimitry Andric void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) { 7900b57cec5SDimitry Andric BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; 7910b57cec5SDimitry Andric BBI.Size = 0; 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric for (const MachineInstr &MI : *MBB) 7940b57cec5SDimitry Andric BBI.Size += TII->getInstSizeInBytes(MI); 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric /// getOffsetOf - Return the current offset of the specified machine instruction 7980b57cec5SDimitry Andric /// from the start of the function. This offset changes as stuff is moved 7990b57cec5SDimitry Andric /// around inside the function. 8000b57cec5SDimitry Andric unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const { 8010b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric // The offset is composed of two things: the sum of the sizes of all MBB's 8040b57cec5SDimitry Andric // before this instruction's block, and the offset from the start of the block 8050b57cec5SDimitry Andric // it is in. 8060b57cec5SDimitry Andric unsigned Offset = BBInfo[MBB->getNumber()].Offset; 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // Sum instructions before MI in MBB. 8090b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { 8100b57cec5SDimitry Andric assert(I != MBB->end() && "Didn't find MI in its own basic block?"); 8110b57cec5SDimitry Andric Offset += TII->getInstSizeInBytes(*I); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric return Offset; 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric /// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB 8170b57cec5SDimitry Andric /// ID. 8180b57cec5SDimitry Andric static bool CompareMBBNumbers(const MachineBasicBlock *LHS, 8190b57cec5SDimitry Andric const MachineBasicBlock *RHS) { 8200b57cec5SDimitry Andric return LHS->getNumber() < RHS->getNumber(); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric /// updateForInsertedWaterBlock - When a block is newly inserted into the 8240b57cec5SDimitry Andric /// machine function, it upsets all of the block numbers. Renumber the blocks 8250b57cec5SDimitry Andric /// and update the arrays that parallel this numbering. 8260b57cec5SDimitry Andric void MipsConstantIslands::updateForInsertedWaterBlock 8270b57cec5SDimitry Andric (MachineBasicBlock *NewBB) { 8280b57cec5SDimitry Andric // Renumber the MBB's to keep them consecutive. 8290b57cec5SDimitry Andric NewBB->getParent()->RenumberBlocks(NewBB); 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // Insert an entry into BBInfo to align it properly with the (newly 8320b57cec5SDimitry Andric // renumbered) block numbers. 8330b57cec5SDimitry Andric BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric // Next, update WaterList. Specifically, we need to add NewMBB as having 8360b57cec5SDimitry Andric // available water after it. 8370b57cec5SDimitry Andric water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers); 8380b57cec5SDimitry Andric WaterList.insert(IP, NewBB); 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric unsigned MipsConstantIslands::getUserOffset(CPUser &U) const { 8420b57cec5SDimitry Andric return getOffsetOf(U.MI); 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric /// Split the basic block containing MI into two blocks, which are joined by 8460b57cec5SDimitry Andric /// an unconditional branch. Update data structures and renumber blocks to 8470b57cec5SDimitry Andric /// account for this change and returns the newly created block. 8480b57cec5SDimitry Andric MachineBasicBlock * 8490b57cec5SDimitry Andric MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { 8500b57cec5SDimitry Andric MachineBasicBlock *OrigBB = MI.getParent(); 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric // Create a new MBB for the code after the OrigBB. 8530b57cec5SDimitry Andric MachineBasicBlock *NewBB = 8540b57cec5SDimitry Andric MF->CreateMachineBasicBlock(OrigBB->getBasicBlock()); 8550b57cec5SDimitry Andric MachineFunction::iterator MBBI = ++OrigBB->getIterator(); 8560b57cec5SDimitry Andric MF->insert(MBBI, NewBB); 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric // Splice the instructions starting with MI over to NewBB. 8590b57cec5SDimitry Andric NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric // Add an unconditional branch from OrigBB to NewBB. 8620b57cec5SDimitry Andric // Note the new unconditional branch is not being recorded. 8630b57cec5SDimitry Andric // There doesn't seem to be meaningful DebugInfo available; this doesn't 8640b57cec5SDimitry Andric // correspond to anything in the source. 8650b57cec5SDimitry Andric BuildMI(OrigBB, DebugLoc(), TII->get(Mips::Bimm16)).addMBB(NewBB); 8660b57cec5SDimitry Andric ++NumSplit; 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric // Update the CFG. All succs of OrigBB are now succs of NewBB. 8690b57cec5SDimitry Andric NewBB->transferSuccessors(OrigBB); 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric // OrigBB branches to NewBB. 8720b57cec5SDimitry Andric OrigBB->addSuccessor(NewBB); 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric // Update internal data structures to account for the newly inserted MBB. 8750b57cec5SDimitry Andric // This is almost the same as updateForInsertedWaterBlock, except that 8760b57cec5SDimitry Andric // the Water goes after OrigBB, not NewBB. 8770b57cec5SDimitry Andric MF->RenumberBlocks(NewBB); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Insert an entry into BBInfo to align it properly with the (newly 8800b57cec5SDimitry Andric // renumbered) block numbers. 8810b57cec5SDimitry Andric BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric // Next, update WaterList. Specifically, we need to add OrigMBB as having 8840b57cec5SDimitry Andric // available water after it (but not if it's already there, which happens 8850b57cec5SDimitry Andric // when splitting before a conditional branch that is followed by an 8860b57cec5SDimitry Andric // unconditional branch - in that case we want to insert NewBB). 8870b57cec5SDimitry Andric water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers); 8880b57cec5SDimitry Andric MachineBasicBlock* WaterBB = *IP; 8890b57cec5SDimitry Andric if (WaterBB == OrigBB) 8900b57cec5SDimitry Andric WaterList.insert(std::next(IP), NewBB); 8910b57cec5SDimitry Andric else 8920b57cec5SDimitry Andric WaterList.insert(IP, OrigBB); 8930b57cec5SDimitry Andric NewWaterList.insert(OrigBB); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric // Figure out how large the OrigBB is. As the first half of the original 8960b57cec5SDimitry Andric // block, it cannot contain a tablejump. The size includes 8970b57cec5SDimitry Andric // the new jump we added. (It should be possible to do this without 8980b57cec5SDimitry Andric // recounting everything, but it's very confusing, and this is rarely 8990b57cec5SDimitry Andric // executed.) 9000b57cec5SDimitry Andric computeBlockSize(OrigBB); 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric // Figure out how large the NewMBB is. As the second half of the original 9030b57cec5SDimitry Andric // block, it may contain a tablejump. 9040b57cec5SDimitry Andric computeBlockSize(NewBB); 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric // All BBOffsets following these blocks must be modified. 9070b57cec5SDimitry Andric adjustBBOffsetsAfter(OrigBB); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric return NewBB; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool 9130b57cec5SDimitry Andric /// reference) is within MaxDisp of TrialOffset (a proposed location of a 9140b57cec5SDimitry Andric /// constant pool entry). 9150b57cec5SDimitry Andric bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset, 9160b57cec5SDimitry Andric unsigned TrialOffset, unsigned MaxDisp, 9170b57cec5SDimitry Andric bool NegativeOK) { 9180b57cec5SDimitry Andric if (UserOffset <= TrialOffset) { 9190b57cec5SDimitry Andric // User before the Trial. 9200b57cec5SDimitry Andric if (TrialOffset - UserOffset <= MaxDisp) 9210b57cec5SDimitry Andric return true; 9220b57cec5SDimitry Andric } else if (NegativeOK) { 9230b57cec5SDimitry Andric if (UserOffset - TrialOffset <= MaxDisp) 9240b57cec5SDimitry Andric return true; 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric return false; 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric /// isWaterInRange - Returns true if a CPE placed after the specified 9300b57cec5SDimitry Andric /// Water (a basic block) will be in range for the specific MI. 9310b57cec5SDimitry Andric /// 9320b57cec5SDimitry Andric /// Compute how much the function will grow by inserting a CPE after Water. 9330b57cec5SDimitry Andric bool MipsConstantIslands::isWaterInRange(unsigned UserOffset, 9340b57cec5SDimitry Andric MachineBasicBlock* Water, CPUser &U, 9350b57cec5SDimitry Andric unsigned &Growth) { 9368bcb0991SDimitry Andric unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(); 9378bcb0991SDimitry Andric unsigned NextBlockOffset; 9388bcb0991SDimitry Andric Align NextBlockAlignment; 9390b57cec5SDimitry Andric MachineFunction::const_iterator NextBlock = ++Water->getIterator(); 9400b57cec5SDimitry Andric if (NextBlock == MF->end()) { 9410b57cec5SDimitry Andric NextBlockOffset = BBInfo[Water->getNumber()].postOffset(); 942*5ffd83dbSDimitry Andric NextBlockAlignment = Align(1); 9430b57cec5SDimitry Andric } else { 9440b57cec5SDimitry Andric NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset; 9450b57cec5SDimitry Andric NextBlockAlignment = NextBlock->getAlignment(); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric unsigned Size = U.CPEMI->getOperand(2).getImm(); 9480b57cec5SDimitry Andric unsigned CPEEnd = CPEOffset + Size; 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric // The CPE may be able to hide in the alignment padding before the next 9510b57cec5SDimitry Andric // block. It may also cause more padding to be required if it is more aligned 9520b57cec5SDimitry Andric // that the next block. 9530b57cec5SDimitry Andric if (CPEEnd > NextBlockOffset) { 9540b57cec5SDimitry Andric Growth = CPEEnd - NextBlockOffset; 9550b57cec5SDimitry Andric // Compute the padding that would go at the end of the CPE to align the next 9560b57cec5SDimitry Andric // block. 9578bcb0991SDimitry Andric Growth += offsetToAlignment(CPEEnd, NextBlockAlignment); 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric // If the CPE is to be inserted before the instruction, that will raise 9600b57cec5SDimitry Andric // the offset of the instruction. Also account for unknown alignment padding 9610b57cec5SDimitry Andric // in blocks between CPE and the user. 9620b57cec5SDimitry Andric if (CPEOffset < UserOffset) 9630b57cec5SDimitry Andric UserOffset += Growth; 9640b57cec5SDimitry Andric } else 9650b57cec5SDimitry Andric // CPE fits in existing padding. 9660b57cec5SDimitry Andric Growth = 0; 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric return isOffsetInRange(UserOffset, CPEOffset, U); 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric /// isCPEntryInRange - Returns true if the distance between specific MI and 9720b57cec5SDimitry Andric /// specific ConstPool entry instruction can fit in MI's displacement field. 9730b57cec5SDimitry Andric bool MipsConstantIslands::isCPEntryInRange 9740b57cec5SDimitry Andric (MachineInstr *MI, unsigned UserOffset, 9750b57cec5SDimitry Andric MachineInstr *CPEMI, unsigned MaxDisp, 9760b57cec5SDimitry Andric bool NegOk, bool DoDump) { 9770b57cec5SDimitry Andric unsigned CPEOffset = getOffsetOf(CPEMI); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric if (DoDump) { 9800b57cec5SDimitry Andric LLVM_DEBUG({ 9810b57cec5SDimitry Andric unsigned Block = MI->getParent()->getNumber(); 9820b57cec5SDimitry Andric const BasicBlockInfo &BBI = BBInfo[Block]; 9830b57cec5SDimitry Andric dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm() 9840b57cec5SDimitry Andric << " max delta=" << MaxDisp 9850b57cec5SDimitry Andric << format(" insn address=%#x", UserOffset) << " in " 9860b57cec5SDimitry Andric << printMBBReference(*MI->getParent()) << ": " 9870b57cec5SDimitry Andric << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI 9880b57cec5SDimitry Andric << format("CPE address=%#x offset=%+d: ", CPEOffset, 9890b57cec5SDimitry Andric int(CPEOffset - UserOffset)); 9900b57cec5SDimitry Andric }); 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk); 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric #ifndef NDEBUG 9970b57cec5SDimitry Andric /// BBIsJumpedOver - Return true of the specified basic block's only predecessor 9980b57cec5SDimitry Andric /// unconditionally branches to its only successor. 9990b57cec5SDimitry Andric static bool BBIsJumpedOver(MachineBasicBlock *MBB) { 10000b57cec5SDimitry Andric if (MBB->pred_size() != 1 || MBB->succ_size() != 1) 10010b57cec5SDimitry Andric return false; 10020b57cec5SDimitry Andric MachineBasicBlock *Succ = *MBB->succ_begin(); 10030b57cec5SDimitry Andric MachineBasicBlock *Pred = *MBB->pred_begin(); 10040b57cec5SDimitry Andric MachineInstr *PredMI = &Pred->back(); 10050b57cec5SDimitry Andric if (PredMI->getOpcode() == Mips::Bimm16) 10060b57cec5SDimitry Andric return PredMI->getOperand(0).getMBB() == Succ; 10070b57cec5SDimitry Andric return false; 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric #endif 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) { 10120b57cec5SDimitry Andric unsigned BBNum = BB->getNumber(); 10130b57cec5SDimitry Andric for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) { 10140b57cec5SDimitry Andric // Get the offset and known bits at the end of the layout predecessor. 10150b57cec5SDimitry Andric // Include the alignment of the current block. 10160b57cec5SDimitry Andric unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size; 10170b57cec5SDimitry Andric BBInfo[i].Offset = Offset; 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric } 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric /// decrementCPEReferenceCount - find the constant pool entry with index CPI 10220b57cec5SDimitry Andric /// and instruction CPEMI, and decrement its refcount. If the refcount 10230b57cec5SDimitry Andric /// becomes 0 remove the entry and instruction. Returns true if we removed 10240b57cec5SDimitry Andric /// the entry, false if we didn't. 10250b57cec5SDimitry Andric bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI, 10260b57cec5SDimitry Andric MachineInstr *CPEMI) { 10270b57cec5SDimitry Andric // Find the old entry. Eliminate it if it is no longer used. 10280b57cec5SDimitry Andric CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); 10290b57cec5SDimitry Andric assert(CPE && "Unexpected!"); 10300b57cec5SDimitry Andric if (--CPE->RefCount == 0) { 10310b57cec5SDimitry Andric removeDeadCPEMI(CPEMI); 10320b57cec5SDimitry Andric CPE->CPEMI = nullptr; 10330b57cec5SDimitry Andric --NumCPEs; 10340b57cec5SDimitry Andric return true; 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric return false; 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric /// LookForCPEntryInRange - see if the currently referenced CPE is in range; 10400b57cec5SDimitry Andric /// if not, see if an in-range clone of the CPE is in range, and if so, 10410b57cec5SDimitry Andric /// change the data structures so the user references the clone. Returns: 10420b57cec5SDimitry Andric /// 0 = no existing entry found 10430b57cec5SDimitry Andric /// 1 = entry found, and there were no code insertions or deletions 10440b57cec5SDimitry Andric /// 2 = entry found, and there were code insertions or deletions 10450b57cec5SDimitry Andric int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) 10460b57cec5SDimitry Andric { 10470b57cec5SDimitry Andric MachineInstr *UserMI = U.MI; 10480b57cec5SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric // Check to see if the CPE is already in-range. 10510b57cec5SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk, 10520b57cec5SDimitry Andric true)) { 10530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "In range\n"); 10540b57cec5SDimitry Andric return 1; 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric // No. Look for previously created clones of the CPE that are in range. 10580b57cec5SDimitry Andric unsigned CPI = CPEMI->getOperand(1).getIndex(); 10590b57cec5SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[CPI]; 10600b57cec5SDimitry Andric for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { 10610b57cec5SDimitry Andric // We already tried this one 10620b57cec5SDimitry Andric if (CPEs[i].CPEMI == CPEMI) 10630b57cec5SDimitry Andric continue; 10640b57cec5SDimitry Andric // Removing CPEs can leave empty entries, skip 10650b57cec5SDimitry Andric if (CPEs[i].CPEMI == nullptr) 10660b57cec5SDimitry Andric continue; 10670b57cec5SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(), 10680b57cec5SDimitry Andric U.NegOk)) { 10690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" 10700b57cec5SDimitry Andric << CPEs[i].CPI << "\n"); 10710b57cec5SDimitry Andric // Point the CPUser node to the replacement 10720b57cec5SDimitry Andric U.CPEMI = CPEs[i].CPEMI; 10730b57cec5SDimitry Andric // Change the CPI in the instruction operand to refer to the clone. 10740b57cec5SDimitry Andric for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) 10750b57cec5SDimitry Andric if (UserMI->getOperand(j).isCPI()) { 10760b57cec5SDimitry Andric UserMI->getOperand(j).setIndex(CPEs[i].CPI); 10770b57cec5SDimitry Andric break; 10780b57cec5SDimitry Andric } 10790b57cec5SDimitry Andric // Adjust the refcount of the clone... 10800b57cec5SDimitry Andric CPEs[i].RefCount++; 10810b57cec5SDimitry Andric // ...and the original. If we didn't remove the old entry, none of the 10820b57cec5SDimitry Andric // addresses changed, so we don't need another pass. 10830b57cec5SDimitry Andric return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric return 0; 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric /// LookForCPEntryInRange - see if the currently referenced CPE is in range; 10900b57cec5SDimitry Andric /// This version checks if the longer form of the instruction can be used to 10910b57cec5SDimitry Andric /// to satisfy things. 10920b57cec5SDimitry Andric /// if not, see if an in-range clone of the CPE is in range, and if so, 10930b57cec5SDimitry Andric /// change the data structures so the user references the clone. Returns: 10940b57cec5SDimitry Andric /// 0 = no existing entry found 10950b57cec5SDimitry Andric /// 1 = entry found, and there were no code insertions or deletions 10960b57cec5SDimitry Andric /// 2 = entry found, and there were code insertions or deletions 10970b57cec5SDimitry Andric int MipsConstantIslands::findLongFormInRangeCPEntry 10980b57cec5SDimitry Andric (CPUser& U, unsigned UserOffset) 10990b57cec5SDimitry Andric { 11000b57cec5SDimitry Andric MachineInstr *UserMI = U.MI; 11010b57cec5SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric // Check to see if the CPE is already in-range. 11040b57cec5SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEMI, 11050b57cec5SDimitry Andric U.getLongFormMaxDisp(), U.NegOk, 11060b57cec5SDimitry Andric true)) { 11070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "In range\n"); 11080b57cec5SDimitry Andric UserMI->setDesc(TII->get(U.getLongFormOpcode())); 11090b57cec5SDimitry Andric U.setMaxDisp(U.getLongFormMaxDisp()); 11100b57cec5SDimitry Andric return 2; // instruction is longer length now 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric // No. Look for previously created clones of the CPE that are in range. 11140b57cec5SDimitry Andric unsigned CPI = CPEMI->getOperand(1).getIndex(); 11150b57cec5SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[CPI]; 11160b57cec5SDimitry Andric for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { 11170b57cec5SDimitry Andric // We already tried this one 11180b57cec5SDimitry Andric if (CPEs[i].CPEMI == CPEMI) 11190b57cec5SDimitry Andric continue; 11200b57cec5SDimitry Andric // Removing CPEs can leave empty entries, skip 11210b57cec5SDimitry Andric if (CPEs[i].CPEMI == nullptr) 11220b57cec5SDimitry Andric continue; 11230b57cec5SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, 11240b57cec5SDimitry Andric U.getLongFormMaxDisp(), U.NegOk)) { 11250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" 11260b57cec5SDimitry Andric << CPEs[i].CPI << "\n"); 11270b57cec5SDimitry Andric // Point the CPUser node to the replacement 11280b57cec5SDimitry Andric U.CPEMI = CPEs[i].CPEMI; 11290b57cec5SDimitry Andric // Change the CPI in the instruction operand to refer to the clone. 11300b57cec5SDimitry Andric for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) 11310b57cec5SDimitry Andric if (UserMI->getOperand(j).isCPI()) { 11320b57cec5SDimitry Andric UserMI->getOperand(j).setIndex(CPEs[i].CPI); 11330b57cec5SDimitry Andric break; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric // Adjust the refcount of the clone... 11360b57cec5SDimitry Andric CPEs[i].RefCount++; 11370b57cec5SDimitry Andric // ...and the original. If we didn't remove the old entry, none of the 11380b57cec5SDimitry Andric // addresses changed, so we don't need another pass. 11390b57cec5SDimitry Andric return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric return 0; 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric /// getUnconditionalBrDisp - Returns the maximum displacement that can fit in 11460b57cec5SDimitry Andric /// the specific unconditional branch instruction. 11470b57cec5SDimitry Andric static inline unsigned getUnconditionalBrDisp(int Opc) { 11480b57cec5SDimitry Andric switch (Opc) { 11490b57cec5SDimitry Andric case Mips::Bimm16: 11500b57cec5SDimitry Andric return ((1<<10)-1)*2; 11510b57cec5SDimitry Andric case Mips::BimmX16: 11520b57cec5SDimitry Andric return ((1<<16)-1)*2; 11530b57cec5SDimitry Andric default: 11540b57cec5SDimitry Andric break; 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric return ((1<<16)-1)*2; 11570b57cec5SDimitry Andric } 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric /// findAvailableWater - Look for an existing entry in the WaterList in which 11600b57cec5SDimitry Andric /// we can place the CPE referenced from U so it's within range of U's MI. 11610b57cec5SDimitry Andric /// Returns true if found, false if not. If it returns true, WaterIter 11620b57cec5SDimitry Andric /// is set to the WaterList entry. 11630b57cec5SDimitry Andric /// To ensure that this pass 11640b57cec5SDimitry Andric /// terminates, the CPE location for a particular CPUser is only allowed to 11650b57cec5SDimitry Andric /// move to a lower address, so search backward from the end of the list and 11660b57cec5SDimitry Andric /// prefer the first water that is in range. 11670b57cec5SDimitry Andric bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset, 11680b57cec5SDimitry Andric water_iterator &WaterIter) { 11690b57cec5SDimitry Andric if (WaterList.empty()) 11700b57cec5SDimitry Andric return false; 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric unsigned BestGrowth = ~0u; 11730b57cec5SDimitry Andric for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();; 11740b57cec5SDimitry Andric --IP) { 11750b57cec5SDimitry Andric MachineBasicBlock* WaterBB = *IP; 11760b57cec5SDimitry Andric // Check if water is in range and is either at a lower address than the 11770b57cec5SDimitry Andric // current "high water mark" or a new water block that was created since 11780b57cec5SDimitry Andric // the previous iteration by inserting an unconditional branch. In the 11790b57cec5SDimitry Andric // latter case, we want to allow resetting the high water mark back to 11800b57cec5SDimitry Andric // this new water since we haven't seen it before. Inserting branches 11810b57cec5SDimitry Andric // should be relatively uncommon and when it does happen, we want to be 11820b57cec5SDimitry Andric // sure to take advantage of it for all the CPEs near that block, so that 11830b57cec5SDimitry Andric // we don't insert more branches than necessary. 11840b57cec5SDimitry Andric unsigned Growth; 11850b57cec5SDimitry Andric if (isWaterInRange(UserOffset, WaterBB, U, Growth) && 11860b57cec5SDimitry Andric (WaterBB->getNumber() < U.HighWaterMark->getNumber() || 11870b57cec5SDimitry Andric NewWaterList.count(WaterBB)) && Growth < BestGrowth) { 11880b57cec5SDimitry Andric // This is the least amount of required padding seen so far. 11890b57cec5SDimitry Andric BestGrowth = Growth; 11900b57cec5SDimitry Andric WaterIter = IP; 11910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB) 11920b57cec5SDimitry Andric << " Growth=" << Growth << '\n'); 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric // Keep looking unless it is perfect. 11950b57cec5SDimitry Andric if (BestGrowth == 0) 11960b57cec5SDimitry Andric return true; 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric if (IP == B) 11990b57cec5SDimitry Andric break; 12000b57cec5SDimitry Andric } 12010b57cec5SDimitry Andric return BestGrowth != ~0u; 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric /// createNewWater - No existing WaterList entry will work for 12050b57cec5SDimitry Andric /// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the 12060b57cec5SDimitry Andric /// block is used if in range, and the conditional branch munged so control 12070b57cec5SDimitry Andric /// flow is correct. Otherwise the block is split to create a hole with an 12080b57cec5SDimitry Andric /// unconditional branch around it. In either case NewMBB is set to a 12090b57cec5SDimitry Andric /// block following which the new island can be inserted (the WaterList 12100b57cec5SDimitry Andric /// is not adjusted). 12110b57cec5SDimitry Andric void MipsConstantIslands::createNewWater(unsigned CPUserIndex, 12120b57cec5SDimitry Andric unsigned UserOffset, 12130b57cec5SDimitry Andric MachineBasicBlock *&NewMBB) { 12140b57cec5SDimitry Andric CPUser &U = CPUsers[CPUserIndex]; 12150b57cec5SDimitry Andric MachineInstr *UserMI = U.MI; 12160b57cec5SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 12170b57cec5SDimitry Andric MachineBasicBlock *UserMBB = UserMI->getParent(); 12180b57cec5SDimitry Andric const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()]; 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric // If the block does not end in an unconditional branch already, and if the 12210b57cec5SDimitry Andric // end of the block is within range, make new water there. 12220b57cec5SDimitry Andric if (BBHasFallthrough(UserMBB)) { 12230b57cec5SDimitry Andric // Size of branch to insert. 12240b57cec5SDimitry Andric unsigned Delta = 2; 12250b57cec5SDimitry Andric // Compute the offset where the CPE will begin. 12268bcb0991SDimitry Andric unsigned CPEOffset = UserBBI.postOffset() + Delta; 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric if (isOffsetInRange(UserOffset, CPEOffset, U)) { 12290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB) 12300b57cec5SDimitry Andric << format(", expected CPE offset %#x\n", CPEOffset)); 12310b57cec5SDimitry Andric NewMBB = &*++UserMBB->getIterator(); 12320b57cec5SDimitry Andric // Add an unconditional branch from UserMBB to fallthrough block. Record 12330b57cec5SDimitry Andric // it for branch lengthening; this new branch will not get out of range, 12340b57cec5SDimitry Andric // but if the preceding conditional branch is out of range, the targets 12350b57cec5SDimitry Andric // will be exchanged, and the altered branch may be out of range, so the 12360b57cec5SDimitry Andric // machinery has to know about it. 12370b57cec5SDimitry Andric int UncondBr = Mips::Bimm16; 12380b57cec5SDimitry Andric BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); 12390b57cec5SDimitry Andric unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); 12400b57cec5SDimitry Andric ImmBranches.push_back(ImmBranch(&UserMBB->back(), 12410b57cec5SDimitry Andric MaxDisp, false, UncondBr)); 12420b57cec5SDimitry Andric BBInfo[UserMBB->getNumber()].Size += Delta; 12430b57cec5SDimitry Andric adjustBBOffsetsAfter(UserMBB); 12440b57cec5SDimitry Andric return; 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric // What a big block. Find a place within the block to split it. 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric // Try to split the block so it's fully aligned. Compute the latest split 12510b57cec5SDimitry Andric // point where we can add a 4-byte branch instruction, and then align to 12528bcb0991SDimitry Andric // Align which is the largest possible alignment in the function. 12538bcb0991SDimitry Andric const Align Align = MF->getAlignment(); 12540b57cec5SDimitry Andric unsigned BaseInsertOffset = UserOffset + U.getMaxDisp(); 12550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x", 12560b57cec5SDimitry Andric BaseInsertOffset)); 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric // The 4 in the following is for the unconditional branch we'll be inserting 12590b57cec5SDimitry Andric // Alignment of the island is handled 12600b57cec5SDimitry Andric // inside isOffsetInRange. 12610b57cec5SDimitry Andric BaseInsertOffset -= 4; 12620b57cec5SDimitry Andric 12630b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) 12648bcb0991SDimitry Andric << " la=" << Log2(Align) << '\n'); 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric // This could point off the end of the block if we've already got constant 12670b57cec5SDimitry Andric // pool entries following this block; only the last one is in the water list. 12680b57cec5SDimitry Andric // Back past any possible branches (allow for a conditional and a maximally 12690b57cec5SDimitry Andric // long unconditional). 12700b57cec5SDimitry Andric if (BaseInsertOffset + 8 >= UserBBI.postOffset()) { 12710b57cec5SDimitry Andric BaseInsertOffset = UserBBI.postOffset() - 8; 12720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric unsigned EndInsertOffset = BaseInsertOffset + 4 + 12750b57cec5SDimitry Andric CPEMI->getOperand(2).getImm(); 12760b57cec5SDimitry Andric MachineBasicBlock::iterator MI = UserMI; 12770b57cec5SDimitry Andric ++MI; 12780b57cec5SDimitry Andric unsigned CPUIndex = CPUserIndex+1; 12790b57cec5SDimitry Andric unsigned NumCPUsers = CPUsers.size(); 12800b57cec5SDimitry Andric //MachineInstr *LastIT = 0; 12810b57cec5SDimitry Andric for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI); 12820b57cec5SDimitry Andric Offset < BaseInsertOffset; 12830b57cec5SDimitry Andric Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) { 12840b57cec5SDimitry Andric assert(MI != UserMBB->end() && "Fell off end of block"); 12850b57cec5SDimitry Andric if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { 12860b57cec5SDimitry Andric CPUser &U = CPUsers[CPUIndex]; 12870b57cec5SDimitry Andric if (!isOffsetInRange(Offset, EndInsertOffset, U)) { 12880b57cec5SDimitry Andric // Shift intertion point by one unit of alignment so it is within reach. 12898bcb0991SDimitry Andric BaseInsertOffset -= Align.value(); 12908bcb0991SDimitry Andric EndInsertOffset -= Align.value(); 12910b57cec5SDimitry Andric } 12920b57cec5SDimitry Andric // This is overly conservative, as we don't account for CPEMIs being 12930b57cec5SDimitry Andric // reused within the block, but it doesn't matter much. Also assume CPEs 12940b57cec5SDimitry Andric // are added in order with alignment padding. We may eventually be able 12950b57cec5SDimitry Andric // to pack the aligned CPEs better. 12960b57cec5SDimitry Andric EndInsertOffset += U.CPEMI->getOperand(2).getImm(); 12970b57cec5SDimitry Andric CPUIndex++; 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric NewMBB = splitBlockBeforeInstr(*--MI); 13020b57cec5SDimitry Andric } 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric /// handleConstantPoolUser - Analyze the specified user, checking to see if it 13050b57cec5SDimitry Andric /// is out-of-range. If so, pick up the constant pool value and move it some 13060b57cec5SDimitry Andric /// place in-range. Return true if we changed any addresses (thus must run 13070b57cec5SDimitry Andric /// another pass of branch lengthening), false otherwise. 13080b57cec5SDimitry Andric bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { 13090b57cec5SDimitry Andric CPUser &U = CPUsers[CPUserIndex]; 13100b57cec5SDimitry Andric MachineInstr *UserMI = U.MI; 13110b57cec5SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 13120b57cec5SDimitry Andric unsigned CPI = CPEMI->getOperand(1).getIndex(); 13130b57cec5SDimitry Andric unsigned Size = CPEMI->getOperand(2).getImm(); 13140b57cec5SDimitry Andric // Compute this only once, it's expensive. 13150b57cec5SDimitry Andric unsigned UserOffset = getUserOffset(U); 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric // See if the current entry is within range, or there is a clone of it 13180b57cec5SDimitry Andric // in range. 13190b57cec5SDimitry Andric int result = findInRangeCPEntry(U, UserOffset); 13200b57cec5SDimitry Andric if (result==1) return false; 13210b57cec5SDimitry Andric else if (result==2) return true; 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric // Look for water where we can place this CPE. 13240b57cec5SDimitry Andric MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock(); 13250b57cec5SDimitry Andric MachineBasicBlock *NewMBB; 13260b57cec5SDimitry Andric water_iterator IP; 13270b57cec5SDimitry Andric if (findAvailableWater(U, UserOffset, IP)) { 13280b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Found water in range\n"); 13290b57cec5SDimitry Andric MachineBasicBlock *WaterBB = *IP; 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andric // If the original WaterList entry was "new water" on this iteration, 13320b57cec5SDimitry Andric // propagate that to the new island. This is just keeping NewWaterList 13330b57cec5SDimitry Andric // updated to match the WaterList, which will be updated below. 13340b57cec5SDimitry Andric if (NewWaterList.erase(WaterBB)) 13350b57cec5SDimitry Andric NewWaterList.insert(NewIsland); 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric // The new CPE goes before the following block (NewMBB). 13380b57cec5SDimitry Andric NewMBB = &*++WaterBB->getIterator(); 13390b57cec5SDimitry Andric } else { 13400b57cec5SDimitry Andric // No water found. 13410b57cec5SDimitry Andric // we first see if a longer form of the instrucion could have reached 13420b57cec5SDimitry Andric // the constant. in that case we won't bother to split 13430b57cec5SDimitry Andric if (!NoLoadRelaxation) { 13440b57cec5SDimitry Andric result = findLongFormInRangeCPEntry(U, UserOffset); 13450b57cec5SDimitry Andric if (result != 0) return true; 13460b57cec5SDimitry Andric } 13470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "No water found\n"); 13480b57cec5SDimitry Andric createNewWater(CPUserIndex, UserOffset, NewMBB); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric // splitBlockBeforeInstr adds to WaterList, which is important when it is 13510b57cec5SDimitry Andric // called while handling branches so that the water will be seen on the 13520b57cec5SDimitry Andric // next iteration for constant pools, but in this context, we don't want 13530b57cec5SDimitry Andric // it. Check for this so it will be removed from the WaterList. 13540b57cec5SDimitry Andric // Also remove any entry from NewWaterList. 13550b57cec5SDimitry Andric MachineBasicBlock *WaterBB = &*--NewMBB->getIterator(); 13560b57cec5SDimitry Andric IP = llvm::find(WaterList, WaterBB); 13570b57cec5SDimitry Andric if (IP != WaterList.end()) 13580b57cec5SDimitry Andric NewWaterList.erase(WaterBB); 13590b57cec5SDimitry Andric 13600b57cec5SDimitry Andric // We are adding new water. Update NewWaterList. 13610b57cec5SDimitry Andric NewWaterList.insert(NewIsland); 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric // Remove the original WaterList entry; we want subsequent insertions in 13650b57cec5SDimitry Andric // this vicinity to go after the one we're about to insert. This 13660b57cec5SDimitry Andric // considerably reduces the number of times we have to move the same CPE 13670b57cec5SDimitry Andric // more than once and is also important to ensure the algorithm terminates. 13680b57cec5SDimitry Andric if (IP != WaterList.end()) 13690b57cec5SDimitry Andric WaterList.erase(IP); 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric // Okay, we know we can put an island before NewMBB now, do it! 13720b57cec5SDimitry Andric MF->insert(NewMBB->getIterator(), NewIsland); 13730b57cec5SDimitry Andric 13740b57cec5SDimitry Andric // Update internal data structures to account for the newly inserted MBB. 13750b57cec5SDimitry Andric updateForInsertedWaterBlock(NewIsland); 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric // Decrement the old entry, and remove it if refcount becomes 0. 13780b57cec5SDimitry Andric decrementCPEReferenceCount(CPI, CPEMI); 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric // No existing clone of this CPE is within range. 13810b57cec5SDimitry Andric // We will be generating a new clone. Get a UID for it. 13820b57cec5SDimitry Andric unsigned ID = createPICLabelUId(); 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric // Now that we have an island to add the CPE to, clone the original CPE and 13850b57cec5SDimitry Andric // add it to the island. 13860b57cec5SDimitry Andric U.HighWaterMark = NewIsland; 13870b57cec5SDimitry Andric U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY)) 13880b57cec5SDimitry Andric .addImm(ID).addConstantPoolIndex(CPI).addImm(Size); 13890b57cec5SDimitry Andric CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); 13900b57cec5SDimitry Andric ++NumCPEs; 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric // Mark the basic block as aligned as required by the const-pool entry. 13938bcb0991SDimitry Andric NewIsland->setAlignment(getCPEAlign(*U.CPEMI)); 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric // Increase the size of the island block to account for the new entry. 13960b57cec5SDimitry Andric BBInfo[NewIsland->getNumber()].Size += Size; 13970b57cec5SDimitry Andric adjustBBOffsetsAfter(&*--NewIsland->getIterator()); 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric // Finally, change the CPI in the instruction operand to be ID. 14000b57cec5SDimitry Andric for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i) 14010b57cec5SDimitry Andric if (UserMI->getOperand(i).isCPI()) { 14020b57cec5SDimitry Andric UserMI->getOperand(i).setIndex(ID); 14030b57cec5SDimitry Andric break; 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric LLVM_DEBUG( 14070b57cec5SDimitry Andric dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI 14080b57cec5SDimitry Andric << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric return true; 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric /// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update 14140b57cec5SDimitry Andric /// sizes and offsets of impacted basic blocks. 14150b57cec5SDimitry Andric void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) { 14160b57cec5SDimitry Andric MachineBasicBlock *CPEBB = CPEMI->getParent(); 14170b57cec5SDimitry Andric unsigned Size = CPEMI->getOperand(2).getImm(); 14180b57cec5SDimitry Andric CPEMI->eraseFromParent(); 14190b57cec5SDimitry Andric BBInfo[CPEBB->getNumber()].Size -= Size; 14200b57cec5SDimitry Andric // All succeeding offsets have the current size value added in, fix this. 14210b57cec5SDimitry Andric if (CPEBB->empty()) { 14220b57cec5SDimitry Andric BBInfo[CPEBB->getNumber()].Size = 0; 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andric // This block no longer needs to be aligned. 14258bcb0991SDimitry Andric CPEBB->setAlignment(Align(1)); 14268bcb0991SDimitry Andric } else { 14270b57cec5SDimitry Andric // Entries are sorted by descending alignment, so realign from the front. 14288bcb0991SDimitry Andric CPEBB->setAlignment(getCPEAlign(*CPEBB->begin())); 14298bcb0991SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric adjustBBOffsetsAfter(CPEBB); 14320b57cec5SDimitry Andric // An island has only one predecessor BB and one successor BB. Check if 14330b57cec5SDimitry Andric // this BB's predecessor jumps directly to this BB's successor. This 14340b57cec5SDimitry Andric // shouldn't happen currently. 14350b57cec5SDimitry Andric assert(!BBIsJumpedOver(CPEBB) && "How did this happen?"); 14360b57cec5SDimitry Andric // FIXME: remove the empty blocks after all the work is done? 14370b57cec5SDimitry Andric } 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric /// removeUnusedCPEntries - Remove constant pool entries whose refcounts 14400b57cec5SDimitry Andric /// are zero. 14410b57cec5SDimitry Andric bool MipsConstantIslands::removeUnusedCPEntries() { 14420b57cec5SDimitry Andric unsigned MadeChange = false; 14430b57cec5SDimitry Andric for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { 14440b57cec5SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[i]; 14450b57cec5SDimitry Andric for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) { 14460b57cec5SDimitry Andric if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) { 14470b57cec5SDimitry Andric removeDeadCPEMI(CPEs[j].CPEMI); 14480b57cec5SDimitry Andric CPEs[j].CPEMI = nullptr; 14490b57cec5SDimitry Andric MadeChange = true; 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric return MadeChange; 14540b57cec5SDimitry Andric } 14550b57cec5SDimitry Andric 14560b57cec5SDimitry Andric /// isBBInRange - Returns true if the distance between specific MI and 14570b57cec5SDimitry Andric /// specific BB can fit in MI's displacement field. 14580b57cec5SDimitry Andric bool MipsConstantIslands::isBBInRange 14590b57cec5SDimitry Andric (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) { 14600b57cec5SDimitry Andric unsigned PCAdj = 4; 14610b57cec5SDimitry Andric unsigned BrOffset = getOffsetOf(MI) + PCAdj; 14620b57cec5SDimitry Andric unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) 14650b57cec5SDimitry Andric << " from " << printMBBReference(*MI->getParent()) 14660b57cec5SDimitry Andric << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) 14670b57cec5SDimitry Andric << " to " << DestOffset << " offset " 14680b57cec5SDimitry Andric << int(DestOffset - BrOffset) << "\t" << *MI); 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric if (BrOffset <= DestOffset) { 14710b57cec5SDimitry Andric // Branch before the Dest. 14720b57cec5SDimitry Andric if (DestOffset-BrOffset <= MaxDisp) 14730b57cec5SDimitry Andric return true; 14740b57cec5SDimitry Andric } else { 14750b57cec5SDimitry Andric if (BrOffset-DestOffset <= MaxDisp) 14760b57cec5SDimitry Andric return true; 14770b57cec5SDimitry Andric } 14780b57cec5SDimitry Andric return false; 14790b57cec5SDimitry Andric } 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric /// fixupImmediateBr - Fix up an immediate branch whose destination is too far 14820b57cec5SDimitry Andric /// away to fit in its displacement field. 14830b57cec5SDimitry Andric bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) { 14840b57cec5SDimitry Andric MachineInstr *MI = Br.MI; 14850b57cec5SDimitry Andric unsigned TargetOperand = branchTargetOperand(MI); 14860b57cec5SDimitry Andric MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB(); 14870b57cec5SDimitry Andric 14880b57cec5SDimitry Andric // Check to see if the DestBB is already in-range. 14890b57cec5SDimitry Andric if (isBBInRange(MI, DestBB, Br.MaxDisp)) 14900b57cec5SDimitry Andric return false; 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric if (!Br.isCond) 14930b57cec5SDimitry Andric return fixupUnconditionalBr(Br); 14940b57cec5SDimitry Andric return fixupConditionalBr(Br); 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric /// fixupUnconditionalBr - Fix up an unconditional branch whose destination is 14980b57cec5SDimitry Andric /// too far away to fit in its displacement field. If the LR register has been 14990b57cec5SDimitry Andric /// spilled in the epilogue, then we can use BL to implement a far jump. 15000b57cec5SDimitry Andric /// Otherwise, add an intermediate branch instruction to a branch. 15010b57cec5SDimitry Andric bool 15020b57cec5SDimitry Andric MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { 15030b57cec5SDimitry Andric MachineInstr *MI = Br.MI; 15040b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 15050b57cec5SDimitry Andric MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); 15060b57cec5SDimitry Andric // Use BL to implement far jump. 15070b57cec5SDimitry Andric unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2; 15080b57cec5SDimitry Andric if (isBBInRange(MI, DestBB, BimmX16MaxDisp)) { 15090b57cec5SDimitry Andric Br.MaxDisp = BimmX16MaxDisp; 15100b57cec5SDimitry Andric MI->setDesc(TII->get(Mips::BimmX16)); 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric else { 15130b57cec5SDimitry Andric // need to give the math a more careful look here 15140b57cec5SDimitry Andric // this is really a segment address and not 15150b57cec5SDimitry Andric // a PC relative address. FIXME. But I think that 15160b57cec5SDimitry Andric // just reducing the bits by 1 as I've done is correct. 15170b57cec5SDimitry Andric // The basic block we are branching too much be longword aligned. 15180b57cec5SDimitry Andric // we know that RA is saved because we always save it right now. 15190b57cec5SDimitry Andric // this requirement will be relaxed later but we also have an alternate 15200b57cec5SDimitry Andric // way to implement this that I will implement that does not need jal. 1521480093f4SDimitry Andric // We should have a way to back out this alignment restriction 1522480093f4SDimitry Andric // if we "can" later. but it is not harmful. 15230b57cec5SDimitry Andric // 15248bcb0991SDimitry Andric DestBB->setAlignment(Align(4)); 15250b57cec5SDimitry Andric Br.MaxDisp = ((1<<24)-1) * 2; 15260b57cec5SDimitry Andric MI->setDesc(TII->get(Mips::JalB16)); 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric BBInfo[MBB->getNumber()].Size += 2; 15290b57cec5SDimitry Andric adjustBBOffsetsAfter(MBB); 15300b57cec5SDimitry Andric HasFarJump = true; 15310b57cec5SDimitry Andric ++NumUBrFixed; 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Changed B to long jump " << *MI); 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric return true; 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric /// fixupConditionalBr - Fix up a conditional branch whose destination is too 15390b57cec5SDimitry Andric /// far away to fit in its displacement field. It is converted to an inverse 15400b57cec5SDimitry Andric /// conditional branch + an unconditional branch to the destination. 15410b57cec5SDimitry Andric bool 15420b57cec5SDimitry Andric MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { 15430b57cec5SDimitry Andric MachineInstr *MI = Br.MI; 15440b57cec5SDimitry Andric unsigned TargetOperand = branchTargetOperand(MI); 15450b57cec5SDimitry Andric MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB(); 15460b57cec5SDimitry Andric unsigned Opcode = MI->getOpcode(); 15470b57cec5SDimitry Andric unsigned LongFormOpcode = longformBranchOpcode(Opcode); 15480b57cec5SDimitry Andric unsigned LongFormMaxOff = branchMaxOffsets(LongFormOpcode); 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric // Check to see if the DestBB is already in-range. 15510b57cec5SDimitry Andric if (isBBInRange(MI, DestBB, LongFormMaxOff)) { 15520b57cec5SDimitry Andric Br.MaxDisp = LongFormMaxOff; 15530b57cec5SDimitry Andric MI->setDesc(TII->get(LongFormOpcode)); 15540b57cec5SDimitry Andric return true; 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric // Add an unconditional branch to the destination and invert the branch 15580b57cec5SDimitry Andric // condition to jump over it: 15590b57cec5SDimitry Andric // bteqz L1 15600b57cec5SDimitry Andric // => 15610b57cec5SDimitry Andric // bnez L2 15620b57cec5SDimitry Andric // b L1 15630b57cec5SDimitry Andric // L2: 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric // If the branch is at the end of its MBB and that has a fall-through block, 15660b57cec5SDimitry Andric // direct the updated conditional branch to the fall-through block. Otherwise, 15670b57cec5SDimitry Andric // split the MBB before the next instruction. 15680b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 15690b57cec5SDimitry Andric MachineInstr *BMI = &MBB->back(); 15700b57cec5SDimitry Andric bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); 15710b57cec5SDimitry Andric unsigned OppositeBranchOpcode = TII->getOppositeBranchOpc(Opcode); 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric ++NumCBrFixed; 15740b57cec5SDimitry Andric if (BMI != MI) { 15750b57cec5SDimitry Andric if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) && 15760b57cec5SDimitry Andric BMI->isUnconditionalBranch()) { 15770b57cec5SDimitry Andric // Last MI in the BB is an unconditional branch. Can we simply invert the 15780b57cec5SDimitry Andric // condition and swap destinations: 15790b57cec5SDimitry Andric // beqz L1 15800b57cec5SDimitry Andric // b L2 15810b57cec5SDimitry Andric // => 15820b57cec5SDimitry Andric // bnez L2 15830b57cec5SDimitry Andric // b L1 15840b57cec5SDimitry Andric unsigned BMITargetOperand = branchTargetOperand(BMI); 15850b57cec5SDimitry Andric MachineBasicBlock *NewDest = 15860b57cec5SDimitry Andric BMI->getOperand(BMITargetOperand).getMBB(); 15870b57cec5SDimitry Andric if (isBBInRange(MI, NewDest, Br.MaxDisp)) { 15880b57cec5SDimitry Andric LLVM_DEBUG( 15890b57cec5SDimitry Andric dbgs() << " Invert Bcc condition and swap its destination with " 15900b57cec5SDimitry Andric << *BMI); 15910b57cec5SDimitry Andric MI->setDesc(TII->get(OppositeBranchOpcode)); 15920b57cec5SDimitry Andric BMI->getOperand(BMITargetOperand).setMBB(DestBB); 15930b57cec5SDimitry Andric MI->getOperand(TargetOperand).setMBB(NewDest); 15940b57cec5SDimitry Andric return true; 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric if (NeedSplit) { 16000b57cec5SDimitry Andric splitBlockBeforeInstr(*MI); 16010b57cec5SDimitry Andric // No need for the branch to the next block. We're adding an unconditional 16020b57cec5SDimitry Andric // branch to the destination. 16030b57cec5SDimitry Andric int delta = TII->getInstSizeInBytes(MBB->back()); 16040b57cec5SDimitry Andric BBInfo[MBB->getNumber()].Size -= delta; 16050b57cec5SDimitry Andric MBB->back().eraseFromParent(); 16060b57cec5SDimitry Andric // BBInfo[SplitBB].Offset is wrong temporarily, fixed below 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric MachineBasicBlock *NextBB = &*++MBB->getIterator(); 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Insert B to " << printMBBReference(*DestBB) 16110b57cec5SDimitry Andric << " also invert condition and change dest. to " 16120b57cec5SDimitry Andric << printMBBReference(*NextBB) << "\n"); 16130b57cec5SDimitry Andric 16140b57cec5SDimitry Andric // Insert a new conditional branch and a new unconditional branch. 16150b57cec5SDimitry Andric // Also update the ImmBranch as well as adding a new entry for the new branch. 16160b57cec5SDimitry Andric if (MI->getNumExplicitOperands() == 2) { 16170b57cec5SDimitry Andric BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode)) 16180b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 16190b57cec5SDimitry Andric .addMBB(NextBB); 16200b57cec5SDimitry Andric } else { 16210b57cec5SDimitry Andric BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode)) 16220b57cec5SDimitry Andric .addMBB(NextBB); 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric Br.MI = &MBB->back(); 16250b57cec5SDimitry Andric BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); 16260b57cec5SDimitry Andric BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); 16270b57cec5SDimitry Andric BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); 16280b57cec5SDimitry Andric unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); 16290b57cec5SDimitry Andric ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric // Remove the old conditional branch. It may or may not still be in MBB. 16320b57cec5SDimitry Andric BBInfo[MI->getParent()->getNumber()].Size -= TII->getInstSizeInBytes(*MI); 16330b57cec5SDimitry Andric MI->eraseFromParent(); 16340b57cec5SDimitry Andric adjustBBOffsetsAfter(MBB); 16350b57cec5SDimitry Andric return true; 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric void MipsConstantIslands::prescanForConstants() { 16390b57cec5SDimitry Andric unsigned J = 0; 16400b57cec5SDimitry Andric (void)J; 16410b57cec5SDimitry Andric for (MachineFunction::iterator B = 16420b57cec5SDimitry Andric MF->begin(), E = MF->end(); B != E; ++B) { 16430b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator I = 16440b57cec5SDimitry Andric B->instr_begin(), EB = B->instr_end(); I != EB; ++I) { 16450b57cec5SDimitry Andric switch(I->getDesc().getOpcode()) { 16460b57cec5SDimitry Andric case Mips::LwConstant32: { 16470b57cec5SDimitry Andric PrescannedForConstants = true; 16480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); 16490b57cec5SDimitry Andric J = I->getNumOperands(); 16500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "num operands " << J << "\n"); 16510b57cec5SDimitry Andric MachineOperand& Literal = I->getOperand(1); 16520b57cec5SDimitry Andric if (Literal.isImm()) { 16530b57cec5SDimitry Andric int64_t V = Literal.getImm(); 16540b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "literal " << V << "\n"); 16550b57cec5SDimitry Andric Type *Int32Ty = 16560b57cec5SDimitry Andric Type::getInt32Ty(MF->getFunction().getContext()); 16570b57cec5SDimitry Andric const Constant *C = ConstantInt::get(Int32Ty, V); 1658*5ffd83dbSDimitry Andric unsigned index = MCP->getConstantPoolIndex(C, Align(4)); 16590b57cec5SDimitry Andric I->getOperand(2).ChangeToImmediate(index); 16600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); 16610b57cec5SDimitry Andric I->setDesc(TII->get(Mips::LwRxPcTcp16)); 16620b57cec5SDimitry Andric I->RemoveOperand(1); 16630b57cec5SDimitry Andric I->RemoveOperand(1); 16640b57cec5SDimitry Andric I->addOperand(MachineOperand::CreateCPI(index, 0)); 16650b57cec5SDimitry Andric I->addOperand(MachineOperand::CreateImm(4)); 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric break; 16680b57cec5SDimitry Andric } 16690b57cec5SDimitry Andric default: 16700b57cec5SDimitry Andric break; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric /// Returns a pass that converts branches to long branches. 16770b57cec5SDimitry Andric FunctionPass *llvm::createMipsConstantIslandPass() { 16780b57cec5SDimitry Andric return new MipsConstantIslands(); 16790b57cec5SDimitry Andric } 1680