xref: /llvm-project/llvm/lib/Target/AMDGPU/R600MachineCFGStructurizer.cpp (revision 63fae3ed656241a1d6a19c3e773ecc9bfff3e182)
157baa14dSJay Foad //===- R600MachineCFGStructurizer.cpp - CFG Structurizer ------------------===//
257baa14dSJay Foad //
357baa14dSJay Foad // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457baa14dSJay Foad // See https://llvm.org/LICENSE.txt for license information.
557baa14dSJay Foad // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
657baa14dSJay Foad //
757baa14dSJay Foad //==-----------------------------------------------------------------------===//
857baa14dSJay Foad 
957baa14dSJay Foad #include "MCTargetDesc/R600MCTargetDesc.h"
1057baa14dSJay Foad #include "R600.h"
1157baa14dSJay Foad #include "R600RegisterInfo.h"
1257baa14dSJay Foad #include "R600Subtarget.h"
13989f1c72Sserge-sans-paille #include "llvm/ADT/DepthFirstIterator.h"
1457baa14dSJay Foad #include "llvm/ADT/SCCIterator.h"
1557baa14dSJay Foad #include "llvm/ADT/Statistic.h"
1657baa14dSJay Foad #include "llvm/CodeGen/MachineFunction.h"
1757baa14dSJay Foad #include "llvm/CodeGen/MachineFunctionPass.h"
1857baa14dSJay Foad #include "llvm/CodeGen/MachineJumpTableInfo.h"
1957baa14dSJay Foad #include "llvm/CodeGen/MachineLoopInfo.h"
2057baa14dSJay Foad #include "llvm/CodeGen/MachinePostDominators.h"
2157baa14dSJay Foad #include "llvm/InitializePasses.h"
2257baa14dSJay Foad 
2357baa14dSJay Foad using namespace llvm;
2457baa14dSJay Foad 
2557baa14dSJay Foad #define DEBUG_TYPE "structcfg"
2657baa14dSJay Foad 
270b43d573SJay Foad enum { DEFAULT_VEC_SLOTS = 8 };
2857baa14dSJay Foad 
2957baa14dSJay Foad // TODO: move-begin.
3057baa14dSJay Foad 
3157baa14dSJay Foad //===----------------------------------------------------------------------===//
3257baa14dSJay Foad //
3357baa14dSJay Foad // Statistics for CFGStructurizer.
3457baa14dSJay Foad //
3557baa14dSJay Foad //===----------------------------------------------------------------------===//
3657baa14dSJay Foad 
3757baa14dSJay Foad STATISTIC(numSerialPatternMatch,    "CFGStructurizer number of serial pattern "
3857baa14dSJay Foad     "matched");
3957baa14dSJay Foad STATISTIC(numIfPatternMatch,        "CFGStructurizer number of if pattern "
4057baa14dSJay Foad     "matched");
4157baa14dSJay Foad STATISTIC(numClonedBlock,           "CFGStructurizer cloned blocks");
4257baa14dSJay Foad STATISTIC(numClonedInstr,           "CFGStructurizer cloned instructions");
4357baa14dSJay Foad 
4457baa14dSJay Foad namespace llvm {
4557baa14dSJay Foad 
4657baa14dSJay Foad void initializeR600MachineCFGStructurizerPass(PassRegistry &);
4757baa14dSJay Foad 
4857baa14dSJay Foad } // end namespace llvm
4957baa14dSJay Foad 
5057baa14dSJay Foad namespace {
5157baa14dSJay Foad 
5257baa14dSJay Foad //===----------------------------------------------------------------------===//
5357baa14dSJay Foad //
5457baa14dSJay Foad // Miscellaneous utility for CFGStructurizer.
5557baa14dSJay Foad //
5657baa14dSJay Foad //===----------------------------------------------------------------------===//
5757baa14dSJay Foad 
5857baa14dSJay Foad #define SHOWNEWINSTR(i) LLVM_DEBUG(dbgs() << "New instr: " << *i << "\n");
5957baa14dSJay Foad 
6057baa14dSJay Foad #define SHOWNEWBLK(b, msg)                                                     \
6157baa14dSJay Foad   LLVM_DEBUG(dbgs() << msg << "BB" << b->getNumber() << "size " << b->size();  \
6257baa14dSJay Foad              dbgs() << "\n";);
6357baa14dSJay Foad 
6457baa14dSJay Foad #define SHOWBLK_DETAIL(b, msg)                                                 \
6557baa14dSJay Foad   LLVM_DEBUG(if (b) {                                                          \
6657baa14dSJay Foad     dbgs() << msg << "BB" << b->getNumber() << "size " << b->size();           \
6757baa14dSJay Foad     b->print(dbgs());                                                          \
6857baa14dSJay Foad     dbgs() << "\n";                                                            \
6957baa14dSJay Foad   });
7057baa14dSJay Foad 
7157baa14dSJay Foad #define INVALIDSCCNUM -1
7257baa14dSJay Foad 
7357baa14dSJay Foad //===----------------------------------------------------------------------===//
7457baa14dSJay Foad //
7557baa14dSJay Foad // supporting data structure for CFGStructurizer
7657baa14dSJay Foad //
7757baa14dSJay Foad //===----------------------------------------------------------------------===//
7857baa14dSJay Foad 
7957baa14dSJay Foad class BlockInformation {
8057baa14dSJay Foad public:
8157baa14dSJay Foad   bool IsRetired = false;
8257baa14dSJay Foad   int SccNum = INVALIDSCCNUM;
8357baa14dSJay Foad 
8457baa14dSJay Foad   BlockInformation() = default;
8557baa14dSJay Foad };
8657baa14dSJay Foad 
8757baa14dSJay Foad //===----------------------------------------------------------------------===//
8857baa14dSJay Foad //
8957baa14dSJay Foad // CFGStructurizer
9057baa14dSJay Foad //
9157baa14dSJay Foad //===----------------------------------------------------------------------===//
9257baa14dSJay Foad 
9357baa14dSJay Foad class R600MachineCFGStructurizer : public MachineFunctionPass {
9457baa14dSJay Foad public:
9557baa14dSJay Foad   using MBBVector = SmallVector<MachineBasicBlock *, 32>;
9657baa14dSJay Foad   using MBBInfoMap = std::map<MachineBasicBlock *, BlockInformation *>;
9757baa14dSJay Foad   using LoopLandInfoMap = std::map<MachineLoop *, MachineBasicBlock *>;
9857baa14dSJay Foad 
9957baa14dSJay Foad   enum PathToKind {
10057baa14dSJay Foad     Not_SinglePath = 0,
10157baa14dSJay Foad     SinglePath_InPath = 1,
10257baa14dSJay Foad     SinglePath_NotInPath = 2
10357baa14dSJay Foad   };
10457baa14dSJay Foad 
10557baa14dSJay Foad   static char ID;
10657baa14dSJay Foad 
10757baa14dSJay Foad   R600MachineCFGStructurizer() : MachineFunctionPass(ID) {
10857baa14dSJay Foad     initializeR600MachineCFGStructurizerPass(*PassRegistry::getPassRegistry());
10957baa14dSJay Foad   }
11057baa14dSJay Foad 
11157baa14dSJay Foad   StringRef getPassName() const override {
11257baa14dSJay Foad     return "AMDGPU Control Flow Graph structurizer Pass";
11357baa14dSJay Foad   }
11457baa14dSJay Foad 
11557baa14dSJay Foad   void getAnalysisUsage(AnalysisUsage &AU) const override {
116837dc542Spaperchalice     AU.addRequired<MachineDominatorTreeWrapperPass>();
1174b24c2dfSpaperchalice     AU.addRequired<MachinePostDominatorTreeWrapperPass>();
11879d0de2aSpaperchalice     AU.addRequired<MachineLoopInfoWrapperPass>();
11957baa14dSJay Foad     MachineFunctionPass::getAnalysisUsage(AU);
12057baa14dSJay Foad   }
12157baa14dSJay Foad 
12257baa14dSJay Foad   /// Perform the CFG structurization
12357baa14dSJay Foad   bool run();
12457baa14dSJay Foad 
12557baa14dSJay Foad   /// Perform the CFG preparation
12657baa14dSJay Foad   /// This step will remove every unconditionnal/dead jump instructions and make
12757baa14dSJay Foad   /// sure all loops have an exit block
12857baa14dSJay Foad   bool prepare();
12957baa14dSJay Foad 
13057baa14dSJay Foad   bool runOnMachineFunction(MachineFunction &MF) override {
13157baa14dSJay Foad     // FIXME: This pass causes verification failures.
13257baa14dSJay Foad     MF.getProperties().set(
13357baa14dSJay Foad         MachineFunctionProperties::Property::FailsVerification);
13457baa14dSJay Foad 
13557baa14dSJay Foad     TII = MF.getSubtarget<R600Subtarget>().getInstrInfo();
13657baa14dSJay Foad     TRI = &TII->getRegisterInfo();
13757baa14dSJay Foad     LLVM_DEBUG(MF.dump(););
13857baa14dSJay Foad     OrderedBlks.clear();
13957baa14dSJay Foad     Visited.clear();
14057baa14dSJay Foad     FuncRep = &MF;
14179d0de2aSpaperchalice     MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
14257baa14dSJay Foad     LLVM_DEBUG(dbgs() << "LoopInfo:\n"; PrintLoopinfo(*MLI););
143837dc542Spaperchalice     MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
144837dc542Spaperchalice     LLVM_DEBUG(MDT->print(dbgs()););
1454b24c2dfSpaperchalice     PDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
14657baa14dSJay Foad     LLVM_DEBUG(PDT->print(dbgs()););
14757baa14dSJay Foad     prepare();
14857baa14dSJay Foad     run();
14957baa14dSJay Foad     LLVM_DEBUG(MF.dump(););
15057baa14dSJay Foad     return true;
15157baa14dSJay Foad   }
15257baa14dSJay Foad 
15357baa14dSJay Foad protected:
15457baa14dSJay Foad   MachineDominatorTree *MDT;
15557baa14dSJay Foad   MachinePostDominatorTree *PDT;
15657baa14dSJay Foad   MachineLoopInfo *MLI;
15757baa14dSJay Foad   const R600InstrInfo *TII = nullptr;
15857baa14dSJay Foad   const R600RegisterInfo *TRI = nullptr;
15957baa14dSJay Foad 
16057baa14dSJay Foad   // PRINT FUNCTIONS
16157baa14dSJay Foad   /// Print the ordered Blocks.
16257baa14dSJay Foad   void printOrderedBlocks() const {
16357baa14dSJay Foad     size_t i = 0;
16457baa14dSJay Foad     for (MBBVector::const_iterator iterBlk = OrderedBlks.begin(),
16557baa14dSJay Foad         iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
16657baa14dSJay Foad       dbgs() << "BB" << (*iterBlk)->getNumber();
16757baa14dSJay Foad       dbgs() << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
16857baa14dSJay Foad       if (i != 0 && i % 10 == 0) {
16957baa14dSJay Foad         dbgs() << "\n";
17057baa14dSJay Foad       } else {
17157baa14dSJay Foad         dbgs() << " ";
17257baa14dSJay Foad       }
17357baa14dSJay Foad     }
17457baa14dSJay Foad   }
17557baa14dSJay Foad 
17657baa14dSJay Foad   static void PrintLoopinfo(const MachineLoopInfo &LoopInfo) {
17757baa14dSJay Foad     for (const MachineLoop *L : LoopInfo)
17857baa14dSJay Foad       L->print(dbgs());
17957baa14dSJay Foad   }
18057baa14dSJay Foad 
18157baa14dSJay Foad   // UTILITY FUNCTIONS
18257baa14dSJay Foad   int getSCCNum(MachineBasicBlock *MBB) const;
18357baa14dSJay Foad   MachineBasicBlock *getLoopLandInfo(MachineLoop *LoopRep) const;
18457baa14dSJay Foad   bool hasBackEdge(MachineBasicBlock *MBB) const;
18557baa14dSJay Foad   bool isRetiredBlock(MachineBasicBlock *MBB) const;
18657baa14dSJay Foad   bool isActiveLoophead(MachineBasicBlock *MBB) const;
18757baa14dSJay Foad   PathToKind singlePathTo(MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
18857baa14dSJay Foad       bool AllowSideEntry = true) const;
18957baa14dSJay Foad   int countActiveBlock(MBBVector::const_iterator It,
19057baa14dSJay Foad       MBBVector::const_iterator E) const;
19157baa14dSJay Foad   bool needMigrateBlock(MachineBasicBlock *MBB) const;
19257baa14dSJay Foad 
19357baa14dSJay Foad   // Utility Functions
19457baa14dSJay Foad   void reversePredicateSetter(MachineBasicBlock::iterator I,
19557baa14dSJay Foad                               MachineBasicBlock &MBB);
19657baa14dSJay Foad   /// Compute the reversed DFS post order of Blocks
19757baa14dSJay Foad   void orderBlocks(MachineFunction *MF);
19857baa14dSJay Foad 
19957baa14dSJay Foad   // Function originally from CFGStructTraits
20057baa14dSJay Foad   void insertInstrEnd(MachineBasicBlock *MBB, int NewOpcode,
20157baa14dSJay Foad                       const DebugLoc &DL = DebugLoc());
20257baa14dSJay Foad   MachineInstr *insertInstrBefore(MachineBasicBlock *MBB, int NewOpcode,
20357baa14dSJay Foad                                   const DebugLoc &DL = DebugLoc());
20457baa14dSJay Foad   MachineInstr *insertInstrBefore(MachineBasicBlock::iterator I, int NewOpcode);
20557baa14dSJay Foad   void insertCondBranchBefore(MachineBasicBlock::iterator I, int NewOpcode,
20657baa14dSJay Foad                               const DebugLoc &DL);
20757baa14dSJay Foad   void insertCondBranchBefore(MachineBasicBlock *MBB,
20857baa14dSJay Foad                               MachineBasicBlock::iterator I, int NewOpcode,
20957baa14dSJay Foad                               int RegNum, const DebugLoc &DL);
21057baa14dSJay Foad 
21157baa14dSJay Foad   static int getBranchNzeroOpcode(int OldOpcode);
21257baa14dSJay Foad   static int getBranchZeroOpcode(int OldOpcode);
21357baa14dSJay Foad   static int getContinueNzeroOpcode(int OldOpcode);
21457baa14dSJay Foad   static int getContinueZeroOpcode(int OldOpcode);
21557baa14dSJay Foad   static MachineBasicBlock *getTrueBranch(MachineInstr *MI);
21657baa14dSJay Foad   static void setTrueBranch(MachineInstr *MI, MachineBasicBlock *MBB);
21757baa14dSJay Foad   static MachineBasicBlock *getFalseBranch(MachineBasicBlock *MBB,
21857baa14dSJay Foad       MachineInstr *MI);
21957baa14dSJay Foad   static bool isCondBranch(MachineInstr *MI);
22057baa14dSJay Foad   static bool isUncondBranch(MachineInstr *MI);
22157baa14dSJay Foad   static DebugLoc getLastDebugLocInBB(MachineBasicBlock *MBB);
22257baa14dSJay Foad   static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *MBB);
22357baa14dSJay Foad 
22457baa14dSJay Foad   /// The correct naming for this is getPossibleLoopendBlockBranchInstr.
22557baa14dSJay Foad   ///
22657baa14dSJay Foad   /// BB with backward-edge could have move instructions after the branch
22757baa14dSJay Foad   /// instruction.  Such move instruction "belong to" the loop backward-edge.
22857baa14dSJay Foad   MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *MBB);
22957baa14dSJay Foad 
23057baa14dSJay Foad   static MachineInstr *getReturnInstr(MachineBasicBlock *MBB);
23157baa14dSJay Foad   static bool isReturnBlock(MachineBasicBlock *MBB);
23257baa14dSJay Foad   static void cloneSuccessorList(MachineBasicBlock *DstMBB,
23357baa14dSJay Foad       MachineBasicBlock *SrcMBB);
23457baa14dSJay Foad   static MachineBasicBlock *clone(MachineBasicBlock *MBB);
23557baa14dSJay Foad 
23657baa14dSJay Foad   /// MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose
23757baa14dSJay Foad   /// because the AMDGPU instruction is not recognized as terminator fix this
23857baa14dSJay Foad   /// and retire this routine
23957baa14dSJay Foad   void replaceInstrUseOfBlockWith(MachineBasicBlock *SrcMBB,
24057baa14dSJay Foad       MachineBasicBlock *OldMBB, MachineBasicBlock *NewBlk);
24157baa14dSJay Foad 
24257baa14dSJay Foad   static void wrapup(MachineBasicBlock *MBB);
24357baa14dSJay Foad 
24457baa14dSJay Foad   int patternMatch(MachineBasicBlock *MBB);
24557baa14dSJay Foad   int patternMatchGroup(MachineBasicBlock *MBB);
24657baa14dSJay Foad   int serialPatternMatch(MachineBasicBlock *MBB);
24757baa14dSJay Foad   int ifPatternMatch(MachineBasicBlock *MBB);
24857baa14dSJay Foad   int loopendPatternMatch();
24957baa14dSJay Foad   int mergeLoop(MachineLoop *LoopRep);
25057baa14dSJay Foad 
25157baa14dSJay Foad   /// return true iff src1Blk->succ_empty() && src1Blk and src2Blk are in
25257baa14dSJay Foad   /// the same loop with LoopLandInfo without explicitly keeping track of
25357baa14dSJay Foad   /// loopContBlks and loopBreakBlks, this is a method to get the information.
25457baa14dSJay Foad   bool isSameloopDetachedContbreak(MachineBasicBlock *Src1MBB,
25557baa14dSJay Foad       MachineBasicBlock *Src2MBB);
25657baa14dSJay Foad   int handleJumpintoIf(MachineBasicBlock *HeadMBB,
25757baa14dSJay Foad       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
25857baa14dSJay Foad   int handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
25957baa14dSJay Foad       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
26057baa14dSJay Foad   int improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
26157baa14dSJay Foad       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
26257baa14dSJay Foad       MachineBasicBlock **LandMBBPtr);
26357baa14dSJay Foad   void showImproveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
26457baa14dSJay Foad       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
26557baa14dSJay Foad       MachineBasicBlock *LandMBB, bool Detail = false);
26657baa14dSJay Foad   int cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
26757baa14dSJay Foad       MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB);
26857baa14dSJay Foad   void mergeSerialBlock(MachineBasicBlock *DstMBB,
26957baa14dSJay Foad       MachineBasicBlock *SrcMBB);
27057baa14dSJay Foad 
27157baa14dSJay Foad   void mergeIfthenelseBlock(MachineInstr *BranchMI,
27257baa14dSJay Foad       MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
27357baa14dSJay Foad       MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB);
27457baa14dSJay Foad   void mergeLooplandBlock(MachineBasicBlock *DstMBB,
27557baa14dSJay Foad       MachineBasicBlock *LandMBB);
27657baa14dSJay Foad   void mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
27757baa14dSJay Foad       MachineBasicBlock *LandMBB);
27857baa14dSJay Foad   void settleLoopcontBlock(MachineBasicBlock *ContingMBB,
27957baa14dSJay Foad       MachineBasicBlock *ContMBB);
28057baa14dSJay Foad 
28157baa14dSJay Foad   /// normalizeInfiniteLoopExit change
28257baa14dSJay Foad   ///   B1:
28357baa14dSJay Foad   ///        uncond_br LoopHeader
28457baa14dSJay Foad   ///
28557baa14dSJay Foad   /// to
28657baa14dSJay Foad   ///   B1:
28757baa14dSJay Foad   ///        cond_br 1 LoopHeader dummyExit
28857baa14dSJay Foad   /// and return the newly added dummy exit block
28957baa14dSJay Foad   MachineBasicBlock *normalizeInfiniteLoopExit(MachineLoop *LoopRep);
29057baa14dSJay Foad   void removeUnconditionalBranch(MachineBasicBlock *MBB);
29157baa14dSJay Foad 
29257baa14dSJay Foad   /// Remove duplicate branches instructions in a block.
29357baa14dSJay Foad   /// For instance
29457baa14dSJay Foad   /// B0:
29557baa14dSJay Foad   ///    cond_br X B1 B2
29657baa14dSJay Foad   ///    cond_br X B1 B2
29757baa14dSJay Foad   /// is transformed to
29857baa14dSJay Foad   /// B0:
29957baa14dSJay Foad   ///    cond_br X B1 B2
30057baa14dSJay Foad   void removeRedundantConditionalBranch(MachineBasicBlock *MBB);
30157baa14dSJay Foad 
30257baa14dSJay Foad   void addDummyExitBlock(SmallVectorImpl<MachineBasicBlock *> &RetMBB);
30357baa14dSJay Foad   void removeSuccessor(MachineBasicBlock *MBB);
30457baa14dSJay Foad   MachineBasicBlock *cloneBlockForPredecessor(MachineBasicBlock *MBB,
30557baa14dSJay Foad       MachineBasicBlock *PredMBB);
30657baa14dSJay Foad   void migrateInstruction(MachineBasicBlock *SrcMBB,
30757baa14dSJay Foad       MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I);
30857baa14dSJay Foad   void recordSccnum(MachineBasicBlock *MBB, int SCCNum);
30957baa14dSJay Foad   void retireBlock(MachineBasicBlock *MBB);
31057baa14dSJay Foad 
31157baa14dSJay Foad private:
31257baa14dSJay Foad   MBBInfoMap BlockInfoMap;
31357baa14dSJay Foad   LoopLandInfoMap LLInfoMap;
31457baa14dSJay Foad   std::map<MachineLoop *, bool> Visited;
31557baa14dSJay Foad   MachineFunction *FuncRep;
31657baa14dSJay Foad   SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> OrderedBlks;
31757baa14dSJay Foad };
31857baa14dSJay Foad 
31957baa14dSJay Foad } // end anonymous namespace
32057baa14dSJay Foad 
32157baa14dSJay Foad char R600MachineCFGStructurizer::ID = 0;
32257baa14dSJay Foad 
32357baa14dSJay Foad int R600MachineCFGStructurizer::getSCCNum(MachineBasicBlock *MBB) const {
32457baa14dSJay Foad   MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
32557baa14dSJay Foad   if (It == BlockInfoMap.end())
32657baa14dSJay Foad     return INVALIDSCCNUM;
32757baa14dSJay Foad   return (*It).second->SccNum;
32857baa14dSJay Foad }
32957baa14dSJay Foad 
33057baa14dSJay Foad MachineBasicBlock *R600MachineCFGStructurizer::getLoopLandInfo(MachineLoop *LoopRep)
33157baa14dSJay Foad     const {
33257baa14dSJay Foad   LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
33357baa14dSJay Foad   if (It == LLInfoMap.end())
33457baa14dSJay Foad     return nullptr;
33557baa14dSJay Foad   return (*It).second;
33657baa14dSJay Foad }
33757baa14dSJay Foad 
33857baa14dSJay Foad bool R600MachineCFGStructurizer::hasBackEdge(MachineBasicBlock *MBB) const {
33957baa14dSJay Foad   MachineLoop *LoopRep = MLI->getLoopFor(MBB);
34057baa14dSJay Foad   if (!LoopRep)
34157baa14dSJay Foad     return false;
34257baa14dSJay Foad   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
34357baa14dSJay Foad   return MBB->isSuccessor(LoopHeader);
34457baa14dSJay Foad }
34557baa14dSJay Foad 
34657baa14dSJay Foad bool R600MachineCFGStructurizer::isRetiredBlock(MachineBasicBlock *MBB) const {
34757baa14dSJay Foad   MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
34857baa14dSJay Foad   if (It == BlockInfoMap.end())
34957baa14dSJay Foad     return false;
35057baa14dSJay Foad   return (*It).second->IsRetired;
35157baa14dSJay Foad }
35257baa14dSJay Foad 
35357baa14dSJay Foad bool R600MachineCFGStructurizer::isActiveLoophead(MachineBasicBlock *MBB) const {
35457baa14dSJay Foad   MachineLoop *LoopRep = MLI->getLoopFor(MBB);
35557baa14dSJay Foad   while (LoopRep && LoopRep->getHeader() == MBB) {
35657baa14dSJay Foad     MachineBasicBlock *LoopLand = getLoopLandInfo(LoopRep);
35757baa14dSJay Foad     if(!LoopLand)
35857baa14dSJay Foad       return true;
35957baa14dSJay Foad     if (!isRetiredBlock(LoopLand))
36057baa14dSJay Foad       return true;
36157baa14dSJay Foad     LoopRep = LoopRep->getParentLoop();
36257baa14dSJay Foad   }
36357baa14dSJay Foad   return false;
36457baa14dSJay Foad }
36557baa14dSJay Foad 
36657baa14dSJay Foad R600MachineCFGStructurizer::PathToKind R600MachineCFGStructurizer::singlePathTo(
36757baa14dSJay Foad     MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
36857baa14dSJay Foad     bool AllowSideEntry) const {
36957baa14dSJay Foad   assert(DstMBB);
37057baa14dSJay Foad   if (SrcMBB == DstMBB)
37157baa14dSJay Foad     return SinglePath_InPath;
37257baa14dSJay Foad   while (SrcMBB && SrcMBB->succ_size() == 1) {
37357baa14dSJay Foad     SrcMBB = *SrcMBB->succ_begin();
37457baa14dSJay Foad     if (SrcMBB == DstMBB)
37557baa14dSJay Foad       return SinglePath_InPath;
37657baa14dSJay Foad     if (!AllowSideEntry && SrcMBB->pred_size() > 1)
37757baa14dSJay Foad       return Not_SinglePath;
37857baa14dSJay Foad   }
37957baa14dSJay Foad   if (SrcMBB && SrcMBB->succ_size()==0)
38057baa14dSJay Foad     return SinglePath_NotInPath;
38157baa14dSJay Foad   return Not_SinglePath;
38257baa14dSJay Foad }
38357baa14dSJay Foad 
38457baa14dSJay Foad int R600MachineCFGStructurizer::countActiveBlock(MBBVector::const_iterator It,
38557baa14dSJay Foad     MBBVector::const_iterator E) const {
38657baa14dSJay Foad   int Count = 0;
38757baa14dSJay Foad   while (It != E) {
38857baa14dSJay Foad     if (!isRetiredBlock(*It))
38957baa14dSJay Foad       ++Count;
39057baa14dSJay Foad     ++It;
39157baa14dSJay Foad   }
39257baa14dSJay Foad   return Count;
39357baa14dSJay Foad }
39457baa14dSJay Foad 
39557baa14dSJay Foad bool R600MachineCFGStructurizer::needMigrateBlock(MachineBasicBlock *MBB) const {
39657baa14dSJay Foad   unsigned BlockSizeThreshold = 30;
39757baa14dSJay Foad   unsigned CloneInstrThreshold = 100;
39857baa14dSJay Foad   bool MultiplePreds = MBB && (MBB->pred_size() > 1);
39957baa14dSJay Foad 
40057baa14dSJay Foad   if(!MultiplePreds)
40157baa14dSJay Foad     return false;
40257baa14dSJay Foad   unsigned BlkSize = MBB->size();
40357baa14dSJay Foad   return ((BlkSize > BlockSizeThreshold) &&
40457baa14dSJay Foad       (BlkSize * (MBB->pred_size() - 1) > CloneInstrThreshold));
40557baa14dSJay Foad }
40657baa14dSJay Foad 
40757baa14dSJay Foad void R600MachineCFGStructurizer::reversePredicateSetter(
40857baa14dSJay Foad     MachineBasicBlock::iterator I, MachineBasicBlock &MBB) {
40957baa14dSJay Foad   assert(I.isValid() && "Expected valid iterator");
41057baa14dSJay Foad   for (;; --I) {
41157baa14dSJay Foad     if (I == MBB.end())
41257baa14dSJay Foad       continue;
41357baa14dSJay Foad     if (I->getOpcode() == R600::PRED_X) {
41457baa14dSJay Foad       switch (I->getOperand(2).getImm()) {
41557baa14dSJay Foad       case R600::PRED_SETE_INT:
41657baa14dSJay Foad         I->getOperand(2).setImm(R600::PRED_SETNE_INT);
41757baa14dSJay Foad         return;
41857baa14dSJay Foad       case R600::PRED_SETNE_INT:
41957baa14dSJay Foad         I->getOperand(2).setImm(R600::PRED_SETE_INT);
42057baa14dSJay Foad         return;
42157baa14dSJay Foad       case R600::PRED_SETE:
42257baa14dSJay Foad         I->getOperand(2).setImm(R600::PRED_SETNE);
42357baa14dSJay Foad         return;
42457baa14dSJay Foad       case R600::PRED_SETNE:
42557baa14dSJay Foad         I->getOperand(2).setImm(R600::PRED_SETE);
42657baa14dSJay Foad         return;
42757baa14dSJay Foad       default:
42857baa14dSJay Foad         llvm_unreachable("PRED_X Opcode invalid!");
42957baa14dSJay Foad       }
43057baa14dSJay Foad     }
43157baa14dSJay Foad   }
43257baa14dSJay Foad }
43357baa14dSJay Foad 
43457baa14dSJay Foad void R600MachineCFGStructurizer::insertInstrEnd(MachineBasicBlock *MBB,
43557baa14dSJay Foad                                            int NewOpcode, const DebugLoc &DL) {
43657baa14dSJay Foad   MachineInstr *MI =
43757baa14dSJay Foad       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
43857baa14dSJay Foad   MBB->push_back(MI);
43957baa14dSJay Foad   //assume the instruction doesn't take any reg operand ...
44057baa14dSJay Foad   SHOWNEWINSTR(MI);
44157baa14dSJay Foad }
44257baa14dSJay Foad 
44357baa14dSJay Foad MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(MachineBasicBlock *MBB,
44457baa14dSJay Foad                                                        int NewOpcode,
44557baa14dSJay Foad                                                        const DebugLoc &DL) {
44657baa14dSJay Foad   MachineInstr *MI =
44757baa14dSJay Foad       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
44857baa14dSJay Foad   if (!MBB->empty())
44957baa14dSJay Foad     MBB->insert(MBB->begin(), MI);
45057baa14dSJay Foad   else
45157baa14dSJay Foad     MBB->push_back(MI);
45257baa14dSJay Foad   SHOWNEWINSTR(MI);
45357baa14dSJay Foad   return MI;
45457baa14dSJay Foad }
45557baa14dSJay Foad 
45657baa14dSJay Foad MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(
45757baa14dSJay Foad     MachineBasicBlock::iterator I, int NewOpcode) {
45857baa14dSJay Foad   MachineInstr *OldMI = &(*I);
45957baa14dSJay Foad   MachineBasicBlock *MBB = OldMI->getParent();
46057baa14dSJay Foad   MachineInstr *NewMBB =
46157baa14dSJay Foad       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DebugLoc());
46257baa14dSJay Foad   MBB->insert(I, NewMBB);
46357baa14dSJay Foad   //assume the instruction doesn't take any reg operand ...
46457baa14dSJay Foad   SHOWNEWINSTR(NewMBB);
46557baa14dSJay Foad   return NewMBB;
46657baa14dSJay Foad }
46757baa14dSJay Foad 
46857baa14dSJay Foad void R600MachineCFGStructurizer::insertCondBranchBefore(
46957baa14dSJay Foad     MachineBasicBlock::iterator I, int NewOpcode, const DebugLoc &DL) {
47057baa14dSJay Foad   MachineInstr *OldMI = &(*I);
47157baa14dSJay Foad   MachineBasicBlock *MBB = OldMI->getParent();
47257baa14dSJay Foad   MachineFunction *MF = MBB->getParent();
47357baa14dSJay Foad   MachineInstr *NewMI = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
47457baa14dSJay Foad   MBB->insert(I, NewMI);
47557baa14dSJay Foad   MachineInstrBuilder MIB(*MF, NewMI);
47657baa14dSJay Foad   MIB.addReg(OldMI->getOperand(1).getReg(), false);
47757baa14dSJay Foad   SHOWNEWINSTR(NewMI);
47857baa14dSJay Foad   //erase later oldInstr->eraseFromParent();
47957baa14dSJay Foad }
48057baa14dSJay Foad 
48157baa14dSJay Foad void R600MachineCFGStructurizer::insertCondBranchBefore(
48257baa14dSJay Foad     MachineBasicBlock *blk, MachineBasicBlock::iterator I, int NewOpcode,
48357baa14dSJay Foad     int RegNum, const DebugLoc &DL) {
48457baa14dSJay Foad   MachineFunction *MF = blk->getParent();
48557baa14dSJay Foad   MachineInstr *NewInstr = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
48657baa14dSJay Foad   //insert before
48757baa14dSJay Foad   blk->insert(I, NewInstr);
48857baa14dSJay Foad   MachineInstrBuilder(*MF, NewInstr).addReg(RegNum, false);
48957baa14dSJay Foad   SHOWNEWINSTR(NewInstr);
49057baa14dSJay Foad }
49157baa14dSJay Foad 
49257baa14dSJay Foad int R600MachineCFGStructurizer::getBranchNzeroOpcode(int OldOpcode) {
49357baa14dSJay Foad   switch(OldOpcode) {
49457baa14dSJay Foad   case R600::JUMP_COND:
49557baa14dSJay Foad   case R600::JUMP: return R600::IF_PREDICATE_SET;
49657baa14dSJay Foad   case R600::BRANCH_COND_i32:
49757baa14dSJay Foad   case R600::BRANCH_COND_f32: return R600::IF_LOGICALNZ_f32;
49857baa14dSJay Foad   default: llvm_unreachable("internal error");
49957baa14dSJay Foad   }
50057baa14dSJay Foad   return -1;
50157baa14dSJay Foad }
50257baa14dSJay Foad 
50357baa14dSJay Foad int R600MachineCFGStructurizer::getBranchZeroOpcode(int OldOpcode) {
50457baa14dSJay Foad   switch(OldOpcode) {
50557baa14dSJay Foad   case R600::JUMP_COND:
50657baa14dSJay Foad   case R600::JUMP: return R600::IF_PREDICATE_SET;
50757baa14dSJay Foad   case R600::BRANCH_COND_i32:
50857baa14dSJay Foad   case R600::BRANCH_COND_f32: return R600::IF_LOGICALZ_f32;
50957baa14dSJay Foad   default: llvm_unreachable("internal error");
51057baa14dSJay Foad   }
51157baa14dSJay Foad   return -1;
51257baa14dSJay Foad }
51357baa14dSJay Foad 
51457baa14dSJay Foad int R600MachineCFGStructurizer::getContinueNzeroOpcode(int OldOpcode) {
51557baa14dSJay Foad   switch(OldOpcode) {
51657baa14dSJay Foad   case R600::JUMP_COND:
51757baa14dSJay Foad   case R600::JUMP: return R600::CONTINUE_LOGICALNZ_i32;
51857baa14dSJay Foad   default: llvm_unreachable("internal error");
51957baa14dSJay Foad   }
52057baa14dSJay Foad   return -1;
52157baa14dSJay Foad }
52257baa14dSJay Foad 
52357baa14dSJay Foad int R600MachineCFGStructurizer::getContinueZeroOpcode(int OldOpcode) {
52457baa14dSJay Foad   switch(OldOpcode) {
52557baa14dSJay Foad   case R600::JUMP_COND:
52657baa14dSJay Foad   case R600::JUMP: return R600::CONTINUE_LOGICALZ_i32;
52757baa14dSJay Foad   default: llvm_unreachable("internal error");
52857baa14dSJay Foad   }
52957baa14dSJay Foad   return -1;
53057baa14dSJay Foad }
53157baa14dSJay Foad 
53257baa14dSJay Foad MachineBasicBlock *R600MachineCFGStructurizer::getTrueBranch(MachineInstr *MI) {
53357baa14dSJay Foad   return MI->getOperand(0).getMBB();
53457baa14dSJay Foad }
53557baa14dSJay Foad 
53657baa14dSJay Foad void R600MachineCFGStructurizer::setTrueBranch(MachineInstr *MI,
53757baa14dSJay Foad     MachineBasicBlock *MBB) {
53857baa14dSJay Foad   MI->getOperand(0).setMBB(MBB);
53957baa14dSJay Foad }
54057baa14dSJay Foad 
54157baa14dSJay Foad MachineBasicBlock *
54257baa14dSJay Foad R600MachineCFGStructurizer::getFalseBranch(MachineBasicBlock *MBB,
54357baa14dSJay Foad     MachineInstr *MI) {
54457baa14dSJay Foad   assert(MBB->succ_size() == 2);
54557baa14dSJay Foad   MachineBasicBlock *TrueBranch = getTrueBranch(MI);
54657baa14dSJay Foad   MachineBasicBlock::succ_iterator It = MBB->succ_begin();
54757baa14dSJay Foad   MachineBasicBlock::succ_iterator Next = It;
54857baa14dSJay Foad   ++Next;
54957baa14dSJay Foad   return (*It == TrueBranch) ? *Next : *It;
55057baa14dSJay Foad }
55157baa14dSJay Foad 
55257baa14dSJay Foad bool R600MachineCFGStructurizer::isCondBranch(MachineInstr *MI) {
55357baa14dSJay Foad   switch (MI->getOpcode()) {
55457baa14dSJay Foad     case R600::JUMP_COND:
55557baa14dSJay Foad     case R600::BRANCH_COND_i32:
55657baa14dSJay Foad     case R600::BRANCH_COND_f32: return true;
55757baa14dSJay Foad   default:
55857baa14dSJay Foad     return false;
55957baa14dSJay Foad   }
56057baa14dSJay Foad   return false;
56157baa14dSJay Foad }
56257baa14dSJay Foad 
56357baa14dSJay Foad bool R600MachineCFGStructurizer::isUncondBranch(MachineInstr *MI) {
56457baa14dSJay Foad   switch (MI->getOpcode()) {
56557baa14dSJay Foad   case R600::JUMP:
56657baa14dSJay Foad   case R600::BRANCH:
56757baa14dSJay Foad     return true;
56857baa14dSJay Foad   default:
56957baa14dSJay Foad     return false;
57057baa14dSJay Foad   }
57157baa14dSJay Foad   return false;
57257baa14dSJay Foad }
57357baa14dSJay Foad 
57457baa14dSJay Foad DebugLoc R600MachineCFGStructurizer::getLastDebugLocInBB(MachineBasicBlock *MBB) {
57557baa14dSJay Foad   //get DebugLoc from the first MachineBasicBlock instruction with debug info
57657baa14dSJay Foad   DebugLoc DL;
57757baa14dSJay Foad   for (MachineInstr &MI : *MBB)
57857baa14dSJay Foad     if (MI.getDebugLoc())
57957baa14dSJay Foad       DL = MI.getDebugLoc();
58057baa14dSJay Foad   return DL;
58157baa14dSJay Foad }
58257baa14dSJay Foad 
58357baa14dSJay Foad MachineInstr *R600MachineCFGStructurizer::getNormalBlockBranchInstr(
58457baa14dSJay Foad     MachineBasicBlock *MBB) {
58557baa14dSJay Foad   MachineBasicBlock::reverse_iterator It = MBB->rbegin();
58657baa14dSJay Foad   MachineInstr *MI = &*It;
58757baa14dSJay Foad   if (MI && (isCondBranch(MI) || isUncondBranch(MI)))
58857baa14dSJay Foad     return MI;
58957baa14dSJay Foad   return nullptr;
59057baa14dSJay Foad }
59157baa14dSJay Foad 
59257baa14dSJay Foad MachineInstr *R600MachineCFGStructurizer::getLoopendBlockBranchInstr(
59357baa14dSJay Foad     MachineBasicBlock *MBB) {
59457baa14dSJay Foad   for (MachineBasicBlock::reverse_iterator It = MBB->rbegin(), E = MBB->rend();
59557baa14dSJay Foad       It != E; ++It) {
59657baa14dSJay Foad     // FIXME: Simplify
59757baa14dSJay Foad     MachineInstr *MI = &*It;
59857baa14dSJay Foad     if (MI) {
59957baa14dSJay Foad       if (isCondBranch(MI) || isUncondBranch(MI))
60057baa14dSJay Foad         return MI;
601*63fae3edSJay Foad       if (!TII->isMov(MI->getOpcode()))
60257baa14dSJay Foad         break;
60357baa14dSJay Foad     }
60457baa14dSJay Foad   }
60557baa14dSJay Foad   return nullptr;
60657baa14dSJay Foad }
60757baa14dSJay Foad 
60857baa14dSJay Foad MachineInstr *R600MachineCFGStructurizer::getReturnInstr(MachineBasicBlock *MBB) {
60957baa14dSJay Foad   MachineBasicBlock::reverse_iterator It = MBB->rbegin();
61057baa14dSJay Foad   if (It != MBB->rend()) {
61157baa14dSJay Foad     MachineInstr *instr = &(*It);
61257baa14dSJay Foad     if (instr->getOpcode() == R600::RETURN)
61357baa14dSJay Foad       return instr;
61457baa14dSJay Foad   }
61557baa14dSJay Foad   return nullptr;
61657baa14dSJay Foad }
61757baa14dSJay Foad 
61857baa14dSJay Foad bool R600MachineCFGStructurizer::isReturnBlock(MachineBasicBlock *MBB) {
61957baa14dSJay Foad   MachineInstr *MI = getReturnInstr(MBB);
62057baa14dSJay Foad   bool IsReturn = MBB->succ_empty();
62157baa14dSJay Foad   if (MI)
62257baa14dSJay Foad     assert(IsReturn);
62357baa14dSJay Foad   else if (IsReturn)
62457baa14dSJay Foad     LLVM_DEBUG(dbgs() << "BB" << MBB->getNumber()
62557baa14dSJay Foad                       << " is return block without RETURN instr\n";);
62657baa14dSJay Foad   return  IsReturn;
62757baa14dSJay Foad }
62857baa14dSJay Foad 
62957baa14dSJay Foad void R600MachineCFGStructurizer::cloneSuccessorList(MachineBasicBlock *DstMBB,
63057baa14dSJay Foad     MachineBasicBlock *SrcMBB) {
63157baa14dSJay Foad   for (MachineBasicBlock *Succ : SrcMBB->successors())
63257baa14dSJay Foad     DstMBB->addSuccessor(Succ);  // *iter's predecessor is also taken care of
63357baa14dSJay Foad }
63457baa14dSJay Foad 
63557baa14dSJay Foad MachineBasicBlock *R600MachineCFGStructurizer::clone(MachineBasicBlock *MBB) {
63657baa14dSJay Foad   MachineFunction *Func = MBB->getParent();
63757baa14dSJay Foad   MachineBasicBlock *NewMBB = Func->CreateMachineBasicBlock();
63857baa14dSJay Foad   Func->push_back(NewMBB);  //insert to function
63957baa14dSJay Foad   for (const MachineInstr &It : *MBB)
64057baa14dSJay Foad     NewMBB->push_back(Func->CloneMachineInstr(&It));
64157baa14dSJay Foad   return NewMBB;
64257baa14dSJay Foad }
64357baa14dSJay Foad 
64457baa14dSJay Foad void R600MachineCFGStructurizer::replaceInstrUseOfBlockWith(
64557baa14dSJay Foad     MachineBasicBlock *SrcMBB, MachineBasicBlock *OldMBB,
64657baa14dSJay Foad     MachineBasicBlock *NewBlk) {
64757baa14dSJay Foad   MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
64857baa14dSJay Foad   if (BranchMI && isCondBranch(BranchMI) &&
64957baa14dSJay Foad       getTrueBranch(BranchMI) == OldMBB)
65057baa14dSJay Foad     setTrueBranch(BranchMI, NewBlk);
65157baa14dSJay Foad }
65257baa14dSJay Foad 
65357baa14dSJay Foad void R600MachineCFGStructurizer::wrapup(MachineBasicBlock *MBB) {
65457baa14dSJay Foad   assert((!MBB->getParent()->getJumpTableInfo()
65557baa14dSJay Foad           || MBB->getParent()->getJumpTableInfo()->isEmpty())
65657baa14dSJay Foad          && "found a jump table");
65757baa14dSJay Foad 
65857baa14dSJay Foad    //collect continue right before endloop
65957baa14dSJay Foad    SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> ContInstr;
66057baa14dSJay Foad    MachineBasicBlock::iterator Pre = MBB->begin();
66157baa14dSJay Foad    MachineBasicBlock::iterator E = MBB->end();
66257baa14dSJay Foad    MachineBasicBlock::iterator It = Pre;
66357baa14dSJay Foad    while (It != E) {
66457baa14dSJay Foad      if (Pre->getOpcode() == R600::CONTINUE
66557baa14dSJay Foad          && It->getOpcode() == R600::ENDLOOP)
66657baa14dSJay Foad        ContInstr.push_back(&*Pre);
66757baa14dSJay Foad      Pre = It;
66857baa14dSJay Foad      ++It;
66957baa14dSJay Foad    }
67057baa14dSJay Foad 
67157baa14dSJay Foad    //delete continue right before endloop
672c7309dadSJay Foad    for (auto *MI : ContInstr)
673c7309dadSJay Foad      MI->eraseFromParent();
67457baa14dSJay Foad 
67557baa14dSJay Foad    // TODO to fix up jump table so later phase won't be confused.  if
67657baa14dSJay Foad    // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
67757baa14dSJay Foad    // there isn't such an interface yet.  alternatively, replace all the other
67857baa14dSJay Foad    // blocks in the jump table with the entryBlk //}
67957baa14dSJay Foad }
68057baa14dSJay Foad 
68157baa14dSJay Foad bool R600MachineCFGStructurizer::prepare() {
68257baa14dSJay Foad   bool Changed = false;
68357baa14dSJay Foad 
68457baa14dSJay Foad   //FIXME: if not reducible flow graph, make it so ???
68557baa14dSJay Foad 
68657baa14dSJay Foad   LLVM_DEBUG(dbgs() << "R600MachineCFGStructurizer::prepare\n";);
68757baa14dSJay Foad 
68857baa14dSJay Foad   orderBlocks(FuncRep);
68957baa14dSJay Foad 
69057baa14dSJay Foad   SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> RetBlks;
69157baa14dSJay Foad 
69257baa14dSJay Foad   // Add an ExitBlk to loop that don't have one
69357baa14dSJay Foad   for (MachineLoop *LoopRep : *MLI) {
69457baa14dSJay Foad     MBBVector ExitingMBBs;
69557baa14dSJay Foad     LoopRep->getExitingBlocks(ExitingMBBs);
69657baa14dSJay Foad 
69757baa14dSJay Foad     if (ExitingMBBs.size() == 0) {
69857baa14dSJay Foad       MachineBasicBlock* DummyExitBlk = normalizeInfiniteLoopExit(LoopRep);
69957baa14dSJay Foad       if (DummyExitBlk)
70057baa14dSJay Foad         RetBlks.push_back(DummyExitBlk);
70157baa14dSJay Foad     }
70257baa14dSJay Foad   }
70357baa14dSJay Foad 
70457baa14dSJay Foad   // Remove unconditional branch instr.
70557baa14dSJay Foad   // Add dummy exit block iff there are multiple returns.
70657baa14dSJay Foad   for (MachineBasicBlock *MBB : OrderedBlks) {
70757baa14dSJay Foad     removeUnconditionalBranch(MBB);
70857baa14dSJay Foad     removeRedundantConditionalBranch(MBB);
70957baa14dSJay Foad     if (isReturnBlock(MBB)) {
71057baa14dSJay Foad       RetBlks.push_back(MBB);
71157baa14dSJay Foad     }
71257baa14dSJay Foad     assert(MBB->succ_size() <= 2);
71357baa14dSJay Foad   }
71457baa14dSJay Foad 
71557baa14dSJay Foad   if (RetBlks.size() >= 2) {
71657baa14dSJay Foad     addDummyExitBlock(RetBlks);
71757baa14dSJay Foad     Changed = true;
71857baa14dSJay Foad   }
71957baa14dSJay Foad 
72057baa14dSJay Foad   return Changed;
72157baa14dSJay Foad }
72257baa14dSJay Foad 
72357baa14dSJay Foad bool R600MachineCFGStructurizer::run() {
72457baa14dSJay Foad   //Assume reducible CFG...
72557baa14dSJay Foad   LLVM_DEBUG(dbgs() << "R600MachineCFGStructurizer::run\n");
72657baa14dSJay Foad 
72757baa14dSJay Foad #ifdef STRESSTEST
72857baa14dSJay Foad   //Use the worse block ordering to test the algorithm.
72957baa14dSJay Foad   ReverseVector(orderedBlks);
73057baa14dSJay Foad #endif
73157baa14dSJay Foad 
73257baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Ordered blocks:\n"; printOrderedBlocks(););
73357baa14dSJay Foad   int NumIter = 0;
73457baa14dSJay Foad   bool Finish = false;
73557baa14dSJay Foad   MachineBasicBlock *MBB;
73657baa14dSJay Foad   bool MakeProgress = false;
73757baa14dSJay Foad   int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
73857baa14dSJay Foad                                         OrderedBlks.end());
73957baa14dSJay Foad 
74057baa14dSJay Foad   do {
74157baa14dSJay Foad     ++NumIter;
74257baa14dSJay Foad     LLVM_DEBUG(dbgs() << "numIter = " << NumIter
74357baa14dSJay Foad                       << ", numRemaintedBlk = " << NumRemainedBlk << "\n";);
744bec8dff3SFangrui Song     (void)NumIter;
74557baa14dSJay Foad 
74657baa14dSJay Foad     SmallVectorImpl<MachineBasicBlock *>::const_iterator It =
74757baa14dSJay Foad         OrderedBlks.begin();
74857baa14dSJay Foad     SmallVectorImpl<MachineBasicBlock *>::const_iterator E =
74957baa14dSJay Foad         OrderedBlks.end();
75057baa14dSJay Foad 
75157baa14dSJay Foad     SmallVectorImpl<MachineBasicBlock *>::const_iterator SccBeginIter =
75257baa14dSJay Foad         It;
75357baa14dSJay Foad     MachineBasicBlock *SccBeginMBB = nullptr;
75457baa14dSJay Foad     int SccNumBlk = 0;  // The number of active blocks, init to a
75557baa14dSJay Foad                         // maximum possible number.
75657baa14dSJay Foad     int SccNumIter;     // Number of iteration in this SCC.
75757baa14dSJay Foad 
75857baa14dSJay Foad     while (It != E) {
75957baa14dSJay Foad       MBB = *It;
76057baa14dSJay Foad 
76157baa14dSJay Foad       if (!SccBeginMBB) {
76257baa14dSJay Foad         SccBeginIter = It;
76357baa14dSJay Foad         SccBeginMBB = MBB;
76457baa14dSJay Foad         SccNumIter = 0;
76557baa14dSJay Foad         SccNumBlk = NumRemainedBlk; // Init to maximum possible number.
76657baa14dSJay Foad         LLVM_DEBUG(dbgs() << "start processing SCC" << getSCCNum(SccBeginMBB);
76757baa14dSJay Foad                    dbgs() << "\n";);
76857baa14dSJay Foad       }
76957baa14dSJay Foad 
77057baa14dSJay Foad       if (!isRetiredBlock(MBB))
77157baa14dSJay Foad         patternMatch(MBB);
77257baa14dSJay Foad 
77357baa14dSJay Foad       ++It;
77457baa14dSJay Foad 
77557baa14dSJay Foad       bool ContNextScc = true;
77657baa14dSJay Foad       if (It == E
77757baa14dSJay Foad           || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
77857baa14dSJay Foad         // Just finish one scc.
77957baa14dSJay Foad         ++SccNumIter;
78057baa14dSJay Foad         int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
78157baa14dSJay Foad         if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
78257baa14dSJay Foad           LLVM_DEBUG(dbgs() << "Can't reduce SCC " << getSCCNum(MBB)
78357baa14dSJay Foad                             << ", sccNumIter = " << SccNumIter;
78457baa14dSJay Foad                      dbgs() << "doesn't make any progress\n";);
785bec8dff3SFangrui Song           (void)SccNumIter;
78657baa14dSJay Foad           ContNextScc = true;
78757baa14dSJay Foad         } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
78857baa14dSJay Foad           SccNumBlk = sccRemainedNumBlk;
78957baa14dSJay Foad           It = SccBeginIter;
79057baa14dSJay Foad           ContNextScc = false;
79157baa14dSJay Foad           LLVM_DEBUG(dbgs() << "repeat processing SCC" << getSCCNum(MBB)
79257baa14dSJay Foad                             << "sccNumIter = " << SccNumIter << '\n';);
79357baa14dSJay Foad         } else {
79457baa14dSJay Foad           // Finish the current scc.
79557baa14dSJay Foad           ContNextScc = true;
79657baa14dSJay Foad         }
79757baa14dSJay Foad       } else {
79857baa14dSJay Foad         // Continue on next component in the current scc.
79957baa14dSJay Foad         ContNextScc = false;
80057baa14dSJay Foad       }
80157baa14dSJay Foad 
80257baa14dSJay Foad       if (ContNextScc)
80357baa14dSJay Foad         SccBeginMBB = nullptr;
80457baa14dSJay Foad     } //while, "one iteration" over the function.
80557baa14dSJay Foad 
80657baa14dSJay Foad     MachineBasicBlock *EntryMBB =
80757baa14dSJay Foad         *GraphTraits<MachineFunction *>::nodes_begin(FuncRep);
80857baa14dSJay Foad     if (EntryMBB->succ_empty()) {
80957baa14dSJay Foad       Finish = true;
81057baa14dSJay Foad       LLVM_DEBUG(dbgs() << "Reduce to one block\n";);
81157baa14dSJay Foad     } else {
81257baa14dSJay Foad       int NewnumRemainedBlk
81357baa14dSJay Foad         = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
81457baa14dSJay Foad       // consider cloned blocks ??
81557baa14dSJay Foad       if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
81657baa14dSJay Foad         MakeProgress = true;
81757baa14dSJay Foad         NumRemainedBlk = NewnumRemainedBlk;
81857baa14dSJay Foad       } else {
81957baa14dSJay Foad         MakeProgress = false;
82057baa14dSJay Foad         LLVM_DEBUG(dbgs() << "No progress\n";);
82157baa14dSJay Foad       }
82257baa14dSJay Foad     }
82357baa14dSJay Foad   } while (!Finish && MakeProgress);
82457baa14dSJay Foad 
82557baa14dSJay Foad   // Misc wrap up to maintain the consistency of the Function representation.
82657baa14dSJay Foad   wrapup(*GraphTraits<MachineFunction *>::nodes_begin(FuncRep));
82757baa14dSJay Foad 
82857baa14dSJay Foad   // Detach retired Block, release memory.
82957baa14dSJay Foad   for (auto &It : BlockInfoMap) {
83057baa14dSJay Foad     if (It.second && It.second->IsRetired) {
83157baa14dSJay Foad       assert((It.first)->getNumber() != -1);
83257baa14dSJay Foad       LLVM_DEBUG(dbgs() << "Erase BB" << (It.first)->getNumber() << "\n";);
83357baa14dSJay Foad       It.first->eraseFromParent(); // Remove from the parent Function.
83457baa14dSJay Foad     }
83557baa14dSJay Foad     delete It.second;
83657baa14dSJay Foad   }
83757baa14dSJay Foad   BlockInfoMap.clear();
83857baa14dSJay Foad   LLInfoMap.clear();
83957baa14dSJay Foad 
84057baa14dSJay Foad   if (!Finish) {
84157baa14dSJay Foad     LLVM_DEBUG(FuncRep->viewCFG());
84257baa14dSJay Foad     report_fatal_error("IRREDUCIBLE_CFG");
84357baa14dSJay Foad   }
84457baa14dSJay Foad 
84557baa14dSJay Foad   return true;
84657baa14dSJay Foad }
84757baa14dSJay Foad 
84857baa14dSJay Foad void R600MachineCFGStructurizer::orderBlocks(MachineFunction *MF) {
84957baa14dSJay Foad   int SccNum = 0;
85057baa14dSJay Foad   for (scc_iterator<MachineFunction *> It = scc_begin(MF); !It.isAtEnd();
85157baa14dSJay Foad        ++It, ++SccNum) {
85257baa14dSJay Foad     const std::vector<MachineBasicBlock *> &SccNext = *It;
85357baa14dSJay Foad     for (MachineBasicBlock *MBB : SccNext) {
85457baa14dSJay Foad       OrderedBlks.push_back(MBB);
85557baa14dSJay Foad       recordSccnum(MBB, SccNum);
85657baa14dSJay Foad     }
85757baa14dSJay Foad   }
85857baa14dSJay Foad 
85957baa14dSJay Foad   // walk through all the block in func to check for unreachable
86057baa14dSJay Foad   for (auto *MBB : nodes(MF)) {
86157baa14dSJay Foad     SccNum = getSCCNum(MBB);
86257baa14dSJay Foad     if (SccNum == INVALIDSCCNUM)
86357baa14dSJay Foad       dbgs() << "unreachable block BB" << MBB->getNumber() << "\n";
86457baa14dSJay Foad   }
86557baa14dSJay Foad }
86657baa14dSJay Foad 
86757baa14dSJay Foad int R600MachineCFGStructurizer::patternMatch(MachineBasicBlock *MBB) {
86857baa14dSJay Foad   int NumMatch = 0;
86957baa14dSJay Foad   int CurMatch;
87057baa14dSJay Foad 
87157baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Begin patternMatch BB" << MBB->getNumber() << "\n";);
87257baa14dSJay Foad 
87357baa14dSJay Foad   while ((CurMatch = patternMatchGroup(MBB)) > 0)
87457baa14dSJay Foad     NumMatch += CurMatch;
87557baa14dSJay Foad 
87657baa14dSJay Foad   LLVM_DEBUG(dbgs() << "End patternMatch BB" << MBB->getNumber()
87757baa14dSJay Foad                     << ", numMatch = " << NumMatch << "\n";);
87857baa14dSJay Foad 
87957baa14dSJay Foad   return NumMatch;
88057baa14dSJay Foad }
88157baa14dSJay Foad 
88257baa14dSJay Foad int R600MachineCFGStructurizer::patternMatchGroup(MachineBasicBlock *MBB) {
88357baa14dSJay Foad   int NumMatch = 0;
88457baa14dSJay Foad   NumMatch += loopendPatternMatch();
88557baa14dSJay Foad   NumMatch += serialPatternMatch(MBB);
88657baa14dSJay Foad   NumMatch += ifPatternMatch(MBB);
88757baa14dSJay Foad   return NumMatch;
88857baa14dSJay Foad }
88957baa14dSJay Foad 
89057baa14dSJay Foad int R600MachineCFGStructurizer::serialPatternMatch(MachineBasicBlock *MBB) {
89157baa14dSJay Foad   if (MBB->succ_size() != 1)
89257baa14dSJay Foad     return 0;
89357baa14dSJay Foad 
89457baa14dSJay Foad   MachineBasicBlock *childBlk = *MBB->succ_begin();
89557baa14dSJay Foad   if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk))
89657baa14dSJay Foad     return 0;
89757baa14dSJay Foad 
89857baa14dSJay Foad   mergeSerialBlock(MBB, childBlk);
89957baa14dSJay Foad   ++numSerialPatternMatch;
90057baa14dSJay Foad   return 1;
90157baa14dSJay Foad }
90257baa14dSJay Foad 
90357baa14dSJay Foad int R600MachineCFGStructurizer::ifPatternMatch(MachineBasicBlock *MBB) {
90457baa14dSJay Foad   //two edges
90557baa14dSJay Foad   if (MBB->succ_size() != 2)
90657baa14dSJay Foad     return 0;
90757baa14dSJay Foad   if (hasBackEdge(MBB))
90857baa14dSJay Foad     return 0;
90957baa14dSJay Foad   MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
91057baa14dSJay Foad   if (!BranchMI)
91157baa14dSJay Foad     return 0;
91257baa14dSJay Foad 
91357baa14dSJay Foad   assert(isCondBranch(BranchMI));
91457baa14dSJay Foad   int NumMatch = 0;
91557baa14dSJay Foad 
91657baa14dSJay Foad   MachineBasicBlock *TrueMBB = getTrueBranch(BranchMI);
91757baa14dSJay Foad   NumMatch += serialPatternMatch(TrueMBB);
91857baa14dSJay Foad   NumMatch += ifPatternMatch(TrueMBB);
91957baa14dSJay Foad   MachineBasicBlock *FalseMBB = getFalseBranch(MBB, BranchMI);
92057baa14dSJay Foad   NumMatch += serialPatternMatch(FalseMBB);
92157baa14dSJay Foad   NumMatch += ifPatternMatch(FalseMBB);
92257baa14dSJay Foad   MachineBasicBlock *LandBlk;
92357baa14dSJay Foad   int Cloned = 0;
92457baa14dSJay Foad 
92557baa14dSJay Foad   assert (!TrueMBB->succ_empty() || !FalseMBB->succ_empty());
92657baa14dSJay Foad   // TODO: Simplify
92757baa14dSJay Foad   if (TrueMBB->succ_size() == 1 && FalseMBB->succ_size() == 1
92857baa14dSJay Foad     && *TrueMBB->succ_begin() == *FalseMBB->succ_begin()) {
92957baa14dSJay Foad     // Diamond pattern
93057baa14dSJay Foad     LandBlk = *TrueMBB->succ_begin();
93157baa14dSJay Foad   } else if (TrueMBB->succ_size() == 1 && *TrueMBB->succ_begin() == FalseMBB) {
93257baa14dSJay Foad     // Triangle pattern, false is empty
93357baa14dSJay Foad     LandBlk = FalseMBB;
93457baa14dSJay Foad     FalseMBB = nullptr;
93557baa14dSJay Foad   } else if (FalseMBB->succ_size() == 1
93657baa14dSJay Foad              && *FalseMBB->succ_begin() == TrueMBB) {
93757baa14dSJay Foad     // Triangle pattern, true is empty
93857baa14dSJay Foad     // We reverse the predicate to make a triangle, empty false pattern;
93957baa14dSJay Foad     std::swap(TrueMBB, FalseMBB);
94057baa14dSJay Foad     reversePredicateSetter(MBB->end(), *MBB);
94157baa14dSJay Foad     LandBlk = FalseMBB;
94257baa14dSJay Foad     FalseMBB = nullptr;
94357baa14dSJay Foad   } else if (FalseMBB->succ_size() == 1
94457baa14dSJay Foad              && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
94557baa14dSJay Foad     LandBlk = *FalseMBB->succ_begin();
94657baa14dSJay Foad   } else if (TrueMBB->succ_size() == 1
94757baa14dSJay Foad     && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
94857baa14dSJay Foad     LandBlk = *TrueMBB->succ_begin();
94957baa14dSJay Foad   } else {
95057baa14dSJay Foad     return NumMatch + handleJumpintoIf(MBB, TrueMBB, FalseMBB);
95157baa14dSJay Foad   }
95257baa14dSJay Foad 
95357baa14dSJay Foad   // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
95457baa14dSJay Foad   // new BB created for landBlk==NULL may introduce new challenge to the
95557baa14dSJay Foad   // reduction process.
95657baa14dSJay Foad   if (LandBlk &&
95757baa14dSJay Foad       ((TrueMBB && TrueMBB->pred_size() > 1)
95857baa14dSJay Foad       || (FalseMBB && FalseMBB->pred_size() > 1))) {
95957baa14dSJay Foad      Cloned += improveSimpleJumpintoIf(MBB, TrueMBB, FalseMBB, &LandBlk);
96057baa14dSJay Foad   }
96157baa14dSJay Foad 
96257baa14dSJay Foad   if (TrueMBB && TrueMBB->pred_size() > 1) {
96357baa14dSJay Foad     TrueMBB = cloneBlockForPredecessor(TrueMBB, MBB);
96457baa14dSJay Foad     ++Cloned;
96557baa14dSJay Foad   }
96657baa14dSJay Foad 
96757baa14dSJay Foad   if (FalseMBB && FalseMBB->pred_size() > 1) {
96857baa14dSJay Foad     FalseMBB = cloneBlockForPredecessor(FalseMBB, MBB);
96957baa14dSJay Foad     ++Cloned;
97057baa14dSJay Foad   }
97157baa14dSJay Foad 
97257baa14dSJay Foad   mergeIfthenelseBlock(BranchMI, MBB, TrueMBB, FalseMBB, LandBlk);
97357baa14dSJay Foad 
97457baa14dSJay Foad   ++numIfPatternMatch;
97557baa14dSJay Foad 
97657baa14dSJay Foad   numClonedBlock += Cloned;
97757baa14dSJay Foad 
97857baa14dSJay Foad   return 1 + Cloned + NumMatch;
97957baa14dSJay Foad }
98057baa14dSJay Foad 
98157baa14dSJay Foad int R600MachineCFGStructurizer::loopendPatternMatch() {
98257baa14dSJay Foad   std::deque<MachineLoop *> NestedLoops;
98357baa14dSJay Foad   for (auto &It: *MLI)
98457baa14dSJay Foad     for (MachineLoop *ML : depth_first(It))
98557baa14dSJay Foad       NestedLoops.push_front(ML);
98657baa14dSJay Foad 
98757baa14dSJay Foad   if (NestedLoops.empty())
98857baa14dSJay Foad     return 0;
98957baa14dSJay Foad 
99057baa14dSJay Foad   // Process nested loop outside->inside (we did push_front),
99157baa14dSJay Foad   // so "continue" to a outside loop won't be mistaken as "break"
99257baa14dSJay Foad   // of the current loop.
99357baa14dSJay Foad   int Num = 0;
99457baa14dSJay Foad   for (MachineLoop *ExaminedLoop : NestedLoops) {
99557baa14dSJay Foad     if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
99657baa14dSJay Foad       continue;
99757baa14dSJay Foad     LLVM_DEBUG(dbgs() << "Processing:\n"; ExaminedLoop->dump(););
99857baa14dSJay Foad     int NumBreak = mergeLoop(ExaminedLoop);
99957baa14dSJay Foad     if (NumBreak == -1)
100057baa14dSJay Foad       break;
100157baa14dSJay Foad     Num += NumBreak;
100257baa14dSJay Foad   }
100357baa14dSJay Foad   return Num;
100457baa14dSJay Foad }
100557baa14dSJay Foad 
100657baa14dSJay Foad int R600MachineCFGStructurizer::mergeLoop(MachineLoop *LoopRep) {
100757baa14dSJay Foad   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
100857baa14dSJay Foad   MBBVector ExitingMBBs;
100957baa14dSJay Foad   LoopRep->getExitingBlocks(ExitingMBBs);
101057baa14dSJay Foad   assert(!ExitingMBBs.empty() && "Infinite Loop not supported");
101157baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Loop has " << ExitingMBBs.size()
101257baa14dSJay Foad                     << " exiting blocks\n";);
101357baa14dSJay Foad   // We assume a single ExitBlk
101457baa14dSJay Foad   MBBVector ExitBlks;
101557baa14dSJay Foad   LoopRep->getExitBlocks(ExitBlks);
101657baa14dSJay Foad   SmallPtrSet<MachineBasicBlock *, 2> ExitBlkSet;
10175e22a536SKazu Hirata   for (MachineBasicBlock *MBB : ExitBlks)
10185e22a536SKazu Hirata     ExitBlkSet.insert(MBB);
101957baa14dSJay Foad   assert(ExitBlkSet.size() == 1);
102057baa14dSJay Foad   MachineBasicBlock *ExitBlk = *ExitBlks.begin();
102157baa14dSJay Foad   assert(ExitBlk && "Loop has several exit block");
102257baa14dSJay Foad   MBBVector LatchBlks;
102357baa14dSJay Foad   for (auto *LB : inverse_children<MachineBasicBlock*>(LoopHeader))
102457baa14dSJay Foad     if (LoopRep->contains(LB))
102557baa14dSJay Foad       LatchBlks.push_back(LB);
102657baa14dSJay Foad 
10275e22a536SKazu Hirata   for (MachineBasicBlock *MBB : ExitingMBBs)
10285e22a536SKazu Hirata     mergeLoopbreakBlock(MBB, ExitBlk);
10295e22a536SKazu Hirata   for (MachineBasicBlock *MBB : LatchBlks)
10305e22a536SKazu Hirata     settleLoopcontBlock(MBB, LoopHeader);
103157baa14dSJay Foad   int Match = 0;
103257baa14dSJay Foad   do {
103357baa14dSJay Foad     Match = 0;
103457baa14dSJay Foad     Match += serialPatternMatch(LoopHeader);
103557baa14dSJay Foad     Match += ifPatternMatch(LoopHeader);
103657baa14dSJay Foad   } while (Match > 0);
103757baa14dSJay Foad   mergeLooplandBlock(LoopHeader, ExitBlk);
103857baa14dSJay Foad   MachineLoop *ParentLoop = LoopRep->getParentLoop();
103957baa14dSJay Foad   if (ParentLoop)
104057baa14dSJay Foad     MLI->changeLoopFor(LoopHeader, ParentLoop);
104157baa14dSJay Foad   else
104257baa14dSJay Foad     MLI->removeBlock(LoopHeader);
104357baa14dSJay Foad   Visited[LoopRep] = true;
104457baa14dSJay Foad   return 1;
104557baa14dSJay Foad }
104657baa14dSJay Foad 
104757baa14dSJay Foad bool R600MachineCFGStructurizer::isSameloopDetachedContbreak(
104857baa14dSJay Foad     MachineBasicBlock *Src1MBB, MachineBasicBlock *Src2MBB) {
104957baa14dSJay Foad   if (Src1MBB->succ_empty()) {
105057baa14dSJay Foad     MachineLoop *LoopRep = MLI->getLoopFor(Src1MBB);
105157baa14dSJay Foad     if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
105257baa14dSJay Foad       MachineBasicBlock *&TheEntry = LLInfoMap[LoopRep];
105357baa14dSJay Foad       if (TheEntry) {
105457baa14dSJay Foad         LLVM_DEBUG(dbgs() << "isLoopContBreakBlock yes src1 = BB"
105557baa14dSJay Foad                           << Src1MBB->getNumber() << " src2 = BB"
105657baa14dSJay Foad                           << Src2MBB->getNumber() << "\n";);
105757baa14dSJay Foad         return true;
105857baa14dSJay Foad       }
105957baa14dSJay Foad     }
106057baa14dSJay Foad   }
106157baa14dSJay Foad   return false;
106257baa14dSJay Foad }
106357baa14dSJay Foad 
106457baa14dSJay Foad int R600MachineCFGStructurizer::handleJumpintoIf(MachineBasicBlock *HeadMBB,
106557baa14dSJay Foad     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
106657baa14dSJay Foad   int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
106757baa14dSJay Foad   if (Num == 0) {
106857baa14dSJay Foad     LLVM_DEBUG(dbgs() << "handleJumpintoIf swap trueBlk and FalseBlk"
106957baa14dSJay Foad                       << "\n";);
107057baa14dSJay Foad     Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
107157baa14dSJay Foad   }
107257baa14dSJay Foad   return Num;
107357baa14dSJay Foad }
107457baa14dSJay Foad 
107557baa14dSJay Foad int R600MachineCFGStructurizer::handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
107657baa14dSJay Foad     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
107757baa14dSJay Foad   int Num = 0;
107857baa14dSJay Foad   MachineBasicBlock *DownBlk;
107957baa14dSJay Foad 
108057baa14dSJay Foad   //trueBlk could be the common post dominator
108157baa14dSJay Foad   DownBlk = TrueMBB;
108257baa14dSJay Foad 
108357baa14dSJay Foad   LLVM_DEBUG(dbgs() << "handleJumpintoIfImp head = BB" << HeadMBB->getNumber()
108457baa14dSJay Foad                     << " true = BB" << TrueMBB->getNumber()
108557baa14dSJay Foad                     << ", numSucc=" << TrueMBB->succ_size() << " false = BB"
108657baa14dSJay Foad                     << FalseMBB->getNumber() << "\n";);
108757baa14dSJay Foad 
108857baa14dSJay Foad   while (DownBlk) {
108957baa14dSJay Foad     LLVM_DEBUG(dbgs() << "check down = BB" << DownBlk->getNumber(););
109057baa14dSJay Foad 
109157baa14dSJay Foad     if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
109257baa14dSJay Foad       LLVM_DEBUG(dbgs() << " working\n";);
109357baa14dSJay Foad 
109457baa14dSJay Foad       Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
109557baa14dSJay Foad       Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
109657baa14dSJay Foad 
109757baa14dSJay Foad       numClonedBlock += Num;
109857baa14dSJay Foad       Num += serialPatternMatch(*HeadMBB->succ_begin());
109957baa14dSJay Foad       Num += serialPatternMatch(*std::next(HeadMBB->succ_begin()));
110057baa14dSJay Foad       Num += ifPatternMatch(HeadMBB);
110157baa14dSJay Foad       assert(Num > 0);
110257baa14dSJay Foad 
110357baa14dSJay Foad       break;
110457baa14dSJay Foad     }
110557baa14dSJay Foad     LLVM_DEBUG(dbgs() << " not working\n";);
110657baa14dSJay Foad     DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) : nullptr;
110757baa14dSJay Foad   } // walk down the postDomTree
110857baa14dSJay Foad 
110957baa14dSJay Foad   return Num;
111057baa14dSJay Foad }
111157baa14dSJay Foad 
111257baa14dSJay Foad #ifndef NDEBUG
111357baa14dSJay Foad void R600MachineCFGStructurizer::showImproveSimpleJumpintoIf(
111457baa14dSJay Foad     MachineBasicBlock *HeadMBB, MachineBasicBlock *TrueMBB,
111557baa14dSJay Foad     MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB, bool Detail) {
111657baa14dSJay Foad   dbgs() << "head = BB" << HeadMBB->getNumber()
111757baa14dSJay Foad          << " size = " << HeadMBB->size();
111857baa14dSJay Foad   if (Detail) {
111957baa14dSJay Foad     dbgs() << "\n";
112057baa14dSJay Foad     HeadMBB->print(dbgs());
112157baa14dSJay Foad     dbgs() << "\n";
112257baa14dSJay Foad   }
112357baa14dSJay Foad 
112457baa14dSJay Foad   if (TrueMBB) {
112557baa14dSJay Foad     dbgs() << ", true = BB" << TrueMBB->getNumber() << " size = "
112657baa14dSJay Foad            << TrueMBB->size() << " numPred = " << TrueMBB->pred_size();
112757baa14dSJay Foad     if (Detail) {
112857baa14dSJay Foad       dbgs() << "\n";
112957baa14dSJay Foad       TrueMBB->print(dbgs());
113057baa14dSJay Foad       dbgs() << "\n";
113157baa14dSJay Foad     }
113257baa14dSJay Foad   }
113357baa14dSJay Foad   if (FalseMBB) {
113457baa14dSJay Foad     dbgs() << ", false = BB" << FalseMBB->getNumber() << " size = "
113557baa14dSJay Foad            << FalseMBB->size() << " numPred = " << FalseMBB->pred_size();
113657baa14dSJay Foad     if (Detail) {
113757baa14dSJay Foad       dbgs() << "\n";
113857baa14dSJay Foad       FalseMBB->print(dbgs());
113957baa14dSJay Foad       dbgs() << "\n";
114057baa14dSJay Foad     }
114157baa14dSJay Foad   }
114257baa14dSJay Foad   if (LandMBB) {
114357baa14dSJay Foad     dbgs() << ", land = BB" << LandMBB->getNumber() << " size = "
114457baa14dSJay Foad            << LandMBB->size() << " numPred = " << LandMBB->pred_size();
114557baa14dSJay Foad     if (Detail) {
114657baa14dSJay Foad       dbgs() << "\n";
114757baa14dSJay Foad       LandMBB->print(dbgs());
114857baa14dSJay Foad       dbgs() << "\n";
114957baa14dSJay Foad     }
115057baa14dSJay Foad   }
115157baa14dSJay Foad 
115257baa14dSJay Foad   dbgs() << "\n";
115357baa14dSJay Foad }
115457baa14dSJay Foad #endif
115557baa14dSJay Foad 
115657baa14dSJay Foad int R600MachineCFGStructurizer::improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
115757baa14dSJay Foad     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
115857baa14dSJay Foad     MachineBasicBlock **LandMBBPtr) {
115957baa14dSJay Foad   bool MigrateTrue = false;
116057baa14dSJay Foad   bool MigrateFalse = false;
116157baa14dSJay Foad 
116257baa14dSJay Foad   MachineBasicBlock *LandBlk = *LandMBBPtr;
116357baa14dSJay Foad 
116457baa14dSJay Foad   assert((!TrueMBB || TrueMBB->succ_size() <= 1)
116557baa14dSJay Foad          && (!FalseMBB || FalseMBB->succ_size() <= 1));
116657baa14dSJay Foad 
116757baa14dSJay Foad   if (TrueMBB == FalseMBB)
116857baa14dSJay Foad     return 0;
116957baa14dSJay Foad 
117057baa14dSJay Foad   MigrateTrue = needMigrateBlock(TrueMBB);
117157baa14dSJay Foad   MigrateFalse = needMigrateBlock(FalseMBB);
117257baa14dSJay Foad 
117357baa14dSJay Foad   if (!MigrateTrue && !MigrateFalse)
117457baa14dSJay Foad     return 0;
117557baa14dSJay Foad 
117657baa14dSJay Foad   // If we need to migrate either trueBlk and falseBlk, migrate the rest that
117757baa14dSJay Foad   // have more than one predecessors.  without doing this, its predecessor
117857baa14dSJay Foad   // rather than headBlk will have undefined value in initReg.
117957baa14dSJay Foad   if (!MigrateTrue && TrueMBB && TrueMBB->pred_size() > 1)
118057baa14dSJay Foad     MigrateTrue = true;
118157baa14dSJay Foad   if (!MigrateFalse && FalseMBB && FalseMBB->pred_size() > 1)
118257baa14dSJay Foad     MigrateFalse = true;
118357baa14dSJay Foad 
118457baa14dSJay Foad   LLVM_DEBUG(
118557baa14dSJay Foad       dbgs() << "before improveSimpleJumpintoIf: ";
118657baa14dSJay Foad       showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
118757baa14dSJay Foad 
118857baa14dSJay Foad   // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
118957baa14dSJay Foad   //
119057baa14dSJay Foad   // new: headBlk => if () {initReg = 1; org trueBlk branch} else
119157baa14dSJay Foad   //      {initReg = 0; org falseBlk branch }
119257baa14dSJay Foad   //      => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
119357baa14dSJay Foad   //      => org landBlk
119457baa14dSJay Foad   //      if landBlk->pred_size() > 2, put the about if-else inside
119557baa14dSJay Foad   //      if (initReg !=2) {...}
119657baa14dSJay Foad   //
119757baa14dSJay Foad   // add initReg = initVal to headBlk
119857baa14dSJay Foad 
119957baa14dSJay Foad   const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
120057baa14dSJay Foad   if (!MigrateTrue || !MigrateFalse) {
120157baa14dSJay Foad     // XXX: We have an opportunity here to optimize the "branch into if" case
120257baa14dSJay Foad     // here.  Branch into if looks like this:
120357baa14dSJay Foad     //                        entry
120457baa14dSJay Foad     //                       /     |
120557baa14dSJay Foad     //           diamond_head       branch_from
120657baa14dSJay Foad     //             /      \           |
120757baa14dSJay Foad     // diamond_false        diamond_true
120857baa14dSJay Foad     //             \      /
120957baa14dSJay Foad     //               done
121057baa14dSJay Foad     //
121157baa14dSJay Foad     // The diamond_head block begins the "if" and the diamond_true block
121257baa14dSJay Foad     // is the block being "branched into".
121357baa14dSJay Foad     //
121457baa14dSJay Foad     // If MigrateTrue is true, then TrueBB is the block being "branched into"
121557baa14dSJay Foad     // and if MigrateFalse is true, then FalseBB is the block being
121657baa14dSJay Foad     // "branched into"
121757baa14dSJay Foad     //
121857baa14dSJay Foad     // Here is the pseudo code for how I think the optimization should work:
121957baa14dSJay Foad     // 1. Insert MOV GPR0, 0 before the branch instruction in diamond_head.
122057baa14dSJay Foad     // 2. Insert MOV GPR0, 1 before the branch instruction in branch_from.
122157baa14dSJay Foad     // 3. Move the branch instruction from diamond_head into its own basic
122257baa14dSJay Foad     //    block (new_block).
122357baa14dSJay Foad     // 4. Add an unconditional branch from diamond_head to new_block
122457baa14dSJay Foad     // 5. Replace the branch instruction in branch_from with an unconditional
122557baa14dSJay Foad     //    branch to new_block.  If branch_from has multiple predecessors, then
122657baa14dSJay Foad     //    we need to replace the True/False block in the branch
122757baa14dSJay Foad     //    instruction instead of replacing it.
122857baa14dSJay Foad     // 6. Change the condition of the branch instruction in new_block from
122957baa14dSJay Foad     //    COND to (COND || GPR0)
123057baa14dSJay Foad     //
123157baa14dSJay Foad     // In order insert these MOV instruction, we will need to use the
123257baa14dSJay Foad     // RegisterScavenger.  Usually liveness stops being tracked during
123357baa14dSJay Foad     // the late machine optimization passes, however if we implement
123457baa14dSJay Foad     // bool TargetRegisterInfo::requiresRegisterScavenging(
123557baa14dSJay Foad     //                                                const MachineFunction &MF)
123657baa14dSJay Foad     // and have it return true, liveness will be tracked correctly
123757baa14dSJay Foad     // by generic optimization passes.  We will also need to make sure that
123857baa14dSJay Foad     // all of our target-specific passes that run after regalloc and before
123957baa14dSJay Foad     // the CFGStructurizer track liveness and we will need to modify this pass
124057baa14dSJay Foad     // to correctly track liveness.
124157baa14dSJay Foad     //
124257baa14dSJay Foad     // After the above changes, the new CFG should look like this:
124357baa14dSJay Foad     //                        entry
124457baa14dSJay Foad     //                       /     |
124557baa14dSJay Foad     //           diamond_head       branch_from
124657baa14dSJay Foad     //                       \     /
124757baa14dSJay Foad     //                      new_block
124857baa14dSJay Foad     //                      /      |
124957baa14dSJay Foad     //         diamond_false        diamond_true
125057baa14dSJay Foad     //                      \      /
125157baa14dSJay Foad     //                        done
125257baa14dSJay Foad     //
125357baa14dSJay Foad     // Without this optimization, we are forced to duplicate the diamond_true
125457baa14dSJay Foad     // block and we will end up with a CFG like this:
125557baa14dSJay Foad     //
125657baa14dSJay Foad     //                        entry
125757baa14dSJay Foad     //                       /     |
125857baa14dSJay Foad     //           diamond_head       branch_from
125957baa14dSJay Foad     //             /      \                   |
126057baa14dSJay Foad     // diamond_false        diamond_true      diamond_true (duplicate)
126157baa14dSJay Foad     //             \      /                   |
126257baa14dSJay Foad     //               done --------------------|
126357baa14dSJay Foad     //
126457baa14dSJay Foad     // Duplicating diamond_true can be very costly especially if it has a
126557baa14dSJay Foad     // lot of instructions.
126657baa14dSJay Foad     return 0;
126757baa14dSJay Foad   }
126857baa14dSJay Foad 
126957baa14dSJay Foad   int NumNewBlk = 0;
127057baa14dSJay Foad 
127157baa14dSJay Foad   bool LandBlkHasOtherPred = (LandBlk->pred_size() > 2);
127257baa14dSJay Foad 
127357baa14dSJay Foad   //insert R600::ENDIF to avoid special case "input landBlk == NULL"
127457baa14dSJay Foad   MachineBasicBlock::iterator I = insertInstrBefore(LandBlk, R600::ENDIF);
127557baa14dSJay Foad 
127657baa14dSJay Foad   if (LandBlkHasOtherPred) {
127757baa14dSJay Foad     report_fatal_error("Extra register needed to handle CFG");
127857baa14dSJay Foad     Register CmpResReg =
127957baa14dSJay Foad         HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
128057baa14dSJay Foad     report_fatal_error("Extra compare instruction needed to handle CFG");
128157baa14dSJay Foad     insertCondBranchBefore(LandBlk, I, R600::IF_PREDICATE_SET,
128257baa14dSJay Foad         CmpResReg, DebugLoc());
128357baa14dSJay Foad   }
128457baa14dSJay Foad 
128557baa14dSJay Foad   // XXX: We are running this after RA, so creating virtual registers will
128657baa14dSJay Foad   // cause an assertion failure in the PostRA scheduling pass.
128757baa14dSJay Foad   Register InitReg =
128857baa14dSJay Foad       HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
128957baa14dSJay Foad   insertCondBranchBefore(LandBlk, I, R600::IF_PREDICATE_SET, InitReg,
129057baa14dSJay Foad       DebugLoc());
129157baa14dSJay Foad 
129257baa14dSJay Foad   if (MigrateTrue) {
129357baa14dSJay Foad     migrateInstruction(TrueMBB, LandBlk, I);
129457baa14dSJay Foad     // need to uncondionally insert the assignment to ensure a path from its
129557baa14dSJay Foad     // predecessor rather than headBlk has valid value in initReg if
129657baa14dSJay Foad     // (initVal != 1).
129757baa14dSJay Foad     report_fatal_error("Extra register needed to handle CFG");
129857baa14dSJay Foad   }
129957baa14dSJay Foad   insertInstrBefore(I, R600::ELSE);
130057baa14dSJay Foad 
130157baa14dSJay Foad   if (MigrateFalse) {
130257baa14dSJay Foad     migrateInstruction(FalseMBB, LandBlk, I);
130357baa14dSJay Foad     // need to uncondionally insert the assignment to ensure a path from its
130457baa14dSJay Foad     // predecessor rather than headBlk has valid value in initReg if
130557baa14dSJay Foad     // (initVal != 0)
130657baa14dSJay Foad     report_fatal_error("Extra register needed to handle CFG");
130757baa14dSJay Foad   }
130857baa14dSJay Foad 
130957baa14dSJay Foad   if (LandBlkHasOtherPred) {
131057baa14dSJay Foad     // add endif
131157baa14dSJay Foad     insertInstrBefore(I, R600::ENDIF);
131257baa14dSJay Foad 
131357baa14dSJay Foad     // put initReg = 2 to other predecessors of landBlk
131457baa14dSJay Foad     for (MachineBasicBlock *MBB : LandBlk->predecessors())
131557baa14dSJay Foad       if (MBB != TrueMBB && MBB != FalseMBB)
131657baa14dSJay Foad         report_fatal_error("Extra register needed to handle CFG");
131757baa14dSJay Foad   }
131857baa14dSJay Foad   LLVM_DEBUG(
131957baa14dSJay Foad       dbgs() << "result from improveSimpleJumpintoIf: ";
132057baa14dSJay Foad       showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
132157baa14dSJay Foad 
132257baa14dSJay Foad   // update landBlk
132357baa14dSJay Foad   *LandMBBPtr = LandBlk;
132457baa14dSJay Foad 
132557baa14dSJay Foad   return NumNewBlk;
132657baa14dSJay Foad }
132757baa14dSJay Foad 
132857baa14dSJay Foad void R600MachineCFGStructurizer::mergeSerialBlock(MachineBasicBlock *DstMBB,
132957baa14dSJay Foad     MachineBasicBlock *SrcMBB) {
133057baa14dSJay Foad   LLVM_DEBUG(dbgs() << "serialPattern BB" << DstMBB->getNumber() << " <= BB"
133157baa14dSJay Foad                     << SrcMBB->getNumber() << "\n";);
133257baa14dSJay Foad   DstMBB->splice(DstMBB->end(), SrcMBB, SrcMBB->begin(), SrcMBB->end());
133357baa14dSJay Foad 
133457baa14dSJay Foad   DstMBB->removeSuccessor(SrcMBB, true);
133557baa14dSJay Foad   cloneSuccessorList(DstMBB, SrcMBB);
133657baa14dSJay Foad 
133757baa14dSJay Foad   removeSuccessor(SrcMBB);
133857baa14dSJay Foad   MLI->removeBlock(SrcMBB);
133957baa14dSJay Foad   retireBlock(SrcMBB);
134057baa14dSJay Foad }
134157baa14dSJay Foad 
134257baa14dSJay Foad void R600MachineCFGStructurizer::mergeIfthenelseBlock(MachineInstr *BranchMI,
134357baa14dSJay Foad     MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
134457baa14dSJay Foad     MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB) {
134557baa14dSJay Foad   assert (TrueMBB);
134657baa14dSJay Foad   LLVM_DEBUG(dbgs() << "ifPattern BB" << MBB->getNumber(); dbgs() << "{  ";
134757baa14dSJay Foad              if (TrueMBB) { dbgs() << "BB" << TrueMBB->getNumber(); } dbgs()
134857baa14dSJay Foad              << "  } else ";
134957baa14dSJay Foad              dbgs() << "{  "; if (FalseMBB) {
135057baa14dSJay Foad                dbgs() << "BB" << FalseMBB->getNumber();
135157baa14dSJay Foad              } dbgs() << "  }\n ";
135257baa14dSJay Foad              dbgs() << "landBlock: "; if (!LandMBB) { dbgs() << "NULL"; } else {
135357baa14dSJay Foad                dbgs() << "BB" << LandMBB->getNumber();
135457baa14dSJay Foad              } dbgs() << "\n";);
135557baa14dSJay Foad 
135657baa14dSJay Foad   int OldOpcode = BranchMI->getOpcode();
135757baa14dSJay Foad   DebugLoc BranchDL = BranchMI->getDebugLoc();
135857baa14dSJay Foad 
135957baa14dSJay Foad //    transform to
136057baa14dSJay Foad //    if cond
136157baa14dSJay Foad //       trueBlk
136257baa14dSJay Foad //    else
136357baa14dSJay Foad //       falseBlk
136457baa14dSJay Foad //    endif
136557baa14dSJay Foad //    landBlk
136657baa14dSJay Foad 
136757baa14dSJay Foad   MachineBasicBlock::iterator I = BranchMI;
136857baa14dSJay Foad   insertCondBranchBefore(I, getBranchNzeroOpcode(OldOpcode),
136957baa14dSJay Foad       BranchDL);
137057baa14dSJay Foad 
137157baa14dSJay Foad   if (TrueMBB) {
137257baa14dSJay Foad     MBB->splice(I, TrueMBB, TrueMBB->begin(), TrueMBB->end());
137357baa14dSJay Foad     MBB->removeSuccessor(TrueMBB, true);
137457baa14dSJay Foad     if (LandMBB && TrueMBB->succ_size()!=0)
137557baa14dSJay Foad       TrueMBB->removeSuccessor(LandMBB, true);
137657baa14dSJay Foad     retireBlock(TrueMBB);
137757baa14dSJay Foad     MLI->removeBlock(TrueMBB);
137857baa14dSJay Foad   }
137957baa14dSJay Foad 
138057baa14dSJay Foad   if (FalseMBB) {
138157baa14dSJay Foad     insertInstrBefore(I, R600::ELSE);
138257baa14dSJay Foad     MBB->splice(I, FalseMBB, FalseMBB->begin(),
138357baa14dSJay Foad                    FalseMBB->end());
138457baa14dSJay Foad     MBB->removeSuccessor(FalseMBB, true);
138557baa14dSJay Foad     if (LandMBB && !FalseMBB->succ_empty())
138657baa14dSJay Foad       FalseMBB->removeSuccessor(LandMBB, true);
138757baa14dSJay Foad     retireBlock(FalseMBB);
138857baa14dSJay Foad     MLI->removeBlock(FalseMBB);
138957baa14dSJay Foad   }
139057baa14dSJay Foad   insertInstrBefore(I, R600::ENDIF);
139157baa14dSJay Foad 
139257baa14dSJay Foad   BranchMI->eraseFromParent();
139357baa14dSJay Foad 
139457baa14dSJay Foad   if (LandMBB && TrueMBB && FalseMBB)
139557baa14dSJay Foad     MBB->addSuccessor(LandMBB);
139657baa14dSJay Foad }
139757baa14dSJay Foad 
139857baa14dSJay Foad void R600MachineCFGStructurizer::mergeLooplandBlock(MachineBasicBlock *DstBlk,
139957baa14dSJay Foad     MachineBasicBlock *LandMBB) {
140057baa14dSJay Foad   LLVM_DEBUG(dbgs() << "loopPattern header = BB" << DstBlk->getNumber()
140157baa14dSJay Foad                     << " land = BB" << LandMBB->getNumber() << "\n";);
140257baa14dSJay Foad 
140357baa14dSJay Foad   insertInstrBefore(DstBlk, R600::WHILELOOP, DebugLoc());
140457baa14dSJay Foad   insertInstrEnd(DstBlk, R600::ENDLOOP, DebugLoc());
140557baa14dSJay Foad   DstBlk->replaceSuccessor(DstBlk, LandMBB);
140657baa14dSJay Foad }
140757baa14dSJay Foad 
140857baa14dSJay Foad void R600MachineCFGStructurizer::mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
140957baa14dSJay Foad     MachineBasicBlock *LandMBB) {
141057baa14dSJay Foad   LLVM_DEBUG(dbgs() << "loopbreakPattern exiting = BB"
141157baa14dSJay Foad                     << ExitingMBB->getNumber() << " land = BB"
141257baa14dSJay Foad                     << LandMBB->getNumber() << "\n";);
141357baa14dSJay Foad   MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
141457baa14dSJay Foad   assert(BranchMI && isCondBranch(BranchMI));
141557baa14dSJay Foad   DebugLoc DL = BranchMI->getDebugLoc();
141657baa14dSJay Foad   MachineBasicBlock *TrueBranch = getTrueBranch(BranchMI);
141757baa14dSJay Foad   MachineBasicBlock::iterator I = BranchMI;
141857baa14dSJay Foad   if (TrueBranch != LandMBB)
141957baa14dSJay Foad     reversePredicateSetter(I, *I->getParent());
142057baa14dSJay Foad   insertCondBranchBefore(ExitingMBB, I, R600::IF_PREDICATE_SET, R600::PREDICATE_BIT, DL);
142157baa14dSJay Foad   insertInstrBefore(I, R600::BREAK);
142257baa14dSJay Foad   insertInstrBefore(I, R600::ENDIF);
142357baa14dSJay Foad   //now branchInst can be erase safely
142457baa14dSJay Foad   BranchMI->eraseFromParent();
142557baa14dSJay Foad   //now take care of successors, retire blocks
142657baa14dSJay Foad   ExitingMBB->removeSuccessor(LandMBB, true);
142757baa14dSJay Foad }
142857baa14dSJay Foad 
142957baa14dSJay Foad void R600MachineCFGStructurizer::settleLoopcontBlock(MachineBasicBlock *ContingMBB,
143057baa14dSJay Foad     MachineBasicBlock *ContMBB) {
143157baa14dSJay Foad   LLVM_DEBUG(dbgs() << "settleLoopcontBlock conting = BB"
143257baa14dSJay Foad                     << ContingMBB->getNumber() << ", cont = BB"
143357baa14dSJay Foad                     << ContMBB->getNumber() << "\n";);
143457baa14dSJay Foad 
143557baa14dSJay Foad   MachineInstr *MI = getLoopendBlockBranchInstr(ContingMBB);
143657baa14dSJay Foad   if (MI) {
143757baa14dSJay Foad     assert(isCondBranch(MI));
143857baa14dSJay Foad     MachineBasicBlock::iterator I = MI;
143957baa14dSJay Foad     MachineBasicBlock *TrueBranch = getTrueBranch(MI);
144057baa14dSJay Foad     int OldOpcode = MI->getOpcode();
144157baa14dSJay Foad     DebugLoc DL = MI->getDebugLoc();
144257baa14dSJay Foad 
144357baa14dSJay Foad     bool UseContinueLogical = ((&*ContingMBB->rbegin()) == MI);
144457baa14dSJay Foad 
144557baa14dSJay Foad     if (!UseContinueLogical) {
144657baa14dSJay Foad       int BranchOpcode =
144757baa14dSJay Foad           TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
144857baa14dSJay Foad           getBranchZeroOpcode(OldOpcode);
144957baa14dSJay Foad       insertCondBranchBefore(I, BranchOpcode, DL);
145057baa14dSJay Foad       // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
145157baa14dSJay Foad       insertInstrEnd(ContingMBB, R600::CONTINUE, DL);
145257baa14dSJay Foad       insertInstrEnd(ContingMBB, R600::ENDIF, DL);
145357baa14dSJay Foad     } else {
145457baa14dSJay Foad       int BranchOpcode =
145557baa14dSJay Foad           TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
145657baa14dSJay Foad           getContinueZeroOpcode(OldOpcode);
145757baa14dSJay Foad       insertCondBranchBefore(I, BranchOpcode, DL);
145857baa14dSJay Foad     }
145957baa14dSJay Foad 
146057baa14dSJay Foad     MI->eraseFromParent();
146157baa14dSJay Foad   } else {
146257baa14dSJay Foad     // if we've arrived here then we've already erased the branch instruction
146357baa14dSJay Foad     // travel back up the basic block to see the last reference of our debug
146457baa14dSJay Foad     // location we've just inserted that reference here so it should be
146557baa14dSJay Foad     // representative insertEnd to ensure phi-moves, if exist, go before the
146657baa14dSJay Foad     // continue-instr.
146757baa14dSJay Foad     insertInstrEnd(ContingMBB, R600::CONTINUE,
146857baa14dSJay Foad         getLastDebugLocInBB(ContingMBB));
146957baa14dSJay Foad   }
147057baa14dSJay Foad }
147157baa14dSJay Foad 
147257baa14dSJay Foad int R600MachineCFGStructurizer::cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
147357baa14dSJay Foad     MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB) {
147457baa14dSJay Foad   int Cloned = 0;
147557baa14dSJay Foad   assert(PreMBB->isSuccessor(SrcMBB));
147657baa14dSJay Foad   while (SrcMBB && SrcMBB != DstMBB) {
147757baa14dSJay Foad     assert(SrcMBB->succ_size() == 1);
147857baa14dSJay Foad     if (SrcMBB->pred_size() > 1) {
147957baa14dSJay Foad       SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
148057baa14dSJay Foad       ++Cloned;
148157baa14dSJay Foad     }
148257baa14dSJay Foad 
148357baa14dSJay Foad     PreMBB = SrcMBB;
148457baa14dSJay Foad     SrcMBB = *SrcMBB->succ_begin();
148557baa14dSJay Foad   }
148657baa14dSJay Foad 
148757baa14dSJay Foad   return Cloned;
148857baa14dSJay Foad }
148957baa14dSJay Foad 
149057baa14dSJay Foad MachineBasicBlock *
149157baa14dSJay Foad R600MachineCFGStructurizer::cloneBlockForPredecessor(MachineBasicBlock *MBB,
149257baa14dSJay Foad     MachineBasicBlock *PredMBB) {
149357baa14dSJay Foad   assert(PredMBB->isSuccessor(MBB) && "succBlk is not a predecessor of curBlk");
149457baa14dSJay Foad 
149557baa14dSJay Foad   MachineBasicBlock *CloneMBB = clone(MBB);  //clone instructions
149657baa14dSJay Foad   replaceInstrUseOfBlockWith(PredMBB, MBB, CloneMBB);
149757baa14dSJay Foad   //srcBlk, oldBlk, newBlk
149857baa14dSJay Foad 
149957baa14dSJay Foad   PredMBB->replaceSuccessor(MBB, CloneMBB);
150057baa14dSJay Foad 
150157baa14dSJay Foad   // add all successor to cloneBlk
150257baa14dSJay Foad   cloneSuccessorList(CloneMBB, MBB);
150357baa14dSJay Foad 
150457baa14dSJay Foad   numClonedInstr += MBB->size();
150557baa14dSJay Foad 
150657baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Cloned block: "
150757baa14dSJay Foad                     << "BB" << MBB->getNumber() << "size " << MBB->size()
150857baa14dSJay Foad                     << "\n";);
150957baa14dSJay Foad 
151057baa14dSJay Foad   SHOWNEWBLK(CloneMBB, "result of Cloned block: ");
151157baa14dSJay Foad 
151257baa14dSJay Foad   return CloneMBB;
151357baa14dSJay Foad }
151457baa14dSJay Foad 
151557baa14dSJay Foad void R600MachineCFGStructurizer::migrateInstruction(MachineBasicBlock *SrcMBB,
151657baa14dSJay Foad     MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I) {
151757baa14dSJay Foad   MachineBasicBlock::iterator SpliceEnd;
151857baa14dSJay Foad   //look for the input branchinstr, not the AMDGPU branchinstr
151957baa14dSJay Foad   MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
152057baa14dSJay Foad   if (!BranchMI) {
152157baa14dSJay Foad     LLVM_DEBUG(dbgs() << "migrateInstruction don't see branch instr\n";);
152257baa14dSJay Foad     SpliceEnd = SrcMBB->end();
152357baa14dSJay Foad   } else {
152457baa14dSJay Foad     LLVM_DEBUG(dbgs() << "migrateInstruction see branch instr: " << *BranchMI);
152557baa14dSJay Foad     SpliceEnd = BranchMI;
152657baa14dSJay Foad   }
152757baa14dSJay Foad   LLVM_DEBUG(dbgs() << "migrateInstruction before splice dstSize = "
152857baa14dSJay Foad                     << DstMBB->size() << "srcSize = " << SrcMBB->size()
152957baa14dSJay Foad                     << "\n";);
153057baa14dSJay Foad 
153157baa14dSJay Foad   //splice insert before insertPos
153257baa14dSJay Foad   DstMBB->splice(I, SrcMBB, SrcMBB->begin(), SpliceEnd);
153357baa14dSJay Foad 
153457baa14dSJay Foad   LLVM_DEBUG(dbgs() << "migrateInstruction after splice dstSize = "
153557baa14dSJay Foad                     << DstMBB->size() << "srcSize = " << SrcMBB->size()
153657baa14dSJay Foad                     << '\n';);
153757baa14dSJay Foad }
153857baa14dSJay Foad 
153957baa14dSJay Foad MachineBasicBlock *
154057baa14dSJay Foad R600MachineCFGStructurizer::normalizeInfiniteLoopExit(MachineLoop* LoopRep) {
154157baa14dSJay Foad   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
154257baa14dSJay Foad   MachineBasicBlock *LoopLatch = LoopRep->getLoopLatch();
154357baa14dSJay Foad 
154457baa14dSJay Foad   if (!LoopHeader || !LoopLatch)
154557baa14dSJay Foad     return nullptr;
154657baa14dSJay Foad   MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
154757baa14dSJay Foad   // Is LoopRep an infinite loop ?
154857baa14dSJay Foad   if (!BranchMI || !isUncondBranch(BranchMI))
154957baa14dSJay Foad     return nullptr;
155057baa14dSJay Foad 
155157baa14dSJay Foad   MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
155257baa14dSJay Foad   FuncRep->push_back(DummyExitBlk);  //insert to function
155357baa14dSJay Foad   SHOWNEWBLK(DummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
155457baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Old branch instr: " << *BranchMI << "\n";);
155557baa14dSJay Foad   LLVMContext &Ctx = LoopHeader->getParent()->getFunction().getContext();
155657baa14dSJay Foad   Ctx.emitError("Extra register needed to handle CFG");
155757baa14dSJay Foad   return nullptr;
155857baa14dSJay Foad }
155957baa14dSJay Foad 
156057baa14dSJay Foad void R600MachineCFGStructurizer::removeUnconditionalBranch(MachineBasicBlock *MBB) {
156157baa14dSJay Foad   MachineInstr *BranchMI;
156257baa14dSJay Foad 
156357baa14dSJay Foad   // I saw two unconditional branch in one basic block in example
156457baa14dSJay Foad   // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
156557baa14dSJay Foad   while ((BranchMI = getLoopendBlockBranchInstr(MBB))
156657baa14dSJay Foad           && isUncondBranch(BranchMI)) {
156757baa14dSJay Foad     LLVM_DEBUG(dbgs() << "Removing uncond branch instr: " << *BranchMI);
156857baa14dSJay Foad     BranchMI->eraseFromParent();
156957baa14dSJay Foad   }
157057baa14dSJay Foad }
157157baa14dSJay Foad 
157257baa14dSJay Foad void R600MachineCFGStructurizer::removeRedundantConditionalBranch(
157357baa14dSJay Foad     MachineBasicBlock *MBB) {
157457baa14dSJay Foad   if (MBB->succ_size() != 2)
157557baa14dSJay Foad     return;
157657baa14dSJay Foad   MachineBasicBlock *MBB1 = *MBB->succ_begin();
157757baa14dSJay Foad   MachineBasicBlock *MBB2 = *std::next(MBB->succ_begin());
157857baa14dSJay Foad   if (MBB1 != MBB2)
157957baa14dSJay Foad     return;
158057baa14dSJay Foad 
158157baa14dSJay Foad   MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
158257baa14dSJay Foad   assert(BranchMI && isCondBranch(BranchMI));
158357baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Removing unneeded cond branch instr: " << *BranchMI);
158457baa14dSJay Foad   BranchMI->eraseFromParent();
158557baa14dSJay Foad   SHOWNEWBLK(MBB1, "Removing redundant successor");
158657baa14dSJay Foad   MBB->removeSuccessor(MBB1, true);
158757baa14dSJay Foad }
158857baa14dSJay Foad 
158957baa14dSJay Foad void R600MachineCFGStructurizer::addDummyExitBlock(
159057baa14dSJay Foad     SmallVectorImpl<MachineBasicBlock*> &RetMBB) {
159157baa14dSJay Foad   MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
159257baa14dSJay Foad   FuncRep->push_back(DummyExitBlk);  //insert to function
159357baa14dSJay Foad   insertInstrEnd(DummyExitBlk, R600::RETURN);
159457baa14dSJay Foad 
159557baa14dSJay Foad   for (MachineBasicBlock *MBB : RetMBB) {
159657baa14dSJay Foad     if (MachineInstr *MI = getReturnInstr(MBB))
159757baa14dSJay Foad       MI->eraseFromParent();
159857baa14dSJay Foad     MBB->addSuccessor(DummyExitBlk);
159957baa14dSJay Foad     LLVM_DEBUG(dbgs() << "Add dummyExitBlock to BB" << MBB->getNumber()
160057baa14dSJay Foad                       << " successors\n";);
160157baa14dSJay Foad   }
160257baa14dSJay Foad   SHOWNEWBLK(DummyExitBlk, "DummyExitBlock: ");
160357baa14dSJay Foad }
160457baa14dSJay Foad 
160557baa14dSJay Foad void R600MachineCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
160657baa14dSJay Foad   while (MBB->succ_size())
160757baa14dSJay Foad     MBB->removeSuccessor(*MBB->succ_begin());
160857baa14dSJay Foad }
160957baa14dSJay Foad 
161057baa14dSJay Foad void R600MachineCFGStructurizer::recordSccnum(MachineBasicBlock *MBB,
161157baa14dSJay Foad     int SccNum) {
161257baa14dSJay Foad   BlockInformation *&srcBlkInfo = BlockInfoMap[MBB];
161357baa14dSJay Foad   if (!srcBlkInfo)
161457baa14dSJay Foad     srcBlkInfo = new BlockInformation();
161557baa14dSJay Foad   srcBlkInfo->SccNum = SccNum;
161657baa14dSJay Foad }
161757baa14dSJay Foad 
161857baa14dSJay Foad void R600MachineCFGStructurizer::retireBlock(MachineBasicBlock *MBB) {
161957baa14dSJay Foad   LLVM_DEBUG(dbgs() << "Retiring BB" << MBB->getNumber() << "\n";);
162057baa14dSJay Foad 
162157baa14dSJay Foad   BlockInformation *&SrcBlkInfo = BlockInfoMap[MBB];
162257baa14dSJay Foad 
162357baa14dSJay Foad   if (!SrcBlkInfo)
162457baa14dSJay Foad     SrcBlkInfo = new BlockInformation();
162557baa14dSJay Foad 
162657baa14dSJay Foad   SrcBlkInfo->IsRetired = true;
162757baa14dSJay Foad   assert(MBB->succ_empty() && MBB->pred_empty() && "can't retire block yet");
162857baa14dSJay Foad }
162957baa14dSJay Foad 
163057baa14dSJay Foad INITIALIZE_PASS_BEGIN(R600MachineCFGStructurizer, "amdgpustructurizer",
163157baa14dSJay Foad                       "AMDGPU CFG Structurizer", false, false)
1632837dc542Spaperchalice INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
16334b24c2dfSpaperchalice INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
163479d0de2aSpaperchalice INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
163557baa14dSJay Foad INITIALIZE_PASS_END(R600MachineCFGStructurizer, "amdgpustructurizer",
163657baa14dSJay Foad                       "AMDGPU CFG Structurizer", false, false)
163757baa14dSJay Foad 
163857baa14dSJay Foad FunctionPass *llvm::createR600MachineCFGStructurizerPass() {
163957baa14dSJay Foad   return new R600MachineCFGStructurizer();
164057baa14dSJay Foad }
1641