xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
branchTargetOperand(MachineInstr * MI)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 
longformBranchOpcode(unsigned int Opcode)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.
branchMaxOffsets(unsigned int Opcode)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 
postOffset__anon52b951230111::MipsConstantIslands::BasicBlockInfo2258bcb0991SDimitry 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 
CPUser__anon52b951230111::MipsConstantIslands::CPUser2670b57cec5SDimitry 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.
getMaxDisp__anon52b951230111::MipsConstantIslands::CPUser2770b57cec5SDimitry Andric       unsigned getMaxDisp() const {
2780b57cec5SDimitry Andric         unsigned xMaxDisp = ConstantIslandsSmallOffset?
2790b57cec5SDimitry Andric                             ConstantIslandsSmallOffset: MaxDisp;
2800b57cec5SDimitry Andric         return xMaxDisp;
2810b57cec5SDimitry Andric       }
2820b57cec5SDimitry Andric 
setMaxDisp__anon52b951230111::MipsConstantIslands::CPUser2830b57cec5SDimitry Andric       void setMaxDisp(unsigned val) {
2840b57cec5SDimitry Andric         MaxDisp = val;
2850b57cec5SDimitry Andric       }
2860b57cec5SDimitry Andric 
getLongFormMaxDisp__anon52b951230111::MipsConstantIslands::CPUser2870b57cec5SDimitry Andric       unsigned getLongFormMaxDisp() const {
2880b57cec5SDimitry Andric         return LongFormMaxDisp;
2890b57cec5SDimitry Andric       }
2900b57cec5SDimitry Andric 
getLongFormOpcode__anon52b951230111::MipsConstantIslands::CPUser2910b57cec5SDimitry 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 
CPEntry__anon52b951230111::MipsConstantIslands::CPEntry3080b57cec5SDimitry 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 
ImmBranch__anon52b951230111::MipsConstantIslands::ImmBranch3290b57cec5SDimitry 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 
initPICLabelUId(unsigned UId)3500b57cec5SDimitry Andric   void initPICLabelUId(unsigned UId) {
3510b57cec5SDimitry Andric     PICLabelUId = UId;
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric 
createPICLabelUId()3540b57cec5SDimitry Andric   unsigned createPICLabelUId() {
3550b57cec5SDimitry Andric     return PICLabelUId++;
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   public:
3590b57cec5SDimitry Andric     static char ID;
3600b57cec5SDimitry Andric 
MipsConstantIslands()3610b57cec5SDimitry Andric     MipsConstantIslands() : MachineFunctionPass(ID) {}
3620b57cec5SDimitry Andric 
getPassName() const3630b57cec5SDimitry Andric     StringRef getPassName() const override { return "Mips Constant Islands"; }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &F) override;
3660b57cec5SDimitry Andric 
getRequiredProperties() const3670b57cec5SDimitry 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 
isOffsetInRange(unsigned UserOffset,unsigned TrialOffset,const CPUser & U)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
dumpBBs()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 
runOnMachineFunction(MachineFunction & mf)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();
439*81ad6265SDimitry Andric   STI = &mf.getSubtarget<MipsSubtarget>();
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
doInitialPlacement(std::vector<MachineInstr * > & CPEMIs)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).
5325ffd83dbSDimitry 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) {
555e8d8bef9SDimitry Andric     unsigned Size = CPs[i].getSizeInBytes(TD);
5560b57cec5SDimitry Andric     assert(Size >= 4 && "Too small constant pool entry");
5575ffd83dbSDimitry 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.
5605ffd83dbSDimitry 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.
5635ffd83dbSDimitry 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 = "
5815ffd83dbSDimitry 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.
BBHasFallthrough(MachineBasicBlock * MBB)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);
596e8d8bef9SDimitry Andric   return llvm::is_contained(MBB->successors(), NextBB);
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric /// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI,
6000b57cec5SDimitry Andric /// look up the corresponding CPEntry.
6010b57cec5SDimitry Andric MipsConstantIslands::CPEntry
findConstPoolEntry(unsigned CPI,const MachineInstr * CPEMI)6020b57cec5SDimitry Andric *MipsConstantIslands::findConstPoolEntry(unsigned CPI,
6030b57cec5SDimitry Andric                                         const MachineInstr *CPEMI) {
6040b57cec5SDimitry Andric   std::vector<CPEntry> &CPEs = CPEntries[CPI];
6050b57cec5SDimitry Andric   // Number of entries per constpool index should be small, just do a
6060b57cec5SDimitry Andric   // linear search.
60704eeddc0SDimitry Andric   for (CPEntry &CPE : CPEs) {
60804eeddc0SDimitry Andric     if (CPE.CPEMI == CPEMI)
60904eeddc0SDimitry Andric       return &CPE;
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric   return nullptr;
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric 
6148bcb0991SDimitry Andric /// getCPEAlign - Returns the required alignment of the constant pool entry
6150b57cec5SDimitry Andric /// represented by CPEMI.  Alignment is measured in log2(bytes) units.
getCPEAlign(const MachineInstr & CPEMI)6168bcb0991SDimitry Andric Align MipsConstantIslands::getCPEAlign(const MachineInstr &CPEMI) {
6170b57cec5SDimitry Andric   assert(CPEMI.getOpcode() == Mips::CONSTPOOL_ENTRY);
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   // Everything is 4-byte aligned unless AlignConstantIslands is set.
6200b57cec5SDimitry Andric   if (!AlignConstantIslands)
6218bcb0991SDimitry Andric     return Align(4);
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   unsigned CPI = CPEMI.getOperand(1).getIndex();
6240b57cec5SDimitry Andric   assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
6255ffd83dbSDimitry Andric   return MCP->getConstants()[CPI].getAlign();
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric /// initializeFunctionInfo - Do the initial scan of the function, building up
6290b57cec5SDimitry Andric /// information about the sizes of each block, the location of all the water,
6300b57cec5SDimitry Andric /// and finding all of the constant pool users.
6310b57cec5SDimitry Andric void MipsConstantIslands::
initializeFunctionInfo(const std::vector<MachineInstr * > & CPEMIs)6320b57cec5SDimitry Andric initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
6330b57cec5SDimitry Andric   BBInfo.clear();
6340b57cec5SDimitry Andric   BBInfo.resize(MF->getNumBlockIDs());
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   // First thing, compute the size of all basic blocks, and see if the function
6370b57cec5SDimitry Andric   // has any inline assembly in it. If so, we have to be conservative about
6380b57cec5SDimitry Andric   // alignment assumptions, as we don't know for sure the size of any
6390b57cec5SDimitry Andric   // instructions in the inline assembly.
6404824e7fdSDimitry Andric   for (MachineBasicBlock &MBB : *MF)
6414824e7fdSDimitry Andric     computeBlockSize(&MBB);
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   // Compute block offsets.
6440b57cec5SDimitry Andric   adjustBBOffsetsAfter(&MF->front());
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   // Now go back through the instructions and build up our data structures.
6470b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : *MF) {
6480b57cec5SDimitry Andric     // If this block doesn't fall through into the next MBB, then this is
6490b57cec5SDimitry Andric     // 'water' that a constant pool island could be placed.
6500b57cec5SDimitry Andric     if (!BBHasFallthrough(&MBB))
6510b57cec5SDimitry Andric       WaterList.push_back(&MBB);
6520b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
6530b57cec5SDimitry Andric       if (MI.isDebugInstr())
6540b57cec5SDimitry Andric         continue;
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric       int Opc = MI.getOpcode();
6570b57cec5SDimitry Andric       if (MI.isBranch()) {
6580b57cec5SDimitry Andric         bool isCond = false;
6590b57cec5SDimitry Andric         unsigned Bits = 0;
6600b57cec5SDimitry Andric         unsigned Scale = 1;
6610b57cec5SDimitry Andric         int UOpc = Opc;
6620b57cec5SDimitry Andric         switch (Opc) {
6630b57cec5SDimitry Andric         default:
6640b57cec5SDimitry Andric           continue;  // Ignore other branches for now
6650b57cec5SDimitry Andric         case Mips::Bimm16:
6660b57cec5SDimitry Andric           Bits = 11;
6670b57cec5SDimitry Andric           Scale = 2;
6680b57cec5SDimitry Andric           isCond = false;
6690b57cec5SDimitry Andric           break;
6700b57cec5SDimitry Andric         case Mips::BimmX16:
6710b57cec5SDimitry Andric           Bits = 16;
6720b57cec5SDimitry Andric           Scale = 2;
6730b57cec5SDimitry Andric           isCond = false;
6740b57cec5SDimitry Andric           break;
6750b57cec5SDimitry Andric         case Mips::BeqzRxImm16:
6760b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
6770b57cec5SDimitry Andric           Bits = 8;
6780b57cec5SDimitry Andric           Scale = 2;
6790b57cec5SDimitry Andric           isCond = true;
6800b57cec5SDimitry Andric           break;
6810b57cec5SDimitry Andric         case Mips::BeqzRxImmX16:
6820b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
6830b57cec5SDimitry Andric           Bits = 16;
6840b57cec5SDimitry Andric           Scale = 2;
6850b57cec5SDimitry Andric           isCond = true;
6860b57cec5SDimitry Andric           break;
6870b57cec5SDimitry Andric         case Mips::BnezRxImm16:
6880b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
6890b57cec5SDimitry Andric           Bits = 8;
6900b57cec5SDimitry Andric           Scale = 2;
6910b57cec5SDimitry Andric           isCond = true;
6920b57cec5SDimitry Andric           break;
6930b57cec5SDimitry Andric         case Mips::BnezRxImmX16:
6940b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
6950b57cec5SDimitry Andric           Bits = 16;
6960b57cec5SDimitry Andric           Scale = 2;
6970b57cec5SDimitry Andric           isCond = true;
6980b57cec5SDimitry Andric           break;
6990b57cec5SDimitry Andric         case Mips::Bteqz16:
7000b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
7010b57cec5SDimitry Andric           Bits = 8;
7020b57cec5SDimitry Andric           Scale = 2;
7030b57cec5SDimitry Andric           isCond = true;
7040b57cec5SDimitry Andric           break;
7050b57cec5SDimitry Andric         case Mips::BteqzX16:
7060b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
7070b57cec5SDimitry Andric           Bits = 16;
7080b57cec5SDimitry Andric           Scale = 2;
7090b57cec5SDimitry Andric           isCond = true;
7100b57cec5SDimitry Andric           break;
7110b57cec5SDimitry Andric         case Mips::Btnez16:
7120b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
7130b57cec5SDimitry Andric           Bits = 8;
7140b57cec5SDimitry Andric           Scale = 2;
7150b57cec5SDimitry Andric           isCond = true;
7160b57cec5SDimitry Andric           break;
7170b57cec5SDimitry Andric         case Mips::BtnezX16:
7180b57cec5SDimitry Andric           UOpc=Mips::Bimm16;
7190b57cec5SDimitry Andric           Bits = 16;
7200b57cec5SDimitry Andric           Scale = 2;
7210b57cec5SDimitry Andric           isCond = true;
7220b57cec5SDimitry Andric           break;
7230b57cec5SDimitry Andric         }
7240b57cec5SDimitry Andric         // Record this immediate branch.
7250b57cec5SDimitry Andric         unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
7260b57cec5SDimitry Andric         ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc));
7270b57cec5SDimitry Andric       }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric       if (Opc == Mips::CONSTPOOL_ENTRY)
7300b57cec5SDimitry Andric         continue;
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric       // Scan the instructions for constant pool operands.
7334824e7fdSDimitry Andric       for (const MachineOperand &MO : MI.operands())
7344824e7fdSDimitry Andric         if (MO.isCPI()) {
7350b57cec5SDimitry Andric           // We found one.  The addressing mode tells us the max displacement
7360b57cec5SDimitry Andric           // from the PC that this instruction permits.
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric           // Basic size info comes from the TSFlags field.
7390b57cec5SDimitry Andric           unsigned Bits = 0;
7400b57cec5SDimitry Andric           unsigned Scale = 1;
7410b57cec5SDimitry Andric           bool NegOk = false;
7420b57cec5SDimitry Andric           unsigned LongFormBits = 0;
7430b57cec5SDimitry Andric           unsigned LongFormScale = 0;
7440b57cec5SDimitry Andric           unsigned LongFormOpcode = 0;
7450b57cec5SDimitry Andric           switch (Opc) {
7460b57cec5SDimitry Andric           default:
7470b57cec5SDimitry Andric             llvm_unreachable("Unknown addressing mode for CP reference!");
7480b57cec5SDimitry Andric           case Mips::LwRxPcTcp16:
7490b57cec5SDimitry Andric             Bits = 8;
7500b57cec5SDimitry Andric             Scale = 4;
7510b57cec5SDimitry Andric             LongFormOpcode = Mips::LwRxPcTcpX16;
7520b57cec5SDimitry Andric             LongFormBits = 14;
7530b57cec5SDimitry Andric             LongFormScale = 1;
7540b57cec5SDimitry Andric             break;
7550b57cec5SDimitry Andric           case Mips::LwRxPcTcpX16:
7560b57cec5SDimitry Andric             Bits = 14;
7570b57cec5SDimitry Andric             Scale = 1;
7580b57cec5SDimitry Andric             NegOk = true;
7590b57cec5SDimitry Andric             break;
7600b57cec5SDimitry Andric           }
7610b57cec5SDimitry Andric           // Remember that this is a user of a CP entry.
7624824e7fdSDimitry Andric           unsigned CPI = MO.getIndex();
7630b57cec5SDimitry Andric           MachineInstr *CPEMI = CPEMIs[CPI];
7640b57cec5SDimitry Andric           unsigned MaxOffs = ((1 << Bits)-1) * Scale;
7650b57cec5SDimitry Andric           unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
7660b57cec5SDimitry Andric           CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
7670b57cec5SDimitry Andric                                    LongFormOpcode));
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric           // Increment corresponding CPEntry reference count.
7700b57cec5SDimitry Andric           CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
7710b57cec5SDimitry Andric           assert(CPE && "Cannot find a corresponding CPEntry!");
7720b57cec5SDimitry Andric           CPE->RefCount++;
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric           // Instructions can only use one CP entry, don't bother scanning the
7750b57cec5SDimitry Andric           // rest of the operands.
7760b57cec5SDimitry Andric           break;
7770b57cec5SDimitry Andric         }
7780b57cec5SDimitry Andric     }
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric /// computeBlockSize - Compute the size and some alignment information for MBB.
7830b57cec5SDimitry Andric /// This function updates BBInfo directly.
computeBlockSize(MachineBasicBlock * MBB)7840b57cec5SDimitry Andric void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {
7850b57cec5SDimitry Andric   BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
7860b57cec5SDimitry Andric   BBI.Size = 0;
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   for (const MachineInstr &MI : *MBB)
7890b57cec5SDimitry Andric     BBI.Size += TII->getInstSizeInBytes(MI);
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric /// getOffsetOf - Return the current offset of the specified machine instruction
7930b57cec5SDimitry Andric /// from the start of the function.  This offset changes as stuff is moved
7940b57cec5SDimitry Andric /// around inside the function.
getOffsetOf(MachineInstr * MI) const7950b57cec5SDimitry Andric unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const {
7960b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric   // The offset is composed of two things: the sum of the sizes of all MBB's
7990b57cec5SDimitry Andric   // before this instruction's block, and the offset from the start of the block
8000b57cec5SDimitry Andric   // it is in.
8010b57cec5SDimitry Andric   unsigned Offset = BBInfo[MBB->getNumber()].Offset;
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   // Sum instructions before MI in MBB.
8040b57cec5SDimitry Andric   for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) {
8050b57cec5SDimitry Andric     assert(I != MBB->end() && "Didn't find MI in its own basic block?");
8060b57cec5SDimitry Andric     Offset += TII->getInstSizeInBytes(*I);
8070b57cec5SDimitry Andric   }
8080b57cec5SDimitry Andric   return Offset;
8090b57cec5SDimitry Andric }
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric /// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB
8120b57cec5SDimitry Andric /// ID.
CompareMBBNumbers(const MachineBasicBlock * LHS,const MachineBasicBlock * RHS)8130b57cec5SDimitry Andric static bool CompareMBBNumbers(const MachineBasicBlock *LHS,
8140b57cec5SDimitry Andric                               const MachineBasicBlock *RHS) {
8150b57cec5SDimitry Andric   return LHS->getNumber() < RHS->getNumber();
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric /// updateForInsertedWaterBlock - When a block is newly inserted into the
8190b57cec5SDimitry Andric /// machine function, it upsets all of the block numbers.  Renumber the blocks
8200b57cec5SDimitry Andric /// and update the arrays that parallel this numbering.
updateForInsertedWaterBlock(MachineBasicBlock * NewBB)8210b57cec5SDimitry Andric void MipsConstantIslands::updateForInsertedWaterBlock
8220b57cec5SDimitry Andric   (MachineBasicBlock *NewBB) {
8230b57cec5SDimitry Andric   // Renumber the MBB's to keep them consecutive.
8240b57cec5SDimitry Andric   NewBB->getParent()->RenumberBlocks(NewBB);
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   // Insert an entry into BBInfo to align it properly with the (newly
8270b57cec5SDimitry Andric   // renumbered) block numbers.
8280b57cec5SDimitry Andric   BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   // Next, update WaterList.  Specifically, we need to add NewMBB as having
8310b57cec5SDimitry Andric   // available water after it.
8320b57cec5SDimitry Andric   water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers);
8330b57cec5SDimitry Andric   WaterList.insert(IP, NewBB);
8340b57cec5SDimitry Andric }
8350b57cec5SDimitry Andric 
getUserOffset(CPUser & U) const8360b57cec5SDimitry Andric unsigned MipsConstantIslands::getUserOffset(CPUser &U) const {
8370b57cec5SDimitry Andric   return getOffsetOf(U.MI);
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric /// Split the basic block containing MI into two blocks, which are joined by
8410b57cec5SDimitry Andric /// an unconditional branch.  Update data structures and renumber blocks to
8420b57cec5SDimitry Andric /// account for this change and returns the newly created block.
8430b57cec5SDimitry Andric MachineBasicBlock *
splitBlockBeforeInstr(MachineInstr & MI)8440b57cec5SDimitry Andric MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) {
8450b57cec5SDimitry Andric   MachineBasicBlock *OrigBB = MI.getParent();
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Create a new MBB for the code after the OrigBB.
8480b57cec5SDimitry Andric   MachineBasicBlock *NewBB =
8490b57cec5SDimitry Andric     MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
8500b57cec5SDimitry Andric   MachineFunction::iterator MBBI = ++OrigBB->getIterator();
8510b57cec5SDimitry Andric   MF->insert(MBBI, NewBB);
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   // Splice the instructions starting with MI over to NewBB.
8540b57cec5SDimitry Andric   NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   // Add an unconditional branch from OrigBB to NewBB.
8570b57cec5SDimitry Andric   // Note the new unconditional branch is not being recorded.
8580b57cec5SDimitry Andric   // There doesn't seem to be meaningful DebugInfo available; this doesn't
8590b57cec5SDimitry Andric   // correspond to anything in the source.
8600b57cec5SDimitry Andric   BuildMI(OrigBB, DebugLoc(), TII->get(Mips::Bimm16)).addMBB(NewBB);
8610b57cec5SDimitry Andric   ++NumSplit;
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   // Update the CFG.  All succs of OrigBB are now succs of NewBB.
8640b57cec5SDimitry Andric   NewBB->transferSuccessors(OrigBB);
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   // OrigBB branches to NewBB.
8670b57cec5SDimitry Andric   OrigBB->addSuccessor(NewBB);
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   // Update internal data structures to account for the newly inserted MBB.
8700b57cec5SDimitry Andric   // This is almost the same as updateForInsertedWaterBlock, except that
8710b57cec5SDimitry Andric   // the Water goes after OrigBB, not NewBB.
8720b57cec5SDimitry Andric   MF->RenumberBlocks(NewBB);
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   // Insert an entry into BBInfo to align it properly with the (newly
8750b57cec5SDimitry Andric   // renumbered) block numbers.
8760b57cec5SDimitry Andric   BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo());
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric   // Next, update WaterList.  Specifically, we need to add OrigMBB as having
8790b57cec5SDimitry Andric   // available water after it (but not if it's already there, which happens
8800b57cec5SDimitry Andric   // when splitting before a conditional branch that is followed by an
8810b57cec5SDimitry Andric   // unconditional branch - in that case we want to insert NewBB).
8820b57cec5SDimitry Andric   water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers);
8830b57cec5SDimitry Andric   MachineBasicBlock* WaterBB = *IP;
8840b57cec5SDimitry Andric   if (WaterBB == OrigBB)
8850b57cec5SDimitry Andric     WaterList.insert(std::next(IP), NewBB);
8860b57cec5SDimitry Andric   else
8870b57cec5SDimitry Andric     WaterList.insert(IP, OrigBB);
8880b57cec5SDimitry Andric   NewWaterList.insert(OrigBB);
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   // Figure out how large the OrigBB is.  As the first half of the original
8910b57cec5SDimitry Andric   // block, it cannot contain a tablejump.  The size includes
8920b57cec5SDimitry Andric   // the new jump we added.  (It should be possible to do this without
8930b57cec5SDimitry Andric   // recounting everything, but it's very confusing, and this is rarely
8940b57cec5SDimitry Andric   // executed.)
8950b57cec5SDimitry Andric   computeBlockSize(OrigBB);
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   // Figure out how large the NewMBB is.  As the second half of the original
8980b57cec5SDimitry Andric   // block, it may contain a tablejump.
8990b57cec5SDimitry Andric   computeBlockSize(NewBB);
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   // All BBOffsets following these blocks must be modified.
9020b57cec5SDimitry Andric   adjustBBOffsetsAfter(OrigBB);
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   return NewBB;
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
9080b57cec5SDimitry Andric /// reference) is within MaxDisp of TrialOffset (a proposed location of a
9090b57cec5SDimitry Andric /// constant pool entry).
isOffsetInRange(unsigned UserOffset,unsigned TrialOffset,unsigned MaxDisp,bool NegativeOK)9100b57cec5SDimitry Andric bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset,
9110b57cec5SDimitry Andric                                          unsigned TrialOffset, unsigned MaxDisp,
9120b57cec5SDimitry Andric                                          bool NegativeOK) {
9130b57cec5SDimitry Andric   if (UserOffset <= TrialOffset) {
9140b57cec5SDimitry Andric     // User before the Trial.
9150b57cec5SDimitry Andric     if (TrialOffset - UserOffset <= MaxDisp)
9160b57cec5SDimitry Andric       return true;
9170b57cec5SDimitry Andric   } else if (NegativeOK) {
9180b57cec5SDimitry Andric     if (UserOffset - TrialOffset <= MaxDisp)
9190b57cec5SDimitry Andric       return true;
9200b57cec5SDimitry Andric   }
9210b57cec5SDimitry Andric   return false;
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric /// isWaterInRange - Returns true if a CPE placed after the specified
9250b57cec5SDimitry Andric /// Water (a basic block) will be in range for the specific MI.
9260b57cec5SDimitry Andric ///
9270b57cec5SDimitry Andric /// Compute how much the function will grow by inserting a CPE after Water.
isWaterInRange(unsigned UserOffset,MachineBasicBlock * Water,CPUser & U,unsigned & Growth)9280b57cec5SDimitry Andric bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,
9290b57cec5SDimitry Andric                                         MachineBasicBlock* Water, CPUser &U,
9300b57cec5SDimitry Andric                                         unsigned &Growth) {
9318bcb0991SDimitry Andric   unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset();
9328bcb0991SDimitry Andric   unsigned NextBlockOffset;
9338bcb0991SDimitry Andric   Align NextBlockAlignment;
9340b57cec5SDimitry Andric   MachineFunction::const_iterator NextBlock = ++Water->getIterator();
9350b57cec5SDimitry Andric   if (NextBlock == MF->end()) {
9360b57cec5SDimitry Andric     NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
9375ffd83dbSDimitry Andric     NextBlockAlignment = Align(1);
9380b57cec5SDimitry Andric   } else {
9390b57cec5SDimitry Andric     NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
9400b57cec5SDimitry Andric     NextBlockAlignment = NextBlock->getAlignment();
9410b57cec5SDimitry Andric   }
9420b57cec5SDimitry Andric   unsigned Size = U.CPEMI->getOperand(2).getImm();
9430b57cec5SDimitry Andric   unsigned CPEEnd = CPEOffset + Size;
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   // The CPE may be able to hide in the alignment padding before the next
9460b57cec5SDimitry Andric   // block. It may also cause more padding to be required if it is more aligned
9470b57cec5SDimitry Andric   // that the next block.
9480b57cec5SDimitry Andric   if (CPEEnd > NextBlockOffset) {
9490b57cec5SDimitry Andric     Growth = CPEEnd - NextBlockOffset;
9500b57cec5SDimitry Andric     // Compute the padding that would go at the end of the CPE to align the next
9510b57cec5SDimitry Andric     // block.
9528bcb0991SDimitry Andric     Growth += offsetToAlignment(CPEEnd, NextBlockAlignment);
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric     // If the CPE is to be inserted before the instruction, that will raise
9550b57cec5SDimitry Andric     // the offset of the instruction. Also account for unknown alignment padding
9560b57cec5SDimitry Andric     // in blocks between CPE and the user.
9570b57cec5SDimitry Andric     if (CPEOffset < UserOffset)
9580b57cec5SDimitry Andric       UserOffset += Growth;
9590b57cec5SDimitry Andric   } else
9600b57cec5SDimitry Andric     // CPE fits in existing padding.
9610b57cec5SDimitry Andric     Growth = 0;
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   return isOffsetInRange(UserOffset, CPEOffset, U);
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric /// isCPEntryInRange - Returns true if the distance between specific MI and
9670b57cec5SDimitry Andric /// specific ConstPool entry instruction can fit in MI's displacement field.
isCPEntryInRange(MachineInstr * MI,unsigned UserOffset,MachineInstr * CPEMI,unsigned MaxDisp,bool NegOk,bool DoDump)9680b57cec5SDimitry Andric bool MipsConstantIslands::isCPEntryInRange
9690b57cec5SDimitry Andric   (MachineInstr *MI, unsigned UserOffset,
9700b57cec5SDimitry Andric    MachineInstr *CPEMI, unsigned MaxDisp,
9710b57cec5SDimitry Andric    bool NegOk, bool DoDump) {
9720b57cec5SDimitry Andric   unsigned CPEOffset  = getOffsetOf(CPEMI);
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   if (DoDump) {
9750b57cec5SDimitry Andric     LLVM_DEBUG({
9760b57cec5SDimitry Andric       unsigned Block = MI->getParent()->getNumber();
9770b57cec5SDimitry Andric       const BasicBlockInfo &BBI = BBInfo[Block];
9780b57cec5SDimitry Andric       dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()
9790b57cec5SDimitry Andric              << " max delta=" << MaxDisp
9800b57cec5SDimitry Andric              << format(" insn address=%#x", UserOffset) << " in "
9810b57cec5SDimitry Andric              << printMBBReference(*MI->getParent()) << ": "
9820b57cec5SDimitry Andric              << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI
9830b57cec5SDimitry Andric              << format("CPE address=%#x offset=%+d: ", CPEOffset,
9840b57cec5SDimitry Andric                        int(CPEOffset - UserOffset));
9850b57cec5SDimitry Andric     });
9860b57cec5SDimitry Andric   }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric #ifndef NDEBUG
9920b57cec5SDimitry Andric /// BBIsJumpedOver - Return true of the specified basic block's only predecessor
9930b57cec5SDimitry Andric /// unconditionally branches to its only successor.
BBIsJumpedOver(MachineBasicBlock * MBB)9940b57cec5SDimitry Andric static bool BBIsJumpedOver(MachineBasicBlock *MBB) {
9950b57cec5SDimitry Andric   if (MBB->pred_size() != 1 || MBB->succ_size() != 1)
9960b57cec5SDimitry Andric     return false;
9970b57cec5SDimitry Andric   MachineBasicBlock *Succ = *MBB->succ_begin();
9980b57cec5SDimitry Andric   MachineBasicBlock *Pred = *MBB->pred_begin();
9990b57cec5SDimitry Andric   MachineInstr *PredMI = &Pred->back();
10000b57cec5SDimitry Andric   if (PredMI->getOpcode() == Mips::Bimm16)
10010b57cec5SDimitry Andric     return PredMI->getOperand(0).getMBB() == Succ;
10020b57cec5SDimitry Andric   return false;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric #endif
10050b57cec5SDimitry Andric 
adjustBBOffsetsAfter(MachineBasicBlock * BB)10060b57cec5SDimitry Andric void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
10070b57cec5SDimitry Andric   unsigned BBNum = BB->getNumber();
10080b57cec5SDimitry Andric   for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
10090b57cec5SDimitry Andric     // Get the offset and known bits at the end of the layout predecessor.
10100b57cec5SDimitry Andric     // Include the alignment of the current block.
10110b57cec5SDimitry Andric     unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
10120b57cec5SDimitry Andric     BBInfo[i].Offset = Offset;
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric }
10150b57cec5SDimitry Andric 
10160b57cec5SDimitry Andric /// decrementCPEReferenceCount - find the constant pool entry with index CPI
10170b57cec5SDimitry Andric /// and instruction CPEMI, and decrement its refcount.  If the refcount
10180b57cec5SDimitry Andric /// becomes 0 remove the entry and instruction.  Returns true if we removed
10190b57cec5SDimitry Andric /// the entry, false if we didn't.
decrementCPEReferenceCount(unsigned CPI,MachineInstr * CPEMI)10200b57cec5SDimitry Andric bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI,
10210b57cec5SDimitry Andric                                                     MachineInstr *CPEMI) {
10220b57cec5SDimitry Andric   // Find the old entry. Eliminate it if it is no longer used.
10230b57cec5SDimitry Andric   CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
10240b57cec5SDimitry Andric   assert(CPE && "Unexpected!");
10250b57cec5SDimitry Andric   if (--CPE->RefCount == 0) {
10260b57cec5SDimitry Andric     removeDeadCPEMI(CPEMI);
10270b57cec5SDimitry Andric     CPE->CPEMI = nullptr;
10280b57cec5SDimitry Andric     --NumCPEs;
10290b57cec5SDimitry Andric     return true;
10300b57cec5SDimitry Andric   }
10310b57cec5SDimitry Andric   return false;
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric /// LookForCPEntryInRange - see if the currently referenced CPE is in range;
10350b57cec5SDimitry Andric /// if not, see if an in-range clone of the CPE is in range, and if so,
10360b57cec5SDimitry Andric /// change the data structures so the user references the clone.  Returns:
10370b57cec5SDimitry Andric /// 0 = no existing entry found
10380b57cec5SDimitry Andric /// 1 = entry found, and there were no code insertions or deletions
10390b57cec5SDimitry Andric /// 2 = entry found, and there were code insertions or deletions
findInRangeCPEntry(CPUser & U,unsigned UserOffset)10400b57cec5SDimitry Andric int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset)
10410b57cec5SDimitry Andric {
10420b57cec5SDimitry Andric   MachineInstr *UserMI = U.MI;
10430b57cec5SDimitry Andric   MachineInstr *CPEMI  = U.CPEMI;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   // Check to see if the CPE is already in-range.
10460b57cec5SDimitry Andric   if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
10470b57cec5SDimitry Andric                        true)) {
10480b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "In range\n");
10490b57cec5SDimitry Andric     return 1;
10500b57cec5SDimitry Andric   }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   // No.  Look for previously created clones of the CPE that are in range.
10530b57cec5SDimitry Andric   unsigned CPI = CPEMI->getOperand(1).getIndex();
10540b57cec5SDimitry Andric   std::vector<CPEntry> &CPEs = CPEntries[CPI];
105504eeddc0SDimitry Andric   for (CPEntry &CPE : CPEs) {
10560b57cec5SDimitry Andric     // We already tried this one
105704eeddc0SDimitry Andric     if (CPE.CPEMI == CPEMI)
10580b57cec5SDimitry Andric       continue;
10590b57cec5SDimitry Andric     // Removing CPEs can leave empty entries, skip
106004eeddc0SDimitry Andric     if (CPE.CPEMI == nullptr)
10610b57cec5SDimitry Andric       continue;
106204eeddc0SDimitry Andric     if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getMaxDisp(),
10630b57cec5SDimitry Andric                          U.NegOk)) {
106404eeddc0SDimitry Andric       LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
106504eeddc0SDimitry Andric                         << "\n");
10660b57cec5SDimitry Andric       // Point the CPUser node to the replacement
106704eeddc0SDimitry Andric       U.CPEMI = CPE.CPEMI;
10680b57cec5SDimitry Andric       // Change the CPI in the instruction operand to refer to the clone.
10694824e7fdSDimitry Andric       for (MachineOperand &MO : UserMI->operands())
10704824e7fdSDimitry Andric         if (MO.isCPI()) {
107104eeddc0SDimitry Andric           MO.setIndex(CPE.CPI);
10720b57cec5SDimitry Andric           break;
10730b57cec5SDimitry Andric         }
10740b57cec5SDimitry Andric       // Adjust the refcount of the clone...
107504eeddc0SDimitry Andric       CPE.RefCount++;
10760b57cec5SDimitry Andric       // ...and the original.  If we didn't remove the old entry, none of the
10770b57cec5SDimitry Andric       // addresses changed, so we don't need another pass.
10780b57cec5SDimitry Andric       return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric   return 0;
10820b57cec5SDimitry Andric }
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric /// LookForCPEntryInRange - see if the currently referenced CPE is in range;
10850b57cec5SDimitry Andric /// This version checks if the longer form of the instruction can be used to
10860b57cec5SDimitry Andric /// to satisfy things.
10870b57cec5SDimitry Andric /// if not, see if an in-range clone of the CPE is in range, and if so,
10880b57cec5SDimitry Andric /// change the data structures so the user references the clone.  Returns:
10890b57cec5SDimitry Andric /// 0 = no existing entry found
10900b57cec5SDimitry Andric /// 1 = entry found, and there were no code insertions or deletions
10910b57cec5SDimitry Andric /// 2 = entry found, and there were code insertions or deletions
findLongFormInRangeCPEntry(CPUser & U,unsigned UserOffset)10920b57cec5SDimitry Andric int MipsConstantIslands::findLongFormInRangeCPEntry
10930b57cec5SDimitry Andric   (CPUser& U, unsigned UserOffset)
10940b57cec5SDimitry Andric {
10950b57cec5SDimitry Andric   MachineInstr *UserMI = U.MI;
10960b57cec5SDimitry Andric   MachineInstr *CPEMI  = U.CPEMI;
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   // Check to see if the CPE is already in-range.
10990b57cec5SDimitry Andric   if (isCPEntryInRange(UserMI, UserOffset, CPEMI,
11000b57cec5SDimitry Andric                        U.getLongFormMaxDisp(), U.NegOk,
11010b57cec5SDimitry Andric                        true)) {
11020b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "In range\n");
11030b57cec5SDimitry Andric     UserMI->setDesc(TII->get(U.getLongFormOpcode()));
11040b57cec5SDimitry Andric     U.setMaxDisp(U.getLongFormMaxDisp());
11050b57cec5SDimitry Andric     return 2;  // instruction is longer length now
11060b57cec5SDimitry Andric   }
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric   // No.  Look for previously created clones of the CPE that are in range.
11090b57cec5SDimitry Andric   unsigned CPI = CPEMI->getOperand(1).getIndex();
11100b57cec5SDimitry Andric   std::vector<CPEntry> &CPEs = CPEntries[CPI];
111104eeddc0SDimitry Andric   for (CPEntry &CPE : CPEs) {
11120b57cec5SDimitry Andric     // We already tried this one
111304eeddc0SDimitry Andric     if (CPE.CPEMI == CPEMI)
11140b57cec5SDimitry Andric       continue;
11150b57cec5SDimitry Andric     // Removing CPEs can leave empty entries, skip
111604eeddc0SDimitry Andric     if (CPE.CPEMI == nullptr)
11170b57cec5SDimitry Andric       continue;
111804eeddc0SDimitry Andric     if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getLongFormMaxDisp(),
111904eeddc0SDimitry Andric                          U.NegOk)) {
112004eeddc0SDimitry Andric       LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
112104eeddc0SDimitry Andric                         << "\n");
11220b57cec5SDimitry Andric       // Point the CPUser node to the replacement
112304eeddc0SDimitry Andric       U.CPEMI = CPE.CPEMI;
11240b57cec5SDimitry Andric       // Change the CPI in the instruction operand to refer to the clone.
11254824e7fdSDimitry Andric       for (MachineOperand &MO : UserMI->operands())
11264824e7fdSDimitry Andric         if (MO.isCPI()) {
112704eeddc0SDimitry Andric           MO.setIndex(CPE.CPI);
11280b57cec5SDimitry Andric           break;
11290b57cec5SDimitry Andric         }
11300b57cec5SDimitry Andric       // Adjust the refcount of the clone...
113104eeddc0SDimitry Andric       CPE.RefCount++;
11320b57cec5SDimitry Andric       // ...and the original.  If we didn't remove the old entry, none of the
11330b57cec5SDimitry Andric       // addresses changed, so we don't need another pass.
11340b57cec5SDimitry Andric       return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric   }
11370b57cec5SDimitry Andric   return 0;
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric /// getUnconditionalBrDisp - Returns the maximum displacement that can fit in
11410b57cec5SDimitry Andric /// the specific unconditional branch instruction.
getUnconditionalBrDisp(int Opc)11420b57cec5SDimitry Andric static inline unsigned getUnconditionalBrDisp(int Opc) {
11430b57cec5SDimitry Andric   switch (Opc) {
11440b57cec5SDimitry Andric   case Mips::Bimm16:
11450b57cec5SDimitry Andric     return ((1<<10)-1)*2;
11460b57cec5SDimitry Andric   case Mips::BimmX16:
11470b57cec5SDimitry Andric     return ((1<<16)-1)*2;
11480b57cec5SDimitry Andric   default:
11490b57cec5SDimitry Andric     break;
11500b57cec5SDimitry Andric   }
11510b57cec5SDimitry Andric   return ((1<<16)-1)*2;
11520b57cec5SDimitry Andric }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric /// findAvailableWater - Look for an existing entry in the WaterList in which
11550b57cec5SDimitry Andric /// we can place the CPE referenced from U so it's within range of U's MI.
11560b57cec5SDimitry Andric /// Returns true if found, false if not.  If it returns true, WaterIter
11570b57cec5SDimitry Andric /// is set to the WaterList entry.
11580b57cec5SDimitry Andric /// To ensure that this pass
11590b57cec5SDimitry Andric /// terminates, the CPE location for a particular CPUser is only allowed to
11600b57cec5SDimitry Andric /// move to a lower address, so search backward from the end of the list and
11610b57cec5SDimitry Andric /// prefer the first water that is in range.
findAvailableWater(CPUser & U,unsigned UserOffset,water_iterator & WaterIter)11620b57cec5SDimitry Andric bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
11630b57cec5SDimitry Andric                                       water_iterator &WaterIter) {
11640b57cec5SDimitry Andric   if (WaterList.empty())
11650b57cec5SDimitry Andric     return false;
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   unsigned BestGrowth = ~0u;
11680b57cec5SDimitry Andric   for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
11690b57cec5SDimitry Andric        --IP) {
11700b57cec5SDimitry Andric     MachineBasicBlock* WaterBB = *IP;
11710b57cec5SDimitry Andric     // Check if water is in range and is either at a lower address than the
11720b57cec5SDimitry Andric     // current "high water mark" or a new water block that was created since
11730b57cec5SDimitry Andric     // the previous iteration by inserting an unconditional branch.  In the
11740b57cec5SDimitry Andric     // latter case, we want to allow resetting the high water mark back to
11750b57cec5SDimitry Andric     // this new water since we haven't seen it before.  Inserting branches
11760b57cec5SDimitry Andric     // should be relatively uncommon and when it does happen, we want to be
11770b57cec5SDimitry Andric     // sure to take advantage of it for all the CPEs near that block, so that
11780b57cec5SDimitry Andric     // we don't insert more branches than necessary.
11790b57cec5SDimitry Andric     unsigned Growth;
11800b57cec5SDimitry Andric     if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
11810b57cec5SDimitry Andric         (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
11820b57cec5SDimitry Andric          NewWaterList.count(WaterBB)) && Growth < BestGrowth) {
11830b57cec5SDimitry Andric       // This is the least amount of required padding seen so far.
11840b57cec5SDimitry Andric       BestGrowth = Growth;
11850b57cec5SDimitry Andric       WaterIter = IP;
11860b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB)
11870b57cec5SDimitry Andric                         << " Growth=" << Growth << '\n');
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric       // Keep looking unless it is perfect.
11900b57cec5SDimitry Andric       if (BestGrowth == 0)
11910b57cec5SDimitry Andric         return true;
11920b57cec5SDimitry Andric     }
11930b57cec5SDimitry Andric     if (IP == B)
11940b57cec5SDimitry Andric       break;
11950b57cec5SDimitry Andric   }
11960b57cec5SDimitry Andric   return BestGrowth != ~0u;
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric /// createNewWater - No existing WaterList entry will work for
12000b57cec5SDimitry Andric /// CPUsers[CPUserIndex], so create a place to put the CPE.  The end of the
12010b57cec5SDimitry Andric /// block is used if in range, and the conditional branch munged so control
12020b57cec5SDimitry Andric /// flow is correct.  Otherwise the block is split to create a hole with an
12030b57cec5SDimitry Andric /// unconditional branch around it.  In either case NewMBB is set to a
12040b57cec5SDimitry Andric /// block following which the new island can be inserted (the WaterList
12050b57cec5SDimitry Andric /// is not adjusted).
createNewWater(unsigned CPUserIndex,unsigned UserOffset,MachineBasicBlock * & NewMBB)12060b57cec5SDimitry Andric void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
12070b57cec5SDimitry Andric                                         unsigned UserOffset,
12080b57cec5SDimitry Andric                                         MachineBasicBlock *&NewMBB) {
12090b57cec5SDimitry Andric   CPUser &U = CPUsers[CPUserIndex];
12100b57cec5SDimitry Andric   MachineInstr *UserMI = U.MI;
12110b57cec5SDimitry Andric   MachineInstr *CPEMI  = U.CPEMI;
12120b57cec5SDimitry Andric   MachineBasicBlock *UserMBB = UserMI->getParent();
12130b57cec5SDimitry Andric   const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric   // If the block does not end in an unconditional branch already, and if the
12160b57cec5SDimitry Andric   // end of the block is within range, make new water there.
12170b57cec5SDimitry Andric   if (BBHasFallthrough(UserMBB)) {
12180b57cec5SDimitry Andric     // Size of branch to insert.
12190b57cec5SDimitry Andric     unsigned Delta = 2;
12200b57cec5SDimitry Andric     // Compute the offset where the CPE will begin.
12218bcb0991SDimitry Andric     unsigned CPEOffset = UserBBI.postOffset() + Delta;
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric     if (isOffsetInRange(UserOffset, CPEOffset, U)) {
12240b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB)
12250b57cec5SDimitry Andric                         << format(", expected CPE offset %#x\n", CPEOffset));
12260b57cec5SDimitry Andric       NewMBB = &*++UserMBB->getIterator();
12270b57cec5SDimitry Andric       // Add an unconditional branch from UserMBB to fallthrough block.  Record
12280b57cec5SDimitry Andric       // it for branch lengthening; this new branch will not get out of range,
12290b57cec5SDimitry Andric       // but if the preceding conditional branch is out of range, the targets
12300b57cec5SDimitry Andric       // will be exchanged, and the altered branch may be out of range, so the
12310b57cec5SDimitry Andric       // machinery has to know about it.
12320b57cec5SDimitry Andric       int UncondBr = Mips::Bimm16;
12330b57cec5SDimitry Andric       BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
12340b57cec5SDimitry Andric       unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
12350b57cec5SDimitry Andric       ImmBranches.push_back(ImmBranch(&UserMBB->back(),
12360b57cec5SDimitry Andric                                       MaxDisp, false, UncondBr));
12370b57cec5SDimitry Andric       BBInfo[UserMBB->getNumber()].Size += Delta;
12380b57cec5SDimitry Andric       adjustBBOffsetsAfter(UserMBB);
12390b57cec5SDimitry Andric       return;
12400b57cec5SDimitry Andric     }
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric   // What a big block.  Find a place within the block to split it.
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric   // Try to split the block so it's fully aligned.  Compute the latest split
12460b57cec5SDimitry Andric   // point where we can add a 4-byte branch instruction, and then align to
12478bcb0991SDimitry Andric   // Align which is the largest possible alignment in the function.
12488bcb0991SDimitry Andric   const Align Align = MF->getAlignment();
12490b57cec5SDimitry Andric   unsigned BaseInsertOffset = UserOffset + U.getMaxDisp();
12500b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x",
12510b57cec5SDimitry Andric                               BaseInsertOffset));
12520b57cec5SDimitry Andric 
12530b57cec5SDimitry Andric   // The 4 in the following is for the unconditional branch we'll be inserting
12540b57cec5SDimitry Andric   // Alignment of the island is handled
12550b57cec5SDimitry Andric   // inside isOffsetInRange.
12560b57cec5SDimitry Andric   BaseInsertOffset -= 4;
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset)
12598bcb0991SDimitry Andric                     << " la=" << Log2(Align) << '\n');
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric   // This could point off the end of the block if we've already got constant
12620b57cec5SDimitry Andric   // pool entries following this block; only the last one is in the water list.
12630b57cec5SDimitry Andric   // Back past any possible branches (allow for a conditional and a maximally
12640b57cec5SDimitry Andric   // long unconditional).
12650b57cec5SDimitry Andric   if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {
12660b57cec5SDimitry Andric     BaseInsertOffset = UserBBI.postOffset() - 8;
12670b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset));
12680b57cec5SDimitry Andric   }
12690b57cec5SDimitry Andric   unsigned EndInsertOffset = BaseInsertOffset + 4 +
12700b57cec5SDimitry Andric     CPEMI->getOperand(2).getImm();
12710b57cec5SDimitry Andric   MachineBasicBlock::iterator MI = UserMI;
12720b57cec5SDimitry Andric   ++MI;
12730b57cec5SDimitry Andric   unsigned CPUIndex = CPUserIndex+1;
12740b57cec5SDimitry Andric   unsigned NumCPUsers = CPUsers.size();
12750b57cec5SDimitry Andric   //MachineInstr *LastIT = 0;
12760b57cec5SDimitry Andric   for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI);
12770b57cec5SDimitry Andric        Offset < BaseInsertOffset;
12780b57cec5SDimitry Andric        Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) {
12790b57cec5SDimitry Andric     assert(MI != UserMBB->end() && "Fell off end of block");
12800b57cec5SDimitry Andric     if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
12810b57cec5SDimitry Andric       CPUser &U = CPUsers[CPUIndex];
12820b57cec5SDimitry Andric       if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
12830b57cec5SDimitry Andric         // Shift intertion point by one unit of alignment so it is within reach.
12848bcb0991SDimitry Andric         BaseInsertOffset -= Align.value();
12858bcb0991SDimitry Andric         EndInsertOffset -= Align.value();
12860b57cec5SDimitry Andric       }
12870b57cec5SDimitry Andric       // This is overly conservative, as we don't account for CPEMIs being
12880b57cec5SDimitry Andric       // reused within the block, but it doesn't matter much.  Also assume CPEs
12890b57cec5SDimitry Andric       // are added in order with alignment padding.  We may eventually be able
12900b57cec5SDimitry Andric       // to pack the aligned CPEs better.
12910b57cec5SDimitry Andric       EndInsertOffset += U.CPEMI->getOperand(2).getImm();
12920b57cec5SDimitry Andric       CPUIndex++;
12930b57cec5SDimitry Andric     }
12940b57cec5SDimitry Andric   }
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   NewMBB = splitBlockBeforeInstr(*--MI);
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric /// handleConstantPoolUser - Analyze the specified user, checking to see if it
13000b57cec5SDimitry Andric /// is out-of-range.  If so, pick up the constant pool value and move it some
13010b57cec5SDimitry Andric /// place in-range.  Return true if we changed any addresses (thus must run
13020b57cec5SDimitry Andric /// another pass of branch lengthening), false otherwise.
handleConstantPoolUser(unsigned CPUserIndex)13030b57cec5SDimitry Andric bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
13040b57cec5SDimitry Andric   CPUser &U = CPUsers[CPUserIndex];
13050b57cec5SDimitry Andric   MachineInstr *UserMI = U.MI;
13060b57cec5SDimitry Andric   MachineInstr *CPEMI  = U.CPEMI;
13070b57cec5SDimitry Andric   unsigned CPI = CPEMI->getOperand(1).getIndex();
13080b57cec5SDimitry Andric   unsigned Size = CPEMI->getOperand(2).getImm();
13090b57cec5SDimitry Andric   // Compute this only once, it's expensive.
13100b57cec5SDimitry Andric   unsigned UserOffset = getUserOffset(U);
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   // See if the current entry is within range, or there is a clone of it
13130b57cec5SDimitry Andric   // in range.
13140b57cec5SDimitry Andric   int result = findInRangeCPEntry(U, UserOffset);
13150b57cec5SDimitry Andric   if (result==1) return false;
13160b57cec5SDimitry Andric   else if (result==2) return true;
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric   // Look for water where we can place this CPE.
13190b57cec5SDimitry Andric   MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
13200b57cec5SDimitry Andric   MachineBasicBlock *NewMBB;
13210b57cec5SDimitry Andric   water_iterator IP;
13220b57cec5SDimitry Andric   if (findAvailableWater(U, UserOffset, IP)) {
13230b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Found water in range\n");
13240b57cec5SDimitry Andric     MachineBasicBlock *WaterBB = *IP;
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric     // If the original WaterList entry was "new water" on this iteration,
13270b57cec5SDimitry Andric     // propagate that to the new island.  This is just keeping NewWaterList
13280b57cec5SDimitry Andric     // updated to match the WaterList, which will be updated below.
13290b57cec5SDimitry Andric     if (NewWaterList.erase(WaterBB))
13300b57cec5SDimitry Andric       NewWaterList.insert(NewIsland);
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric     // The new CPE goes before the following block (NewMBB).
13330b57cec5SDimitry Andric     NewMBB = &*++WaterBB->getIterator();
13340b57cec5SDimitry Andric   } else {
13350b57cec5SDimitry Andric     // No water found.
13360b57cec5SDimitry Andric     // we first see if a longer form of the instrucion could have reached
13370b57cec5SDimitry Andric     // the constant. in that case we won't bother to split
13380b57cec5SDimitry Andric     if (!NoLoadRelaxation) {
13390b57cec5SDimitry Andric       result = findLongFormInRangeCPEntry(U, UserOffset);
13400b57cec5SDimitry Andric       if (result != 0) return true;
13410b57cec5SDimitry Andric     }
13420b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "No water found\n");
13430b57cec5SDimitry Andric     createNewWater(CPUserIndex, UserOffset, NewMBB);
13440b57cec5SDimitry Andric 
13450b57cec5SDimitry Andric     // splitBlockBeforeInstr adds to WaterList, which is important when it is
13460b57cec5SDimitry Andric     // called while handling branches so that the water will be seen on the
13470b57cec5SDimitry Andric     // next iteration for constant pools, but in this context, we don't want
13480b57cec5SDimitry Andric     // it.  Check for this so it will be removed from the WaterList.
13490b57cec5SDimitry Andric     // Also remove any entry from NewWaterList.
13500b57cec5SDimitry Andric     MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
13510b57cec5SDimitry Andric     IP = llvm::find(WaterList, WaterBB);
13520b57cec5SDimitry Andric     if (IP != WaterList.end())
13530b57cec5SDimitry Andric       NewWaterList.erase(WaterBB);
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric     // We are adding new water.  Update NewWaterList.
13560b57cec5SDimitry Andric     NewWaterList.insert(NewIsland);
13570b57cec5SDimitry Andric   }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   // Remove the original WaterList entry; we want subsequent insertions in
13600b57cec5SDimitry Andric   // this vicinity to go after the one we're about to insert.  This
13610b57cec5SDimitry Andric   // considerably reduces the number of times we have to move the same CPE
13620b57cec5SDimitry Andric   // more than once and is also important to ensure the algorithm terminates.
13630b57cec5SDimitry Andric   if (IP != WaterList.end())
13640b57cec5SDimitry Andric     WaterList.erase(IP);
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric   // Okay, we know we can put an island before NewMBB now, do it!
13670b57cec5SDimitry Andric   MF->insert(NewMBB->getIterator(), NewIsland);
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   // Update internal data structures to account for the newly inserted MBB.
13700b57cec5SDimitry Andric   updateForInsertedWaterBlock(NewIsland);
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   // Decrement the old entry, and remove it if refcount becomes 0.
13730b57cec5SDimitry Andric   decrementCPEReferenceCount(CPI, CPEMI);
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric   // No existing clone of this CPE is within range.
13760b57cec5SDimitry Andric   // We will be generating a new clone.  Get a UID for it.
13770b57cec5SDimitry Andric   unsigned ID = createPICLabelUId();
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric   // Now that we have an island to add the CPE to, clone the original CPE and
13800b57cec5SDimitry Andric   // add it to the island.
13810b57cec5SDimitry Andric   U.HighWaterMark = NewIsland;
13820b57cec5SDimitry Andric   U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY))
13830b57cec5SDimitry Andric                 .addImm(ID).addConstantPoolIndex(CPI).addImm(Size);
13840b57cec5SDimitry Andric   CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
13850b57cec5SDimitry Andric   ++NumCPEs;
13860b57cec5SDimitry Andric 
13870b57cec5SDimitry Andric   // Mark the basic block as aligned as required by the const-pool entry.
13888bcb0991SDimitry Andric   NewIsland->setAlignment(getCPEAlign(*U.CPEMI));
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric   // Increase the size of the island block to account for the new entry.
13910b57cec5SDimitry Andric   BBInfo[NewIsland->getNumber()].Size += Size;
13920b57cec5SDimitry Andric   adjustBBOffsetsAfter(&*--NewIsland->getIterator());
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric   // Finally, change the CPI in the instruction operand to be ID.
13954824e7fdSDimitry Andric   for (MachineOperand &MO : UserMI->operands())
13964824e7fdSDimitry Andric     if (MO.isCPI()) {
13974824e7fdSDimitry Andric       MO.setIndex(ID);
13980b57cec5SDimitry Andric       break;
13990b57cec5SDimitry Andric     }
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric   LLVM_DEBUG(
14020b57cec5SDimitry Andric       dbgs() << "  Moved CPE to #" << ID << " CPI=" << CPI
14030b57cec5SDimitry Andric              << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset));
14040b57cec5SDimitry Andric 
14050b57cec5SDimitry Andric   return true;
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric /// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update
14090b57cec5SDimitry Andric /// sizes and offsets of impacted basic blocks.
removeDeadCPEMI(MachineInstr * CPEMI)14100b57cec5SDimitry Andric void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
14110b57cec5SDimitry Andric   MachineBasicBlock *CPEBB = CPEMI->getParent();
14120b57cec5SDimitry Andric   unsigned Size = CPEMI->getOperand(2).getImm();
14130b57cec5SDimitry Andric   CPEMI->eraseFromParent();
14140b57cec5SDimitry Andric   BBInfo[CPEBB->getNumber()].Size -= Size;
14150b57cec5SDimitry Andric   // All succeeding offsets have the current size value added in, fix this.
14160b57cec5SDimitry Andric   if (CPEBB->empty()) {
14170b57cec5SDimitry Andric     BBInfo[CPEBB->getNumber()].Size = 0;
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric     // This block no longer needs to be aligned.
14208bcb0991SDimitry Andric     CPEBB->setAlignment(Align(1));
14218bcb0991SDimitry Andric   } else {
14220b57cec5SDimitry Andric     // Entries are sorted by descending alignment, so realign from the front.
14238bcb0991SDimitry Andric     CPEBB->setAlignment(getCPEAlign(*CPEBB->begin()));
14248bcb0991SDimitry Andric   }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric   adjustBBOffsetsAfter(CPEBB);
14270b57cec5SDimitry Andric   // An island has only one predecessor BB and one successor BB. Check if
14280b57cec5SDimitry Andric   // this BB's predecessor jumps directly to this BB's successor. This
14290b57cec5SDimitry Andric   // shouldn't happen currently.
14300b57cec5SDimitry Andric   assert(!BBIsJumpedOver(CPEBB) && "How did this happen?");
14310b57cec5SDimitry Andric   // FIXME: remove the empty blocks after all the work is done?
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric /// removeUnusedCPEntries - Remove constant pool entries whose refcounts
14350b57cec5SDimitry Andric /// are zero.
removeUnusedCPEntries()14360b57cec5SDimitry Andric bool MipsConstantIslands::removeUnusedCPEntries() {
14370b57cec5SDimitry Andric   unsigned MadeChange = false;
143804eeddc0SDimitry Andric   for (std::vector<CPEntry> &CPEs : CPEntries) {
143904eeddc0SDimitry Andric     for (CPEntry &CPE : CPEs) {
144004eeddc0SDimitry Andric       if (CPE.RefCount == 0 && CPE.CPEMI) {
144104eeddc0SDimitry Andric         removeDeadCPEMI(CPE.CPEMI);
144204eeddc0SDimitry Andric         CPE.CPEMI = nullptr;
14430b57cec5SDimitry Andric         MadeChange = true;
14440b57cec5SDimitry Andric       }
14450b57cec5SDimitry Andric     }
14460b57cec5SDimitry Andric   }
14470b57cec5SDimitry Andric   return MadeChange;
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric /// isBBInRange - Returns true if the distance between specific MI and
14510b57cec5SDimitry Andric /// specific BB can fit in MI's displacement field.
isBBInRange(MachineInstr * MI,MachineBasicBlock * DestBB,unsigned MaxDisp)14520b57cec5SDimitry Andric bool MipsConstantIslands::isBBInRange
14530b57cec5SDimitry Andric   (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) {
14540b57cec5SDimitry Andric   unsigned PCAdj = 4;
14550b57cec5SDimitry Andric   unsigned BrOffset   = getOffsetOf(MI) + PCAdj;
14560b57cec5SDimitry Andric   unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)
14590b57cec5SDimitry Andric                     << " from " << printMBBReference(*MI->getParent())
14600b57cec5SDimitry Andric                     << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
14610b57cec5SDimitry Andric                     << " to " << DestOffset << " offset "
14620b57cec5SDimitry Andric                     << int(DestOffset - BrOffset) << "\t" << *MI);
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric   if (BrOffset <= DestOffset) {
14650b57cec5SDimitry Andric     // Branch before the Dest.
14660b57cec5SDimitry Andric     if (DestOffset-BrOffset <= MaxDisp)
14670b57cec5SDimitry Andric       return true;
14680b57cec5SDimitry Andric   } else {
14690b57cec5SDimitry Andric     if (BrOffset-DestOffset <= MaxDisp)
14700b57cec5SDimitry Andric       return true;
14710b57cec5SDimitry Andric   }
14720b57cec5SDimitry Andric   return false;
14730b57cec5SDimitry Andric }
14740b57cec5SDimitry Andric 
14750b57cec5SDimitry Andric /// fixupImmediateBr - Fix up an immediate branch whose destination is too far
14760b57cec5SDimitry Andric /// away to fit in its displacement field.
fixupImmediateBr(ImmBranch & Br)14770b57cec5SDimitry Andric bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) {
14780b57cec5SDimitry Andric   MachineInstr *MI = Br.MI;
14790b57cec5SDimitry Andric   unsigned TargetOperand = branchTargetOperand(MI);
14800b57cec5SDimitry Andric   MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB();
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric   // Check to see if the DestBB is already in-range.
14830b57cec5SDimitry Andric   if (isBBInRange(MI, DestBB, Br.MaxDisp))
14840b57cec5SDimitry Andric     return false;
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric   if (!Br.isCond)
14870b57cec5SDimitry Andric     return fixupUnconditionalBr(Br);
14880b57cec5SDimitry Andric   return fixupConditionalBr(Br);
14890b57cec5SDimitry Andric }
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric /// fixupUnconditionalBr - Fix up an unconditional branch whose destination is
14920b57cec5SDimitry Andric /// too far away to fit in its displacement field. If the LR register has been
14930b57cec5SDimitry Andric /// spilled in the epilogue, then we can use BL to implement a far jump.
14940b57cec5SDimitry Andric /// Otherwise, add an intermediate branch instruction to a branch.
14950b57cec5SDimitry Andric bool
fixupUnconditionalBr(ImmBranch & Br)14960b57cec5SDimitry Andric MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
14970b57cec5SDimitry Andric   MachineInstr *MI = Br.MI;
14980b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
14990b57cec5SDimitry Andric   MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
15000b57cec5SDimitry Andric   // Use BL to implement far jump.
15010b57cec5SDimitry Andric   unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2;
15020b57cec5SDimitry Andric   if (isBBInRange(MI, DestBB, BimmX16MaxDisp)) {
15030b57cec5SDimitry Andric     Br.MaxDisp = BimmX16MaxDisp;
15040b57cec5SDimitry Andric     MI->setDesc(TII->get(Mips::BimmX16));
15050b57cec5SDimitry Andric   }
15060b57cec5SDimitry Andric   else {
15070b57cec5SDimitry Andric     // need to give the math a more careful look here
15080b57cec5SDimitry Andric     // this is really a segment address and not
15090b57cec5SDimitry Andric     // a PC relative address. FIXME. But I think that
15100b57cec5SDimitry Andric     // just reducing the bits by 1 as I've done is correct.
15110b57cec5SDimitry Andric     // The basic block we are branching too much be longword aligned.
15120b57cec5SDimitry Andric     // we know that RA is saved because we always save it right now.
15130b57cec5SDimitry Andric     // this requirement will be relaxed later but we also have an alternate
15140b57cec5SDimitry Andric     // way to implement this that I will implement that does not need jal.
1515480093f4SDimitry Andric     // We should have a way to back out this alignment restriction
1516480093f4SDimitry Andric     // if we "can" later. but it is not harmful.
15170b57cec5SDimitry Andric     //
15188bcb0991SDimitry Andric     DestBB->setAlignment(Align(4));
15190b57cec5SDimitry Andric     Br.MaxDisp = ((1<<24)-1) * 2;
15200b57cec5SDimitry Andric     MI->setDesc(TII->get(Mips::JalB16));
15210b57cec5SDimitry Andric   }
15220b57cec5SDimitry Andric   BBInfo[MBB->getNumber()].Size += 2;
15230b57cec5SDimitry Andric   adjustBBOffsetsAfter(MBB);
15240b57cec5SDimitry Andric   HasFarJump = true;
15250b57cec5SDimitry Andric   ++NumUBrFixed;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "  Changed B to long jump " << *MI);
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric   return true;
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric /// fixupConditionalBr - Fix up a conditional branch whose destination is too
15330b57cec5SDimitry Andric /// far away to fit in its displacement field. It is converted to an inverse
15340b57cec5SDimitry Andric /// conditional branch + an unconditional branch to the destination.
15350b57cec5SDimitry Andric bool
fixupConditionalBr(ImmBranch & Br)15360b57cec5SDimitry Andric MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
15370b57cec5SDimitry Andric   MachineInstr *MI = Br.MI;
15380b57cec5SDimitry Andric   unsigned TargetOperand = branchTargetOperand(MI);
15390b57cec5SDimitry Andric   MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB();
15400b57cec5SDimitry Andric   unsigned Opcode = MI->getOpcode();
15410b57cec5SDimitry Andric   unsigned LongFormOpcode = longformBranchOpcode(Opcode);
15420b57cec5SDimitry Andric   unsigned LongFormMaxOff = branchMaxOffsets(LongFormOpcode);
15430b57cec5SDimitry Andric 
15440b57cec5SDimitry Andric   // Check to see if the DestBB is already in-range.
15450b57cec5SDimitry Andric   if (isBBInRange(MI, DestBB, LongFormMaxOff)) {
15460b57cec5SDimitry Andric     Br.MaxDisp = LongFormMaxOff;
15470b57cec5SDimitry Andric     MI->setDesc(TII->get(LongFormOpcode));
15480b57cec5SDimitry Andric     return true;
15490b57cec5SDimitry Andric   }
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric   // Add an unconditional branch to the destination and invert the branch
15520b57cec5SDimitry Andric   // condition to jump over it:
15530b57cec5SDimitry Andric   // bteqz L1
15540b57cec5SDimitry Andric   // =>
15550b57cec5SDimitry Andric   // bnez L2
15560b57cec5SDimitry Andric   // b   L1
15570b57cec5SDimitry Andric   // L2:
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   // If the branch is at the end of its MBB and that has a fall-through block,
15600b57cec5SDimitry Andric   // direct the updated conditional branch to the fall-through block. Otherwise,
15610b57cec5SDimitry Andric   // split the MBB before the next instruction.
15620b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
15630b57cec5SDimitry Andric   MachineInstr *BMI = &MBB->back();
15640b57cec5SDimitry Andric   bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB);
15650b57cec5SDimitry Andric   unsigned OppositeBranchOpcode = TII->getOppositeBranchOpc(Opcode);
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric   ++NumCBrFixed;
15680b57cec5SDimitry Andric   if (BMI != MI) {
15690b57cec5SDimitry Andric     if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) &&
15700b57cec5SDimitry Andric         BMI->isUnconditionalBranch()) {
15710b57cec5SDimitry Andric       // Last MI in the BB is an unconditional branch. Can we simply invert the
15720b57cec5SDimitry Andric       // condition and swap destinations:
15730b57cec5SDimitry Andric       // beqz L1
15740b57cec5SDimitry Andric       // b   L2
15750b57cec5SDimitry Andric       // =>
15760b57cec5SDimitry Andric       // bnez L2
15770b57cec5SDimitry Andric       // b   L1
15780b57cec5SDimitry Andric       unsigned BMITargetOperand = branchTargetOperand(BMI);
15790b57cec5SDimitry Andric       MachineBasicBlock *NewDest =
15800b57cec5SDimitry Andric         BMI->getOperand(BMITargetOperand).getMBB();
15810b57cec5SDimitry Andric       if (isBBInRange(MI, NewDest, Br.MaxDisp)) {
15820b57cec5SDimitry Andric         LLVM_DEBUG(
15830b57cec5SDimitry Andric             dbgs() << "  Invert Bcc condition and swap its destination with "
15840b57cec5SDimitry Andric                    << *BMI);
15850b57cec5SDimitry Andric         MI->setDesc(TII->get(OppositeBranchOpcode));
15860b57cec5SDimitry Andric         BMI->getOperand(BMITargetOperand).setMBB(DestBB);
15870b57cec5SDimitry Andric         MI->getOperand(TargetOperand).setMBB(NewDest);
15880b57cec5SDimitry Andric         return true;
15890b57cec5SDimitry Andric       }
15900b57cec5SDimitry Andric     }
15910b57cec5SDimitry Andric   }
15920b57cec5SDimitry Andric 
15930b57cec5SDimitry Andric   if (NeedSplit) {
15940b57cec5SDimitry Andric     splitBlockBeforeInstr(*MI);
15950b57cec5SDimitry Andric     // No need for the branch to the next block. We're adding an unconditional
15960b57cec5SDimitry Andric     // branch to the destination.
15970b57cec5SDimitry Andric     int delta = TII->getInstSizeInBytes(MBB->back());
15980b57cec5SDimitry Andric     BBInfo[MBB->getNumber()].Size -= delta;
15990b57cec5SDimitry Andric     MBB->back().eraseFromParent();
16000b57cec5SDimitry Andric     // BBInfo[SplitBB].Offset is wrong temporarily, fixed below
16010b57cec5SDimitry Andric   }
16020b57cec5SDimitry Andric   MachineBasicBlock *NextBB = &*++MBB->getIterator();
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "  Insert B to " << printMBBReference(*DestBB)
16050b57cec5SDimitry Andric                     << " also invert condition and change dest. to "
16060b57cec5SDimitry Andric                     << printMBBReference(*NextBB) << "\n");
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric   // Insert a new conditional branch and a new unconditional branch.
16090b57cec5SDimitry Andric   // Also update the ImmBranch as well as adding a new entry for the new branch.
16100b57cec5SDimitry Andric   if (MI->getNumExplicitOperands() == 2) {
16110b57cec5SDimitry Andric     BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode))
16120b57cec5SDimitry Andric            .addReg(MI->getOperand(0).getReg())
16130b57cec5SDimitry Andric            .addMBB(NextBB);
16140b57cec5SDimitry Andric   } else {
16150b57cec5SDimitry Andric     BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode))
16160b57cec5SDimitry Andric            .addMBB(NextBB);
16170b57cec5SDimitry Andric   }
16180b57cec5SDimitry Andric   Br.MI = &MBB->back();
16190b57cec5SDimitry Andric   BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back());
16200b57cec5SDimitry Andric   BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB);
16210b57cec5SDimitry Andric   BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back());
16220b57cec5SDimitry Andric   unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr);
16230b57cec5SDimitry Andric   ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric   // Remove the old conditional branch.  It may or may not still be in MBB.
16260b57cec5SDimitry Andric   BBInfo[MI->getParent()->getNumber()].Size -= TII->getInstSizeInBytes(*MI);
16270b57cec5SDimitry Andric   MI->eraseFromParent();
16280b57cec5SDimitry Andric   adjustBBOffsetsAfter(MBB);
16290b57cec5SDimitry Andric   return true;
16300b57cec5SDimitry Andric }
16310b57cec5SDimitry Andric 
prescanForConstants()16320b57cec5SDimitry Andric void MipsConstantIslands::prescanForConstants() {
16330b57cec5SDimitry Andric   unsigned J = 0;
16340b57cec5SDimitry Andric   (void)J;
16354824e7fdSDimitry Andric   for (MachineBasicBlock &B : *MF) {
16364824e7fdSDimitry Andric     for (MachineBasicBlock::instr_iterator I = B.instr_begin(),
16374824e7fdSDimitry Andric                                            EB = B.instr_end();
16384824e7fdSDimitry Andric          I != EB; ++I) {
16390b57cec5SDimitry Andric       switch(I->getDesc().getOpcode()) {
16400b57cec5SDimitry Andric         case Mips::LwConstant32: {
16410b57cec5SDimitry Andric           PrescannedForConstants = true;
16420b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n");
16430b57cec5SDimitry Andric           J = I->getNumOperands();
16440b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "num operands " << J << "\n");
16450b57cec5SDimitry Andric           MachineOperand& Literal = I->getOperand(1);
16460b57cec5SDimitry Andric           if (Literal.isImm()) {
16470b57cec5SDimitry Andric             int64_t V = Literal.getImm();
16480b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "literal " << V << "\n");
16490b57cec5SDimitry Andric             Type *Int32Ty =
16500b57cec5SDimitry Andric               Type::getInt32Ty(MF->getFunction().getContext());
16510b57cec5SDimitry Andric             const Constant *C = ConstantInt::get(Int32Ty, V);
16525ffd83dbSDimitry Andric             unsigned index = MCP->getConstantPoolIndex(C, Align(4));
16530b57cec5SDimitry Andric             I->getOperand(2).ChangeToImmediate(index);
16540b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n");
16550b57cec5SDimitry Andric             I->setDesc(TII->get(Mips::LwRxPcTcp16));
1656*81ad6265SDimitry Andric             I->removeOperand(1);
1657*81ad6265SDimitry Andric             I->removeOperand(1);
16580b57cec5SDimitry Andric             I->addOperand(MachineOperand::CreateCPI(index, 0));
16590b57cec5SDimitry Andric             I->addOperand(MachineOperand::CreateImm(4));
16600b57cec5SDimitry Andric           }
16610b57cec5SDimitry Andric           break;
16620b57cec5SDimitry Andric         }
16630b57cec5SDimitry Andric         default:
16640b57cec5SDimitry Andric           break;
16650b57cec5SDimitry Andric       }
16660b57cec5SDimitry Andric     }
16670b57cec5SDimitry Andric   }
16680b57cec5SDimitry Andric }
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric /// Returns a pass that converts branches to long branches.
createMipsConstantIslandPass()16710b57cec5SDimitry Andric FunctionPass *llvm::createMipsConstantIslandPass() {
16720b57cec5SDimitry Andric   return new MipsConstantIslands();
16730b57cec5SDimitry Andric }
1674