xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYConstantIslandPass.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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