104eeddc0SDimitry Andric //===- CSKYConstantIslandPass.cpp - Emit PC Relative loads ----------------===// 204eeddc0SDimitry Andric // 304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 604eeddc0SDimitry Andric // 704eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 804eeddc0SDimitry Andric // 904eeddc0SDimitry Andric // 1004eeddc0SDimitry Andric // Loading constants inline is expensive on CSKY and it's in general better 1104eeddc0SDimitry Andric // to place the constant nearby in code space and then it can be loaded with a 1204eeddc0SDimitry Andric // simple 16/32 bit load instruction like lrw. 1304eeddc0SDimitry Andric // 1404eeddc0SDimitry Andric // The constants can be not just numbers but addresses of functions and labels. 1504eeddc0SDimitry Andric // This can be particularly helpful in static relocation mode for embedded 1604eeddc0SDimitry Andric // non-linux targets. 1704eeddc0SDimitry Andric // 1804eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 1904eeddc0SDimitry Andric 2004eeddc0SDimitry Andric #include "CSKY.h" 2104eeddc0SDimitry Andric #include "CSKYConstantPoolValue.h" 2204eeddc0SDimitry Andric #include "CSKYMachineFunctionInfo.h" 2304eeddc0SDimitry Andric #include "CSKYSubtarget.h" 2404eeddc0SDimitry Andric #include "llvm/ADT/STLExtras.h" 2504eeddc0SDimitry Andric #include "llvm/ADT/SmallSet.h" 2604eeddc0SDimitry Andric #include "llvm/ADT/SmallVector.h" 2704eeddc0SDimitry Andric #include "llvm/ADT/Statistic.h" 2804eeddc0SDimitry Andric #include "llvm/ADT/StringRef.h" 2904eeddc0SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 3004eeddc0SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 3104eeddc0SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 3281ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 3304eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 3404eeddc0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 3504eeddc0SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 3604eeddc0SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 3704eeddc0SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 3804eeddc0SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 3904eeddc0SDimitry Andric #include "llvm/Config/llvm-config.h" 4004eeddc0SDimitry Andric #include "llvm/IR/Constants.h" 4104eeddc0SDimitry Andric #include "llvm/IR/DataLayout.h" 4204eeddc0SDimitry Andric #include "llvm/IR/DebugLoc.h" 4304eeddc0SDimitry Andric #include "llvm/IR/Function.h" 4404eeddc0SDimitry Andric #include "llvm/IR/Type.h" 4504eeddc0SDimitry Andric #include "llvm/Support/CommandLine.h" 4604eeddc0SDimitry Andric #include "llvm/Support/Compiler.h" 4704eeddc0SDimitry Andric #include "llvm/Support/Debug.h" 4804eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h" 4904eeddc0SDimitry Andric #include "llvm/Support/Format.h" 5004eeddc0SDimitry Andric #include "llvm/Support/MathExtras.h" 5104eeddc0SDimitry Andric #include "llvm/Support/raw_ostream.h" 5204eeddc0SDimitry Andric #include <algorithm> 5304eeddc0SDimitry Andric #include <cassert> 5404eeddc0SDimitry Andric #include <cstdint> 5504eeddc0SDimitry Andric #include <iterator> 5604eeddc0SDimitry Andric #include <vector> 5704eeddc0SDimitry Andric 5804eeddc0SDimitry Andric using namespace llvm; 5904eeddc0SDimitry Andric 6004eeddc0SDimitry Andric #define DEBUG_TYPE "CSKY-constant-islands" 6104eeddc0SDimitry Andric 6204eeddc0SDimitry Andric STATISTIC(NumCPEs, "Number of constpool entries"); 6304eeddc0SDimitry Andric STATISTIC(NumSplit, "Number of uncond branches inserted"); 6404eeddc0SDimitry Andric STATISTIC(NumCBrFixed, "Number of cond branches fixed"); 6504eeddc0SDimitry Andric STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); 6604eeddc0SDimitry Andric 6704eeddc0SDimitry Andric namespace { 6804eeddc0SDimitry Andric 6904eeddc0SDimitry Andric using Iter = MachineBasicBlock::iterator; 7004eeddc0SDimitry Andric using ReverseIter = MachineBasicBlock::reverse_iterator; 7104eeddc0SDimitry Andric 7204eeddc0SDimitry Andric /// CSKYConstantIslands - Due to limited PC-relative displacements, CSKY 7304eeddc0SDimitry Andric /// requires constant pool entries to be scattered among the instructions 7404eeddc0SDimitry Andric /// inside a function. To do this, it completely ignores the normal LLVM 7504eeddc0SDimitry Andric /// constant pool; instead, it places constants wherever it feels like with 7604eeddc0SDimitry Andric /// special instructions. 7704eeddc0SDimitry Andric /// 7804eeddc0SDimitry Andric /// The terminology used in this pass includes: 7904eeddc0SDimitry Andric /// Islands - Clumps of constants placed in the function. 8004eeddc0SDimitry Andric /// Water - Potential places where an island could be formed. 8104eeddc0SDimitry Andric /// CPE - A constant pool entry that has been placed somewhere, which 8204eeddc0SDimitry Andric /// tracks a list of users. 8304eeddc0SDimitry Andric 8404eeddc0SDimitry Andric class CSKYConstantIslands : public MachineFunctionPass { 8504eeddc0SDimitry Andric /// BasicBlockInfo - Information about the offset and size of a single 8604eeddc0SDimitry Andric /// basic block. 8704eeddc0SDimitry Andric struct BasicBlockInfo { 8804eeddc0SDimitry Andric /// Offset - Distance from the beginning of the function to the beginning 8904eeddc0SDimitry Andric /// of this basic block. 9004eeddc0SDimitry Andric /// 9104eeddc0SDimitry Andric /// Offsets are computed assuming worst case padding before an aligned 9204eeddc0SDimitry Andric /// block. This means that subtracting basic block offsets always gives a 9304eeddc0SDimitry Andric /// conservative estimate of the real distance which may be smaller. 9404eeddc0SDimitry Andric /// 9504eeddc0SDimitry Andric /// Because worst case padding is used, the computed offset of an aligned 9604eeddc0SDimitry Andric /// block may not actually be aligned. 9704eeddc0SDimitry Andric unsigned Offset = 0; 9804eeddc0SDimitry Andric 9904eeddc0SDimitry Andric /// Size - Size of the basic block in bytes. If the block contains 10004eeddc0SDimitry Andric /// inline assembly, this is a worst case estimate. 10104eeddc0SDimitry Andric /// 10204eeddc0SDimitry Andric /// The size does not include any alignment padding whether from the 10304eeddc0SDimitry Andric /// beginning of the block, or from an aligned jump table at the end. 10404eeddc0SDimitry Andric unsigned Size = 0; 10504eeddc0SDimitry Andric 10604eeddc0SDimitry Andric BasicBlockInfo() = default; 10704eeddc0SDimitry Andric 10804eeddc0SDimitry Andric unsigned postOffset() const { return Offset + Size; } 10904eeddc0SDimitry Andric }; 11004eeddc0SDimitry Andric 11104eeddc0SDimitry Andric std::vector<BasicBlockInfo> BBInfo; 11204eeddc0SDimitry Andric 11304eeddc0SDimitry Andric /// WaterList - A sorted list of basic blocks where islands could be placed 11404eeddc0SDimitry Andric /// (i.e. blocks that don't fall through to the following block, due 11504eeddc0SDimitry Andric /// to a return, unreachable, or unconditional branch). 11604eeddc0SDimitry Andric std::vector<MachineBasicBlock *> WaterList; 11704eeddc0SDimitry Andric 11804eeddc0SDimitry Andric /// NewWaterList - The subset of WaterList that was created since the 11904eeddc0SDimitry Andric /// previous iteration by inserting unconditional branches. 12004eeddc0SDimitry Andric SmallSet<MachineBasicBlock *, 4> NewWaterList; 12104eeddc0SDimitry Andric 12204eeddc0SDimitry Andric using water_iterator = std::vector<MachineBasicBlock *>::iterator; 12304eeddc0SDimitry Andric 12404eeddc0SDimitry Andric /// CPUser - One user of a constant pool, keeping the machine instruction 12504eeddc0SDimitry Andric /// pointer, the constant pool being referenced, and the max displacement 12604eeddc0SDimitry Andric /// allowed from the instruction to the CP. The HighWaterMark records the 12704eeddc0SDimitry Andric /// highest basic block where a new CPEntry can be placed. To ensure this 12804eeddc0SDimitry Andric /// pass terminates, the CP entries are initially placed at the end of the 12904eeddc0SDimitry Andric /// function and then move monotonically to lower addresses. The 13004eeddc0SDimitry Andric /// exception to this rule is when the current CP entry for a particular 13104eeddc0SDimitry Andric /// CPUser is out of range, but there is another CP entry for the same 13204eeddc0SDimitry Andric /// constant value in range. We want to use the existing in-range CP 13304eeddc0SDimitry Andric /// entry, but if it later moves out of range, the search for new water 13404eeddc0SDimitry Andric /// should resume where it left off. The HighWaterMark is used to record 13504eeddc0SDimitry Andric /// that point. 13604eeddc0SDimitry Andric struct CPUser { 13704eeddc0SDimitry Andric MachineInstr *MI; 13804eeddc0SDimitry Andric MachineInstr *CPEMI; 13904eeddc0SDimitry Andric MachineBasicBlock *HighWaterMark; 14004eeddc0SDimitry Andric 14104eeddc0SDimitry Andric private: 14204eeddc0SDimitry Andric unsigned MaxDisp; 14304eeddc0SDimitry Andric 14404eeddc0SDimitry Andric public: 14504eeddc0SDimitry Andric bool NegOk; 14604eeddc0SDimitry Andric 14704eeddc0SDimitry Andric CPUser(MachineInstr *Mi, MachineInstr *Cpemi, unsigned Maxdisp, bool Neg) 14804eeddc0SDimitry Andric : MI(Mi), CPEMI(Cpemi), MaxDisp(Maxdisp), NegOk(Neg) { 14904eeddc0SDimitry Andric HighWaterMark = CPEMI->getParent(); 15004eeddc0SDimitry Andric } 15104eeddc0SDimitry Andric 15204eeddc0SDimitry Andric /// getMaxDisp - Returns the maximum displacement supported by MI. 15304eeddc0SDimitry Andric unsigned getMaxDisp() const { return MaxDisp - 16; } 15404eeddc0SDimitry Andric 15504eeddc0SDimitry Andric void setMaxDisp(unsigned Val) { MaxDisp = Val; } 15604eeddc0SDimitry Andric }; 15704eeddc0SDimitry Andric 15804eeddc0SDimitry Andric /// CPUsers - Keep track of all of the machine instructions that use various 15904eeddc0SDimitry Andric /// constant pools and their max displacement. 16004eeddc0SDimitry Andric std::vector<CPUser> CPUsers; 16104eeddc0SDimitry Andric 16204eeddc0SDimitry Andric /// CPEntry - One per constant pool entry, keeping the machine instruction 16304eeddc0SDimitry Andric /// pointer, the constpool index, and the number of CPUser's which 16404eeddc0SDimitry Andric /// reference this entry. 16504eeddc0SDimitry Andric struct CPEntry { 16604eeddc0SDimitry Andric MachineInstr *CPEMI; 16704eeddc0SDimitry Andric unsigned CPI; 16804eeddc0SDimitry Andric unsigned RefCount; 16904eeddc0SDimitry Andric 17004eeddc0SDimitry Andric CPEntry(MachineInstr *Cpemi, unsigned Cpi, unsigned Rc = 0) 17104eeddc0SDimitry Andric : CPEMI(Cpemi), CPI(Cpi), RefCount(Rc) {} 17204eeddc0SDimitry Andric }; 17304eeddc0SDimitry Andric 17404eeddc0SDimitry Andric /// CPEntries - Keep track of all of the constant pool entry machine 17504eeddc0SDimitry Andric /// instructions. For each original constpool index (i.e. those that 17604eeddc0SDimitry Andric /// existed upon entry to this pass), it keeps a vector of entries. 17704eeddc0SDimitry Andric /// Original elements are cloned as we go along; the clones are 17804eeddc0SDimitry Andric /// put in the vector of the original element, but have distinct CPIs. 17904eeddc0SDimitry Andric std::vector<std::vector<CPEntry>> CPEntries; 18004eeddc0SDimitry Andric 18104eeddc0SDimitry Andric /// ImmBranch - One per immediate branch, keeping the machine instruction 18204eeddc0SDimitry Andric /// pointer, conditional or unconditional, the max displacement, 18304eeddc0SDimitry Andric /// and (if isCond is true) the corresponding unconditional branch 18404eeddc0SDimitry Andric /// opcode. 18504eeddc0SDimitry Andric struct ImmBranch { 18604eeddc0SDimitry Andric MachineInstr *MI; 18704eeddc0SDimitry Andric unsigned MaxDisp : 31; 18804eeddc0SDimitry Andric bool IsCond : 1; 18904eeddc0SDimitry Andric int UncondBr; 19004eeddc0SDimitry Andric 19104eeddc0SDimitry Andric ImmBranch(MachineInstr *Mi, unsigned Maxdisp, bool Cond, int Ubr) 19204eeddc0SDimitry Andric : MI(Mi), MaxDisp(Maxdisp), IsCond(Cond), UncondBr(Ubr) {} 19304eeddc0SDimitry Andric }; 19404eeddc0SDimitry Andric 19504eeddc0SDimitry Andric /// ImmBranches - Keep track of all the immediate branch instructions. 19604eeddc0SDimitry Andric /// 19704eeddc0SDimitry Andric std::vector<ImmBranch> ImmBranches; 19804eeddc0SDimitry Andric 19904eeddc0SDimitry Andric const CSKYSubtarget *STI = nullptr; 20004eeddc0SDimitry Andric const CSKYInstrInfo *TII; 20104eeddc0SDimitry Andric CSKYMachineFunctionInfo *MFI; 20204eeddc0SDimitry Andric MachineFunction *MF = nullptr; 20304eeddc0SDimitry Andric MachineConstantPool *MCP = nullptr; 20404eeddc0SDimitry Andric 20504eeddc0SDimitry Andric unsigned PICLabelUId; 20604eeddc0SDimitry Andric 20704eeddc0SDimitry Andric void initPICLabelUId(unsigned UId) { PICLabelUId = UId; } 20804eeddc0SDimitry Andric 20904eeddc0SDimitry Andric unsigned createPICLabelUId() { return PICLabelUId++; } 21004eeddc0SDimitry Andric 21104eeddc0SDimitry Andric public: 21204eeddc0SDimitry Andric static char ID; 21304eeddc0SDimitry Andric 21404eeddc0SDimitry Andric CSKYConstantIslands() : MachineFunctionPass(ID) {} 21504eeddc0SDimitry Andric 21604eeddc0SDimitry Andric StringRef getPassName() const override { return "CSKY Constant Islands"; } 21704eeddc0SDimitry Andric 21804eeddc0SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 21904eeddc0SDimitry Andric 22004eeddc0SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 221*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 22204eeddc0SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 22304eeddc0SDimitry Andric } 22404eeddc0SDimitry Andric 22504eeddc0SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 22604eeddc0SDimitry Andric return MachineFunctionProperties().set( 22704eeddc0SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 22804eeddc0SDimitry Andric } 22904eeddc0SDimitry Andric 23004eeddc0SDimitry Andric void doInitialPlacement(std::vector<MachineInstr *> &CPEMIs); 23104eeddc0SDimitry Andric CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); 23204eeddc0SDimitry Andric Align getCPEAlign(const MachineInstr &CPEMI); 23304eeddc0SDimitry Andric void initializeFunctionInfo(const std::vector<MachineInstr *> &CPEMIs); 23404eeddc0SDimitry Andric unsigned getOffsetOf(MachineInstr *MI) const; 23504eeddc0SDimitry Andric unsigned getUserOffset(CPUser &) const; 23604eeddc0SDimitry Andric void dumpBBs(); 23704eeddc0SDimitry Andric 23804eeddc0SDimitry Andric bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, unsigned Disp, 23904eeddc0SDimitry Andric bool NegativeOK); 24004eeddc0SDimitry Andric bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, 24104eeddc0SDimitry Andric const CPUser &U); 24204eeddc0SDimitry Andric 24304eeddc0SDimitry Andric void computeBlockSize(MachineBasicBlock *MBB); 24404eeddc0SDimitry Andric MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI); 24504eeddc0SDimitry Andric void updateForInsertedWaterBlock(MachineBasicBlock *NewBB); 24604eeddc0SDimitry Andric void adjustBBOffsetsAfter(MachineBasicBlock *BB); 24704eeddc0SDimitry Andric bool decrementCPEReferenceCount(unsigned CPI, MachineInstr *CPEMI); 24804eeddc0SDimitry Andric int findInRangeCPEntry(CPUser &U, unsigned UserOffset); 24904eeddc0SDimitry Andric bool findAvailableWater(CPUser &U, unsigned UserOffset, 25004eeddc0SDimitry Andric water_iterator &WaterIter); 25104eeddc0SDimitry Andric void createNewWater(unsigned CPUserIndex, unsigned UserOffset, 25204eeddc0SDimitry Andric MachineBasicBlock *&NewMBB); 25304eeddc0SDimitry Andric bool handleConstantPoolUser(unsigned CPUserIndex); 25404eeddc0SDimitry Andric void removeDeadCPEMI(MachineInstr *CPEMI); 25504eeddc0SDimitry Andric bool removeUnusedCPEntries(); 25604eeddc0SDimitry Andric bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset, 25704eeddc0SDimitry Andric MachineInstr *CPEMI, unsigned Disp, bool NegOk, 25804eeddc0SDimitry Andric bool DoDump = false); 25904eeddc0SDimitry Andric bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, CPUser &U, 26004eeddc0SDimitry Andric unsigned &Growth); 26104eeddc0SDimitry Andric bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); 26204eeddc0SDimitry Andric bool fixupImmediateBr(ImmBranch &Br); 26304eeddc0SDimitry Andric bool fixupConditionalBr(ImmBranch &Br); 26404eeddc0SDimitry Andric bool fixupUnconditionalBr(ImmBranch &Br); 26504eeddc0SDimitry Andric }; 26604eeddc0SDimitry Andric } // end anonymous namespace 26704eeddc0SDimitry Andric 26804eeddc0SDimitry Andric char CSKYConstantIslands::ID = 0; 26904eeddc0SDimitry Andric 27004eeddc0SDimitry Andric bool CSKYConstantIslands::isOffsetInRange(unsigned UserOffset, 27104eeddc0SDimitry Andric unsigned TrialOffset, 27204eeddc0SDimitry Andric const CPUser &U) { 27304eeddc0SDimitry Andric return isOffsetInRange(UserOffset, TrialOffset, U.getMaxDisp(), U.NegOk); 27404eeddc0SDimitry Andric } 27504eeddc0SDimitry Andric 27604eeddc0SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 27704eeddc0SDimitry Andric /// print block size and offset information - debugging 27804eeddc0SDimitry Andric LLVM_DUMP_METHOD void CSKYConstantIslands::dumpBBs() { 27904eeddc0SDimitry Andric for (unsigned J = 0, E = BBInfo.size(); J != E; ++J) { 28004eeddc0SDimitry Andric const BasicBlockInfo &BBI = BBInfo[J]; 28104eeddc0SDimitry Andric dbgs() << format("%08x %bb.%u\t", BBI.Offset, J) 28204eeddc0SDimitry Andric << format(" size=%#x\n", BBInfo[J].Size); 28304eeddc0SDimitry Andric } 28404eeddc0SDimitry Andric } 28504eeddc0SDimitry Andric #endif 28604eeddc0SDimitry Andric 28704eeddc0SDimitry Andric bool CSKYConstantIslands::runOnMachineFunction(MachineFunction &Mf) { 28804eeddc0SDimitry Andric MF = &Mf; 28904eeddc0SDimitry Andric MCP = Mf.getConstantPool(); 29081ad6265SDimitry Andric STI = &Mf.getSubtarget<CSKYSubtarget>(); 29104eeddc0SDimitry Andric 29204eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "***** CSKYConstantIslands: " 29304eeddc0SDimitry Andric << MCP->getConstants().size() << " CP entries, aligned to " 29404eeddc0SDimitry Andric << MCP->getConstantPoolAlign().value() << " bytes *****\n"); 29504eeddc0SDimitry Andric 29604eeddc0SDimitry Andric TII = STI->getInstrInfo(); 29704eeddc0SDimitry Andric MFI = MF->getInfo<CSKYMachineFunctionInfo>(); 29804eeddc0SDimitry Andric 29904eeddc0SDimitry Andric // This pass invalidates liveness information when it splits basic blocks. 30004eeddc0SDimitry Andric MF->getRegInfo().invalidateLiveness(); 30104eeddc0SDimitry Andric 30204eeddc0SDimitry Andric // Renumber all of the machine basic blocks in the function, guaranteeing that 30304eeddc0SDimitry Andric // the numbers agree with the position of the block in the function. 30404eeddc0SDimitry Andric MF->RenumberBlocks(); 30504eeddc0SDimitry Andric 30604eeddc0SDimitry Andric bool MadeChange = false; 30704eeddc0SDimitry Andric 30804eeddc0SDimitry Andric // Perform the initial placement of the constant pool entries. To start with, 30904eeddc0SDimitry Andric // we put them all at the end of the function. 31004eeddc0SDimitry Andric std::vector<MachineInstr *> CPEMIs; 31104eeddc0SDimitry Andric if (!MCP->isEmpty()) 31204eeddc0SDimitry Andric doInitialPlacement(CPEMIs); 31304eeddc0SDimitry Andric 31404eeddc0SDimitry Andric /// The next UID to take is the first unused one. 31504eeddc0SDimitry Andric initPICLabelUId(CPEMIs.size()); 31604eeddc0SDimitry Andric 31704eeddc0SDimitry Andric // Do the initial scan of the function, building up information about the 31804eeddc0SDimitry Andric // sizes of each block, the location of all the water, and finding all of the 31904eeddc0SDimitry Andric // constant pool users. 32004eeddc0SDimitry Andric initializeFunctionInfo(CPEMIs); 32104eeddc0SDimitry Andric CPEMIs.clear(); 32204eeddc0SDimitry Andric LLVM_DEBUG(dumpBBs()); 32304eeddc0SDimitry Andric 32404eeddc0SDimitry Andric /// Remove dead constant pool entries. 32504eeddc0SDimitry Andric MadeChange |= removeUnusedCPEntries(); 32604eeddc0SDimitry Andric 32704eeddc0SDimitry Andric // Iteratively place constant pool entries and fix up branches until there 32804eeddc0SDimitry Andric // is no change. 32904eeddc0SDimitry Andric unsigned NoCPIters = 0, NoBRIters = 0; 33004eeddc0SDimitry Andric (void)NoBRIters; 33104eeddc0SDimitry Andric while (true) { 33204eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); 33304eeddc0SDimitry Andric bool CPChange = false; 33404eeddc0SDimitry Andric for (unsigned I = 0, E = CPUsers.size(); I != E; ++I) 33504eeddc0SDimitry Andric CPChange |= handleConstantPoolUser(I); 33604eeddc0SDimitry Andric if (CPChange && ++NoCPIters > 30) 33704eeddc0SDimitry Andric report_fatal_error("Constant Island pass failed to converge!"); 33804eeddc0SDimitry Andric LLVM_DEBUG(dumpBBs()); 33904eeddc0SDimitry Andric 34004eeddc0SDimitry Andric // Clear NewWaterList now. If we split a block for branches, it should 34104eeddc0SDimitry Andric // appear as "new water" for the next iteration of constant pool placement. 34204eeddc0SDimitry Andric NewWaterList.clear(); 34304eeddc0SDimitry Andric 34404eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); 34504eeddc0SDimitry Andric bool BRChange = false; 34604eeddc0SDimitry Andric for (unsigned I = 0, E = ImmBranches.size(); I != E; ++I) 34704eeddc0SDimitry Andric BRChange |= fixupImmediateBr(ImmBranches[I]); 34804eeddc0SDimitry Andric if (BRChange && ++NoBRIters > 30) 34904eeddc0SDimitry Andric report_fatal_error("Branch Fix Up pass failed to converge!"); 35004eeddc0SDimitry Andric LLVM_DEBUG(dumpBBs()); 35104eeddc0SDimitry Andric if (!CPChange && !BRChange) 35204eeddc0SDimitry Andric break; 35304eeddc0SDimitry Andric MadeChange = true; 35404eeddc0SDimitry Andric } 35504eeddc0SDimitry Andric 35604eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << '\n'; dumpBBs()); 35704eeddc0SDimitry Andric 35804eeddc0SDimitry Andric BBInfo.clear(); 35904eeddc0SDimitry Andric WaterList.clear(); 36004eeddc0SDimitry Andric CPUsers.clear(); 36104eeddc0SDimitry Andric CPEntries.clear(); 36204eeddc0SDimitry Andric ImmBranches.clear(); 36304eeddc0SDimitry Andric return MadeChange; 36404eeddc0SDimitry Andric } 36504eeddc0SDimitry Andric 36604eeddc0SDimitry Andric /// doInitialPlacement - Perform the initial placement of the constant pool 36704eeddc0SDimitry Andric /// entries. To start with, we put them all at the end of the function. 36804eeddc0SDimitry Andric void CSKYConstantIslands::doInitialPlacement( 36904eeddc0SDimitry Andric std::vector<MachineInstr *> &CPEMIs) { 37004eeddc0SDimitry Andric // Create the basic block to hold the CPE's. 37104eeddc0SDimitry Andric MachineBasicBlock *BB = MF->CreateMachineBasicBlock(); 37204eeddc0SDimitry Andric MF->push_back(BB); 37304eeddc0SDimitry Andric 37404eeddc0SDimitry Andric // MachineConstantPool measures alignment in bytes. We measure in log2(bytes). 37504eeddc0SDimitry Andric const Align MaxAlign = MCP->getConstantPoolAlign(); 37604eeddc0SDimitry Andric 37704eeddc0SDimitry Andric // Mark the basic block as required by the const-pool. 37804eeddc0SDimitry Andric BB->setAlignment(Align(2)); 37904eeddc0SDimitry Andric 38004eeddc0SDimitry Andric // The function needs to be as aligned as the basic blocks. The linker may 38104eeddc0SDimitry Andric // move functions around based on their alignment. 38204eeddc0SDimitry Andric MF->ensureAlignment(BB->getAlignment()); 38304eeddc0SDimitry Andric 38404eeddc0SDimitry Andric // Order the entries in BB by descending alignment. That ensures correct 38504eeddc0SDimitry Andric // alignment of all entries as long as BB is sufficiently aligned. Keep 38604eeddc0SDimitry Andric // track of the insertion point for each alignment. We are going to bucket 38704eeddc0SDimitry Andric // sort the entries as they are created. 38804eeddc0SDimitry Andric SmallVector<MachineBasicBlock::iterator, 8> InsPoint(Log2(MaxAlign) + 1, 38904eeddc0SDimitry Andric BB->end()); 39004eeddc0SDimitry Andric 39104eeddc0SDimitry Andric // Add all of the constants from the constant pool to the end block, use an 39204eeddc0SDimitry Andric // identity mapping of CPI's to CPE's. 39304eeddc0SDimitry Andric const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); 39404eeddc0SDimitry Andric 39504eeddc0SDimitry Andric const DataLayout &TD = MF->getDataLayout(); 39604eeddc0SDimitry Andric for (unsigned I = 0, E = CPs.size(); I != E; ++I) { 39704eeddc0SDimitry Andric unsigned Size = CPs[I].getSizeInBytes(TD); 39804eeddc0SDimitry Andric assert(Size >= 4 && "Too small constant pool entry"); 39904eeddc0SDimitry Andric Align Alignment = CPs[I].getAlign(); 40004eeddc0SDimitry Andric // Verify that all constant pool entries are a multiple of their alignment. 40104eeddc0SDimitry Andric // If not, we would have to pad them out so that instructions stay aligned. 40204eeddc0SDimitry Andric assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!"); 40304eeddc0SDimitry Andric 40404eeddc0SDimitry Andric // Insert CONSTPOOL_ENTRY before entries with a smaller alignment. 40504eeddc0SDimitry Andric unsigned LogAlign = Log2(Alignment); 40604eeddc0SDimitry Andric MachineBasicBlock::iterator InsAt = InsPoint[LogAlign]; 40704eeddc0SDimitry Andric 40804eeddc0SDimitry Andric MachineInstr *CPEMI = 40904eeddc0SDimitry Andric BuildMI(*BB, InsAt, DebugLoc(), TII->get(CSKY::CONSTPOOL_ENTRY)) 41004eeddc0SDimitry Andric .addImm(I) 41104eeddc0SDimitry Andric .addConstantPoolIndex(I) 41204eeddc0SDimitry Andric .addImm(Size); 41304eeddc0SDimitry Andric 41404eeddc0SDimitry Andric CPEMIs.push_back(CPEMI); 41504eeddc0SDimitry Andric 41604eeddc0SDimitry Andric // Ensure that future entries with higher alignment get inserted before 41704eeddc0SDimitry Andric // CPEMI. This is bucket sort with iterators. 41804eeddc0SDimitry Andric for (unsigned A = LogAlign + 1; A <= Log2(MaxAlign); ++A) 41904eeddc0SDimitry Andric if (InsPoint[A] == InsAt) 42004eeddc0SDimitry Andric InsPoint[A] = CPEMI; 42104eeddc0SDimitry Andric // Add a new CPEntry, but no corresponding CPUser yet. 42204eeddc0SDimitry Andric CPEntries.emplace_back(1, CPEntry(CPEMI, I)); 42304eeddc0SDimitry Andric ++NumCPEs; 42404eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Moved CPI#" << I << " to end of function, size = " 42504eeddc0SDimitry Andric << Size << ", align = " << Alignment.value() << '\n'); 42604eeddc0SDimitry Andric } 42704eeddc0SDimitry Andric LLVM_DEBUG(BB->dump()); 42804eeddc0SDimitry Andric } 42904eeddc0SDimitry Andric 43004eeddc0SDimitry Andric /// BBHasFallthrough - Return true if the specified basic block can fallthrough 43104eeddc0SDimitry Andric /// into the block immediately after it. 43204eeddc0SDimitry Andric static bool bbHasFallthrough(MachineBasicBlock *MBB) { 43304eeddc0SDimitry Andric // Get the next machine basic block in the function. 43404eeddc0SDimitry Andric MachineFunction::iterator MBBI = MBB->getIterator(); 43504eeddc0SDimitry Andric // Can't fall off end of function. 43604eeddc0SDimitry Andric if (std::next(MBBI) == MBB->getParent()->end()) 43704eeddc0SDimitry Andric return false; 43804eeddc0SDimitry Andric 43904eeddc0SDimitry Andric MachineBasicBlock *NextBB = &*std::next(MBBI); 44004eeddc0SDimitry Andric for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), 44104eeddc0SDimitry Andric E = MBB->succ_end(); 44204eeddc0SDimitry Andric I != E; ++I) 44304eeddc0SDimitry Andric if (*I == NextBB) 44404eeddc0SDimitry Andric return true; 44504eeddc0SDimitry Andric 44604eeddc0SDimitry Andric return false; 44704eeddc0SDimitry Andric } 44804eeddc0SDimitry Andric 44904eeddc0SDimitry Andric /// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, 45004eeddc0SDimitry Andric /// look up the corresponding CPEntry. 45104eeddc0SDimitry Andric CSKYConstantIslands::CPEntry * 45204eeddc0SDimitry Andric CSKYConstantIslands::findConstPoolEntry(unsigned CPI, 45304eeddc0SDimitry Andric const MachineInstr *CPEMI) { 45404eeddc0SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[CPI]; 45504eeddc0SDimitry Andric // Number of entries per constpool index should be small, just do a 45604eeddc0SDimitry Andric // linear search. 45704eeddc0SDimitry Andric for (unsigned I = 0, E = CPEs.size(); I != E; ++I) { 45804eeddc0SDimitry Andric if (CPEs[I].CPEMI == CPEMI) 45904eeddc0SDimitry Andric return &CPEs[I]; 46004eeddc0SDimitry Andric } 46104eeddc0SDimitry Andric return nullptr; 46204eeddc0SDimitry Andric } 46304eeddc0SDimitry Andric 46404eeddc0SDimitry Andric /// getCPEAlign - Returns the required alignment of the constant pool entry 46504eeddc0SDimitry Andric /// represented by CPEMI. Alignment is measured in log2(bytes) units. 46604eeddc0SDimitry Andric Align CSKYConstantIslands::getCPEAlign(const MachineInstr &CPEMI) { 46704eeddc0SDimitry Andric assert(CPEMI.getOpcode() == CSKY::CONSTPOOL_ENTRY); 46804eeddc0SDimitry Andric 46904eeddc0SDimitry Andric unsigned CPI = CPEMI.getOperand(1).getIndex(); 47004eeddc0SDimitry Andric assert(CPI < MCP->getConstants().size() && "Invalid constant pool index."); 47104eeddc0SDimitry Andric return MCP->getConstants()[CPI].getAlign(); 47204eeddc0SDimitry Andric } 47304eeddc0SDimitry Andric 47404eeddc0SDimitry Andric /// initializeFunctionInfo - Do the initial scan of the function, building up 47504eeddc0SDimitry Andric /// information about the sizes of each block, the location of all the water, 47604eeddc0SDimitry Andric /// and finding all of the constant pool users. 47704eeddc0SDimitry Andric void CSKYConstantIslands::initializeFunctionInfo( 47804eeddc0SDimitry Andric const std::vector<MachineInstr *> &CPEMIs) { 47904eeddc0SDimitry Andric BBInfo.clear(); 48004eeddc0SDimitry Andric BBInfo.resize(MF->getNumBlockIDs()); 48104eeddc0SDimitry Andric 48204eeddc0SDimitry Andric // First thing, compute the size of all basic blocks, and see if the function 48304eeddc0SDimitry Andric // has any inline assembly in it. If so, we have to be conservative about 48404eeddc0SDimitry Andric // alignment assumptions, as we don't know for sure the size of any 48504eeddc0SDimitry Andric // instructions in the inline assembly. 48604eeddc0SDimitry Andric for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) 48704eeddc0SDimitry Andric computeBlockSize(&*I); 48804eeddc0SDimitry Andric 48904eeddc0SDimitry Andric // Compute block offsets. 49004eeddc0SDimitry Andric adjustBBOffsetsAfter(&MF->front()); 49104eeddc0SDimitry Andric 49204eeddc0SDimitry Andric // Now go back through the instructions and build up our data structures. 49304eeddc0SDimitry Andric for (MachineBasicBlock &MBB : *MF) { 49404eeddc0SDimitry Andric // If this block doesn't fall through into the next MBB, then this is 49504eeddc0SDimitry Andric // 'water' that a constant pool island could be placed. 49604eeddc0SDimitry Andric if (!bbHasFallthrough(&MBB)) 49704eeddc0SDimitry Andric WaterList.push_back(&MBB); 49804eeddc0SDimitry Andric for (MachineInstr &MI : MBB) { 49904eeddc0SDimitry Andric if (MI.isDebugInstr()) 50004eeddc0SDimitry Andric continue; 50104eeddc0SDimitry Andric 50204eeddc0SDimitry Andric int Opc = MI.getOpcode(); 50304eeddc0SDimitry Andric if (MI.isBranch() && !MI.isIndirectBranch()) { 50404eeddc0SDimitry Andric bool IsCond = MI.isConditionalBranch(); 50504eeddc0SDimitry Andric unsigned Bits = 0; 50604eeddc0SDimitry Andric unsigned Scale = 1; 50704eeddc0SDimitry Andric int UOpc = CSKY::BR32; 50804eeddc0SDimitry Andric 50904eeddc0SDimitry Andric switch (MI.getOpcode()) { 51004eeddc0SDimitry Andric case CSKY::BR16: 51104eeddc0SDimitry Andric case CSKY::BF16: 51204eeddc0SDimitry Andric case CSKY::BT16: 51304eeddc0SDimitry Andric Bits = 10; 51404eeddc0SDimitry Andric Scale = 2; 51504eeddc0SDimitry Andric break; 51604eeddc0SDimitry Andric default: 51704eeddc0SDimitry Andric Bits = 16; 51804eeddc0SDimitry Andric Scale = 2; 51904eeddc0SDimitry Andric break; 52004eeddc0SDimitry Andric } 52104eeddc0SDimitry Andric 52204eeddc0SDimitry Andric // Record this immediate branch. 52304eeddc0SDimitry Andric unsigned MaxOffs = ((1 << (Bits - 1)) - 1) * Scale; 52404eeddc0SDimitry Andric ImmBranches.push_back(ImmBranch(&MI, MaxOffs, IsCond, UOpc)); 52504eeddc0SDimitry Andric } 52604eeddc0SDimitry Andric 52704eeddc0SDimitry Andric if (Opc == CSKY::CONSTPOOL_ENTRY) 52804eeddc0SDimitry Andric continue; 52904eeddc0SDimitry Andric 53004eeddc0SDimitry Andric // Scan the instructions for constant pool operands. 53104eeddc0SDimitry Andric for (unsigned Op = 0, E = MI.getNumOperands(); Op != E; ++Op) 53204eeddc0SDimitry Andric if (MI.getOperand(Op).isCPI()) { 53304eeddc0SDimitry Andric // We found one. The addressing mode tells us the max displacement 53404eeddc0SDimitry Andric // from the PC that this instruction permits. 53504eeddc0SDimitry Andric 53604eeddc0SDimitry Andric // Basic size info comes from the TSFlags field. 53704eeddc0SDimitry Andric unsigned Bits = 0; 53804eeddc0SDimitry Andric unsigned Scale = 1; 53904eeddc0SDimitry Andric bool NegOk = false; 54004eeddc0SDimitry Andric 54104eeddc0SDimitry Andric switch (Opc) { 54204eeddc0SDimitry Andric default: 54304eeddc0SDimitry Andric llvm_unreachable("Unknown addressing mode for CP reference!"); 54404eeddc0SDimitry Andric case CSKY::MOVIH32: 54504eeddc0SDimitry Andric case CSKY::ORI32: 54604eeddc0SDimitry Andric continue; 54704eeddc0SDimitry Andric case CSKY::PseudoTLSLA32: 54804eeddc0SDimitry Andric case CSKY::JSRI32: 54904eeddc0SDimitry Andric case CSKY::JMPI32: 55004eeddc0SDimitry Andric case CSKY::LRW32: 55104eeddc0SDimitry Andric case CSKY::LRW32_Gen: 55204eeddc0SDimitry Andric Bits = 16; 55304eeddc0SDimitry Andric Scale = 4; 55404eeddc0SDimitry Andric break; 55504eeddc0SDimitry Andric case CSKY::f2FLRW_S: 55604eeddc0SDimitry Andric case CSKY::f2FLRW_D: 55704eeddc0SDimitry Andric Bits = 8; 55804eeddc0SDimitry Andric Scale = 4; 55904eeddc0SDimitry Andric break; 56004eeddc0SDimitry Andric case CSKY::GRS32: 56104eeddc0SDimitry Andric Bits = 17; 56204eeddc0SDimitry Andric Scale = 2; 56304eeddc0SDimitry Andric NegOk = true; 56404eeddc0SDimitry Andric break; 56504eeddc0SDimitry Andric } 56604eeddc0SDimitry Andric // Remember that this is a user of a CP entry. 56704eeddc0SDimitry Andric unsigned CPI = MI.getOperand(Op).getIndex(); 56804eeddc0SDimitry Andric MachineInstr *CPEMI = CPEMIs[CPI]; 56904eeddc0SDimitry Andric unsigned MaxOffs = ((1 << Bits) - 1) * Scale; 57004eeddc0SDimitry Andric CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk)); 57104eeddc0SDimitry Andric 57204eeddc0SDimitry Andric // Increment corresponding CPEntry reference count. 57304eeddc0SDimitry Andric CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); 57404eeddc0SDimitry Andric assert(CPE && "Cannot find a corresponding CPEntry!"); 57504eeddc0SDimitry Andric CPE->RefCount++; 57604eeddc0SDimitry Andric } 57704eeddc0SDimitry Andric } 57804eeddc0SDimitry Andric } 57904eeddc0SDimitry Andric } 58004eeddc0SDimitry Andric 58104eeddc0SDimitry Andric /// computeBlockSize - Compute the size and some alignment information for MBB. 58204eeddc0SDimitry Andric /// This function updates BBInfo directly. 58304eeddc0SDimitry Andric void CSKYConstantIslands::computeBlockSize(MachineBasicBlock *MBB) { 58404eeddc0SDimitry Andric BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; 58504eeddc0SDimitry Andric BBI.Size = 0; 58604eeddc0SDimitry Andric 58704eeddc0SDimitry Andric for (const MachineInstr &MI : *MBB) 58804eeddc0SDimitry Andric BBI.Size += TII->getInstSizeInBytes(MI); 58904eeddc0SDimitry Andric } 59004eeddc0SDimitry Andric 59104eeddc0SDimitry Andric /// getOffsetOf - Return the current offset of the specified machine instruction 59204eeddc0SDimitry Andric /// from the start of the function. This offset changes as stuff is moved 59304eeddc0SDimitry Andric /// around inside the function. 59404eeddc0SDimitry Andric unsigned CSKYConstantIslands::getOffsetOf(MachineInstr *MI) const { 59504eeddc0SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 59604eeddc0SDimitry Andric 59704eeddc0SDimitry Andric // The offset is composed of two things: the sum of the sizes of all MBB's 59804eeddc0SDimitry Andric // before this instruction's block, and the offset from the start of the block 59904eeddc0SDimitry Andric // it is in. 60004eeddc0SDimitry Andric unsigned Offset = BBInfo[MBB->getNumber()].Offset; 60104eeddc0SDimitry Andric 60204eeddc0SDimitry Andric // Sum instructions before MI in MBB. 60304eeddc0SDimitry Andric for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { 60404eeddc0SDimitry Andric assert(I != MBB->end() && "Didn't find MI in its own basic block?"); 60504eeddc0SDimitry Andric Offset += TII->getInstSizeInBytes(*I); 60604eeddc0SDimitry Andric } 60704eeddc0SDimitry Andric return Offset; 60804eeddc0SDimitry Andric } 60904eeddc0SDimitry Andric 61004eeddc0SDimitry Andric /// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB 61104eeddc0SDimitry Andric /// ID. 61204eeddc0SDimitry Andric static bool compareMbbNumbers(const MachineBasicBlock *LHS, 61304eeddc0SDimitry Andric const MachineBasicBlock *RHS) { 61404eeddc0SDimitry Andric return LHS->getNumber() < RHS->getNumber(); 61504eeddc0SDimitry Andric } 61604eeddc0SDimitry Andric 61704eeddc0SDimitry Andric /// updateForInsertedWaterBlock - When a block is newly inserted into the 61804eeddc0SDimitry Andric /// machine function, it upsets all of the block numbers. Renumber the blocks 61904eeddc0SDimitry Andric /// and update the arrays that parallel this numbering. 62004eeddc0SDimitry Andric void CSKYConstantIslands::updateForInsertedWaterBlock( 62104eeddc0SDimitry Andric MachineBasicBlock *NewBB) { 62204eeddc0SDimitry Andric // Renumber the MBB's to keep them consecutive. 62304eeddc0SDimitry Andric NewBB->getParent()->RenumberBlocks(NewBB); 62404eeddc0SDimitry Andric 62504eeddc0SDimitry Andric // Insert an entry into BBInfo to align it properly with the (newly 62604eeddc0SDimitry Andric // renumbered) block numbers. 62704eeddc0SDimitry Andric BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); 62804eeddc0SDimitry Andric 62904eeddc0SDimitry Andric // Next, update WaterList. Specifically, we need to add NewMBB as having 63004eeddc0SDimitry Andric // available water after it. 63104eeddc0SDimitry Andric water_iterator IP = llvm::lower_bound(WaterList, NewBB, compareMbbNumbers); 63204eeddc0SDimitry Andric WaterList.insert(IP, NewBB); 63304eeddc0SDimitry Andric } 63404eeddc0SDimitry Andric 63504eeddc0SDimitry Andric unsigned CSKYConstantIslands::getUserOffset(CPUser &U) const { 63604eeddc0SDimitry Andric unsigned UserOffset = getOffsetOf(U.MI); 63704eeddc0SDimitry Andric 63804eeddc0SDimitry Andric UserOffset &= ~3u; 63904eeddc0SDimitry Andric 64004eeddc0SDimitry Andric return UserOffset; 64104eeddc0SDimitry Andric } 64204eeddc0SDimitry Andric 64304eeddc0SDimitry Andric /// Split the basic block containing MI into two blocks, which are joined by 64404eeddc0SDimitry Andric /// an unconditional branch. Update data structures and renumber blocks to 64504eeddc0SDimitry Andric /// account for this change and returns the newly created block. 64604eeddc0SDimitry Andric MachineBasicBlock * 64704eeddc0SDimitry Andric CSKYConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { 64804eeddc0SDimitry Andric MachineBasicBlock *OrigBB = MI.getParent(); 64904eeddc0SDimitry Andric 65004eeddc0SDimitry Andric // Create a new MBB for the code after the OrigBB. 65104eeddc0SDimitry Andric MachineBasicBlock *NewBB = 65204eeddc0SDimitry Andric MF->CreateMachineBasicBlock(OrigBB->getBasicBlock()); 65304eeddc0SDimitry Andric MachineFunction::iterator MBBI = ++OrigBB->getIterator(); 65404eeddc0SDimitry Andric MF->insert(MBBI, NewBB); 65504eeddc0SDimitry Andric 65604eeddc0SDimitry Andric // Splice the instructions starting with MI over to NewBB. 65704eeddc0SDimitry Andric NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); 65804eeddc0SDimitry Andric 65904eeddc0SDimitry Andric // Add an unconditional branch from OrigBB to NewBB. 66004eeddc0SDimitry Andric // Note the new unconditional branch is not being recorded. 66104eeddc0SDimitry Andric // There doesn't seem to be meaningful DebugInfo available; this doesn't 66204eeddc0SDimitry Andric // correspond to anything in the source. 66304eeddc0SDimitry Andric 66404eeddc0SDimitry Andric // TODO: Add support for 16bit instr. 66504eeddc0SDimitry Andric BuildMI(OrigBB, DebugLoc(), TII->get(CSKY::BR32)).addMBB(NewBB); 66604eeddc0SDimitry Andric ++NumSplit; 66704eeddc0SDimitry Andric 66804eeddc0SDimitry Andric // Update the CFG. All succs of OrigBB are now succs of NewBB. 66904eeddc0SDimitry Andric NewBB->transferSuccessors(OrigBB); 67004eeddc0SDimitry Andric 67104eeddc0SDimitry Andric // OrigBB branches to NewBB. 67204eeddc0SDimitry Andric OrigBB->addSuccessor(NewBB); 67304eeddc0SDimitry Andric 67404eeddc0SDimitry Andric // Update internal data structures to account for the newly inserted MBB. 67504eeddc0SDimitry Andric // This is almost the same as updateForInsertedWaterBlock, except that 67604eeddc0SDimitry Andric // the Water goes after OrigBB, not NewBB. 67704eeddc0SDimitry Andric MF->RenumberBlocks(NewBB); 67804eeddc0SDimitry Andric 67904eeddc0SDimitry Andric // Insert an entry into BBInfo to align it properly with the (newly 68004eeddc0SDimitry Andric // renumbered) block numbers. 68104eeddc0SDimitry Andric BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); 68204eeddc0SDimitry Andric 68304eeddc0SDimitry Andric // Next, update WaterList. Specifically, we need to add OrigMBB as having 68404eeddc0SDimitry Andric // available water after it (but not if it's already there, which happens 68504eeddc0SDimitry Andric // when splitting before a conditional branch that is followed by an 68604eeddc0SDimitry Andric // unconditional branch - in that case we want to insert NewBB). 68704eeddc0SDimitry Andric water_iterator IP = llvm::lower_bound(WaterList, OrigBB, compareMbbNumbers); 68804eeddc0SDimitry Andric MachineBasicBlock *WaterBB = *IP; 68904eeddc0SDimitry Andric if (WaterBB == OrigBB) 69004eeddc0SDimitry Andric WaterList.insert(std::next(IP), NewBB); 69104eeddc0SDimitry Andric else 69204eeddc0SDimitry Andric WaterList.insert(IP, OrigBB); 69304eeddc0SDimitry Andric NewWaterList.insert(OrigBB); 69404eeddc0SDimitry Andric 69504eeddc0SDimitry Andric // Figure out how large the OrigBB is. As the first half of the original 69604eeddc0SDimitry Andric // block, it cannot contain a tablejump. The size includes 69704eeddc0SDimitry Andric // the new jump we added. (It should be possible to do this without 69804eeddc0SDimitry Andric // recounting everything, but it's very confusing, and this is rarely 69904eeddc0SDimitry Andric // executed.) 70004eeddc0SDimitry Andric computeBlockSize(OrigBB); 70104eeddc0SDimitry Andric 70204eeddc0SDimitry Andric // Figure out how large the NewMBB is. As the second half of the original 70304eeddc0SDimitry Andric // block, it may contain a tablejump. 70404eeddc0SDimitry Andric computeBlockSize(NewBB); 70504eeddc0SDimitry Andric 70604eeddc0SDimitry Andric // All BBOffsets following these blocks must be modified. 70704eeddc0SDimitry Andric adjustBBOffsetsAfter(OrigBB); 70804eeddc0SDimitry Andric 70904eeddc0SDimitry Andric return NewBB; 71004eeddc0SDimitry Andric } 71104eeddc0SDimitry Andric 71204eeddc0SDimitry Andric /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool 71304eeddc0SDimitry Andric /// reference) is within MaxDisp of TrialOffset (a proposed location of a 71404eeddc0SDimitry Andric /// constant pool entry). 71504eeddc0SDimitry Andric bool CSKYConstantIslands::isOffsetInRange(unsigned UserOffset, 71604eeddc0SDimitry Andric unsigned TrialOffset, 71704eeddc0SDimitry Andric unsigned MaxDisp, bool NegativeOK) { 71804eeddc0SDimitry Andric if (UserOffset <= TrialOffset) { 71904eeddc0SDimitry Andric // User before the Trial. 72004eeddc0SDimitry Andric if (TrialOffset - UserOffset <= MaxDisp) 72104eeddc0SDimitry Andric return true; 72204eeddc0SDimitry Andric } else if (NegativeOK) { 72304eeddc0SDimitry Andric if (UserOffset - TrialOffset <= MaxDisp) 72404eeddc0SDimitry Andric return true; 72504eeddc0SDimitry Andric } 72604eeddc0SDimitry Andric return false; 72704eeddc0SDimitry Andric } 72804eeddc0SDimitry Andric 72904eeddc0SDimitry Andric /// isWaterInRange - Returns true if a CPE placed after the specified 73004eeddc0SDimitry Andric /// Water (a basic block) will be in range for the specific MI. 73104eeddc0SDimitry Andric /// 73204eeddc0SDimitry Andric /// Compute how much the function will grow by inserting a CPE after Water. 73304eeddc0SDimitry Andric bool CSKYConstantIslands::isWaterInRange(unsigned UserOffset, 73404eeddc0SDimitry Andric MachineBasicBlock *Water, CPUser &U, 73504eeddc0SDimitry Andric unsigned &Growth) { 73604eeddc0SDimitry Andric unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(); 73704eeddc0SDimitry Andric unsigned NextBlockOffset; 73804eeddc0SDimitry Andric Align NextBlockAlignment; 73904eeddc0SDimitry Andric MachineFunction::const_iterator NextBlock = ++Water->getIterator(); 74004eeddc0SDimitry Andric if (NextBlock == MF->end()) { 74104eeddc0SDimitry Andric NextBlockOffset = BBInfo[Water->getNumber()].postOffset(); 74204eeddc0SDimitry Andric NextBlockAlignment = Align(4); 74304eeddc0SDimitry Andric } else { 74404eeddc0SDimitry Andric NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset; 74504eeddc0SDimitry Andric NextBlockAlignment = NextBlock->getAlignment(); 74604eeddc0SDimitry Andric } 74704eeddc0SDimitry Andric unsigned Size = U.CPEMI->getOperand(2).getImm(); 74804eeddc0SDimitry Andric unsigned CPEEnd = CPEOffset + Size; 74904eeddc0SDimitry Andric 75004eeddc0SDimitry Andric // The CPE may be able to hide in the alignment padding before the next 75104eeddc0SDimitry Andric // block. It may also cause more padding to be required if it is more aligned 75204eeddc0SDimitry Andric // that the next block. 75304eeddc0SDimitry Andric if (CPEEnd > NextBlockOffset) { 75404eeddc0SDimitry Andric Growth = CPEEnd - NextBlockOffset; 75504eeddc0SDimitry Andric // Compute the padding that would go at the end of the CPE to align the next 75604eeddc0SDimitry Andric // block. 75704eeddc0SDimitry Andric Growth += offsetToAlignment(CPEEnd, NextBlockAlignment); 75804eeddc0SDimitry Andric 75904eeddc0SDimitry Andric // If the CPE is to be inserted before the instruction, that will raise 76004eeddc0SDimitry Andric // the offset of the instruction. Also account for unknown alignment padding 76104eeddc0SDimitry Andric // in blocks between CPE and the user. 76204eeddc0SDimitry Andric if (CPEOffset < UserOffset) 76304eeddc0SDimitry Andric UserOffset += Growth; 76404eeddc0SDimitry Andric } else 76504eeddc0SDimitry Andric // CPE fits in existing padding. 76604eeddc0SDimitry Andric Growth = 0; 76704eeddc0SDimitry Andric 76804eeddc0SDimitry Andric return isOffsetInRange(UserOffset, CPEOffset, U); 76904eeddc0SDimitry Andric } 77004eeddc0SDimitry Andric 77104eeddc0SDimitry Andric /// isCPEntryInRange - Returns true if the distance between specific MI and 77204eeddc0SDimitry Andric /// specific ConstPool entry instruction can fit in MI's displacement field. 77304eeddc0SDimitry Andric bool CSKYConstantIslands::isCPEntryInRange(MachineInstr *MI, 77404eeddc0SDimitry Andric unsigned UserOffset, 77504eeddc0SDimitry Andric MachineInstr *CPEMI, 77604eeddc0SDimitry Andric unsigned MaxDisp, bool NegOk, 77704eeddc0SDimitry Andric bool DoDump) { 77804eeddc0SDimitry Andric unsigned CPEOffset = getOffsetOf(CPEMI); 77904eeddc0SDimitry Andric 78004eeddc0SDimitry Andric if (DoDump) { 78104eeddc0SDimitry Andric LLVM_DEBUG({ 78204eeddc0SDimitry Andric unsigned Block = MI->getParent()->getNumber(); 78304eeddc0SDimitry Andric const BasicBlockInfo &BBI = BBInfo[Block]; 78404eeddc0SDimitry Andric dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm() 78504eeddc0SDimitry Andric << " max delta=" << MaxDisp 78604eeddc0SDimitry Andric << format(" insn address=%#x", UserOffset) << " in " 78704eeddc0SDimitry Andric << printMBBReference(*MI->getParent()) << ": " 78804eeddc0SDimitry Andric << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI 78904eeddc0SDimitry Andric << format("CPE address=%#x offset=%+d: ", CPEOffset, 79004eeddc0SDimitry Andric int(CPEOffset - UserOffset)); 79104eeddc0SDimitry Andric }); 79204eeddc0SDimitry Andric } 79304eeddc0SDimitry Andric 79404eeddc0SDimitry Andric return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk); 79504eeddc0SDimitry Andric } 79604eeddc0SDimitry Andric 79704eeddc0SDimitry Andric #ifndef NDEBUG 79804eeddc0SDimitry Andric /// BBIsJumpedOver - Return true of the specified basic block's only predecessor 79904eeddc0SDimitry Andric /// unconditionally branches to its only successor. 80004eeddc0SDimitry Andric static bool bbIsJumpedOver(MachineBasicBlock *MBB) { 80104eeddc0SDimitry Andric if (MBB->pred_size() != 1 || MBB->succ_size() != 1) 80204eeddc0SDimitry Andric return false; 80304eeddc0SDimitry Andric MachineBasicBlock *Succ = *MBB->succ_begin(); 80404eeddc0SDimitry Andric MachineBasicBlock *Pred = *MBB->pred_begin(); 80504eeddc0SDimitry Andric MachineInstr *PredMI = &Pred->back(); 80604eeddc0SDimitry Andric if (PredMI->getOpcode() == CSKY::BR32 /*TODO: change to 16bit instr. */) 80704eeddc0SDimitry Andric return PredMI->getOperand(0).getMBB() == Succ; 80804eeddc0SDimitry Andric return false; 80904eeddc0SDimitry Andric } 81004eeddc0SDimitry Andric #endif 81104eeddc0SDimitry Andric 81204eeddc0SDimitry Andric void CSKYConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) { 81304eeddc0SDimitry Andric unsigned BBNum = BB->getNumber(); 81404eeddc0SDimitry Andric for (unsigned I = BBNum + 1, E = MF->getNumBlockIDs(); I < E; ++I) { 81504eeddc0SDimitry Andric // Get the offset and known bits at the end of the layout predecessor. 81604eeddc0SDimitry Andric // Include the alignment of the current block. 81704eeddc0SDimitry Andric unsigned Offset = BBInfo[I - 1].Offset + BBInfo[I - 1].Size; 81804eeddc0SDimitry Andric BBInfo[I].Offset = Offset; 81904eeddc0SDimitry Andric } 82004eeddc0SDimitry Andric } 82104eeddc0SDimitry Andric 82204eeddc0SDimitry Andric /// decrementCPEReferenceCount - find the constant pool entry with index CPI 82304eeddc0SDimitry Andric /// and instruction CPEMI, and decrement its refcount. If the refcount 82404eeddc0SDimitry Andric /// becomes 0 remove the entry and instruction. Returns true if we removed 82504eeddc0SDimitry Andric /// the entry, false if we didn't. 82604eeddc0SDimitry Andric bool CSKYConstantIslands::decrementCPEReferenceCount(unsigned CPI, 82704eeddc0SDimitry Andric MachineInstr *CPEMI) { 82804eeddc0SDimitry Andric // Find the old entry. Eliminate it if it is no longer used. 82904eeddc0SDimitry Andric CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); 83004eeddc0SDimitry Andric assert(CPE && "Unexpected!"); 83104eeddc0SDimitry Andric if (--CPE->RefCount == 0) { 83204eeddc0SDimitry Andric removeDeadCPEMI(CPEMI); 83304eeddc0SDimitry Andric CPE->CPEMI = nullptr; 83404eeddc0SDimitry Andric --NumCPEs; 83504eeddc0SDimitry Andric return true; 83604eeddc0SDimitry Andric } 83704eeddc0SDimitry Andric return false; 83804eeddc0SDimitry Andric } 83904eeddc0SDimitry Andric 84004eeddc0SDimitry Andric /// LookForCPEntryInRange - see if the currently referenced CPE is in range; 84104eeddc0SDimitry Andric /// if not, see if an in-range clone of the CPE is in range, and if so, 84204eeddc0SDimitry Andric /// change the data structures so the user references the clone. Returns: 84304eeddc0SDimitry Andric /// 0 = no existing entry found 84404eeddc0SDimitry Andric /// 1 = entry found, and there were no code insertions or deletions 84504eeddc0SDimitry Andric /// 2 = entry found, and there were code insertions or deletions 84604eeddc0SDimitry Andric int CSKYConstantIslands::findInRangeCPEntry(CPUser &U, unsigned UserOffset) { 84704eeddc0SDimitry Andric MachineInstr *UserMI = U.MI; 84804eeddc0SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 84904eeddc0SDimitry Andric 85004eeddc0SDimitry Andric // Check to see if the CPE is already in-range. 85104eeddc0SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk, 85204eeddc0SDimitry Andric true)) { 85304eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "In range\n"); 85404eeddc0SDimitry Andric return 1; 85504eeddc0SDimitry Andric } 85604eeddc0SDimitry Andric 85704eeddc0SDimitry Andric // No. Look for previously created clones of the CPE that are in range. 85804eeddc0SDimitry Andric unsigned CPI = CPEMI->getOperand(1).getIndex(); 85904eeddc0SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[CPI]; 86004eeddc0SDimitry Andric for (unsigned I = 0, E = CPEs.size(); I != E; ++I) { 86104eeddc0SDimitry Andric // We already tried this one 86204eeddc0SDimitry Andric if (CPEs[I].CPEMI == CPEMI) 86304eeddc0SDimitry Andric continue; 86404eeddc0SDimitry Andric // Removing CPEs can leave empty entries, skip 86504eeddc0SDimitry Andric if (CPEs[I].CPEMI == nullptr) 86604eeddc0SDimitry Andric continue; 86704eeddc0SDimitry Andric if (isCPEntryInRange(UserMI, UserOffset, CPEs[I].CPEMI, U.getMaxDisp(), 86804eeddc0SDimitry Andric U.NegOk)) { 86904eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" 87004eeddc0SDimitry Andric << CPEs[I].CPI << "\n"); 87104eeddc0SDimitry Andric // Point the CPUser node to the replacement 87204eeddc0SDimitry Andric U.CPEMI = CPEs[I].CPEMI; 87304eeddc0SDimitry Andric // Change the CPI in the instruction operand to refer to the clone. 87404eeddc0SDimitry Andric for (unsigned J = 0, E = UserMI->getNumOperands(); J != E; ++J) 87504eeddc0SDimitry Andric if (UserMI->getOperand(J).isCPI()) { 87604eeddc0SDimitry Andric UserMI->getOperand(J).setIndex(CPEs[I].CPI); 87704eeddc0SDimitry Andric break; 87804eeddc0SDimitry Andric } 87904eeddc0SDimitry Andric // Adjust the refcount of the clone... 88004eeddc0SDimitry Andric CPEs[I].RefCount++; 88104eeddc0SDimitry Andric // ...and the original. If we didn't remove the old entry, none of the 88204eeddc0SDimitry Andric // addresses changed, so we don't need another pass. 88304eeddc0SDimitry Andric return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; 88404eeddc0SDimitry Andric } 88504eeddc0SDimitry Andric } 88604eeddc0SDimitry Andric return 0; 88704eeddc0SDimitry Andric } 88804eeddc0SDimitry Andric 88904eeddc0SDimitry Andric /// getUnconditionalBrDisp - Returns the maximum displacement that can fit in 89004eeddc0SDimitry Andric /// the specific unconditional branch instruction. 89104eeddc0SDimitry Andric static inline unsigned getUnconditionalBrDisp(int Opc) { 89204eeddc0SDimitry Andric unsigned Bits, Scale; 89304eeddc0SDimitry Andric 89404eeddc0SDimitry Andric switch (Opc) { 89504eeddc0SDimitry Andric case CSKY::BR16: 89604eeddc0SDimitry Andric Bits = 10; 89704eeddc0SDimitry Andric Scale = 2; 89804eeddc0SDimitry Andric break; 89904eeddc0SDimitry Andric case CSKY::BR32: 90004eeddc0SDimitry Andric Bits = 16; 90104eeddc0SDimitry Andric Scale = 2; 90204eeddc0SDimitry Andric break; 90304eeddc0SDimitry Andric default: 90481ad6265SDimitry Andric llvm_unreachable(""); 90504eeddc0SDimitry Andric } 90604eeddc0SDimitry Andric 90704eeddc0SDimitry Andric unsigned MaxOffs = ((1 << (Bits - 1)) - 1) * Scale; 90804eeddc0SDimitry Andric return MaxOffs; 90904eeddc0SDimitry Andric } 91004eeddc0SDimitry Andric 91104eeddc0SDimitry Andric /// findAvailableWater - Look for an existing entry in the WaterList in which 91204eeddc0SDimitry Andric /// we can place the CPE referenced from U so it's within range of U's MI. 91304eeddc0SDimitry Andric /// Returns true if found, false if not. If it returns true, WaterIter 91404eeddc0SDimitry Andric /// is set to the WaterList entry. 91504eeddc0SDimitry Andric /// To ensure that this pass 91604eeddc0SDimitry Andric /// terminates, the CPE location for a particular CPUser is only allowed to 91704eeddc0SDimitry Andric /// move to a lower address, so search backward from the end of the list and 91804eeddc0SDimitry Andric /// prefer the first water that is in range. 91904eeddc0SDimitry Andric bool CSKYConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset, 92004eeddc0SDimitry Andric water_iterator &WaterIter) { 92104eeddc0SDimitry Andric if (WaterList.empty()) 92204eeddc0SDimitry Andric return false; 92304eeddc0SDimitry Andric 92404eeddc0SDimitry Andric unsigned BestGrowth = ~0u; 92504eeddc0SDimitry Andric for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();; 92604eeddc0SDimitry Andric --IP) { 92704eeddc0SDimitry Andric MachineBasicBlock *WaterBB = *IP; 92804eeddc0SDimitry Andric // Check if water is in range and is either at a lower address than the 92904eeddc0SDimitry Andric // current "high water mark" or a new water block that was created since 93004eeddc0SDimitry Andric // the previous iteration by inserting an unconditional branch. In the 93104eeddc0SDimitry Andric // latter case, we want to allow resetting the high water mark back to 93204eeddc0SDimitry Andric // this new water since we haven't seen it before. Inserting branches 93304eeddc0SDimitry Andric // should be relatively uncommon and when it does happen, we want to be 93404eeddc0SDimitry Andric // sure to take advantage of it for all the CPEs near that block, so that 93504eeddc0SDimitry Andric // we don't insert more branches than necessary. 93604eeddc0SDimitry Andric unsigned Growth; 93704eeddc0SDimitry Andric if (isWaterInRange(UserOffset, WaterBB, U, Growth) && 93804eeddc0SDimitry Andric (WaterBB->getNumber() < U.HighWaterMark->getNumber() || 93904eeddc0SDimitry Andric NewWaterList.count(WaterBB)) && 94004eeddc0SDimitry Andric Growth < BestGrowth) { 94104eeddc0SDimitry Andric // This is the least amount of required padding seen so far. 94204eeddc0SDimitry Andric BestGrowth = Growth; 94304eeddc0SDimitry Andric WaterIter = IP; 94404eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB) 94504eeddc0SDimitry Andric << " Growth=" << Growth << '\n'); 94604eeddc0SDimitry Andric 94704eeddc0SDimitry Andric // Keep looking unless it is perfect. 94804eeddc0SDimitry Andric if (BestGrowth == 0) 94904eeddc0SDimitry Andric return true; 95004eeddc0SDimitry Andric } 95104eeddc0SDimitry Andric if (IP == B) 95204eeddc0SDimitry Andric break; 95304eeddc0SDimitry Andric } 95404eeddc0SDimitry Andric return BestGrowth != ~0u; 95504eeddc0SDimitry Andric } 95604eeddc0SDimitry Andric 95704eeddc0SDimitry Andric /// createNewWater - No existing WaterList entry will work for 95804eeddc0SDimitry Andric /// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the 95904eeddc0SDimitry Andric /// block is used if in range, and the conditional branch munged so control 96004eeddc0SDimitry Andric /// flow is correct. Otherwise the block is split to create a hole with an 96104eeddc0SDimitry Andric /// unconditional branch around it. In either case NewMBB is set to a 96204eeddc0SDimitry Andric /// block following which the new island can be inserted (the WaterList 96304eeddc0SDimitry Andric /// is not adjusted). 96404eeddc0SDimitry Andric void CSKYConstantIslands::createNewWater(unsigned CPUserIndex, 96504eeddc0SDimitry Andric unsigned UserOffset, 96604eeddc0SDimitry Andric MachineBasicBlock *&NewMBB) { 96704eeddc0SDimitry Andric CPUser &U = CPUsers[CPUserIndex]; 96804eeddc0SDimitry Andric MachineInstr *UserMI = U.MI; 96904eeddc0SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 97004eeddc0SDimitry Andric MachineBasicBlock *UserMBB = UserMI->getParent(); 97104eeddc0SDimitry Andric const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()]; 97204eeddc0SDimitry Andric 97304eeddc0SDimitry Andric // If the block does not end in an unconditional branch already, and if the 97404eeddc0SDimitry Andric // end of the block is within range, make new water there. 97504eeddc0SDimitry Andric if (bbHasFallthrough(UserMBB)) { 97604eeddc0SDimitry Andric // Size of branch to insert. 97704eeddc0SDimitry Andric unsigned Delta = 4; 97804eeddc0SDimitry Andric // Compute the offset where the CPE will begin. 97904eeddc0SDimitry Andric unsigned CPEOffset = UserBBI.postOffset() + Delta; 98004eeddc0SDimitry Andric 98104eeddc0SDimitry Andric if (isOffsetInRange(UserOffset, CPEOffset, U)) { 98204eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB) 98304eeddc0SDimitry Andric << format(", expected CPE offset %#x\n", CPEOffset)); 98404eeddc0SDimitry Andric NewMBB = &*++UserMBB->getIterator(); 98504eeddc0SDimitry Andric // Add an unconditional branch from UserMBB to fallthrough block. Record 98604eeddc0SDimitry Andric // it for branch lengthening; this new branch will not get out of range, 98704eeddc0SDimitry Andric // but if the preceding conditional branch is out of range, the targets 98804eeddc0SDimitry Andric // will be exchanged, and the altered branch may be out of range, so the 98904eeddc0SDimitry Andric // machinery has to know about it. 99004eeddc0SDimitry Andric 99104eeddc0SDimitry Andric // TODO: Add support for 16bit instr. 99204eeddc0SDimitry Andric int UncondBr = CSKY::BR32; 99304eeddc0SDimitry Andric auto *NewMI = BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)) 99404eeddc0SDimitry Andric .addMBB(NewMBB) 99504eeddc0SDimitry Andric .getInstr(); 99604eeddc0SDimitry Andric unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); 99704eeddc0SDimitry Andric ImmBranches.push_back( 99804eeddc0SDimitry Andric ImmBranch(&UserMBB->back(), MaxDisp, false, UncondBr)); 99904eeddc0SDimitry Andric BBInfo[UserMBB->getNumber()].Size += TII->getInstSizeInBytes(*NewMI); 100004eeddc0SDimitry Andric adjustBBOffsetsAfter(UserMBB); 100104eeddc0SDimitry Andric return; 100204eeddc0SDimitry Andric } 100304eeddc0SDimitry Andric } 100404eeddc0SDimitry Andric 100504eeddc0SDimitry Andric // What a big block. Find a place within the block to split it. 100604eeddc0SDimitry Andric 100704eeddc0SDimitry Andric // Try to split the block so it's fully aligned. Compute the latest split 100804eeddc0SDimitry Andric // point where we can add a 4-byte branch instruction, and then align to 100904eeddc0SDimitry Andric // Align which is the largest possible alignment in the function. 101004eeddc0SDimitry Andric const Align Align = MF->getAlignment(); 101104eeddc0SDimitry Andric unsigned BaseInsertOffset = UserOffset + U.getMaxDisp(); 101204eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x", 101304eeddc0SDimitry Andric BaseInsertOffset)); 101404eeddc0SDimitry Andric 101504eeddc0SDimitry Andric // The 4 in the following is for the unconditional branch we'll be inserting 101604eeddc0SDimitry Andric // Alignment of the island is handled 101704eeddc0SDimitry Andric // inside isOffsetInRange. 101804eeddc0SDimitry Andric BaseInsertOffset -= 4; 101904eeddc0SDimitry Andric 102004eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) 102104eeddc0SDimitry Andric << " la=" << Log2(Align) << '\n'); 102204eeddc0SDimitry Andric 102304eeddc0SDimitry Andric // This could point off the end of the block if we've already got constant 102404eeddc0SDimitry Andric // pool entries following this block; only the last one is in the water list. 102504eeddc0SDimitry Andric // Back past any possible branches (allow for a conditional and a maximally 102604eeddc0SDimitry Andric // long unconditional). 102704eeddc0SDimitry Andric if (BaseInsertOffset + 8 >= UserBBI.postOffset()) { 102804eeddc0SDimitry Andric BaseInsertOffset = UserBBI.postOffset() - 8; 102904eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); 103004eeddc0SDimitry Andric } 103104eeddc0SDimitry Andric unsigned EndInsertOffset = 103204eeddc0SDimitry Andric BaseInsertOffset + 4 + CPEMI->getOperand(2).getImm(); 103304eeddc0SDimitry Andric MachineBasicBlock::iterator MI = UserMI; 103404eeddc0SDimitry Andric ++MI; 103504eeddc0SDimitry Andric unsigned CPUIndex = CPUserIndex + 1; 103604eeddc0SDimitry Andric unsigned NumCPUsers = CPUsers.size(); 103704eeddc0SDimitry Andric for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI); 103804eeddc0SDimitry Andric Offset < BaseInsertOffset; 103904eeddc0SDimitry Andric Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) { 104004eeddc0SDimitry Andric assert(MI != UserMBB->end() && "Fell off end of block"); 104104eeddc0SDimitry Andric if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { 104204eeddc0SDimitry Andric CPUser &U = CPUsers[CPUIndex]; 104304eeddc0SDimitry Andric if (!isOffsetInRange(Offset, EndInsertOffset, U)) { 104404eeddc0SDimitry Andric // Shift intertion point by one unit of alignment so it is within reach. 104504eeddc0SDimitry Andric BaseInsertOffset -= Align.value(); 104604eeddc0SDimitry Andric EndInsertOffset -= Align.value(); 104704eeddc0SDimitry Andric } 104804eeddc0SDimitry Andric // This is overly conservative, as we don't account for CPEMIs being 104904eeddc0SDimitry Andric // reused within the block, but it doesn't matter much. Also assume CPEs 105004eeddc0SDimitry Andric // are added in order with alignment padding. We may eventually be able 105104eeddc0SDimitry Andric // to pack the aligned CPEs better. 105204eeddc0SDimitry Andric EndInsertOffset += U.CPEMI->getOperand(2).getImm(); 105304eeddc0SDimitry Andric CPUIndex++; 105404eeddc0SDimitry Andric } 105504eeddc0SDimitry Andric } 105604eeddc0SDimitry Andric 105704eeddc0SDimitry Andric NewMBB = splitBlockBeforeInstr(*--MI); 105804eeddc0SDimitry Andric } 105904eeddc0SDimitry Andric 106004eeddc0SDimitry Andric /// handleConstantPoolUser - Analyze the specified user, checking to see if it 106104eeddc0SDimitry Andric /// is out-of-range. If so, pick up the constant pool value and move it some 106204eeddc0SDimitry Andric /// place in-range. Return true if we changed any addresses (thus must run 106304eeddc0SDimitry Andric /// another pass of branch lengthening), false otherwise. 106404eeddc0SDimitry Andric bool CSKYConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { 106504eeddc0SDimitry Andric CPUser &U = CPUsers[CPUserIndex]; 106604eeddc0SDimitry Andric MachineInstr *UserMI = U.MI; 106704eeddc0SDimitry Andric MachineInstr *CPEMI = U.CPEMI; 106804eeddc0SDimitry Andric unsigned CPI = CPEMI->getOperand(1).getIndex(); 106904eeddc0SDimitry Andric unsigned Size = CPEMI->getOperand(2).getImm(); 107004eeddc0SDimitry Andric // Compute this only once, it's expensive. 107104eeddc0SDimitry Andric unsigned UserOffset = getUserOffset(U); 107204eeddc0SDimitry Andric 107304eeddc0SDimitry Andric // See if the current entry is within range, or there is a clone of it 107404eeddc0SDimitry Andric // in range. 107504eeddc0SDimitry Andric int result = findInRangeCPEntry(U, UserOffset); 107604eeddc0SDimitry Andric if (result == 1) 107704eeddc0SDimitry Andric return false; 107804eeddc0SDimitry Andric if (result == 2) 107904eeddc0SDimitry Andric return true; 108004eeddc0SDimitry Andric 108104eeddc0SDimitry Andric // Look for water where we can place this CPE. 108204eeddc0SDimitry Andric MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock(); 108304eeddc0SDimitry Andric MachineBasicBlock *NewMBB; 108404eeddc0SDimitry Andric water_iterator IP; 108504eeddc0SDimitry Andric if (findAvailableWater(U, UserOffset, IP)) { 108604eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Found water in range\n"); 108704eeddc0SDimitry Andric MachineBasicBlock *WaterBB = *IP; 108804eeddc0SDimitry Andric 108904eeddc0SDimitry Andric // If the original WaterList entry was "new water" on this iteration, 109004eeddc0SDimitry Andric // propagate that to the new island. This is just keeping NewWaterList 109104eeddc0SDimitry Andric // updated to match the WaterList, which will be updated below. 109204eeddc0SDimitry Andric if (NewWaterList.erase(WaterBB)) 109304eeddc0SDimitry Andric NewWaterList.insert(NewIsland); 109404eeddc0SDimitry Andric 109504eeddc0SDimitry Andric // The new CPE goes before the following block (NewMBB). 109604eeddc0SDimitry Andric NewMBB = &*++WaterBB->getIterator(); 109704eeddc0SDimitry Andric } else { 109804eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "No water found\n"); 109904eeddc0SDimitry Andric createNewWater(CPUserIndex, UserOffset, NewMBB); 110004eeddc0SDimitry Andric 110104eeddc0SDimitry Andric // splitBlockBeforeInstr adds to WaterList, which is important when it is 110204eeddc0SDimitry Andric // called while handling branches so that the water will be seen on the 110304eeddc0SDimitry Andric // next iteration for constant pools, but in this context, we don't want 110404eeddc0SDimitry Andric // it. Check for this so it will be removed from the WaterList. 110504eeddc0SDimitry Andric // Also remove any entry from NewWaterList. 110604eeddc0SDimitry Andric MachineBasicBlock *WaterBB = &*--NewMBB->getIterator(); 110704eeddc0SDimitry Andric IP = llvm::find(WaterList, WaterBB); 110804eeddc0SDimitry Andric if (IP != WaterList.end()) 110904eeddc0SDimitry Andric NewWaterList.erase(WaterBB); 111004eeddc0SDimitry Andric 111104eeddc0SDimitry Andric // We are adding new water. Update NewWaterList. 111204eeddc0SDimitry Andric NewWaterList.insert(NewIsland); 111304eeddc0SDimitry Andric } 111404eeddc0SDimitry Andric 111504eeddc0SDimitry Andric // Remove the original WaterList entry; we want subsequent insertions in 111604eeddc0SDimitry Andric // this vicinity to go after the one we're about to insert. This 111704eeddc0SDimitry Andric // considerably reduces the number of times we have to move the same CPE 111804eeddc0SDimitry Andric // more than once and is also important to ensure the algorithm terminates. 111904eeddc0SDimitry Andric if (IP != WaterList.end()) 112004eeddc0SDimitry Andric WaterList.erase(IP); 112104eeddc0SDimitry Andric 112204eeddc0SDimitry Andric // Okay, we know we can put an island before NewMBB now, do it! 112304eeddc0SDimitry Andric MF->insert(NewMBB->getIterator(), NewIsland); 112404eeddc0SDimitry Andric 112504eeddc0SDimitry Andric // Update internal data structures to account for the newly inserted MBB. 112604eeddc0SDimitry Andric updateForInsertedWaterBlock(NewIsland); 112704eeddc0SDimitry Andric 112804eeddc0SDimitry Andric // Decrement the old entry, and remove it if refcount becomes 0. 112904eeddc0SDimitry Andric decrementCPEReferenceCount(CPI, CPEMI); 113004eeddc0SDimitry Andric 113104eeddc0SDimitry Andric // No existing clone of this CPE is within range. 113204eeddc0SDimitry Andric // We will be generating a new clone. Get a UID for it. 113304eeddc0SDimitry Andric unsigned ID = createPICLabelUId(); 113404eeddc0SDimitry Andric 113504eeddc0SDimitry Andric // Now that we have an island to add the CPE to, clone the original CPE and 113604eeddc0SDimitry Andric // add it to the island. 113704eeddc0SDimitry Andric U.HighWaterMark = NewIsland; 113804eeddc0SDimitry Andric U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(CSKY::CONSTPOOL_ENTRY)) 113904eeddc0SDimitry Andric .addImm(ID) 114004eeddc0SDimitry Andric .addConstantPoolIndex(CPI) 114104eeddc0SDimitry Andric .addImm(Size); 114204eeddc0SDimitry Andric CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); 114304eeddc0SDimitry Andric ++NumCPEs; 114404eeddc0SDimitry Andric 114504eeddc0SDimitry Andric // Mark the basic block as aligned as required by the const-pool entry. 114604eeddc0SDimitry Andric NewIsland->setAlignment(getCPEAlign(*U.CPEMI)); 114704eeddc0SDimitry Andric 114804eeddc0SDimitry Andric // Increase the size of the island block to account for the new entry. 114904eeddc0SDimitry Andric BBInfo[NewIsland->getNumber()].Size += Size; 115004eeddc0SDimitry Andric adjustBBOffsetsAfter(&*--NewIsland->getIterator()); 115104eeddc0SDimitry Andric 115204eeddc0SDimitry Andric // Finally, change the CPI in the instruction operand to be ID. 115304eeddc0SDimitry Andric for (unsigned I = 0, E = UserMI->getNumOperands(); I != E; ++I) 115404eeddc0SDimitry Andric if (UserMI->getOperand(I).isCPI()) { 115504eeddc0SDimitry Andric UserMI->getOperand(I).setIndex(ID); 115604eeddc0SDimitry Andric break; 115704eeddc0SDimitry Andric } 115804eeddc0SDimitry Andric 115904eeddc0SDimitry Andric LLVM_DEBUG( 116004eeddc0SDimitry Andric dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI 116104eeddc0SDimitry Andric << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); 116204eeddc0SDimitry Andric 116304eeddc0SDimitry Andric return true; 116404eeddc0SDimitry Andric } 116504eeddc0SDimitry Andric 116604eeddc0SDimitry Andric /// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update 116704eeddc0SDimitry Andric /// sizes and offsets of impacted basic blocks. 116804eeddc0SDimitry Andric void CSKYConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) { 116904eeddc0SDimitry Andric MachineBasicBlock *CPEBB = CPEMI->getParent(); 117004eeddc0SDimitry Andric unsigned Size = CPEMI->getOperand(2).getImm(); 117104eeddc0SDimitry Andric CPEMI->eraseFromParent(); 117204eeddc0SDimitry Andric BBInfo[CPEBB->getNumber()].Size -= Size; 117304eeddc0SDimitry Andric // All succeeding offsets have the current size value added in, fix this. 117404eeddc0SDimitry Andric if (CPEBB->empty()) { 117504eeddc0SDimitry Andric BBInfo[CPEBB->getNumber()].Size = 0; 117604eeddc0SDimitry Andric 117704eeddc0SDimitry Andric // This block no longer needs to be aligned. 117804eeddc0SDimitry Andric CPEBB->setAlignment(Align(4)); 117904eeddc0SDimitry Andric } else { 118004eeddc0SDimitry Andric // Entries are sorted by descending alignment, so realign from the front. 118104eeddc0SDimitry Andric CPEBB->setAlignment(getCPEAlign(*CPEBB->begin())); 118204eeddc0SDimitry Andric } 118304eeddc0SDimitry Andric 118404eeddc0SDimitry Andric adjustBBOffsetsAfter(CPEBB); 118504eeddc0SDimitry Andric // An island has only one predecessor BB and one successor BB. Check if 118604eeddc0SDimitry Andric // this BB's predecessor jumps directly to this BB's successor. This 118704eeddc0SDimitry Andric // shouldn't happen currently. 118804eeddc0SDimitry Andric assert(!bbIsJumpedOver(CPEBB) && "How did this happen?"); 118904eeddc0SDimitry Andric // FIXME: remove the empty blocks after all the work is done? 119004eeddc0SDimitry Andric } 119104eeddc0SDimitry Andric 119204eeddc0SDimitry Andric /// removeUnusedCPEntries - Remove constant pool entries whose refcounts 119304eeddc0SDimitry Andric /// are zero. 119404eeddc0SDimitry Andric bool CSKYConstantIslands::removeUnusedCPEntries() { 119504eeddc0SDimitry Andric unsigned MadeChange = false; 119604eeddc0SDimitry Andric for (unsigned I = 0, E = CPEntries.size(); I != E; ++I) { 119704eeddc0SDimitry Andric std::vector<CPEntry> &CPEs = CPEntries[I]; 119804eeddc0SDimitry Andric for (unsigned J = 0, Ee = CPEs.size(); J != Ee; ++J) { 119904eeddc0SDimitry Andric if (CPEs[J].RefCount == 0 && CPEs[J].CPEMI) { 120004eeddc0SDimitry Andric removeDeadCPEMI(CPEs[J].CPEMI); 120104eeddc0SDimitry Andric CPEs[J].CPEMI = nullptr; 120204eeddc0SDimitry Andric MadeChange = true; 120304eeddc0SDimitry Andric } 120404eeddc0SDimitry Andric } 120504eeddc0SDimitry Andric } 120604eeddc0SDimitry Andric return MadeChange; 120704eeddc0SDimitry Andric } 120804eeddc0SDimitry Andric 120904eeddc0SDimitry Andric /// isBBInRange - Returns true if the distance between specific MI and 121004eeddc0SDimitry Andric /// specific BB can fit in MI's displacement field. 121104eeddc0SDimitry Andric bool CSKYConstantIslands::isBBInRange(MachineInstr *MI, 121204eeddc0SDimitry Andric MachineBasicBlock *DestBB, 121304eeddc0SDimitry Andric unsigned MaxDisp) { 121404eeddc0SDimitry Andric unsigned BrOffset = getOffsetOf(MI); 121504eeddc0SDimitry Andric unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; 121604eeddc0SDimitry Andric 121704eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) 121804eeddc0SDimitry Andric << " from " << printMBBReference(*MI->getParent()) 121904eeddc0SDimitry Andric << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) 122004eeddc0SDimitry Andric << " to " << DestOffset << " offset " 122104eeddc0SDimitry Andric << int(DestOffset - BrOffset) << "\t" << *MI); 122204eeddc0SDimitry Andric 122304eeddc0SDimitry Andric if (BrOffset <= DestOffset) { 122404eeddc0SDimitry Andric // Branch before the Dest. 122504eeddc0SDimitry Andric if (DestOffset - BrOffset <= MaxDisp) 122604eeddc0SDimitry Andric return true; 122704eeddc0SDimitry Andric } else { 122804eeddc0SDimitry Andric if (BrOffset - DestOffset <= MaxDisp) 122904eeddc0SDimitry Andric return true; 123004eeddc0SDimitry Andric } 123104eeddc0SDimitry Andric return false; 123204eeddc0SDimitry Andric } 123304eeddc0SDimitry Andric 123404eeddc0SDimitry Andric /// fixupImmediateBr - Fix up an immediate branch whose destination is too far 123504eeddc0SDimitry Andric /// away to fit in its displacement field. 123604eeddc0SDimitry Andric bool CSKYConstantIslands::fixupImmediateBr(ImmBranch &Br) { 123704eeddc0SDimitry Andric MachineInstr *MI = Br.MI; 123804eeddc0SDimitry Andric MachineBasicBlock *DestBB = TII->getBranchDestBlock(*MI); 123904eeddc0SDimitry Andric 124004eeddc0SDimitry Andric // Check to see if the DestBB is already in-range. 124104eeddc0SDimitry Andric if (isBBInRange(MI, DestBB, Br.MaxDisp)) 124204eeddc0SDimitry Andric return false; 124304eeddc0SDimitry Andric 124404eeddc0SDimitry Andric if (!Br.IsCond) 124504eeddc0SDimitry Andric return fixupUnconditionalBr(Br); 124604eeddc0SDimitry Andric return fixupConditionalBr(Br); 124704eeddc0SDimitry Andric } 124804eeddc0SDimitry Andric 124904eeddc0SDimitry Andric /// fixupUnconditionalBr - Fix up an unconditional branch whose destination is 125004eeddc0SDimitry Andric /// too far away to fit in its displacement field. If the LR register has been 125104eeddc0SDimitry Andric /// spilled in the epilogue, then we can use BSR to implement a far jump. 125204eeddc0SDimitry Andric /// Otherwise, add an intermediate branch instruction to a branch. 125304eeddc0SDimitry Andric bool CSKYConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { 125404eeddc0SDimitry Andric MachineInstr *MI = Br.MI; 125504eeddc0SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 125604eeddc0SDimitry Andric 125704eeddc0SDimitry Andric if (!MFI->isLRSpilled()) 125804eeddc0SDimitry Andric report_fatal_error("underestimated function size"); 125904eeddc0SDimitry Andric 126004eeddc0SDimitry Andric // Use BSR to implement far jump. 126104eeddc0SDimitry Andric Br.MaxDisp = ((1 << (26 - 1)) - 1) * 2; 126204eeddc0SDimitry Andric MI->setDesc(TII->get(CSKY::BSR32_BR)); 126304eeddc0SDimitry Andric BBInfo[MBB->getNumber()].Size += 4; 126404eeddc0SDimitry Andric adjustBBOffsetsAfter(MBB); 126504eeddc0SDimitry Andric ++NumUBrFixed; 126604eeddc0SDimitry Andric 126704eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << " Changed B to long jump " << *MI); 126804eeddc0SDimitry Andric 126904eeddc0SDimitry Andric return true; 127004eeddc0SDimitry Andric } 127104eeddc0SDimitry Andric 127204eeddc0SDimitry Andric /// fixupConditionalBr - Fix up a conditional branch whose destination is too 127304eeddc0SDimitry Andric /// far away to fit in its displacement field. It is converted to an inverse 127404eeddc0SDimitry Andric /// conditional branch + an unconditional branch to the destination. 127504eeddc0SDimitry Andric bool CSKYConstantIslands::fixupConditionalBr(ImmBranch &Br) { 127604eeddc0SDimitry Andric MachineInstr *MI = Br.MI; 127704eeddc0SDimitry Andric MachineBasicBlock *DestBB = TII->getBranchDestBlock(*MI); 127804eeddc0SDimitry Andric 127904eeddc0SDimitry Andric SmallVector<MachineOperand, 4> Cond; 128004eeddc0SDimitry Andric Cond.push_back(MachineOperand::CreateImm(MI->getOpcode())); 128104eeddc0SDimitry Andric Cond.push_back(MI->getOperand(0)); 128204eeddc0SDimitry Andric TII->reverseBranchCondition(Cond); 128304eeddc0SDimitry Andric 128404eeddc0SDimitry Andric // Add an unconditional branch to the destination and invert the branch 128504eeddc0SDimitry Andric // condition to jump over it: 128604eeddc0SDimitry Andric // bteqz L1 128704eeddc0SDimitry Andric // => 128804eeddc0SDimitry Andric // bnez L2 128904eeddc0SDimitry Andric // b L1 129004eeddc0SDimitry Andric // L2: 129104eeddc0SDimitry Andric 129204eeddc0SDimitry Andric // If the branch is at the end of its MBB and that has a fall-through block, 129304eeddc0SDimitry Andric // direct the updated conditional branch to the fall-through block. Otherwise, 129404eeddc0SDimitry Andric // split the MBB before the next instruction. 129504eeddc0SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 129604eeddc0SDimitry Andric MachineInstr *BMI = &MBB->back(); 129704eeddc0SDimitry Andric bool NeedSplit = (BMI != MI) || !bbHasFallthrough(MBB); 129804eeddc0SDimitry Andric 129904eeddc0SDimitry Andric ++NumCBrFixed; 130004eeddc0SDimitry Andric if (BMI != MI) { 130104eeddc0SDimitry Andric if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) && 130204eeddc0SDimitry Andric BMI->isUnconditionalBranch()) { 130304eeddc0SDimitry Andric // Last MI in the BB is an unconditional branch. Can we simply invert the 130404eeddc0SDimitry Andric // condition and swap destinations: 130504eeddc0SDimitry Andric // beqz L1 130604eeddc0SDimitry Andric // b L2 130704eeddc0SDimitry Andric // => 130804eeddc0SDimitry Andric // bnez L2 130904eeddc0SDimitry Andric // b L1 131004eeddc0SDimitry Andric MachineBasicBlock *NewDest = TII->getBranchDestBlock(*BMI); 131104eeddc0SDimitry Andric if (isBBInRange(MI, NewDest, Br.MaxDisp)) { 131204eeddc0SDimitry Andric LLVM_DEBUG( 131304eeddc0SDimitry Andric dbgs() << " Invert Bcc condition and swap its destination with " 131404eeddc0SDimitry Andric << *BMI); 131504eeddc0SDimitry Andric BMI->getOperand(BMI->getNumExplicitOperands() - 1).setMBB(DestBB); 131604eeddc0SDimitry Andric MI->getOperand(MI->getNumExplicitOperands() - 1).setMBB(NewDest); 131704eeddc0SDimitry Andric 131804eeddc0SDimitry Andric MI->setDesc(TII->get(Cond[0].getImm())); 131904eeddc0SDimitry Andric return true; 132004eeddc0SDimitry Andric } 132104eeddc0SDimitry Andric } 132204eeddc0SDimitry Andric } 132304eeddc0SDimitry Andric 132404eeddc0SDimitry Andric if (NeedSplit) { 132504eeddc0SDimitry Andric splitBlockBeforeInstr(*MI); 132604eeddc0SDimitry Andric // No need for the branch to the next block. We're adding an unconditional 132704eeddc0SDimitry Andric // branch to the destination. 132804eeddc0SDimitry Andric int Delta = TII->getInstSizeInBytes(MBB->back()); 132904eeddc0SDimitry Andric BBInfo[MBB->getNumber()].Size -= Delta; 133004eeddc0SDimitry Andric MBB->back().eraseFromParent(); 133104eeddc0SDimitry Andric // BBInfo[SplitBB].Offset is wrong temporarily, fixed below 133204eeddc0SDimitry Andric 133304eeddc0SDimitry Andric // The conditional successor will be swapped between the BBs after this, so 133404eeddc0SDimitry Andric // update CFG. 133504eeddc0SDimitry Andric MBB->addSuccessor(DestBB); 133604eeddc0SDimitry Andric std::next(MBB->getIterator())->removeSuccessor(DestBB); 133704eeddc0SDimitry Andric } 133804eeddc0SDimitry Andric MachineBasicBlock *NextBB = &*++MBB->getIterator(); 133904eeddc0SDimitry Andric 134004eeddc0SDimitry Andric LLVM_DEBUG(dbgs() << " Insert B to " << printMBBReference(*DestBB) 134104eeddc0SDimitry Andric << " also invert condition and change dest. to " 134204eeddc0SDimitry Andric << printMBBReference(*NextBB) << "\n"); 134304eeddc0SDimitry Andric 134404eeddc0SDimitry Andric // Insert a new conditional branch and a new unconditional branch. 134504eeddc0SDimitry Andric // Also update the ImmBranch as well as adding a new entry for the new branch. 134604eeddc0SDimitry Andric 134704eeddc0SDimitry Andric BuildMI(MBB, DebugLoc(), TII->get(Cond[0].getImm())) 134804eeddc0SDimitry Andric .addReg(MI->getOperand(0).getReg()) 134904eeddc0SDimitry Andric .addMBB(NextBB); 135004eeddc0SDimitry Andric 135104eeddc0SDimitry Andric Br.MI = &MBB->back(); 135204eeddc0SDimitry Andric BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); 135304eeddc0SDimitry Andric BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); 135404eeddc0SDimitry Andric BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); 135504eeddc0SDimitry Andric unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); 135604eeddc0SDimitry Andric ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); 135704eeddc0SDimitry Andric 135804eeddc0SDimitry Andric // Remove the old conditional branch. It may or may not still be in MBB. 135904eeddc0SDimitry Andric BBInfo[MI->getParent()->getNumber()].Size -= TII->getInstSizeInBytes(*MI); 136004eeddc0SDimitry Andric MI->eraseFromParent(); 136104eeddc0SDimitry Andric adjustBBOffsetsAfter(MBB); 136204eeddc0SDimitry Andric return true; 136304eeddc0SDimitry Andric } 136404eeddc0SDimitry Andric 136504eeddc0SDimitry Andric /// Returns a pass that converts branches to long branches. 136604eeddc0SDimitry Andric FunctionPass *llvm::createCSKYConstantIslandPass() { 136704eeddc0SDimitry Andric return new CSKYConstantIslands(); 136804eeddc0SDimitry Andric } 136904eeddc0SDimitry Andric 137004eeddc0SDimitry Andric INITIALIZE_PASS(CSKYConstantIslands, DEBUG_TYPE, 137104eeddc0SDimitry Andric "CSKY constant island placement and branch shortening pass", 137204eeddc0SDimitry Andric false, false) 1373