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