10b57cec5SDimitry Andric //===----------------------- MipsBranchExpansion.cpp ----------------------===// 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 /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This pass do two things: 110b57cec5SDimitry Andric /// - it expands a branch or jump instruction into a long branch if its offset 120b57cec5SDimitry Andric /// is too large to fit into its immediate field, 130b57cec5SDimitry Andric /// - it inserts nops to prevent forbidden slot hazards. 140b57cec5SDimitry Andric /// 150b57cec5SDimitry Andric /// The reason why this pass combines these two tasks is that one of these two 160b57cec5SDimitry Andric /// tasks can break the result of the previous one. 170b57cec5SDimitry Andric /// 180b57cec5SDimitry Andric /// Example of that is a situation where at first, no branch should be expanded, 190b57cec5SDimitry Andric /// but after adding at least one nop somewhere in the code to prevent a 200b57cec5SDimitry Andric /// forbidden slot hazard, offset of some branches may go out of range. In that 210b57cec5SDimitry Andric /// case it is necessary to check again if there is some branch that needs 220b57cec5SDimitry Andric /// expansion. On the other hand, expanding some branch may cause a control 230b57cec5SDimitry Andric /// transfer instruction to appear in the forbidden slot, which is a hazard that 240b57cec5SDimitry Andric /// should be fixed. This pass alternates between this two tasks untill no 250b57cec5SDimitry Andric /// changes are made. Only then we can be sure that all branches are expanded 260b57cec5SDimitry Andric /// properly, and no hazard situations exist. 270b57cec5SDimitry Andric /// 280b57cec5SDimitry Andric /// Regarding branch expanding: 290b57cec5SDimitry Andric /// 300b57cec5SDimitry Andric /// When branch instruction like beqzc or bnezc has offset that is too large 310b57cec5SDimitry Andric /// to fit into its immediate field, it has to be expanded to another 320b57cec5SDimitry Andric /// instruction or series of instructions. 330b57cec5SDimitry Andric /// 340b57cec5SDimitry Andric /// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. 350b57cec5SDimitry Andric /// TODO: Handle out of range bc, b (pseudo) instructions. 360b57cec5SDimitry Andric /// 370b57cec5SDimitry Andric /// Regarding compact branch hazard prevention: 380b57cec5SDimitry Andric /// 3981ad6265SDimitry Andric /// Hazards handled: forbidden slots for MIPSR6, FPU slots for MIPS3 and below, 4081ad6265SDimitry Andric /// load delay slots for MIPS1. 410b57cec5SDimitry Andric /// 420b57cec5SDimitry Andric /// A forbidden slot hazard occurs when a compact branch instruction is executed 430b57cec5SDimitry Andric /// and the adjacent instruction in memory is a control transfer instruction 440b57cec5SDimitry Andric /// such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE. 450b57cec5SDimitry Andric /// 460b57cec5SDimitry Andric /// For example: 470b57cec5SDimitry Andric /// 480b57cec5SDimitry Andric /// 0x8004 bnec a1,v0,<P+0x18> 490b57cec5SDimitry Andric /// 0x8008 beqc a1,a2,<P+0x54> 500b57cec5SDimitry Andric /// 510b57cec5SDimitry Andric /// In such cases, the processor is required to signal a Reserved Instruction 520b57cec5SDimitry Andric /// exception. 530b57cec5SDimitry Andric /// 540b57cec5SDimitry Andric /// Here, if the instruction at 0x8004 is executed, the processor will raise an 550b57cec5SDimitry Andric /// exception as there is a control transfer instruction at 0x8008. 560b57cec5SDimitry Andric /// 570b57cec5SDimitry Andric /// There are two sources of forbidden slot hazards: 580b57cec5SDimitry Andric /// 590b57cec5SDimitry Andric /// A) A previous pass has created a compact branch directly. 600b57cec5SDimitry Andric /// B) Transforming a delay slot branch into compact branch. This case can be 610b57cec5SDimitry Andric /// difficult to process as lookahead for hazards is insufficient, as 620b57cec5SDimitry Andric /// backwards delay slot fillling can also produce hazards in previously 630b57cec5SDimitry Andric /// processed instuctions. 640b57cec5SDimitry Andric /// 650b57cec5SDimitry Andric /// In future this pass can be extended (or new pass can be created) to handle 660b57cec5SDimitry Andric /// other pipeline hazards, such as various MIPS1 hazards, processor errata that 670b57cec5SDimitry Andric /// require instruction reorganization, etc. 680b57cec5SDimitry Andric /// 690b57cec5SDimitry Andric /// This pass has to run after the delay slot filler as that pass can introduce 700b57cec5SDimitry Andric /// pipeline hazards such as compact branch hazard, hence the existing hazard 710b57cec5SDimitry Andric /// recognizer is not suitable. 720b57cec5SDimitry Andric /// 730b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h" 760b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 770b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCNaCl.h" 780b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h" 790b57cec5SDimitry Andric #include "Mips.h" 800b57cec5SDimitry Andric #include "MipsInstrInfo.h" 810b57cec5SDimitry Andric #include "MipsMachineFunction.h" 820b57cec5SDimitry Andric #include "MipsSubtarget.h" 830b57cec5SDimitry Andric #include "MipsTargetMachine.h" 840b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 850b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 860b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 870b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 880b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 890b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 900b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 910b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 920b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 930b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 940b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 950b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 960b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 970b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 980b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 990b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 1000b57cec5SDimitry Andric #include <algorithm> 1010b57cec5SDimitry Andric #include <cassert> 1020b57cec5SDimitry Andric #include <cstdint> 1030b57cec5SDimitry Andric #include <iterator> 1040b57cec5SDimitry Andric #include <utility> 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric using namespace llvm; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric #define DEBUG_TYPE "mips-branch-expansion" 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric STATISTIC(NumInsertedNops, "Number of nops inserted"); 1110b57cec5SDimitry Andric STATISTIC(LongBranches, "Number of long branches."); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric static cl::opt<bool> 1140b57cec5SDimitry Andric SkipLongBranch("skip-mips-long-branch", cl::init(false), 1150b57cec5SDimitry Andric cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric static cl::opt<bool> 1180b57cec5SDimitry Andric ForceLongBranch("force-mips-long-branch", cl::init(false), 1190b57cec5SDimitry Andric cl::desc("MIPS: Expand all branches to long format."), 1200b57cec5SDimitry Andric cl::Hidden); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric namespace { 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric using Iter = MachineBasicBlock::iterator; 1250b57cec5SDimitry Andric using ReverseIter = MachineBasicBlock::reverse_iterator; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric struct MBBInfo { 1280b57cec5SDimitry Andric uint64_t Size = 0; 1290b57cec5SDimitry Andric bool HasLongBranch = false; 1300b57cec5SDimitry Andric MachineInstr *Br = nullptr; 1310b57cec5SDimitry Andric uint64_t Offset = 0; 1320b57cec5SDimitry Andric MBBInfo() = default; 1330b57cec5SDimitry Andric }; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric class MipsBranchExpansion : public MachineFunctionPass { 1360b57cec5SDimitry Andric public: 1370b57cec5SDimitry Andric static char ID; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric MipsBranchExpansion() : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) { 1400b57cec5SDimitry Andric initializeMipsBranchExpansionPass(*PassRegistry::getPassRegistry()); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric StringRef getPassName() const override { 1440b57cec5SDimitry Andric return "Mips Branch Expansion Pass"; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1500b57cec5SDimitry Andric return MachineFunctionProperties().set( 1510b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric private: 1550b57cec5SDimitry Andric void splitMBB(MachineBasicBlock *MBB); 1560b57cec5SDimitry Andric void initMBBInfo(); 1570b57cec5SDimitry Andric int64_t computeOffset(const MachineInstr *Br); 1580b57cec5SDimitry Andric uint64_t computeOffsetFromTheBeginning(int MBB); 1590b57cec5SDimitry Andric void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, 1600b57cec5SDimitry Andric MachineBasicBlock *MBBOpnd); 1610b57cec5SDimitry Andric bool buildProperJumpMI(MachineBasicBlock *MBB, 1620b57cec5SDimitry Andric MachineBasicBlock::iterator Pos, DebugLoc DL); 1630b57cec5SDimitry Andric void expandToLongBranch(MBBInfo &Info); 1640eae32dcSDimitry Andric template <typename Pred, typename Safe> 1650eae32dcSDimitry Andric bool handleSlot(Pred Predicate, Safe SafeInSlot); 1660b57cec5SDimitry Andric bool handleForbiddenSlot(); 1670eae32dcSDimitry Andric bool handleFPUDelaySlot(); 16881ad6265SDimitry Andric bool handleLoadDelaySlot(); 1690b57cec5SDimitry Andric bool handlePossibleLongBranch(); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const MipsSubtarget *STI; 1720b57cec5SDimitry Andric const MipsInstrInfo *TII; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric MachineFunction *MFp; 1750b57cec5SDimitry Andric SmallVector<MBBInfo, 16> MBBInfos; 1760b57cec5SDimitry Andric bool IsPIC; 1770b57cec5SDimitry Andric MipsABIInfo ABI; 1780b57cec5SDimitry Andric bool ForceLongBranchFirstPass = false; 1790b57cec5SDimitry Andric }; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric } // end of anonymous namespace 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric char MipsBranchExpansion::ID = 0; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric INITIALIZE_PASS(MipsBranchExpansion, DEBUG_TYPE, 1860b57cec5SDimitry Andric "Expand out of range branch instructions and fix forbidden" 1870b57cec5SDimitry Andric " slot hazards", 1880b57cec5SDimitry Andric false, false) 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric /// Returns a pass that clears pipeline hazards. 1910b57cec5SDimitry Andric FunctionPass *llvm::createMipsBranchExpansion() { 1920b57cec5SDimitry Andric return new MipsBranchExpansion(); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // Find the next real instruction from the current position in current basic 1960b57cec5SDimitry Andric // block. 1970b57cec5SDimitry Andric static Iter getNextMachineInstrInBB(Iter Position) { 1980b57cec5SDimitry Andric Iter I = Position, E = Position->getParent()->end(); 1990b57cec5SDimitry Andric I = std::find_if_not(I, E, 2000b57cec5SDimitry Andric [](const Iter &Insn) { return Insn->isTransient(); }); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric return I; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric // Find the next real instruction from the current position, looking through 2060b57cec5SDimitry Andric // basic block boundaries. 2070b57cec5SDimitry Andric static std::pair<Iter, bool> getNextMachineInstr(Iter Position, 2080b57cec5SDimitry Andric MachineBasicBlock *Parent) { 2090b57cec5SDimitry Andric if (Position == Parent->end()) { 2100b57cec5SDimitry Andric do { 2110b57cec5SDimitry Andric MachineBasicBlock *Succ = Parent->getNextNode(); 2120b57cec5SDimitry Andric if (Succ != nullptr && Parent->isSuccessor(Succ)) { 2130b57cec5SDimitry Andric Position = Succ->begin(); 2140b57cec5SDimitry Andric Parent = Succ; 2150b57cec5SDimitry Andric } else { 2160b57cec5SDimitry Andric return std::make_pair(Position, true); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric } while (Parent->empty()); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric Iter Instr = getNextMachineInstrInBB(Position); 2220b57cec5SDimitry Andric if (Instr == Parent->end()) { 2230b57cec5SDimitry Andric return getNextMachineInstr(Instr, Parent); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric return std::make_pair(Instr, false); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric /// Iterate over list of Br's operands and search for a MachineBasicBlock 2290b57cec5SDimitry Andric /// operand. 2300b57cec5SDimitry Andric static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { 2310b57cec5SDimitry Andric for (unsigned I = 0, E = Br.getDesc().getNumOperands(); I < E; ++I) { 2320b57cec5SDimitry Andric const MachineOperand &MO = Br.getOperand(I); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric if (MO.isMBB()) 2350b57cec5SDimitry Andric return MO.getMBB(); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric llvm_unreachable("This instruction does not have an MBB operand."); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric // Traverse the list of instructions backwards until a non-debug instruction is 2420b57cec5SDimitry Andric // found or it reaches E. 2430b57cec5SDimitry Andric static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) { 2440b57cec5SDimitry Andric for (; B != E; ++B) 2450b57cec5SDimitry Andric if (!B->isDebugInstr()) 2460b57cec5SDimitry Andric return B; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric return E; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Split MBB if it has two direct jumps/branches. 2520b57cec5SDimitry Andric void MipsBranchExpansion::splitMBB(MachineBasicBlock *MBB) { 2530b57cec5SDimitry Andric ReverseIter End = MBB->rend(); 2540b57cec5SDimitry Andric ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric // Return if MBB has no branch instructions. 2570b57cec5SDimitry Andric if ((LastBr == End) || 2580b57cec5SDimitry Andric (!LastBr->isConditionalBranch() && !LastBr->isUnconditionalBranch())) 2590b57cec5SDimitry Andric return; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric ReverseIter FirstBr = getNonDebugInstr(std::next(LastBr), End); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric // MBB has only one branch instruction if FirstBr is not a branch 2640b57cec5SDimitry Andric // instruction. 2650b57cec5SDimitry Andric if ((FirstBr == End) || 2660b57cec5SDimitry Andric (!FirstBr->isConditionalBranch() && !FirstBr->isUnconditionalBranch())) 2670b57cec5SDimitry Andric return; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric assert(!FirstBr->isIndirectBranch() && "Unexpected indirect branch found."); 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric // Create a new MBB. Move instructions in MBB to the newly created MBB. 2720b57cec5SDimitry Andric MachineBasicBlock *NewMBB = 2730b57cec5SDimitry Andric MFp->CreateMachineBasicBlock(MBB->getBasicBlock()); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // Insert NewMBB and fix control flow. 2760b57cec5SDimitry Andric MachineBasicBlock *Tgt = getTargetMBB(*FirstBr); 2770b57cec5SDimitry Andric NewMBB->transferSuccessors(MBB); 2780b57cec5SDimitry Andric if (Tgt != getTargetMBB(*LastBr)) 2790b57cec5SDimitry Andric NewMBB->removeSuccessor(Tgt, true); 2800b57cec5SDimitry Andric MBB->addSuccessor(NewMBB); 2810b57cec5SDimitry Andric MBB->addSuccessor(Tgt); 2820b57cec5SDimitry Andric MFp->insert(std::next(MachineFunction::iterator(MBB)), NewMBB); 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric NewMBB->splice(NewMBB->end(), MBB, LastBr.getReverse(), MBB->end()); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric // Fill MBBInfos. 2880b57cec5SDimitry Andric void MipsBranchExpansion::initMBBInfo() { 2890b57cec5SDimitry Andric // Split the MBBs if they have two branches. Each basic block should have at 2900b57cec5SDimitry Andric // most one branch after this loop is executed. 2910b57cec5SDimitry Andric for (auto &MBB : *MFp) 2920b57cec5SDimitry Andric splitMBB(&MBB); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric MFp->RenumberBlocks(); 2950b57cec5SDimitry Andric MBBInfos.clear(); 2960b57cec5SDimitry Andric MBBInfos.resize(MFp->size()); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { 2990b57cec5SDimitry Andric MachineBasicBlock *MBB = MFp->getBlockNumbered(I); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // Compute size of MBB. 302*0fca6ea1SDimitry Andric for (MachineInstr &MI : MBB->instrs()) 303*0fca6ea1SDimitry Andric MBBInfos[I].Size += TII->getInstSizeInBytes(MI); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // Compute offset of branch in number of bytes. 3080b57cec5SDimitry Andric int64_t MipsBranchExpansion::computeOffset(const MachineInstr *Br) { 3090b57cec5SDimitry Andric int64_t Offset = 0; 3100b57cec5SDimitry Andric int ThisMBB = Br->getParent()->getNumber(); 3110b57cec5SDimitry Andric int TargetMBB = getTargetMBB(*Br)->getNumber(); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Compute offset of a forward branch. 3140b57cec5SDimitry Andric if (ThisMBB < TargetMBB) { 3150b57cec5SDimitry Andric for (int N = ThisMBB + 1; N < TargetMBB; ++N) 3160b57cec5SDimitry Andric Offset += MBBInfos[N].Size; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric return Offset + 4; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric // Compute offset of a backward branch. 3220b57cec5SDimitry Andric for (int N = ThisMBB; N >= TargetMBB; --N) 3230b57cec5SDimitry Andric Offset += MBBInfos[N].Size; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric return -Offset + 4; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // Returns the distance in bytes up until MBB 3290b57cec5SDimitry Andric uint64_t MipsBranchExpansion::computeOffsetFromTheBeginning(int MBB) { 3300b57cec5SDimitry Andric uint64_t Offset = 0; 3310b57cec5SDimitry Andric for (int N = 0; N < MBB; ++N) 3320b57cec5SDimitry Andric Offset += MBBInfos[N].Size; 3330b57cec5SDimitry Andric return Offset; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric // Replace Br with a branch which has the opposite condition code and a 3370b57cec5SDimitry Andric // MachineBasicBlock operand MBBOpnd. 3380b57cec5SDimitry Andric void MipsBranchExpansion::replaceBranch(MachineBasicBlock &MBB, Iter Br, 3390b57cec5SDimitry Andric const DebugLoc &DL, 3400b57cec5SDimitry Andric MachineBasicBlock *MBBOpnd) { 3410b57cec5SDimitry Andric unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); 3420b57cec5SDimitry Andric const MCInstrDesc &NewDesc = TII->get(NewOpc); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) { 3470b57cec5SDimitry Andric MachineOperand &MO = Br->getOperand(I); 3480b57cec5SDimitry Andric 3495ffd83dbSDimitry Andric switch (MO.getType()) { 3505ffd83dbSDimitry Andric case MachineOperand::MO_Register: 3510b57cec5SDimitry Andric MIB.addReg(MO.getReg()); 3525ffd83dbSDimitry Andric break; 3535ffd83dbSDimitry Andric case MachineOperand::MO_Immediate: 3545ffd83dbSDimitry Andric // Octeon BBIT family of branch has an immediate operand 3555ffd83dbSDimitry Andric // (e.g. BBIT0 $v0, 3, %bb.1). 3565ffd83dbSDimitry Andric if (!TII->isBranchWithImm(Br->getOpcode())) 3575ffd83dbSDimitry Andric llvm_unreachable("Unexpected immediate in branch instruction"); 3585ffd83dbSDimitry Andric MIB.addImm(MO.getImm()); 3595ffd83dbSDimitry Andric break; 3605ffd83dbSDimitry Andric case MachineOperand::MO_MachineBasicBlock: 3610b57cec5SDimitry Andric MIB.addMBB(MBBOpnd); 3625ffd83dbSDimitry Andric break; 3635ffd83dbSDimitry Andric default: 3645ffd83dbSDimitry Andric llvm_unreachable("Unexpected operand type in branch instruction"); 3655ffd83dbSDimitry Andric } 3665ffd83dbSDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric if (Br->hasDelaySlot()) { 3690b57cec5SDimitry Andric // Bundle the instruction in the delay slot to the newly created branch 3700b57cec5SDimitry Andric // and erase the original branch. 3710b57cec5SDimitry Andric assert(Br->isBundledWithSucc()); 3720b57cec5SDimitry Andric MachineBasicBlock::instr_iterator II = Br.getInstrIterator(); 3730b57cec5SDimitry Andric MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric Br->eraseFromParent(); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric bool MipsBranchExpansion::buildProperJumpMI(MachineBasicBlock *MBB, 3790b57cec5SDimitry Andric MachineBasicBlock::iterator Pos, 3800b57cec5SDimitry Andric DebugLoc DL) { 3810b57cec5SDimitry Andric bool HasR6 = ABI.IsN64() ? STI->hasMips64r6() : STI->hasMips32r6(); 3820b57cec5SDimitry Andric bool AddImm = HasR6 && !STI->useIndirectJumpsHazard(); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric unsigned JR = ABI.IsN64() ? Mips::JR64 : Mips::JR; 3850b57cec5SDimitry Andric unsigned JIC = ABI.IsN64() ? Mips::JIC64 : Mips::JIC; 3860b57cec5SDimitry Andric unsigned JR_HB = ABI.IsN64() ? Mips::JR_HB64 : Mips::JR_HB; 3870b57cec5SDimitry Andric unsigned JR_HB_R6 = ABI.IsN64() ? Mips::JR_HB64_R6 : Mips::JR_HB_R6; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric unsigned JumpOp; 3900b57cec5SDimitry Andric if (STI->useIndirectJumpsHazard()) 3910b57cec5SDimitry Andric JumpOp = HasR6 ? JR_HB_R6 : JR_HB; 3920b57cec5SDimitry Andric else 3930b57cec5SDimitry Andric JumpOp = HasR6 ? JIC : JR; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric if (JumpOp == Mips::JIC && STI->inMicroMipsMode()) 3960b57cec5SDimitry Andric JumpOp = Mips::JIC_MMR6; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric unsigned ATReg = ABI.IsN64() ? Mips::AT_64 : Mips::AT; 3990b57cec5SDimitry Andric MachineInstrBuilder Instr = 4000b57cec5SDimitry Andric BuildMI(*MBB, Pos, DL, TII->get(JumpOp)).addReg(ATReg); 4010b57cec5SDimitry Andric if (AddImm) 4020b57cec5SDimitry Andric Instr.addImm(0); 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric return !AddImm; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric // Expand branch instructions to long branches. 4080b57cec5SDimitry Andric // TODO: This function has to be fixed for beqz16 and bnez16, because it 4090b57cec5SDimitry Andric // currently assumes that all branches have 16-bit offsets, and will produce 4100b57cec5SDimitry Andric // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] 4110b57cec5SDimitry Andric // are present. 4120b57cec5SDimitry Andric void MipsBranchExpansion::expandToLongBranch(MBBInfo &I) { 4130b57cec5SDimitry Andric MachineBasicBlock::iterator Pos; 4140b57cec5SDimitry Andric MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); 4150b57cec5SDimitry Andric DebugLoc DL = I.Br->getDebugLoc(); 4160b57cec5SDimitry Andric const BasicBlock *BB = MBB->getBasicBlock(); 4170b57cec5SDimitry Andric MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); 4180b57cec5SDimitry Andric MachineBasicBlock *LongBrMBB = MFp->CreateMachineBasicBlock(BB); 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric MFp->insert(FallThroughMBB, LongBrMBB); 4210b57cec5SDimitry Andric MBB->replaceSuccessor(TgtMBB, LongBrMBB); 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric if (IsPIC) { 4240b57cec5SDimitry Andric MachineBasicBlock *BalTgtMBB = MFp->CreateMachineBasicBlock(BB); 4250b57cec5SDimitry Andric MFp->insert(FallThroughMBB, BalTgtMBB); 4260b57cec5SDimitry Andric LongBrMBB->addSuccessor(BalTgtMBB); 4270b57cec5SDimitry Andric BalTgtMBB->addSuccessor(TgtMBB); 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // We must select between the MIPS32r6/MIPS64r6 BALC (which is a normal 4300b57cec5SDimitry Andric // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an 4310b57cec5SDimitry Andric // pseudo-instruction wrapping BGEZAL). 4320b57cec5SDimitry Andric const unsigned BalOp = 4330b57cec5SDimitry Andric STI->hasMips32r6() 4340b57cec5SDimitry Andric ? STI->inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC 4350b57cec5SDimitry Andric : STI->inMicroMipsMode() ? Mips::BAL_BR_MM : Mips::BAL_BR; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric if (!ABI.IsN64()) { 4380b57cec5SDimitry Andric // Pre R6: 4390b57cec5SDimitry Andric // $longbr: 4400b57cec5SDimitry Andric // addiu $sp, $sp, -8 4410b57cec5SDimitry Andric // sw $ra, 0($sp) 4420b57cec5SDimitry Andric // lui $at, %hi($tgt - $baltgt) 4430b57cec5SDimitry Andric // bal $baltgt 4440b57cec5SDimitry Andric // addiu $at, $at, %lo($tgt - $baltgt) 4450b57cec5SDimitry Andric // $baltgt: 4460b57cec5SDimitry Andric // addu $at, $ra, $at 4470b57cec5SDimitry Andric // lw $ra, 0($sp) 4480b57cec5SDimitry Andric // jr $at 4490b57cec5SDimitry Andric // addiu $sp, $sp, 8 4500b57cec5SDimitry Andric // $fallthrough: 4510b57cec5SDimitry Andric // 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // R6: 4540b57cec5SDimitry Andric // $longbr: 4550b57cec5SDimitry Andric // addiu $sp, $sp, -8 4560b57cec5SDimitry Andric // sw $ra, 0($sp) 4570b57cec5SDimitry Andric // lui $at, %hi($tgt - $baltgt) 4580b57cec5SDimitry Andric // addiu $at, $at, %lo($tgt - $baltgt) 4590b57cec5SDimitry Andric // balc $baltgt 4600b57cec5SDimitry Andric // $baltgt: 4610b57cec5SDimitry Andric // addu $at, $ra, $at 4620b57cec5SDimitry Andric // lw $ra, 0($sp) 4630b57cec5SDimitry Andric // addiu $sp, $sp, 8 4640b57cec5SDimitry Andric // jic $at, 0 4650b57cec5SDimitry Andric // $fallthrough: 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric Pos = LongBrMBB->begin(); 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) 4700b57cec5SDimitry Andric .addReg(Mips::SP) 4710b57cec5SDimitry Andric .addImm(-8); 4720b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)) 4730b57cec5SDimitry Andric .addReg(Mips::RA) 4740b57cec5SDimitry Andric .addReg(Mips::SP) 4750b57cec5SDimitry Andric .addImm(0); 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric // LUi and ADDiu instructions create 32-bit offset of the target basic 4780b57cec5SDimitry Andric // block from the target of BAL(C) instruction. We cannot use immediate 4790b57cec5SDimitry Andric // value for this offset because it cannot be determined accurately when 4800b57cec5SDimitry Andric // the program has inline assembly statements. We therefore use the 4810b57cec5SDimitry Andric // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which 4820b57cec5SDimitry Andric // are resolved during the fixup, so the values will always be correct. 4830b57cec5SDimitry Andric // 4840b57cec5SDimitry Andric // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) 4850b57cec5SDimitry Andric // expressions at this point (it is possible only at the MC layer), 4860b57cec5SDimitry Andric // we replace LUi and ADDiu with pseudo instructions 4870b57cec5SDimitry Andric // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic 4880b57cec5SDimitry Andric // blocks as operands to these instructions. When lowering these pseudo 4890b57cec5SDimitry Andric // instructions to LUi and ADDiu in the MC layer, we will create 4900b57cec5SDimitry Andric // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as 4910b57cec5SDimitry Andric // operands to lowered instructions. 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT) 4940b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_HI) 4950b57cec5SDimitry Andric .addMBB(BalTgtMBB); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric MachineInstrBuilder BalInstr = 4980b57cec5SDimitry Andric BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); 4990b57cec5SDimitry Andric MachineInstrBuilder ADDiuInstr = 5000b57cec5SDimitry Andric BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) 5010b57cec5SDimitry Andric .addReg(Mips::AT) 5020b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_LO) 5030b57cec5SDimitry Andric .addMBB(BalTgtMBB); 5040b57cec5SDimitry Andric if (STI->hasMips32r6()) { 5050b57cec5SDimitry Andric LongBrMBB->insert(Pos, ADDiuInstr); 5060b57cec5SDimitry Andric LongBrMBB->insert(Pos, BalInstr); 5070b57cec5SDimitry Andric } else { 5080b57cec5SDimitry Andric LongBrMBB->insert(Pos, BalInstr); 5090b57cec5SDimitry Andric LongBrMBB->insert(Pos, ADDiuInstr); 5100b57cec5SDimitry Andric LongBrMBB->rbegin()->bundleWithPred(); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric Pos = BalTgtMBB->begin(); 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) 5160b57cec5SDimitry Andric .addReg(Mips::RA) 5170b57cec5SDimitry Andric .addReg(Mips::AT); 5180b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) 5190b57cec5SDimitry Andric .addReg(Mips::SP) 5200b57cec5SDimitry Andric .addImm(0); 5210b57cec5SDimitry Andric if (STI->isTargetNaCl()) 5220b57cec5SDimitry Andric // Bundle-align the target of indirect branch JR. 5230b57cec5SDimitry Andric TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // In NaCl, modifying the sp is not allowed in branch delay slot. 5260b57cec5SDimitry Andric // For MIPS32R6, we can skip using a delay slot branch. 5270b57cec5SDimitry Andric bool hasDelaySlot = buildProperJumpMI(BalTgtMBB, Pos, DL); 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric if (STI->isTargetNaCl() || !hasDelaySlot) { 5300b57cec5SDimitry Andric BuildMI(*BalTgtMBB, std::prev(Pos), DL, TII->get(Mips::ADDiu), Mips::SP) 5310b57cec5SDimitry Andric .addReg(Mips::SP) 5320b57cec5SDimitry Andric .addImm(8); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric if (hasDelaySlot) { 5350b57cec5SDimitry Andric if (STI->isTargetNaCl()) { 53681ad6265SDimitry Andric TII->insertNop(*BalTgtMBB, Pos, DL); 5370b57cec5SDimitry Andric } else { 5380b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) 5390b57cec5SDimitry Andric .addReg(Mips::SP) 5400b57cec5SDimitry Andric .addImm(8); 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric BalTgtMBB->rbegin()->bundleWithPred(); 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric } else { 5450b57cec5SDimitry Andric // Pre R6: 5460b57cec5SDimitry Andric // $longbr: 5470b57cec5SDimitry Andric // daddiu $sp, $sp, -16 5480b57cec5SDimitry Andric // sd $ra, 0($sp) 5490b57cec5SDimitry Andric // daddiu $at, $zero, %hi($tgt - $baltgt) 5500b57cec5SDimitry Andric // dsll $at, $at, 16 5510b57cec5SDimitry Andric // bal $baltgt 5520b57cec5SDimitry Andric // daddiu $at, $at, %lo($tgt - $baltgt) 5530b57cec5SDimitry Andric // $baltgt: 5540b57cec5SDimitry Andric // daddu $at, $ra, $at 5550b57cec5SDimitry Andric // ld $ra, 0($sp) 5560b57cec5SDimitry Andric // jr64 $at 5570b57cec5SDimitry Andric // daddiu $sp, $sp, 16 5580b57cec5SDimitry Andric // $fallthrough: 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric // R6: 5610b57cec5SDimitry Andric // $longbr: 5620b57cec5SDimitry Andric // daddiu $sp, $sp, -16 5630b57cec5SDimitry Andric // sd $ra, 0($sp) 5640b57cec5SDimitry Andric // daddiu $at, $zero, %hi($tgt - $baltgt) 5650b57cec5SDimitry Andric // dsll $at, $at, 16 5660b57cec5SDimitry Andric // daddiu $at, $at, %lo($tgt - $baltgt) 5670b57cec5SDimitry Andric // balc $baltgt 5680b57cec5SDimitry Andric // $baltgt: 5690b57cec5SDimitry Andric // daddu $at, $ra, $at 5700b57cec5SDimitry Andric // ld $ra, 0($sp) 5710b57cec5SDimitry Andric // daddiu $sp, $sp, 16 5720b57cec5SDimitry Andric // jic $at, 0 5730b57cec5SDimitry Andric // $fallthrough: 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric // We assume the branch is within-function, and that offset is within 5760b57cec5SDimitry Andric // +/- 2GB. High 32 bits will therefore always be zero. 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric // Note that this will work even if the offset is negative, because 5790b57cec5SDimitry Andric // of the +1 modification that's added in that case. For example, if the 5800b57cec5SDimitry Andric // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is 5810b57cec5SDimitry Andric // 5820b57cec5SDimitry Andric // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000 5830b57cec5SDimitry Andric // 5840b57cec5SDimitry Andric // and the bits [47:32] are zero. For %highest 5850b57cec5SDimitry Andric // 5860b57cec5SDimitry Andric // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000 5870b57cec5SDimitry Andric // 5880b57cec5SDimitry Andric // and the bits [63:48] are zero. 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric Pos = LongBrMBB->begin(); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) 5930b57cec5SDimitry Andric .addReg(Mips::SP_64) 5940b57cec5SDimitry Andric .addImm(-16); 5950b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)) 5960b57cec5SDimitry Andric .addReg(Mips::RA_64) 5970b57cec5SDimitry Andric .addReg(Mips::SP_64) 5980b57cec5SDimitry Andric .addImm(0); 5990b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu), 6000b57cec5SDimitry Andric Mips::AT_64) 6010b57cec5SDimitry Andric .addReg(Mips::ZERO_64) 6020b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_HI) 6030b57cec5SDimitry Andric .addMBB(BalTgtMBB); 6040b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) 6050b57cec5SDimitry Andric .addReg(Mips::AT_64) 6060b57cec5SDimitry Andric .addImm(16); 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric MachineInstrBuilder BalInstr = 6090b57cec5SDimitry Andric BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); 6100b57cec5SDimitry Andric MachineInstrBuilder DADDiuInstr = 6110b57cec5SDimitry Andric BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) 6120b57cec5SDimitry Andric .addReg(Mips::AT_64) 6130b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_LO) 6140b57cec5SDimitry Andric .addMBB(BalTgtMBB); 6150b57cec5SDimitry Andric if (STI->hasMips32r6()) { 6160b57cec5SDimitry Andric LongBrMBB->insert(Pos, DADDiuInstr); 6170b57cec5SDimitry Andric LongBrMBB->insert(Pos, BalInstr); 6180b57cec5SDimitry Andric } else { 6190b57cec5SDimitry Andric LongBrMBB->insert(Pos, BalInstr); 6200b57cec5SDimitry Andric LongBrMBB->insert(Pos, DADDiuInstr); 6210b57cec5SDimitry Andric LongBrMBB->rbegin()->bundleWithPred(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric Pos = BalTgtMBB->begin(); 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) 6270b57cec5SDimitry Andric .addReg(Mips::RA_64) 6280b57cec5SDimitry Andric .addReg(Mips::AT_64); 6290b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) 6300b57cec5SDimitry Andric .addReg(Mips::SP_64) 6310b57cec5SDimitry Andric .addImm(0); 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric bool hasDelaySlot = buildProperJumpMI(BalTgtMBB, Pos, DL); 6340b57cec5SDimitry Andric // If there is no delay slot, Insert stack adjustment before 6350b57cec5SDimitry Andric if (!hasDelaySlot) { 6360b57cec5SDimitry Andric BuildMI(*BalTgtMBB, std::prev(Pos), DL, TII->get(Mips::DADDiu), 6370b57cec5SDimitry Andric Mips::SP_64) 6380b57cec5SDimitry Andric .addReg(Mips::SP_64) 6390b57cec5SDimitry Andric .addImm(16); 6400b57cec5SDimitry Andric } else { 6410b57cec5SDimitry Andric BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) 6420b57cec5SDimitry Andric .addReg(Mips::SP_64) 6430b57cec5SDimitry Andric .addImm(16); 6440b57cec5SDimitry Andric BalTgtMBB->rbegin()->bundleWithPred(); 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric } else { // Not PIC 6480b57cec5SDimitry Andric Pos = LongBrMBB->begin(); 6490b57cec5SDimitry Andric LongBrMBB->addSuccessor(TgtMBB); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric // Compute the position of the potentiall jump instruction (basic blocks 6520b57cec5SDimitry Andric // before + 4 for the instruction) 6530b57cec5SDimitry Andric uint64_t JOffset = computeOffsetFromTheBeginning(MBB->getNumber()) + 6540b57cec5SDimitry Andric MBBInfos[MBB->getNumber()].Size + 4; 6550b57cec5SDimitry Andric uint64_t TgtMBBOffset = computeOffsetFromTheBeginning(TgtMBB->getNumber()); 6560b57cec5SDimitry Andric // If it's a forward jump, then TgtMBBOffset will be shifted by two 6570b57cec5SDimitry Andric // instructions 6580b57cec5SDimitry Andric if (JOffset < TgtMBBOffset) 6590b57cec5SDimitry Andric TgtMBBOffset += 2 * 4; 6600b57cec5SDimitry Andric // Compare 4 upper bits to check if it's the same segment 6610b57cec5SDimitry Andric bool SameSegmentJump = JOffset >> 28 == TgtMBBOffset >> 28; 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric if (STI->hasMips32r6() && TII->isBranchOffsetInRange(Mips::BC, I.Offset)) { 6640b57cec5SDimitry Andric // R6: 6650b57cec5SDimitry Andric // $longbr: 6660b57cec5SDimitry Andric // bc $tgt 6670b57cec5SDimitry Andric // $fallthrough: 6680b57cec5SDimitry Andric // 6690b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, 6700b57cec5SDimitry Andric TII->get(STI->inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC)) 6710b57cec5SDimitry Andric .addMBB(TgtMBB); 6720b57cec5SDimitry Andric } else if (SameSegmentJump) { 6730b57cec5SDimitry Andric // Pre R6: 6740b57cec5SDimitry Andric // $longbr: 6750b57cec5SDimitry Andric // j $tgt 6760b57cec5SDimitry Andric // nop 6770b57cec5SDimitry Andric // $fallthrough: 6780b57cec5SDimitry Andric // 67981ad6265SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::J)).addMBB(TgtMBB); 68081ad6265SDimitry Andric TII->insertNop(*LongBrMBB, Pos, DL)->bundleWithPred(); 6810b57cec5SDimitry Andric } else { 6820b57cec5SDimitry Andric // At this point, offset where we need to branch does not fit into 6830b57cec5SDimitry Andric // immediate field of the branch instruction and is not in the same 6840b57cec5SDimitry Andric // segment as jump instruction. Therefore we will break it into couple 6850b57cec5SDimitry Andric // instructions, where we first load the offset into register, and then we 6860b57cec5SDimitry Andric // do branch register. 6870b57cec5SDimitry Andric if (ABI.IsN64()) { 6880b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi2Op_64), 6890b57cec5SDimitry Andric Mips::AT_64) 6900b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_HIGHEST); 6910b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), 6920b57cec5SDimitry Andric Mips::AT_64) 6930b57cec5SDimitry Andric .addReg(Mips::AT_64) 6940b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_HIGHER); 6950b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) 6960b57cec5SDimitry Andric .addReg(Mips::AT_64) 6970b57cec5SDimitry Andric .addImm(16); 6980b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), 6990b57cec5SDimitry Andric Mips::AT_64) 7000b57cec5SDimitry Andric .addReg(Mips::AT_64) 7010b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_HI); 7020b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) 7030b57cec5SDimitry Andric .addReg(Mips::AT_64) 7040b57cec5SDimitry Andric .addImm(16); 7050b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), 7060b57cec5SDimitry Andric Mips::AT_64) 7070b57cec5SDimitry Andric .addReg(Mips::AT_64) 7080b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_LO); 7090b57cec5SDimitry Andric } else { 7100b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi2Op), 7110b57cec5SDimitry Andric Mips::AT) 7120b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_HI); 7130b57cec5SDimitry Andric BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_ADDiu2Op), 7140b57cec5SDimitry Andric Mips::AT) 7150b57cec5SDimitry Andric .addReg(Mips::AT) 7160b57cec5SDimitry Andric .addMBB(TgtMBB, MipsII::MO_ABS_LO); 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric buildProperJumpMI(LongBrMBB, Pos, DL); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric if (I.Br->isUnconditionalBranch()) { 7230b57cec5SDimitry Andric // Change branch destination. 7240b57cec5SDimitry Andric assert(I.Br->getDesc().getNumOperands() == 1); 72581ad6265SDimitry Andric I.Br->removeOperand(0); 7260b57cec5SDimitry Andric I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); 7270b57cec5SDimitry Andric } else 7280b57cec5SDimitry Andric // Change branch destination and reverse condition. 7290b57cec5SDimitry Andric replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { 7330b57cec5SDimitry Andric MachineBasicBlock &MBB = F.front(); 7340b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.begin(); 7350b57cec5SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MBB.begin()); 7360b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0) 7370b57cec5SDimitry Andric .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); 7380b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0) 7390b57cec5SDimitry Andric .addReg(Mips::V0) 7400b57cec5SDimitry Andric .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); 7410b57cec5SDimitry Andric MBB.removeLiveIn(Mips::V0); 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440eae32dcSDimitry Andric template <typename Pred, typename Safe> 7450eae32dcSDimitry Andric bool MipsBranchExpansion::handleSlot(Pred Predicate, Safe SafeInSlot) { 7460b57cec5SDimitry Andric bool Changed = false; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) { 7490b57cec5SDimitry Andric for (Iter I = FI->begin(); I != FI->end(); ++I) { 7500b57cec5SDimitry Andric 7510eae32dcSDimitry Andric // Delay slot hazard handling. Use lookahead over state. 7520eae32dcSDimitry Andric if (!Predicate(*I)) 7530b57cec5SDimitry Andric continue; 7540b57cec5SDimitry Andric 7550eae32dcSDimitry Andric Iter IInSlot; 7560b57cec5SDimitry Andric bool LastInstInFunction = 7570b57cec5SDimitry Andric std::next(I) == FI->end() && std::next(FI) == MFp->end(); 7580b57cec5SDimitry Andric if (!LastInstInFunction) { 7590b57cec5SDimitry Andric std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI); 7600b57cec5SDimitry Andric LastInstInFunction |= Res.second; 7610eae32dcSDimitry Andric IInSlot = Res.first; 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 7640eae32dcSDimitry Andric if (LastInstInFunction || !SafeInSlot(*IInSlot, *I)) { 7650b57cec5SDimitry Andric MachineBasicBlock::instr_iterator Iit = I->getIterator(); 7660b57cec5SDimitry Andric if (std::next(Iit) == FI->end() || 7670b57cec5SDimitry Andric std::next(Iit)->getOpcode() != Mips::NOP) { 7680b57cec5SDimitry Andric Changed = true; 76981ad6265SDimitry Andric TII->insertNop(*(I->getParent()), std::next(I), I->getDebugLoc()) 77081ad6265SDimitry Andric ->bundleWithPred(); 7710b57cec5SDimitry Andric NumInsertedNops++; 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric return Changed; 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800eae32dcSDimitry Andric bool MipsBranchExpansion::handleForbiddenSlot() { 7810eae32dcSDimitry Andric // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6. 7820eae32dcSDimitry Andric if (!STI->hasMips32r6() || STI->inMicroMipsMode()) 7830eae32dcSDimitry Andric return false; 7840eae32dcSDimitry Andric 7850eae32dcSDimitry Andric return handleSlot( 7860eae32dcSDimitry Andric [this](auto &I) -> bool { return TII->HasForbiddenSlot(I); }, 7870eae32dcSDimitry Andric [this](auto &IInSlot, auto &I) -> bool { 7880eae32dcSDimitry Andric return TII->SafeInForbiddenSlot(IInSlot); 7890eae32dcSDimitry Andric }); 7900eae32dcSDimitry Andric } 7910eae32dcSDimitry Andric 7920eae32dcSDimitry Andric bool MipsBranchExpansion::handleFPUDelaySlot() { 7930eae32dcSDimitry Andric // FPU delay slots are only defined for MIPS3 and below. 7940eae32dcSDimitry Andric if (STI->hasMips32() || STI->hasMips4()) 7950eae32dcSDimitry Andric return false; 7960eae32dcSDimitry Andric 7970eae32dcSDimitry Andric return handleSlot([this](auto &I) -> bool { return TII->HasFPUDelaySlot(I); }, 7980eae32dcSDimitry Andric [this](auto &IInSlot, auto &I) -> bool { 7990eae32dcSDimitry Andric return TII->SafeInFPUDelaySlot(IInSlot, I); 8000eae32dcSDimitry Andric }); 8010eae32dcSDimitry Andric } 8020eae32dcSDimitry Andric 80381ad6265SDimitry Andric bool MipsBranchExpansion::handleLoadDelaySlot() { 80481ad6265SDimitry Andric // Load delay slot hazards are only for MIPS1. 80581ad6265SDimitry Andric if (STI->hasMips2()) 80681ad6265SDimitry Andric return false; 80781ad6265SDimitry Andric 80881ad6265SDimitry Andric return handleSlot( 80981ad6265SDimitry Andric [this](auto &I) -> bool { return TII->HasLoadDelaySlot(I); }, 81081ad6265SDimitry Andric [this](auto &IInSlot, auto &I) -> bool { 81181ad6265SDimitry Andric return TII->SafeInLoadDelaySlot(IInSlot, I); 81281ad6265SDimitry Andric }); 81381ad6265SDimitry Andric } 81481ad6265SDimitry Andric 8150b57cec5SDimitry Andric bool MipsBranchExpansion::handlePossibleLongBranch() { 8160b57cec5SDimitry Andric if (STI->inMips16Mode() || !STI->enableLongBranchPass()) 8170b57cec5SDimitry Andric return false; 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric if (SkipLongBranch) 8200b57cec5SDimitry Andric return false; 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric bool EverMadeChange = false, MadeChange = true; 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric while (MadeChange) { 8250b57cec5SDimitry Andric MadeChange = false; 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric initMBBInfo(); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { 8300b57cec5SDimitry Andric MachineBasicBlock *MBB = MFp->getBlockNumbered(I); 8310b57cec5SDimitry Andric // Search for MBB's branch instruction. 8320b57cec5SDimitry Andric ReverseIter End = MBB->rend(); 8330b57cec5SDimitry Andric ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End); 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric if ((Br != End) && Br->isBranch() && !Br->isIndirectBranch() && 8360b57cec5SDimitry Andric (Br->isConditionalBranch() || 8370b57cec5SDimitry Andric (Br->isUnconditionalBranch() && IsPIC))) { 8380b57cec5SDimitry Andric int64_t Offset = computeOffset(&*Br); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric if (STI->isTargetNaCl()) { 8410b57cec5SDimitry Andric // The offset calculation does not include sandboxing instructions 8420b57cec5SDimitry Andric // that will be added later in the MC layer. Since at this point we 8430b57cec5SDimitry Andric // don't know the exact amount of code that "sandboxing" will add, we 8440b57cec5SDimitry Andric // conservatively estimate that code will not grow more than 100%. 8450b57cec5SDimitry Andric Offset *= 2; 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric if (ForceLongBranchFirstPass || 8490b57cec5SDimitry Andric !TII->isBranchOffsetInRange(Br->getOpcode(), Offset)) { 8500b57cec5SDimitry Andric MBBInfos[I].Offset = Offset; 8510b57cec5SDimitry Andric MBBInfos[I].Br = &*Br; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric } // End for 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric ForceLongBranchFirstPass = false; 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end(); 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric for (I = MBBInfos.begin(); I != E; ++I) { 8610b57cec5SDimitry Andric // Skip if this MBB doesn't have a branch or the branch has already been 8620b57cec5SDimitry Andric // converted to a long branch. 8630b57cec5SDimitry Andric if (!I->Br) 8640b57cec5SDimitry Andric continue; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric expandToLongBranch(*I); 8670b57cec5SDimitry Andric ++LongBranches; 8680b57cec5SDimitry Andric EverMadeChange = MadeChange = true; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric MFp->RenumberBlocks(); 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric return EverMadeChange; 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) { 8780b57cec5SDimitry Andric const TargetMachine &TM = MF.getTarget(); 8790b57cec5SDimitry Andric IsPIC = TM.isPositionIndependent(); 8800b57cec5SDimitry Andric ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); 88181ad6265SDimitry Andric STI = &MF.getSubtarget<MipsSubtarget>(); 8820b57cec5SDimitry Andric TII = static_cast<const MipsInstrInfo *>(STI->getInstrInfo()); 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric if (IsPIC && ABI.IsO32() && 8850b57cec5SDimitry Andric MF.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) 8860b57cec5SDimitry Andric emitGPDisp(MF, TII); 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric MFp = &MF; 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric ForceLongBranchFirstPass = ForceLongBranch; 89181ad6265SDimitry Andric // Run these at least once. 8920b57cec5SDimitry Andric bool longBranchChanged = handlePossibleLongBranch(); 8930b57cec5SDimitry Andric bool forbiddenSlotChanged = handleForbiddenSlot(); 8940eae32dcSDimitry Andric bool fpuDelaySlotChanged = handleFPUDelaySlot(); 89581ad6265SDimitry Andric bool loadDelaySlotChanged = handleLoadDelaySlot(); 8960b57cec5SDimitry Andric 89781ad6265SDimitry Andric bool Changed = longBranchChanged || forbiddenSlotChanged || 89881ad6265SDimitry Andric fpuDelaySlotChanged || loadDelaySlotChanged; 8990b57cec5SDimitry Andric 90081ad6265SDimitry Andric // Then run them alternatively while there are changes. 9010b57cec5SDimitry Andric while (forbiddenSlotChanged) { 9020b57cec5SDimitry Andric longBranchChanged = handlePossibleLongBranch(); 9030eae32dcSDimitry Andric fpuDelaySlotChanged = handleFPUDelaySlot(); 90481ad6265SDimitry Andric loadDelaySlotChanged = handleLoadDelaySlot(); 90581ad6265SDimitry Andric if (!longBranchChanged && !fpuDelaySlotChanged && !loadDelaySlotChanged) 9060b57cec5SDimitry Andric break; 9070b57cec5SDimitry Andric forbiddenSlotChanged = handleForbiddenSlot(); 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric return Changed; 9110b57cec5SDimitry Andric } 912