xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/BranchFolding.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- BranchFolding.h - Fold machine code branch instructions --*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_BRANCHFOLDING_H
100b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_BRANCHFOLDING_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
160b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
170b57cec5SDimitry Andric #include <vector>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace llvm {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric class BasicBlock;
220b57cec5SDimitry Andric class MachineBranchProbabilityInfo;
230b57cec5SDimitry Andric class MachineFunction;
240b57cec5SDimitry Andric class MachineLoopInfo;
250b57cec5SDimitry Andric class MachineRegisterInfo;
265ffd83dbSDimitry Andric class MBFIWrapper;
27480093f4SDimitry Andric class ProfileSummaryInfo;
280b57cec5SDimitry Andric class TargetInstrInfo;
290b57cec5SDimitry Andric class TargetRegisterInfo;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   class LLVM_LIBRARY_VISIBILITY BranchFolder {
320b57cec5SDimitry Andric   public:
33e8d8bef9SDimitry Andric     explicit BranchFolder(bool DefaultEnableTailMerge, bool CommonHoist,
340b57cec5SDimitry Andric                           MBFIWrapper &FreqInfo,
350b57cec5SDimitry Andric                           const MachineBranchProbabilityInfo &ProbInfo,
36480093f4SDimitry Andric                           ProfileSummaryInfo *PSI,
370b57cec5SDimitry Andric                           // Min tail length to merge. Defaults to commandline
380b57cec5SDimitry Andric                           // flag. Ignored for optsize.
390b57cec5SDimitry Andric                           unsigned MinTailLength = 0);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric     /// Perhaps branch folding, tail merging and other CFG optimizations on the
420b57cec5SDimitry Andric     /// given function.  Block placement changes the layout and may create new
430b57cec5SDimitry Andric     /// tail merging opportunities.
440b57cec5SDimitry Andric     bool OptimizeFunction(MachineFunction &MF, const TargetInstrInfo *tii,
455ffd83dbSDimitry Andric                           const TargetRegisterInfo *tri,
460b57cec5SDimitry Andric                           MachineLoopInfo *mli = nullptr,
470b57cec5SDimitry Andric                           bool AfterPlacement = false);
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   private:
500b57cec5SDimitry Andric     class MergePotentialsElt {
510b57cec5SDimitry Andric       unsigned Hash;
520b57cec5SDimitry Andric       MachineBasicBlock *Block;
53*0fca6ea1SDimitry Andric       DebugLoc BranchDebugLoc;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric     public:
MergePotentialsElt(unsigned h,MachineBasicBlock * b,DebugLoc bdl)56*0fca6ea1SDimitry Andric       MergePotentialsElt(unsigned h, MachineBasicBlock *b, DebugLoc bdl)
57*0fca6ea1SDimitry Andric           : Hash(h), Block(b), BranchDebugLoc(std::move(bdl)) {}
580b57cec5SDimitry Andric 
getHash()590b57cec5SDimitry Andric       unsigned getHash() const { return Hash; }
getBlock()600b57cec5SDimitry Andric       MachineBasicBlock *getBlock() const { return Block; }
610b57cec5SDimitry Andric 
setBlock(MachineBasicBlock * MBB)620b57cec5SDimitry Andric       void setBlock(MachineBasicBlock *MBB) {
630b57cec5SDimitry Andric         Block = MBB;
640b57cec5SDimitry Andric       }
650b57cec5SDimitry Andric 
getBranchDebugLoc()66*0fca6ea1SDimitry Andric       const DebugLoc &getBranchDebugLoc() { return BranchDebugLoc; }
67*0fca6ea1SDimitry Andric 
680b57cec5SDimitry Andric       bool operator<(const MergePotentialsElt &) const;
690b57cec5SDimitry Andric     };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric     using MPIterator = std::vector<MergePotentialsElt>::iterator;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric     std::vector<MergePotentialsElt> MergePotentials;
740b57cec5SDimitry Andric     SmallPtrSet<const MachineBasicBlock*, 2> TriedMerging;
750b57cec5SDimitry Andric     DenseMap<const MachineBasicBlock *, int> EHScopeMembership;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric     class SameTailElt {
780b57cec5SDimitry Andric       MPIterator MPIter;
790b57cec5SDimitry Andric       MachineBasicBlock::iterator TailStartPos;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     public:
SameTailElt(MPIterator mp,MachineBasicBlock::iterator tsp)820b57cec5SDimitry Andric       SameTailElt(MPIterator mp, MachineBasicBlock::iterator tsp)
830b57cec5SDimitry Andric         : MPIter(mp), TailStartPos(tsp) {}
840b57cec5SDimitry Andric 
getMPIter()850b57cec5SDimitry Andric       MPIterator getMPIter() const {
860b57cec5SDimitry Andric         return MPIter;
870b57cec5SDimitry Andric       }
880b57cec5SDimitry Andric 
getMergePotentialsElt()890b57cec5SDimitry Andric       MergePotentialsElt &getMergePotentialsElt() const {
900b57cec5SDimitry Andric         return *getMPIter();
910b57cec5SDimitry Andric       }
920b57cec5SDimitry Andric 
getTailStartPos()930b57cec5SDimitry Andric       MachineBasicBlock::iterator getTailStartPos() const {
940b57cec5SDimitry Andric         return TailStartPos;
950b57cec5SDimitry Andric       }
960b57cec5SDimitry Andric 
getHash()970b57cec5SDimitry Andric       unsigned getHash() const {
980b57cec5SDimitry Andric         return getMergePotentialsElt().getHash();
990b57cec5SDimitry Andric       }
1000b57cec5SDimitry Andric 
getBlock()1010b57cec5SDimitry Andric       MachineBasicBlock *getBlock() const {
1020b57cec5SDimitry Andric         return getMergePotentialsElt().getBlock();
1030b57cec5SDimitry Andric       }
1040b57cec5SDimitry Andric 
tailIsWholeBlock()1050b57cec5SDimitry Andric       bool tailIsWholeBlock() const {
1060b57cec5SDimitry Andric         return TailStartPos == getBlock()->begin();
1070b57cec5SDimitry Andric       }
1080b57cec5SDimitry Andric 
setBlock(MachineBasicBlock * MBB)1090b57cec5SDimitry Andric       void setBlock(MachineBasicBlock *MBB) {
1100b57cec5SDimitry Andric         getMergePotentialsElt().setBlock(MBB);
1110b57cec5SDimitry Andric       }
1120b57cec5SDimitry Andric 
setTailStartPos(MachineBasicBlock::iterator Pos)1130b57cec5SDimitry Andric       void setTailStartPos(MachineBasicBlock::iterator Pos) {
1140b57cec5SDimitry Andric         TailStartPos = Pos;
1150b57cec5SDimitry Andric       }
1160b57cec5SDimitry Andric     };
1170b57cec5SDimitry Andric     std::vector<SameTailElt> SameTails;
1180b57cec5SDimitry Andric 
11906c3fb27SDimitry Andric     bool AfterBlockPlacement = false;
12006c3fb27SDimitry Andric     bool EnableTailMerge = false;
12106c3fb27SDimitry Andric     bool EnableHoistCommonCode = false;
12206c3fb27SDimitry Andric     bool UpdateLiveIns = false;
1230b57cec5SDimitry Andric     unsigned MinCommonTailLength;
12406c3fb27SDimitry Andric     const TargetInstrInfo *TII = nullptr;
12506c3fb27SDimitry Andric     const MachineRegisterInfo *MRI = nullptr;
12606c3fb27SDimitry Andric     const TargetRegisterInfo *TRI = nullptr;
12706c3fb27SDimitry Andric     MachineLoopInfo *MLI = nullptr;
1280b57cec5SDimitry Andric     LivePhysRegs LiveRegs;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   private:
1310b57cec5SDimitry Andric     MBFIWrapper &MBBFreqInfo;
1320b57cec5SDimitry Andric     const MachineBranchProbabilityInfo &MBPI;
133480093f4SDimitry Andric     ProfileSummaryInfo *PSI;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     bool TailMergeBlocks(MachineFunction &MF);
1360b57cec5SDimitry Andric     bool TryTailMergeBlocks(MachineBasicBlock* SuccBB,
1370b57cec5SDimitry Andric                        MachineBasicBlock* PredBB,
1380b57cec5SDimitry Andric                        unsigned MinCommonTailLength);
1390b57cec5SDimitry Andric     void setCommonTailEdgeWeights(MachineBasicBlock &TailMBB);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     /// Delete the instruction OldInst and everything after it, replacing it
1420b57cec5SDimitry Andric     /// with an unconditional branch to NewDest.
1430b57cec5SDimitry Andric     void replaceTailWithBranchTo(MachineBasicBlock::iterator OldInst,
1440b57cec5SDimitry Andric                                  MachineBasicBlock &NewDest);
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric     /// Given a machine basic block and an iterator into it, split the MBB so
1470b57cec5SDimitry Andric     /// that the part before the iterator falls into the part starting at the
1480b57cec5SDimitry Andric     /// iterator.  This returns the new MBB.
1490b57cec5SDimitry Andric     MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB,
1500b57cec5SDimitry Andric                                   MachineBasicBlock::iterator BBI1,
1510b57cec5SDimitry Andric                                   const BasicBlock *BB);
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric     /// Look through all the blocks in MergePotentials that have hash CurHash
1540b57cec5SDimitry Andric     /// (guaranteed to match the last element).  Build the vector SameTails of
1550b57cec5SDimitry Andric     /// all those that have the (same) largest number of instructions in common
1560b57cec5SDimitry Andric     /// of any pair of these blocks.  SameTails entries contain an iterator into
1570b57cec5SDimitry Andric     /// MergePotentials (from which the MachineBasicBlock can be found) and a
1580b57cec5SDimitry Andric     /// MachineBasicBlock::iterator into that MBB indicating the instruction
1590b57cec5SDimitry Andric     /// where the matching code sequence begins.  Order of elements in SameTails
1600b57cec5SDimitry Andric     /// is the reverse of the order in which those blocks appear in
1610b57cec5SDimitry Andric     /// MergePotentials (where they are not necessarily consecutive).
1620b57cec5SDimitry Andric     unsigned ComputeSameTails(unsigned CurHash, unsigned minCommonTailLength,
1630b57cec5SDimitry Andric                               MachineBasicBlock *SuccBB,
1640b57cec5SDimitry Andric                               MachineBasicBlock *PredBB);
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     /// Remove all blocks with hash CurHash from MergePotentials, restoring
1670b57cec5SDimitry Andric     /// branches at ends of blocks as appropriate.
1680b57cec5SDimitry Andric     void RemoveBlocksWithHash(unsigned CurHash, MachineBasicBlock *SuccBB,
169*0fca6ea1SDimitry Andric                               MachineBasicBlock *PredBB,
170*0fca6ea1SDimitry Andric                               const DebugLoc &BranchDL);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric     /// None of the blocks to be tail-merged consist only of the common tail.
1730b57cec5SDimitry Andric     /// Create a block that does by splitting one.
1740b57cec5SDimitry Andric     bool CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
1750b57cec5SDimitry Andric                                    MachineBasicBlock *SuccBB,
1760b57cec5SDimitry Andric                                    unsigned maxCommonTailLength,
1770b57cec5SDimitry Andric                                    unsigned &commonTailIndex);
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric     /// Create merged DebugLocs of identical instructions across SameTails and
1800b57cec5SDimitry Andric     /// assign it to the instruction in common tail; merge MMOs and undef flags.
1810b57cec5SDimitry Andric     void mergeCommonTails(unsigned commonTailIndex);
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric     bool OptimizeBranches(MachineFunction &MF);
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     /// Analyze and optimize control flow related to the specified block. This
1860b57cec5SDimitry Andric     /// is never called on the entry block.
1870b57cec5SDimitry Andric     bool OptimizeBlock(MachineBasicBlock *MBB);
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric     /// Remove the specified dead machine basic block from the function,
1900b57cec5SDimitry Andric     /// updating the CFG.
1910b57cec5SDimitry Andric     void RemoveDeadBlock(MachineBasicBlock *MBB);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric     /// Hoist common instruction sequences at the start of basic blocks to their
1940b57cec5SDimitry Andric     /// common predecessor.
1950b57cec5SDimitry Andric     bool HoistCommonCode(MachineFunction &MF);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     /// If the successors of MBB has common instruction sequence at the start of
1980b57cec5SDimitry Andric     /// the function, move the instructions before MBB terminator if it's legal.
1990b57cec5SDimitry Andric     bool HoistCommonCodeInSuccs(MachineBasicBlock *MBB);
2000b57cec5SDimitry Andric   };
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric } // end namespace llvm
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_BRANCHFOLDING_H
205