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
2757baa14dSJay Foad #define 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
R600MachineCFGStructurizer()10757baa14dSJay Foad R600MachineCFGStructurizer() : MachineFunctionPass(ID) {
10857baa14dSJay Foad initializeR600MachineCFGStructurizerPass(*PassRegistry::getPassRegistry());
10957baa14dSJay Foad }
11057baa14dSJay Foad
getPassName() const11157baa14dSJay Foad StringRef getPassName() const override {
11257baa14dSJay Foad return "AMDGPU Control Flow Graph structurizer Pass";
11357baa14dSJay Foad }
11457baa14dSJay Foad
getAnalysisUsage(AnalysisUsage & AU) const11557baa14dSJay Foad void getAnalysisUsage(AnalysisUsage &AU) const override {
11657baa14dSJay Foad AU.addRequired<MachineDominatorTree>();
11757baa14dSJay Foad AU.addRequired<MachinePostDominatorTree>();
11857baa14dSJay Foad AU.addRequired<MachineLoopInfo>();
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
runOnMachineFunction(MachineFunction & MF)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;
14157baa14dSJay Foad MLI = &getAnalysis<MachineLoopInfo>();
14257baa14dSJay Foad LLVM_DEBUG(dbgs() << "LoopInfo:\n"; PrintLoopinfo(*MLI););
14357baa14dSJay Foad MDT = &getAnalysis<MachineDominatorTree>();
14457baa14dSJay Foad LLVM_DEBUG(MDT->print(dbgs(), (const Module *)nullptr););
14557baa14dSJay Foad PDT = &getAnalysis<MachinePostDominatorTree>();
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.
printOrderedBlocks() const16257baa14dSJay 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
PrintLoopinfo(const MachineLoopInfo & LoopInfo)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
getSCCNum(MachineBasicBlock * MBB) const32357baa14dSJay 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
getLoopLandInfo(MachineLoop * LoopRep) const33057baa14dSJay 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
hasBackEdge(MachineBasicBlock * MBB) const33857baa14dSJay 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
isRetiredBlock(MachineBasicBlock * MBB) const34657baa14dSJay 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
isActiveLoophead(MachineBasicBlock * MBB) const35357baa14dSJay 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
singlePathTo(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,bool AllowSideEntry) const36657baa14dSJay 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
countActiveBlock(MBBVector::const_iterator It,MBBVector::const_iterator E) const38457baa14dSJay 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
needMigrateBlock(MachineBasicBlock * MBB) const39557baa14dSJay 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
reversePredicateSetter(MachineBasicBlock::iterator I,MachineBasicBlock & MBB)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
insertInstrEnd(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)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
insertInstrBefore(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)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
insertInstrBefore(MachineBasicBlock::iterator I,int NewOpcode)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
insertCondBranchBefore(MachineBasicBlock::iterator I,int NewOpcode,const DebugLoc & DL)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
insertCondBranchBefore(MachineBasicBlock * blk,MachineBasicBlock::iterator I,int NewOpcode,int RegNum,const DebugLoc & DL)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
getBranchNzeroOpcode(int OldOpcode)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
getBranchZeroOpcode(int OldOpcode)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
getContinueNzeroOpcode(int OldOpcode)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
getContinueZeroOpcode(int OldOpcode)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
getTrueBranch(MachineInstr * MI)53257baa14dSJay Foad MachineBasicBlock *R600MachineCFGStructurizer::getTrueBranch(MachineInstr *MI) {
53357baa14dSJay Foad return MI->getOperand(0).getMBB();
53457baa14dSJay Foad }
53557baa14dSJay Foad
setTrueBranch(MachineInstr * MI,MachineBasicBlock * MBB)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 *
getFalseBranch(MachineBasicBlock * MBB,MachineInstr * MI)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
isCondBranch(MachineInstr * MI)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
isUncondBranch(MachineInstr * MI)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
getLastDebugLocInBB(MachineBasicBlock * MBB)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
getNormalBlockBranchInstr(MachineBasicBlock * MBB)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
getLoopendBlockBranchInstr(MachineBasicBlock * MBB)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;
60157baa14dSJay Foad else if (!TII->isMov(MI->getOpcode()))
60257baa14dSJay Foad break;
60357baa14dSJay Foad }
60457baa14dSJay Foad }
60557baa14dSJay Foad return nullptr;
60657baa14dSJay Foad }
60757baa14dSJay Foad
getReturnInstr(MachineBasicBlock * MBB)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
isReturnBlock(MachineBasicBlock * MBB)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
cloneSuccessorList(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)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
clone(MachineBasicBlock * MBB)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
replaceInstrUseOfBlockWith(MachineBasicBlock * SrcMBB,MachineBasicBlock * OldMBB,MachineBasicBlock * NewBlk)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
wrapup(MachineBasicBlock * MBB)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
67257baa14dSJay Foad for (unsigned i = 0; i < ContInstr.size(); ++i)
67357baa14dSJay Foad ContInstr[i]->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
prepare()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
run()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";);
744*bec8dff3SFangrui 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";);
785*bec8dff3SFangrui 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
orderBlocks(MachineFunction * MF)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
patternMatch(MachineBasicBlock * MBB)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
patternMatchGroup(MachineBasicBlock * MBB)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
serialPatternMatch(MachineBasicBlock * MBB)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
ifPatternMatch(MachineBasicBlock * MBB)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
loopendPatternMatch()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
mergeLoop(MachineLoop * LoopRep)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;
101757baa14dSJay Foad for (unsigned i = 0, e = ExitBlks.size(); i < e; ++i)
101857baa14dSJay Foad ExitBlkSet.insert(ExitBlks[i]);
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
102757baa14dSJay Foad for (unsigned i = 0, e = ExitingMBBs.size(); i < e; ++i)
102857baa14dSJay Foad mergeLoopbreakBlock(ExitingMBBs[i], ExitBlk);
102957baa14dSJay Foad for (unsigned i = 0, e = LatchBlks.size(); i < e; ++i)
103057baa14dSJay Foad settleLoopcontBlock(LatchBlks[i], 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
isSameloopDetachedContbreak(MachineBasicBlock * Src1MBB,MachineBasicBlock * Src2MBB)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
handleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)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
handleJumpintoIfImp(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)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
showImproveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB,bool Detail)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
improveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock ** LandMBBPtr)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
mergeSerialBlock(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)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
mergeIfthenelseBlock(MachineInstr * BranchMI,MachineBasicBlock * MBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB)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
mergeLooplandBlock(MachineBasicBlock * DstBlk,MachineBasicBlock * LandMBB)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
mergeLoopbreakBlock(MachineBasicBlock * ExitingMBB,MachineBasicBlock * LandMBB)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
settleLoopcontBlock(MachineBasicBlock * ContingMBB,MachineBasicBlock * ContMBB)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
cloneOnSideEntryTo(MachineBasicBlock * PreMBB,MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB)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 *
cloneBlockForPredecessor(MachineBasicBlock * MBB,MachineBasicBlock * PredMBB)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
migrateInstruction(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,MachineBasicBlock::iterator I)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 *
normalizeInfiniteLoopExit(MachineLoop * LoopRep)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
removeUnconditionalBranch(MachineBasicBlock * MBB)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
removeRedundantConditionalBranch(MachineBasicBlock * MBB)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
addDummyExitBlock(SmallVectorImpl<MachineBasicBlock * > & RetMBB)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
removeSuccessor(MachineBasicBlock * MBB)160557baa14dSJay Foad void R600MachineCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
160657baa14dSJay Foad while (MBB->succ_size())
160757baa14dSJay Foad MBB->removeSuccessor(*MBB->succ_begin());
160857baa14dSJay Foad }
160957baa14dSJay Foad
recordSccnum(MachineBasicBlock * MBB,int SccNum)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
retireBlock(MachineBasicBlock * MBB)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)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)163257baa14dSJay Foad INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
163357baa14dSJay Foad INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
163457baa14dSJay Foad INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
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