mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	utils/sort_includes.py script. Most of these are updating the new R600 target and fixing up a few regressions that have creeped in since the last time I sorted the includes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171362 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			3050 lines
		
	
	
		
			98 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			3050 lines
		
	
	
		
			98 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- AMDILCFGStructurizer.cpp - CFG Structurizer -----------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
/// \file
 | 
						|
//==-----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#define DEBUGME 0
 | 
						|
#define DEBUG_TYPE "structcfg"
 | 
						|
 | 
						|
#include "AMDGPUInstrInfo.h"
 | 
						|
#include "AMDIL.h"
 | 
						|
#include "llvm/ADT/SCCIterator.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
#include "llvm/ADT/Statistic.h"
 | 
						|
#include "llvm/Analysis/DominatorInternals.h"
 | 
						|
#include "llvm/Analysis/Dominators.h"
 | 
						|
#include "llvm/CodeGen/MachineDominators.h"
 | 
						|
#include "llvm/CodeGen/MachineFunction.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionPass.h"
 | 
						|
#include "llvm/CodeGen/MachineInstrBuilder.h"
 | 
						|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineLoopInfo.h"
 | 
						|
#include "llvm/CodeGen/MachinePostDominators.h"
 | 
						|
#include "llvm/CodeGen/MachineRegisterInfo.h"
 | 
						|
#include "llvm/Target/TargetInstrInfo.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
// TODO: move-begin.
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Statistics for CFGStructurizer.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
STATISTIC(numSerialPatternMatch,    "CFGStructurizer number of serial pattern "
 | 
						|
    "matched");
 | 
						|
STATISTIC(numIfPatternMatch,        "CFGStructurizer number of if pattern "
 | 
						|
    "matched");
 | 
						|
STATISTIC(numLoopbreakPatternMatch, "CFGStructurizer number of loop-break "
 | 
						|
    "pattern matched");
 | 
						|
STATISTIC(numLoopcontPatternMatch,  "CFGStructurizer number of loop-continue "
 | 
						|
    "pattern matched");
 | 
						|
STATISTIC(numLoopPatternMatch,      "CFGStructurizer number of loop pattern "
 | 
						|
    "matched");
 | 
						|
STATISTIC(numClonedBlock,           "CFGStructurizer cloned blocks");
 | 
						|
STATISTIC(numClonedInstr,           "CFGStructurizer cloned instructions");
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Miscellaneous utility for CFGStructurizer.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
namespace llvmCFGStruct {
 | 
						|
#define SHOWNEWINSTR(i) \
 | 
						|
  if (DEBUGME) errs() << "New instr: " << *i << "\n"
 | 
						|
 | 
						|
#define SHOWNEWBLK(b, msg) \
 | 
						|
if (DEBUGME) { \
 | 
						|
  errs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
 | 
						|
  errs() << "\n"; \
 | 
						|
}
 | 
						|
 | 
						|
#define SHOWBLK_DETAIL(b, msg) \
 | 
						|
if (DEBUGME) { \
 | 
						|
  if (b) { \
 | 
						|
  errs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
 | 
						|
  b->print(errs()); \
 | 
						|
  errs() << "\n"; \
 | 
						|
  } \
 | 
						|
}
 | 
						|
 | 
						|
#define INVALIDSCCNUM -1
 | 
						|
#define INVALIDREGNUM 0
 | 
						|
 | 
						|
template<class LoopinfoT>
 | 
						|
void PrintLoopinfo(const LoopinfoT &LoopInfo, llvm::raw_ostream &OS) {
 | 
						|
  for (typename LoopinfoT::iterator iter = LoopInfo.begin(),
 | 
						|
       iterEnd = LoopInfo.end();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    (*iter)->print(OS, 0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template<class NodeT>
 | 
						|
void ReverseVector(SmallVector<NodeT *, DEFAULT_VEC_SLOTS> &Src) {
 | 
						|
  size_t sz = Src.size();
 | 
						|
  for (size_t i = 0; i < sz/2; ++i) {
 | 
						|
    NodeT *t = Src[i];
 | 
						|
    Src[i] = Src[sz - i - 1];
 | 
						|
    Src[sz - i - 1] = t;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
} //end namespace llvmCFGStruct
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// supporting data structure for CFGStructurizer
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
namespace llvmCFGStruct {
 | 
						|
template<class PassT>
 | 
						|
struct CFGStructTraits {
 | 
						|
};
 | 
						|
 | 
						|
template <class InstrT>
 | 
						|
class BlockInformation {
 | 
						|
public:
 | 
						|
  bool isRetired;
 | 
						|
  int  sccNum;
 | 
						|
  //SmallVector<InstrT*, DEFAULT_VEC_SLOTS> succInstr;
 | 
						|
  //Instructions defining the corresponding successor.
 | 
						|
  BlockInformation() : isRetired(false), sccNum(INVALIDSCCNUM) {}
 | 
						|
};
 | 
						|
 | 
						|
template <class BlockT, class InstrT, class RegiT>
 | 
						|
class LandInformation {
 | 
						|
public:
 | 
						|
  BlockT *landBlk;
 | 
						|
  std::set<RegiT> breakInitRegs;  //Registers that need to "reg = 0", before
 | 
						|
                                  //WHILELOOP(thisloop) init before entering
 | 
						|
                                  //thisloop.
 | 
						|
  std::set<RegiT> contInitRegs;   //Registers that need to "reg = 0", after
 | 
						|
                                  //WHILELOOP(thisloop) init after entering
 | 
						|
                                  //thisloop.
 | 
						|
  std::set<RegiT> endbranchInitRegs; //Init before entering this loop, at loop
 | 
						|
                                     //land block, branch cond on this reg.
 | 
						|
  std::set<RegiT> breakOnRegs;       //registers that need to "if (reg) break
 | 
						|
                                     //endif" after ENDLOOP(thisloop) break
 | 
						|
                                     //outerLoopOf(thisLoop).
 | 
						|
  std::set<RegiT> contOnRegs;       //registers that need to "if (reg) continue
 | 
						|
                                    //endif" after ENDLOOP(thisloop) continue on
 | 
						|
                                    //outerLoopOf(thisLoop).
 | 
						|
  LandInformation() : landBlk(NULL) {}
 | 
						|
};
 | 
						|
 | 
						|
} //end of namespace llvmCFGStruct
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// CFGStructurizer
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
namespace llvmCFGStruct {
 | 
						|
// bixia TODO: port it to BasicBlock, not just MachineBasicBlock.
 | 
						|
template<class PassT>
 | 
						|
class  CFGStructurizer {
 | 
						|
public:
 | 
						|
  typedef enum {
 | 
						|
    Not_SinglePath = 0,
 | 
						|
    SinglePath_InPath = 1,
 | 
						|
    SinglePath_NotInPath = 2
 | 
						|
  } PathToKind;
 | 
						|
 | 
						|
public:
 | 
						|
  typedef typename PassT::InstructionType         InstrT;
 | 
						|
  typedef typename PassT::FunctionType            FuncT;
 | 
						|
  typedef typename PassT::DominatortreeType       DomTreeT;
 | 
						|
  typedef typename PassT::PostDominatortreeType   PostDomTreeT;
 | 
						|
  typedef typename PassT::DomTreeNodeType         DomTreeNodeT;
 | 
						|
  typedef typename PassT::LoopinfoType            LoopInfoT;
 | 
						|
 | 
						|
  typedef GraphTraits<FuncT *>                    FuncGTraits;
 | 
						|
  //typedef FuncGTraits::nodes_iterator BlockIterator;
 | 
						|
  typedef typename FuncT::iterator                BlockIterator;
 | 
						|
 | 
						|
  typedef typename FuncGTraits::NodeType          BlockT;
 | 
						|
  typedef GraphTraits<BlockT *>                   BlockGTraits;
 | 
						|
  typedef GraphTraits<Inverse<BlockT *> >         InvBlockGTraits;
 | 
						|
  //typedef BlockGTraits::succ_iterator InstructionIterator;
 | 
						|
  typedef typename BlockT::iterator               InstrIterator;
 | 
						|
 | 
						|
  typedef CFGStructTraits<PassT>                  CFGTraits;
 | 
						|
  typedef BlockInformation<InstrT>                BlockInfo;
 | 
						|
  typedef std::map<BlockT *, BlockInfo *>         BlockInfoMap;
 | 
						|
 | 
						|
  typedef int                                     RegiT;
 | 
						|
  typedef typename PassT::LoopType                LoopT;
 | 
						|
  typedef LandInformation<BlockT, InstrT, RegiT>  LoopLandInfo;
 | 
						|
        typedef std::map<LoopT *, LoopLandInfo *> LoopLandInfoMap;
 | 
						|
        //landing info for loop break
 | 
						|
  typedef SmallVector<BlockT *, 32>               BlockTSmallerVector;
 | 
						|
 | 
						|
public:
 | 
						|
  CFGStructurizer();
 | 
						|
  ~CFGStructurizer();
 | 
						|
 | 
						|
  /// Perform the CFG structurization
 | 
						|
  bool run(FuncT &Func, PassT &Pass, const AMDGPURegisterInfo *tri);
 | 
						|
 | 
						|
  /// Perform the CFG preparation
 | 
						|
  bool prepare(FuncT &Func, PassT &Pass, const AMDGPURegisterInfo *tri);
 | 
						|
 | 
						|
private:
 | 
						|
  void reversePredicateSetter(typename BlockT::iterator);
 | 
						|
  void   orderBlocks();
 | 
						|
  void   printOrderedBlocks(llvm::raw_ostream &OS);
 | 
						|
  int patternMatch(BlockT *CurBlock);
 | 
						|
  int patternMatchGroup(BlockT *CurBlock);
 | 
						|
 | 
						|
  int serialPatternMatch(BlockT *CurBlock);
 | 
						|
  int ifPatternMatch(BlockT *CurBlock);
 | 
						|
  int switchPatternMatch(BlockT *CurBlock);
 | 
						|
  int loopendPatternMatch(BlockT *CurBlock);
 | 
						|
  int loopPatternMatch(BlockT *CurBlock);
 | 
						|
 | 
						|
  int loopbreakPatternMatch(LoopT *LoopRep, BlockT *LoopHeader);
 | 
						|
  int loopcontPatternMatch(LoopT *LoopRep, BlockT *LoopHeader);
 | 
						|
  //int loopWithoutBreak(BlockT *);
 | 
						|
 | 
						|
  void handleLoopbreak (BlockT *ExitingBlock, LoopT *ExitingLoop,
 | 
						|
                        BlockT *ExitBlock, LoopT *exitLoop, BlockT *landBlock);
 | 
						|
  void handleLoopcontBlock(BlockT *ContingBlock, LoopT *contingLoop,
 | 
						|
                           BlockT *ContBlock, LoopT *contLoop);
 | 
						|
  bool isSameloopDetachedContbreak(BlockT *Src1Block, BlockT *Src2Block);
 | 
						|
  int handleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
 | 
						|
                       BlockT *FalseBlock);
 | 
						|
  int handleJumpintoIfImp(BlockT *HeadBlock, BlockT *TrueBlock,
 | 
						|
                          BlockT *FalseBlock);
 | 
						|
  int improveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
 | 
						|
                              BlockT *FalseBlock, BlockT **LandBlockPtr);
 | 
						|
  void showImproveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
 | 
						|
                                   BlockT *FalseBlock, BlockT *LandBlock,
 | 
						|
                                   bool Detail = false);
 | 
						|
  PathToKind singlePathTo(BlockT *SrcBlock, BlockT *DstBlock,
 | 
						|
                          bool AllowSideEntry = true);
 | 
						|
  BlockT *singlePathEnd(BlockT *srcBlock, BlockT *DstBlock,
 | 
						|
                        bool AllowSideEntry = true);
 | 
						|
  int cloneOnSideEntryTo(BlockT *PreBlock, BlockT *SrcBlock, BlockT *DstBlock);
 | 
						|
  void mergeSerialBlock(BlockT *DstBlock, BlockT *srcBlock);
 | 
						|
 | 
						|
  void mergeIfthenelseBlock(InstrT *BranchInstr, BlockT *CurBlock,
 | 
						|
                            BlockT *TrueBlock, BlockT *FalseBlock,
 | 
						|
                            BlockT *LandBlock);
 | 
						|
  void mergeLooplandBlock(BlockT *DstBlock, LoopLandInfo *LoopLand);
 | 
						|
  void mergeLoopbreakBlock(BlockT *ExitingBlock, BlockT *ExitBlock,
 | 
						|
                           BlockT *ExitLandBlock, RegiT SetReg);
 | 
						|
  void settleLoopcontBlock(BlockT *ContingBlock, BlockT *ContBlock,
 | 
						|
                           RegiT SetReg);
 | 
						|
  BlockT *relocateLoopcontBlock(LoopT *ParentLoopRep, LoopT *LoopRep,
 | 
						|
                                std::set<BlockT*> &ExitBlockSet,
 | 
						|
                                BlockT *ExitLandBlk);
 | 
						|
  BlockT *addLoopEndbranchBlock(LoopT *LoopRep,
 | 
						|
                                BlockTSmallerVector &ExitingBlocks,
 | 
						|
                                BlockTSmallerVector &ExitBlocks);
 | 
						|
  BlockT *normalizeInfiniteLoopExit(LoopT *LoopRep);
 | 
						|
  void removeUnconditionalBranch(BlockT *SrcBlock);
 | 
						|
  void removeRedundantConditionalBranch(BlockT *SrcBlock);
 | 
						|
  void addDummyExitBlock(SmallVector<BlockT *, DEFAULT_VEC_SLOTS> &RetBlocks);
 | 
						|
 | 
						|
  void removeSuccessor(BlockT *SrcBlock);
 | 
						|
  BlockT *cloneBlockForPredecessor(BlockT *CurBlock, BlockT *PredBlock);
 | 
						|
  BlockT *exitingBlock2ExitBlock (LoopT *LoopRep, BlockT *exitingBlock);
 | 
						|
 | 
						|
  void migrateInstruction(BlockT *SrcBlock, BlockT *DstBlock,
 | 
						|
                          InstrIterator InsertPos);
 | 
						|
 | 
						|
  void recordSccnum(BlockT *SrcBlock, int SCCNum);
 | 
						|
  int getSCCNum(BlockT *srcBlk);
 | 
						|
 | 
						|
  void retireBlock(BlockT *DstBlock, BlockT *SrcBlock);
 | 
						|
  bool isRetiredBlock(BlockT *SrcBlock);
 | 
						|
  bool isActiveLoophead(BlockT *CurBlock);
 | 
						|
  bool needMigrateBlock(BlockT *Block);
 | 
						|
 | 
						|
  BlockT *recordLoopLandBlock(LoopT *LoopRep, BlockT *LandBlock,
 | 
						|
                              BlockTSmallerVector &exitBlocks,
 | 
						|
                              std::set<BlockT*> &ExitBlockSet);
 | 
						|
  void setLoopLandBlock(LoopT *LoopRep, BlockT *Block = NULL);
 | 
						|
  BlockT *getLoopLandBlock(LoopT *LoopRep);
 | 
						|
  LoopLandInfo *getLoopLandInfo(LoopT *LoopRep);
 | 
						|
 | 
						|
  void addLoopBreakOnReg(LoopT *LoopRep, RegiT RegNum);
 | 
						|
  void addLoopContOnReg(LoopT *LoopRep, RegiT RegNum);
 | 
						|
  void addLoopBreakInitReg(LoopT *LoopRep, RegiT RegNum);
 | 
						|
  void addLoopContInitReg(LoopT *LoopRep, RegiT RegNum);
 | 
						|
  void addLoopEndbranchInitReg(LoopT *LoopRep, RegiT RegNum);
 | 
						|
 | 
						|
  bool hasBackEdge(BlockT *curBlock);
 | 
						|
  unsigned getLoopDepth  (LoopT *LoopRep);
 | 
						|
  int countActiveBlock(
 | 
						|
    typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator IterStart,
 | 
						|
    typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator IterEnd);
 | 
						|
    BlockT *findNearestCommonPostDom(std::set<BlockT *>&);
 | 
						|
  BlockT *findNearestCommonPostDom(BlockT *Block1, BlockT *Block2);
 | 
						|
 | 
						|
private:
 | 
						|
  DomTreeT *domTree;
 | 
						|
  PostDomTreeT *postDomTree;
 | 
						|
  LoopInfoT *loopInfo;
 | 
						|
  PassT *passRep;
 | 
						|
  FuncT *funcRep;
 | 
						|
 | 
						|
  BlockInfoMap blockInfoMap;
 | 
						|
  LoopLandInfoMap loopLandInfoMap;
 | 
						|
  SmallVector<BlockT *, DEFAULT_VEC_SLOTS> orderedBlks;
 | 
						|
  const AMDGPURegisterInfo *TRI;
 | 
						|
 | 
						|
};  //template class CFGStructurizer
 | 
						|
 | 
						|
template<class PassT> CFGStructurizer<PassT>::CFGStructurizer()
 | 
						|
  : domTree(NULL), postDomTree(NULL), loopInfo(NULL) {
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT> CFGStructurizer<PassT>::~CFGStructurizer() {
 | 
						|
  for (typename BlockInfoMap::iterator I = blockInfoMap.begin(),
 | 
						|
       E = blockInfoMap.end(); I != E; ++I) {
 | 
						|
    delete I->second;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::prepare(FuncT &func, PassT &pass,
 | 
						|
                                     const AMDGPURegisterInfo * tri) {
 | 
						|
  passRep = &pass;
 | 
						|
  funcRep = &func;
 | 
						|
  TRI = tri;
 | 
						|
 | 
						|
  bool changed = false;
 | 
						|
 | 
						|
  //FIXME: if not reducible flow graph, make it so ???
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
        errs() << "AMDGPUCFGStructurizer::prepare\n";
 | 
						|
  }
 | 
						|
 | 
						|
  loopInfo = CFGTraits::getLoopInfo(pass);
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "LoopInfo:\n";
 | 
						|
    PrintLoopinfo(*loopInfo, errs());
 | 
						|
  }
 | 
						|
 | 
						|
  orderBlocks();
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Ordered blocks:\n";
 | 
						|
    printOrderedBlocks(errs());
 | 
						|
  }
 | 
						|
 | 
						|
  SmallVector<BlockT *, DEFAULT_VEC_SLOTS> retBlks;
 | 
						|
 | 
						|
  for (typename LoopInfoT::iterator iter = loopInfo->begin(),
 | 
						|
       iterEnd = loopInfo->end();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    LoopT* loopRep = (*iter);
 | 
						|
    BlockTSmallerVector exitingBlks;
 | 
						|
    loopRep->getExitingBlocks(exitingBlks);
 | 
						|
    
 | 
						|
    if (exitingBlks.size() == 0) {
 | 
						|
      BlockT* dummyExitBlk = normalizeInfiniteLoopExit(loopRep);
 | 
						|
      if (dummyExitBlk != NULL)
 | 
						|
        retBlks.push_back(dummyExitBlk);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Remove unconditional branch instr.
 | 
						|
  // Add dummy exit block iff there are multiple returns.
 | 
						|
 | 
						|
  for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator
 | 
						|
       iterBlk = orderedBlks.begin(), iterEndBlk = orderedBlks.end();
 | 
						|
       iterBlk != iterEndBlk;
 | 
						|
       ++iterBlk) {
 | 
						|
    BlockT *curBlk = *iterBlk;
 | 
						|
    removeUnconditionalBranch(curBlk);
 | 
						|
    removeRedundantConditionalBranch(curBlk);
 | 
						|
    if (CFGTraits::isReturnBlock(curBlk)) {
 | 
						|
      retBlks.push_back(curBlk);
 | 
						|
    }
 | 
						|
    assert(curBlk->succ_size() <= 2);
 | 
						|
  } //for
 | 
						|
 | 
						|
  if (retBlks.size() >= 2) {
 | 
						|
    addDummyExitBlock(retBlks);
 | 
						|
    changed = true;
 | 
						|
  }
 | 
						|
 | 
						|
  return changed;
 | 
						|
} //CFGStructurizer::prepare
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::run(FuncT &func, PassT &pass,
 | 
						|
    const AMDGPURegisterInfo * tri) {
 | 
						|
  passRep = &pass;
 | 
						|
  funcRep = &func;
 | 
						|
  TRI = tri;
 | 
						|
 | 
						|
  //Assume reducible CFG...
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "AMDGPUCFGStructurizer::run\n";
 | 
						|
    func.viewCFG();
 | 
						|
  }
 | 
						|
 | 
						|
  domTree = CFGTraits::getDominatorTree(pass);
 | 
						|
  if (DEBUGME) {
 | 
						|
    domTree->print(errs(), (const llvm::Module*)0);
 | 
						|
  }
 | 
						|
 | 
						|
  postDomTree = CFGTraits::getPostDominatorTree(pass);
 | 
						|
  if (DEBUGME) {
 | 
						|
    postDomTree->print(errs());
 | 
						|
  }
 | 
						|
 | 
						|
  loopInfo = CFGTraits::getLoopInfo(pass);
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "LoopInfo:\n";
 | 
						|
    PrintLoopinfo(*loopInfo, errs());
 | 
						|
  }
 | 
						|
 | 
						|
  orderBlocks();
 | 
						|
#ifdef STRESSTEST
 | 
						|
  //Use the worse block ordering to test the algorithm.
 | 
						|
  ReverseVector(orderedBlks);
 | 
						|
#endif
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Ordered blocks:\n";
 | 
						|
    printOrderedBlocks(errs());
 | 
						|
  }
 | 
						|
  int numIter = 0;
 | 
						|
  bool finish = false;
 | 
						|
  BlockT *curBlk;
 | 
						|
  bool makeProgress = false;
 | 
						|
  int numRemainedBlk = countActiveBlock(orderedBlks.begin(),
 | 
						|
                                        orderedBlks.end());
 | 
						|
 | 
						|
  do {
 | 
						|
    ++numIter;
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "numIter = " << numIter
 | 
						|
             << ", numRemaintedBlk = " << numRemainedBlk << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator
 | 
						|
      iterBlk = orderedBlks.begin();
 | 
						|
    typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator
 | 
						|
      iterBlkEnd = orderedBlks.end();
 | 
						|
 | 
						|
    typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator
 | 
						|
      sccBeginIter = iterBlk;
 | 
						|
    BlockT *sccBeginBlk = NULL;
 | 
						|
    int sccNumBlk = 0;  // The number of active blocks, init to a
 | 
						|
                        // maximum possible number.
 | 
						|
    int sccNumIter;     // Number of iteration in this SCC.
 | 
						|
 | 
						|
    while (iterBlk != iterBlkEnd) {
 | 
						|
      curBlk = *iterBlk;
 | 
						|
 | 
						|
      if (sccBeginBlk == NULL) {
 | 
						|
        sccBeginIter = iterBlk;
 | 
						|
        sccBeginBlk = curBlk;
 | 
						|
        sccNumIter = 0;
 | 
						|
        sccNumBlk = numRemainedBlk; // Init to maximum possible number.
 | 
						|
        if (DEBUGME) {
 | 
						|
              errs() << "start processing SCC" << getSCCNum(sccBeginBlk);
 | 
						|
              errs() << "\n";
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (!isRetiredBlock(curBlk)) {
 | 
						|
        patternMatch(curBlk);
 | 
						|
      }
 | 
						|
 | 
						|
      ++iterBlk;
 | 
						|
 | 
						|
      bool contNextScc = true;
 | 
						|
      if (iterBlk == iterBlkEnd
 | 
						|
          || getSCCNum(sccBeginBlk) != getSCCNum(*iterBlk)) {
 | 
						|
        // Just finish one scc.
 | 
						|
        ++sccNumIter;
 | 
						|
        int sccRemainedNumBlk = countActiveBlock(sccBeginIter, iterBlk);
 | 
						|
        if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= sccNumBlk) {
 | 
						|
          if (DEBUGME) {
 | 
						|
            errs() << "Can't reduce SCC " << getSCCNum(curBlk)
 | 
						|
                   << ", sccNumIter = " << sccNumIter;
 | 
						|
            errs() << "doesn't make any progress\n";
 | 
						|
          }
 | 
						|
          contNextScc = true;
 | 
						|
        } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < sccNumBlk) {
 | 
						|
          sccNumBlk = sccRemainedNumBlk;
 | 
						|
          iterBlk = sccBeginIter;
 | 
						|
          contNextScc = false;
 | 
						|
          if (DEBUGME) {
 | 
						|
            errs() << "repeat processing SCC" << getSCCNum(curBlk)
 | 
						|
                   << "sccNumIter = " << sccNumIter << "\n";
 | 
						|
            func.viewCFG();
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          // Finish the current scc.
 | 
						|
          contNextScc = true;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        // Continue on next component in the current scc.
 | 
						|
        contNextScc = false;
 | 
						|
      }
 | 
						|
 | 
						|
      if (contNextScc) {
 | 
						|
        sccBeginBlk = NULL;
 | 
						|
      }
 | 
						|
    } //while, "one iteration" over the function.
 | 
						|
 | 
						|
    BlockT *entryBlk = FuncGTraits::nodes_begin(&func);
 | 
						|
    if (entryBlk->succ_size() == 0) {
 | 
						|
      finish = true;
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "Reduce to one block\n";
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      int newnumRemainedBlk
 | 
						|
        = countActiveBlock(orderedBlks.begin(), orderedBlks.end());
 | 
						|
      // consider cloned blocks ??
 | 
						|
      if (newnumRemainedBlk == 1 || newnumRemainedBlk < numRemainedBlk) {
 | 
						|
        makeProgress = true;
 | 
						|
        numRemainedBlk = newnumRemainedBlk;
 | 
						|
      } else {
 | 
						|
        makeProgress = false;
 | 
						|
        if (DEBUGME) {
 | 
						|
          errs() << "No progress\n";
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (!finish && makeProgress);
 | 
						|
 | 
						|
  // Misc wrap up to maintain the consistency of the Function representation.
 | 
						|
  CFGTraits::wrapup(FuncGTraits::nodes_begin(&func));
 | 
						|
 | 
						|
  // Detach retired Block, release memory.
 | 
						|
  for (typename BlockInfoMap::iterator iterMap = blockInfoMap.begin(),
 | 
						|
       iterEndMap = blockInfoMap.end(); iterMap != iterEndMap; ++iterMap) {
 | 
						|
    if ((*iterMap).second && (*iterMap).second->isRetired) {
 | 
						|
      assert(((*iterMap).first)->getNumber() != -1);
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "Erase BB" << ((*iterMap).first)->getNumber() << "\n";
 | 
						|
      }
 | 
						|
      (*iterMap).first->eraseFromParent();  //Remove from the parent Function.
 | 
						|
    }
 | 
						|
    delete (*iterMap).second;
 | 
						|
  }
 | 
						|
  blockInfoMap.clear();
 | 
						|
 | 
						|
  // clear loopLandInfoMap
 | 
						|
  for (typename LoopLandInfoMap::iterator iterMap = loopLandInfoMap.begin(),
 | 
						|
       iterEndMap = loopLandInfoMap.end(); iterMap != iterEndMap; ++iterMap) {
 | 
						|
    delete (*iterMap).second;
 | 
						|
  }
 | 
						|
  loopLandInfoMap.clear();
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    func.viewCFG();
 | 
						|
  }
 | 
						|
 | 
						|
  if (!finish) {
 | 
						|
    assert(!"IRREDUCIBL_CF");
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
} //CFGStructurizer::run
 | 
						|
 | 
						|
/// Print the ordered Blocks.
 | 
						|
///
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::printOrderedBlocks(llvm::raw_ostream &os) {
 | 
						|
  size_t i = 0;
 | 
						|
  for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator
 | 
						|
      iterBlk = orderedBlks.begin(), iterBlkEnd = orderedBlks.end();
 | 
						|
       iterBlk != iterBlkEnd;
 | 
						|
       ++iterBlk, ++i) {
 | 
						|
    os << "BB" << (*iterBlk)->getNumber();
 | 
						|
    os << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
 | 
						|
    if (i != 0 && i % 10 == 0) {
 | 
						|
      os << "\n";
 | 
						|
    } else {
 | 
						|
      os << " ";
 | 
						|
    }
 | 
						|
  }
 | 
						|
} //printOrderedBlocks
 | 
						|
 | 
						|
/// Compute the reversed DFS post order of Blocks
 | 
						|
///
 | 
						|
template<class PassT> void CFGStructurizer<PassT>::orderBlocks() {
 | 
						|
  int sccNum = 0;
 | 
						|
  BlockT *bb;
 | 
						|
  for (scc_iterator<FuncT *> sccIter = scc_begin(funcRep),
 | 
						|
       sccEnd = scc_end(funcRep); sccIter != sccEnd; ++sccIter, ++sccNum) {
 | 
						|
    std::vector<BlockT *> &sccNext = *sccIter;
 | 
						|
    for (typename std::vector<BlockT *>::const_iterator
 | 
						|
         blockIter = sccNext.begin(), blockEnd = sccNext.end();
 | 
						|
         blockIter != blockEnd; ++blockIter) {
 | 
						|
      bb = *blockIter;
 | 
						|
      orderedBlks.push_back(bb);
 | 
						|
      recordSccnum(bb, sccNum);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //walk through all the block in func to check for unreachable
 | 
						|
  for (BlockIterator blockIter1 = FuncGTraits::nodes_begin(funcRep),
 | 
						|
       blockEnd1 = FuncGTraits::nodes_end(funcRep);
 | 
						|
       blockIter1 != blockEnd1; ++blockIter1) {
 | 
						|
    BlockT *bb = &(*blockIter1);
 | 
						|
    sccNum = getSCCNum(bb);
 | 
						|
    if (sccNum == INVALIDSCCNUM) {
 | 
						|
      errs() << "unreachable block BB" << bb->getNumber() << "\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
} //orderBlocks
 | 
						|
 | 
						|
template<class PassT> int CFGStructurizer<PassT>::patternMatch(BlockT *curBlk) {
 | 
						|
  int numMatch = 0;
 | 
						|
  int curMatch;
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
        errs() << "Begin patternMatch BB" << curBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  while ((curMatch = patternMatchGroup(curBlk)) > 0) {
 | 
						|
    numMatch += curMatch;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
        errs() << "End patternMatch BB" << curBlk->getNumber()
 | 
						|
      << ", numMatch = " << numMatch << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  return numMatch;
 | 
						|
} //patternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::patternMatchGroup(BlockT *curBlk) {
 | 
						|
  int numMatch = 0;
 | 
						|
  numMatch += serialPatternMatch(curBlk);
 | 
						|
  numMatch += ifPatternMatch(curBlk);
 | 
						|
  numMatch += loopendPatternMatch(curBlk);
 | 
						|
  numMatch += loopPatternMatch(curBlk);
 | 
						|
  return numMatch;
 | 
						|
}//patternMatchGroup
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::serialPatternMatch(BlockT *curBlk) {
 | 
						|
  if (curBlk->succ_size() != 1) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  BlockT *childBlk = *curBlk->succ_begin();
 | 
						|
  if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  mergeSerialBlock(curBlk, childBlk);
 | 
						|
  ++numSerialPatternMatch;
 | 
						|
  return 1;
 | 
						|
} //serialPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::ifPatternMatch(BlockT *curBlk) {
 | 
						|
  //two edges
 | 
						|
  if (curBlk->succ_size() != 2) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (hasBackEdge(curBlk)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(curBlk);
 | 
						|
  if (branchInstr == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  assert(CFGTraits::isCondBranch(branchInstr));
 | 
						|
 | 
						|
  BlockT *trueBlk = CFGTraits::getTrueBranch(branchInstr);
 | 
						|
  BlockT *falseBlk = CFGTraits::getFalseBranch(curBlk, branchInstr);
 | 
						|
  BlockT *landBlk;
 | 
						|
  int cloned = 0;
 | 
						|
 | 
						|
  // TODO: Simplify
 | 
						|
  if (trueBlk->succ_size() == 1 && falseBlk->succ_size() == 1
 | 
						|
    && *trueBlk->succ_begin() == *falseBlk->succ_begin()) {
 | 
						|
    landBlk = *trueBlk->succ_begin();
 | 
						|
  } else if (trueBlk->succ_size() == 0 && falseBlk->succ_size() == 0) {
 | 
						|
    landBlk = NULL;
 | 
						|
  } else if (trueBlk->succ_size() == 1 && *trueBlk->succ_begin() == falseBlk) {
 | 
						|
    landBlk = falseBlk;
 | 
						|
    falseBlk = NULL;
 | 
						|
  } else if (falseBlk->succ_size() == 1
 | 
						|
             && *falseBlk->succ_begin() == trueBlk) {
 | 
						|
    landBlk = trueBlk;
 | 
						|
    trueBlk = NULL;
 | 
						|
  } else if (falseBlk->succ_size() == 1
 | 
						|
             && isSameloopDetachedContbreak(trueBlk, falseBlk)) {
 | 
						|
    landBlk = *falseBlk->succ_begin();
 | 
						|
  } else if (trueBlk->succ_size() == 1
 | 
						|
    && isSameloopDetachedContbreak(falseBlk, trueBlk)) {
 | 
						|
    landBlk = *trueBlk->succ_begin();
 | 
						|
  } else {
 | 
						|
    return handleJumpintoIf(curBlk, trueBlk, falseBlk);
 | 
						|
  }
 | 
						|
 | 
						|
  // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
 | 
						|
  // new BB created for landBlk==NULL may introduce new challenge to the
 | 
						|
  // reduction process.
 | 
						|
  if (landBlk != NULL &&
 | 
						|
      ((trueBlk && trueBlk->pred_size() > 1)
 | 
						|
      || (falseBlk && falseBlk->pred_size() > 1))) {
 | 
						|
     cloned += improveSimpleJumpintoIf(curBlk, trueBlk, falseBlk, &landBlk);
 | 
						|
  }
 | 
						|
 | 
						|
  if (trueBlk && trueBlk->pred_size() > 1) {
 | 
						|
    trueBlk = cloneBlockForPredecessor(trueBlk, curBlk);
 | 
						|
    ++cloned;
 | 
						|
  }
 | 
						|
 | 
						|
  if (falseBlk && falseBlk->pred_size() > 1) {
 | 
						|
    falseBlk = cloneBlockForPredecessor(falseBlk, curBlk);
 | 
						|
    ++cloned;
 | 
						|
  }
 | 
						|
 | 
						|
  mergeIfthenelseBlock(branchInstr, curBlk, trueBlk, falseBlk, landBlk);
 | 
						|
 | 
						|
  ++numIfPatternMatch;
 | 
						|
 | 
						|
  numClonedBlock += cloned;
 | 
						|
 | 
						|
  return 1 + cloned;
 | 
						|
} //ifPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::switchPatternMatch(BlockT *curBlk) {
 | 
						|
  return 0;
 | 
						|
} //switchPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::loopendPatternMatch(BlockT *curBlk) {
 | 
						|
  LoopT *loopRep = loopInfo->getLoopFor(curBlk);
 | 
						|
  typename std::vector<LoopT *> nestedLoops;
 | 
						|
  while (loopRep) {
 | 
						|
    nestedLoops.push_back(loopRep);
 | 
						|
    loopRep = loopRep->getParentLoop();
 | 
						|
  }
 | 
						|
 | 
						|
  if (nestedLoops.size() == 0) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // Process nested loop outside->inside, so "continue" to a outside loop won't
 | 
						|
  // be mistaken as "break" of the current loop.
 | 
						|
  int num = 0;
 | 
						|
  for (typename std::vector<LoopT *>::reverse_iterator
 | 
						|
       iter = nestedLoops.rbegin(), iterEnd = nestedLoops.rend();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    loopRep = *iter;
 | 
						|
 | 
						|
    if (getLoopLandBlock(loopRep) != NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    BlockT *loopHeader = loopRep->getHeader();
 | 
						|
 | 
						|
    int numBreak = loopbreakPatternMatch(loopRep, loopHeader);
 | 
						|
 | 
						|
    if (numBreak == -1) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    int numCont = loopcontPatternMatch(loopRep, loopHeader);
 | 
						|
    num += numBreak + numCont;
 | 
						|
  }
 | 
						|
 | 
						|
  return num;
 | 
						|
} //loopendPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::loopPatternMatch(BlockT *curBlk) {
 | 
						|
  if (curBlk->succ_size() != 0) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  int numLoop = 0;
 | 
						|
  LoopT *loopRep = loopInfo->getLoopFor(curBlk);
 | 
						|
  while (loopRep && loopRep->getHeader() == curBlk) {
 | 
						|
    LoopLandInfo *loopLand = getLoopLandInfo(loopRep);
 | 
						|
    if (loopLand) {
 | 
						|
      BlockT *landBlk = loopLand->landBlk;
 | 
						|
      assert(landBlk);
 | 
						|
      if (!isRetiredBlock(landBlk)) {
 | 
						|
        mergeLooplandBlock(curBlk, loopLand);
 | 
						|
        ++numLoop;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    loopRep = loopRep->getParentLoop();
 | 
						|
  }
 | 
						|
 | 
						|
  numLoopPatternMatch += numLoop;
 | 
						|
 | 
						|
  return numLoop;
 | 
						|
} //loopPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::loopbreakPatternMatch(LoopT *loopRep,
 | 
						|
                                                  BlockT *loopHeader) {
 | 
						|
  BlockTSmallerVector exitingBlks;
 | 
						|
  loopRep->getExitingBlocks(exitingBlks);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Loop has " << exitingBlks.size() << " exiting blocks\n";
 | 
						|
  }
 | 
						|
 | 
						|
  if (exitingBlks.size() == 0) {
 | 
						|
    setLoopLandBlock(loopRep);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // Compute the corresponding exitBlks and exit block set.
 | 
						|
  BlockTSmallerVector exitBlks;
 | 
						|
  std::set<BlockT *> exitBlkSet;
 | 
						|
  for (typename BlockTSmallerVector::const_iterator iter = exitingBlks.begin(),
 | 
						|
       iterEnd = exitingBlks.end(); iter != iterEnd; ++iter) {
 | 
						|
    BlockT *exitingBlk = *iter;
 | 
						|
    BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk);
 | 
						|
    exitBlks.push_back(exitBlk);
 | 
						|
    exitBlkSet.insert(exitBlk);  //non-duplicate insert
 | 
						|
  }
 | 
						|
 | 
						|
  assert(exitBlkSet.size() > 0);
 | 
						|
  assert(exitBlks.size() == exitingBlks.size());
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Loop has " << exitBlkSet.size() << " exit blocks\n";
 | 
						|
  }
 | 
						|
 | 
						|
  // Find exitLandBlk.
 | 
						|
  BlockT *exitLandBlk = NULL;
 | 
						|
  int numCloned = 0;
 | 
						|
  int numSerial = 0;
 | 
						|
 | 
						|
  if (exitBlkSet.size() == 1) {
 | 
						|
    exitLandBlk = *exitBlkSet.begin();
 | 
						|
  } else {
 | 
						|
    exitLandBlk = findNearestCommonPostDom(exitBlkSet);
 | 
						|
 | 
						|
    if (exitLandBlk == NULL) {
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    bool allInPath = true;
 | 
						|
    bool allNotInPath = true;
 | 
						|
    for (typename std::set<BlockT*>::const_iterator
 | 
						|
         iter = exitBlkSet.begin(),
 | 
						|
         iterEnd = exitBlkSet.end();
 | 
						|
         iter != iterEnd; ++iter) {
 | 
						|
      BlockT *exitBlk = *iter;
 | 
						|
 | 
						|
      PathToKind pathKind = singlePathTo(exitBlk, exitLandBlk, true);
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "BB" << exitBlk->getNumber()
 | 
						|
               << " to BB" << exitLandBlk->getNumber() << " PathToKind="
 | 
						|
               << pathKind << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      allInPath = allInPath && (pathKind == SinglePath_InPath);
 | 
						|
      allNotInPath = allNotInPath && (pathKind == SinglePath_NotInPath);
 | 
						|
 | 
						|
      if (!allInPath && !allNotInPath) {
 | 
						|
        if (DEBUGME) {
 | 
						|
              errs() << "singlePath check fail\n";
 | 
						|
        }
 | 
						|
        return -1;
 | 
						|
      }
 | 
						|
    } // check all exit blocks
 | 
						|
 | 
						|
    if (allNotInPath) {
 | 
						|
 | 
						|
      // TODO: Simplify, maybe separate function?
 | 
						|
      LoopT *parentLoopRep = loopRep->getParentLoop();
 | 
						|
      BlockT *parentLoopHeader = NULL;
 | 
						|
      if (parentLoopRep)
 | 
						|
        parentLoopHeader = parentLoopRep->getHeader();
 | 
						|
 | 
						|
      if (exitLandBlk == parentLoopHeader &&
 | 
						|
          (exitLandBlk = relocateLoopcontBlock(parentLoopRep,
 | 
						|
                                               loopRep,
 | 
						|
                                               exitBlkSet,
 | 
						|
                                               exitLandBlk)) != NULL) {
 | 
						|
        if (DEBUGME) {
 | 
						|
          errs() << "relocateLoopcontBlock success\n";
 | 
						|
        }
 | 
						|
      } else if ((exitLandBlk = addLoopEndbranchBlock(loopRep,
 | 
						|
                                                      exitingBlks,
 | 
						|
                                                      exitBlks)) != NULL) {
 | 
						|
        if (DEBUGME) {
 | 
						|
          errs() << "insertEndbranchBlock success\n";
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (DEBUGME) {
 | 
						|
          errs() << "loop exit fail\n";
 | 
						|
        }
 | 
						|
        return -1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // Handle side entry to exit path.
 | 
						|
    exitBlks.clear();
 | 
						|
    exitBlkSet.clear();
 | 
						|
    for (typename BlockTSmallerVector::iterator iterExiting =
 | 
						|
           exitingBlks.begin(),
 | 
						|
         iterExitingEnd = exitingBlks.end();
 | 
						|
         iterExiting != iterExitingEnd; ++iterExiting) {
 | 
						|
      BlockT *exitingBlk = *iterExiting;
 | 
						|
      BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk);
 | 
						|
      BlockT *newExitBlk = exitBlk;
 | 
						|
 | 
						|
      if (exitBlk != exitLandBlk && exitBlk->pred_size() > 1) {
 | 
						|
        newExitBlk = cloneBlockForPredecessor(exitBlk, exitingBlk);
 | 
						|
        ++numCloned;
 | 
						|
      }
 | 
						|
 | 
						|
      numCloned += cloneOnSideEntryTo(exitingBlk, newExitBlk, exitLandBlk);
 | 
						|
 | 
						|
      exitBlks.push_back(newExitBlk);
 | 
						|
      exitBlkSet.insert(newExitBlk);
 | 
						|
    }
 | 
						|
 | 
						|
    for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(),
 | 
						|
         iterExitEnd = exitBlks.end();
 | 
						|
         iterExit != iterExitEnd; ++iterExit) {
 | 
						|
      BlockT *exitBlk = *iterExit;
 | 
						|
      numSerial += serialPatternMatch(exitBlk);
 | 
						|
    }
 | 
						|
 | 
						|
    for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(),
 | 
						|
         iterExitEnd = exitBlks.end();
 | 
						|
         iterExit != iterExitEnd; ++iterExit) {
 | 
						|
      BlockT *exitBlk = *iterExit;
 | 
						|
      if (exitBlk->pred_size() > 1) {
 | 
						|
        if (exitBlk != exitLandBlk) {
 | 
						|
          return -1;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        if (exitBlk != exitLandBlk &&
 | 
						|
            (exitBlk->succ_size() != 1 ||
 | 
						|
            *exitBlk->succ_begin() != exitLandBlk)) {
 | 
						|
          return -1;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } // else
 | 
						|
 | 
						|
  exitLandBlk = recordLoopLandBlock(loopRep, exitLandBlk, exitBlks, exitBlkSet);
 | 
						|
 | 
						|
  // Fold break into the breaking block. Leverage across level breaks.
 | 
						|
  assert(exitingBlks.size() == exitBlks.size());
 | 
						|
  for (typename BlockTSmallerVector::const_iterator iterExit = exitBlks.begin(),
 | 
						|
       iterExiting = exitingBlks.begin(), iterExitEnd = exitBlks.end();
 | 
						|
       iterExit != iterExitEnd; ++iterExit, ++iterExiting) {
 | 
						|
    BlockT *exitBlk = *iterExit;
 | 
						|
    BlockT *exitingBlk = *iterExiting;
 | 
						|
    assert(exitBlk->pred_size() == 1 || exitBlk == exitLandBlk);
 | 
						|
    LoopT *exitingLoop = loopInfo->getLoopFor(exitingBlk);
 | 
						|
    handleLoopbreak(exitingBlk, exitingLoop, exitBlk, loopRep, exitLandBlk);
 | 
						|
  }
 | 
						|
 | 
						|
  int numBreak = static_cast<int>(exitingBlks.size());
 | 
						|
  numLoopbreakPatternMatch += numBreak;
 | 
						|
  numClonedBlock += numCloned;
 | 
						|
  return numBreak + numSerial + numCloned;
 | 
						|
} //loopbreakPatternMatch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::loopcontPatternMatch(LoopT *loopRep,
 | 
						|
                                                 BlockT *loopHeader) {
 | 
						|
  int numCont = 0;
 | 
						|
  SmallVector<BlockT *, DEFAULT_VEC_SLOTS> contBlk;
 | 
						|
  for (typename InvBlockGTraits::ChildIteratorType iter =
 | 
						|
       InvBlockGTraits::child_begin(loopHeader),
 | 
						|
       iterEnd = InvBlockGTraits::child_end(loopHeader);
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    BlockT *curBlk = *iter;
 | 
						|
    if (loopRep->contains(curBlk)) {
 | 
						|
      handleLoopcontBlock(curBlk, loopInfo->getLoopFor(curBlk),
 | 
						|
                          loopHeader, loopRep);
 | 
						|
      contBlk.push_back(curBlk);
 | 
						|
      ++numCont;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::iterator
 | 
						|
       iter = contBlk.begin(), iterEnd = contBlk.end();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    (*iter)->removeSuccessor(loopHeader);
 | 
						|
  }
 | 
						|
 | 
						|
  numLoopcontPatternMatch += numCont;
 | 
						|
 | 
						|
  return numCont;
 | 
						|
} //loopcontPatternMatch
 | 
						|
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::isSameloopDetachedContbreak(BlockT *src1Blk,
 | 
						|
                                                         BlockT *src2Blk) {
 | 
						|
  // return true iff src1Blk->succ_size() == 0 && src1Blk and src2Blk are in the
 | 
						|
  // same loop with LoopLandInfo without explicitly keeping track of
 | 
						|
  // loopContBlks and loopBreakBlks, this is a method to get the information.
 | 
						|
  //
 | 
						|
  if (src1Blk->succ_size() == 0) {
 | 
						|
    LoopT *loopRep = loopInfo->getLoopFor(src1Blk);
 | 
						|
    if (loopRep != NULL && loopRep == loopInfo->getLoopFor(src2Blk)) {
 | 
						|
      LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
      if (theEntry != NULL) {
 | 
						|
        if (DEBUGME) {
 | 
						|
          errs() << "isLoopContBreakBlock yes src1 = BB"
 | 
						|
                 << src1Blk->getNumber()
 | 
						|
                 << " src2 = BB" << src2Blk->getNumber() << "\n";
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}  //isSameloopDetachedContbreak
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::handleJumpintoIf(BlockT *headBlk,
 | 
						|
                                             BlockT *trueBlk,
 | 
						|
                                             BlockT *falseBlk) {
 | 
						|
  int num = handleJumpintoIfImp(headBlk, trueBlk, falseBlk);
 | 
						|
  if (num == 0) {
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "handleJumpintoIf swap trueBlk and FalseBlk" << "\n";
 | 
						|
    }
 | 
						|
    num = handleJumpintoIfImp(headBlk, falseBlk, trueBlk);
 | 
						|
  }
 | 
						|
  return num;
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::handleJumpintoIfImp(BlockT *headBlk,
 | 
						|
                                                BlockT *trueBlk,
 | 
						|
                                                BlockT *falseBlk) {
 | 
						|
  int num = 0;
 | 
						|
  BlockT *downBlk;
 | 
						|
 | 
						|
  //trueBlk could be the common post dominator
 | 
						|
  downBlk = trueBlk;
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "handleJumpintoIfImp head = BB" << headBlk->getNumber()
 | 
						|
           << " true = BB" << trueBlk->getNumber()
 | 
						|
           << ", numSucc=" << trueBlk->succ_size()
 | 
						|
           << " false = BB" << falseBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  while (downBlk) {
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "check down = BB" << downBlk->getNumber();
 | 
						|
    }
 | 
						|
 | 
						|
    if (singlePathTo(falseBlk, downBlk) == SinglePath_InPath) {
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << " working\n";
 | 
						|
      }
 | 
						|
 | 
						|
      num += cloneOnSideEntryTo(headBlk, trueBlk, downBlk);
 | 
						|
      num += cloneOnSideEntryTo(headBlk, falseBlk, downBlk);
 | 
						|
 | 
						|
      numClonedBlock += num;
 | 
						|
      num += serialPatternMatch(*headBlk->succ_begin());
 | 
						|
      num += serialPatternMatch(*(++headBlk->succ_begin()));
 | 
						|
      num += ifPatternMatch(headBlk);
 | 
						|
      assert(num > 0);
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << " not working\n";
 | 
						|
    }
 | 
						|
    downBlk = (downBlk->succ_size() == 1) ? (*downBlk->succ_begin()) : NULL;
 | 
						|
  } // walk down the postDomTree
 | 
						|
 | 
						|
  return num;
 | 
						|
} //handleJumpintoIf
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::showImproveSimpleJumpintoIf(BlockT *headBlk,
 | 
						|
                                                         BlockT *trueBlk,
 | 
						|
                                                         BlockT *falseBlk,
 | 
						|
                                                         BlockT *landBlk,
 | 
						|
                                                         bool detail) {
 | 
						|
  errs() << "head = BB" << headBlk->getNumber()
 | 
						|
         << " size = " << headBlk->size();
 | 
						|
  if (detail) {
 | 
						|
    errs() << "\n";
 | 
						|
    headBlk->print(errs());
 | 
						|
    errs() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  if (trueBlk) {
 | 
						|
    errs() << ", true = BB" << trueBlk->getNumber() << " size = "
 | 
						|
           << trueBlk->size() << " numPred = " << trueBlk->pred_size();
 | 
						|
    if (detail) {
 | 
						|
      errs() << "\n";
 | 
						|
      trueBlk->print(errs());
 | 
						|
      errs() << "\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (falseBlk) {
 | 
						|
    errs() << ", false = BB" << falseBlk->getNumber() << " size = "
 | 
						|
           << falseBlk->size() << " numPred = " << falseBlk->pred_size();
 | 
						|
    if (detail) {
 | 
						|
      errs() << "\n";
 | 
						|
      falseBlk->print(errs());
 | 
						|
      errs() << "\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (landBlk) {
 | 
						|
    errs() << ", land = BB" << landBlk->getNumber() << " size = "
 | 
						|
           << landBlk->size() << " numPred = " << landBlk->pred_size();
 | 
						|
    if (detail) {
 | 
						|
      errs() << "\n";
 | 
						|
      landBlk->print(errs());
 | 
						|
      errs() << "\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
    errs() << "\n";
 | 
						|
} //showImproveSimpleJumpintoIf
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::improveSimpleJumpintoIf(BlockT *headBlk,
 | 
						|
                                                    BlockT *trueBlk,
 | 
						|
                                                    BlockT *falseBlk,
 | 
						|
                                                    BlockT **plandBlk) {
 | 
						|
  bool migrateTrue = false;
 | 
						|
  bool migrateFalse = false;
 | 
						|
 | 
						|
  BlockT *landBlk = *plandBlk;
 | 
						|
 | 
						|
  assert((trueBlk == NULL || trueBlk->succ_size() <= 1)
 | 
						|
         && (falseBlk == NULL || falseBlk->succ_size() <= 1));
 | 
						|
 | 
						|
  if (trueBlk == falseBlk) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  migrateTrue = needMigrateBlock(trueBlk);
 | 
						|
  migrateFalse = needMigrateBlock(falseBlk);
 | 
						|
 | 
						|
  if (!migrateTrue && !migrateFalse) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // If we need to migrate either trueBlk and falseBlk, migrate the rest that
 | 
						|
  // have more than one predecessors.  without doing this, its predecessor
 | 
						|
  // rather than headBlk will have undefined value in initReg.
 | 
						|
  if (!migrateTrue && trueBlk && trueBlk->pred_size() > 1) {
 | 
						|
    migrateTrue = true;
 | 
						|
  }
 | 
						|
  if (!migrateFalse && falseBlk && falseBlk->pred_size() > 1) {
 | 
						|
    migrateFalse = true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "before improveSimpleJumpintoIf: ";
 | 
						|
    showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
 | 
						|
  //
 | 
						|
  // new: headBlk => if () {initReg = 1; org trueBlk branch} else
 | 
						|
  //      {initReg = 0; org falseBlk branch }
 | 
						|
  //      => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
 | 
						|
  //      => org landBlk
 | 
						|
  //      if landBlk->pred_size() > 2, put the about if-else inside
 | 
						|
  //      if (initReg !=2) {...}
 | 
						|
  //
 | 
						|
  // add initReg = initVal to headBlk
 | 
						|
 | 
						|
  const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
 | 
						|
  unsigned initReg =
 | 
						|
    funcRep->getRegInfo().createVirtualRegister(I32RC);
 | 
						|
  if (!migrateTrue || !migrateFalse) {
 | 
						|
    int initVal = migrateTrue ? 0 : 1;
 | 
						|
    CFGTraits::insertAssignInstrBefore(headBlk, passRep, initReg, initVal);
 | 
						|
  }
 | 
						|
 | 
						|
  int numNewBlk = 0;
 | 
						|
 | 
						|
  if (landBlk == NULL) {
 | 
						|
    landBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
    funcRep->push_back(landBlk);  //insert to function
 | 
						|
 | 
						|
    if (trueBlk) {
 | 
						|
      trueBlk->addSuccessor(landBlk);
 | 
						|
    } else {
 | 
						|
      headBlk->addSuccessor(landBlk);
 | 
						|
    }
 | 
						|
 | 
						|
    if (falseBlk) {
 | 
						|
      falseBlk->addSuccessor(landBlk);
 | 
						|
    } else {
 | 
						|
      headBlk->addSuccessor(landBlk);
 | 
						|
    }
 | 
						|
 | 
						|
    numNewBlk ++;
 | 
						|
  }
 | 
						|
 | 
						|
  bool landBlkHasOtherPred = (landBlk->pred_size() > 2);
 | 
						|
 | 
						|
  //insert AMDGPU::ENDIF to avoid special case "input landBlk == NULL"
 | 
						|
  typename BlockT::iterator insertPos =
 | 
						|
    CFGTraits::getInstrPos
 | 
						|
    (landBlk, CFGTraits::insertInstrBefore(landBlk, AMDGPU::ENDIF, passRep));
 | 
						|
 | 
						|
  if (landBlkHasOtherPred) {
 | 
						|
    unsigned immReg =
 | 
						|
      funcRep->getRegInfo().createVirtualRegister(I32RC);
 | 
						|
    CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 2);
 | 
						|
    unsigned cmpResReg =
 | 
						|
      funcRep->getRegInfo().createVirtualRegister(I32RC);
 | 
						|
 | 
						|
    CFGTraits::insertCompareInstrBefore(landBlk, insertPos, passRep, cmpResReg,
 | 
						|
                                        initReg, immReg);
 | 
						|
    CFGTraits::insertCondBranchBefore(landBlk, insertPos,
 | 
						|
                                      AMDGPU::IF_PREDICATE_SET, passRep,
 | 
						|
                                      cmpResReg, DebugLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  CFGTraits::insertCondBranchBefore(landBlk, insertPos, AMDGPU::IF_PREDICATE_SET,
 | 
						|
                                    passRep, initReg, DebugLoc());
 | 
						|
 | 
						|
  if (migrateTrue) {
 | 
						|
    migrateInstruction(trueBlk, landBlk, insertPos);
 | 
						|
    // need to uncondionally insert the assignment to ensure a path from its
 | 
						|
    // predecessor rather than headBlk has valid value in initReg if
 | 
						|
    // (initVal != 1).
 | 
						|
    CFGTraits::insertAssignInstrBefore(trueBlk, passRep, initReg, 1);
 | 
						|
  }
 | 
						|
  CFGTraits::insertInstrBefore(insertPos, AMDGPU::ELSE, passRep);
 | 
						|
 | 
						|
  if (migrateFalse) {
 | 
						|
    migrateInstruction(falseBlk, landBlk, insertPos);
 | 
						|
    // need to uncondionally insert the assignment to ensure a path from its
 | 
						|
    // predecessor rather than headBlk has valid value in initReg if
 | 
						|
    // (initVal != 0)
 | 
						|
    CFGTraits::insertAssignInstrBefore(falseBlk, passRep, initReg, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  if (landBlkHasOtherPred) {
 | 
						|
    // add endif
 | 
						|
    CFGTraits::insertInstrBefore(insertPos, AMDGPU::ENDIF, passRep);
 | 
						|
 | 
						|
    // put initReg = 2 to other predecessors of landBlk
 | 
						|
    for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(),
 | 
						|
         predIterEnd = landBlk->pred_end(); predIter != predIterEnd;
 | 
						|
         ++predIter) {
 | 
						|
      BlockT *curBlk = *predIter;
 | 
						|
      if (curBlk != trueBlk && curBlk != falseBlk) {
 | 
						|
        CFGTraits::insertAssignInstrBefore(curBlk, passRep, initReg, 2);
 | 
						|
      }
 | 
						|
    } //for
 | 
						|
  }
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "result from improveSimpleJumpintoIf: ";
 | 
						|
    showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  // update landBlk
 | 
						|
  *plandBlk = landBlk;
 | 
						|
 | 
						|
  return numNewBlk;
 | 
						|
} //improveSimpleJumpintoIf
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::handleLoopbreak(BlockT *exitingBlk,
 | 
						|
                                              LoopT *exitingLoop,
 | 
						|
                                             BlockT *exitBlk,
 | 
						|
                                              LoopT *exitLoop,
 | 
						|
                                             BlockT *landBlk) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Trying to break loop-depth = " << getLoopDepth(exitLoop)
 | 
						|
           << " from loop-depth = " << getLoopDepth(exitingLoop) << "\n";
 | 
						|
  }
 | 
						|
  const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
 | 
						|
 | 
						|
  RegiT initReg = INVALIDREGNUM;
 | 
						|
  if (exitingLoop != exitLoop) {
 | 
						|
    initReg = static_cast<int>
 | 
						|
      (funcRep->getRegInfo().createVirtualRegister(I32RC));
 | 
						|
    assert(initReg != INVALIDREGNUM);
 | 
						|
    addLoopBreakInitReg(exitLoop, initReg);
 | 
						|
    while (exitingLoop != exitLoop && exitingLoop) {
 | 
						|
      addLoopBreakOnReg(exitingLoop, initReg);
 | 
						|
      exitingLoop = exitingLoop->getParentLoop();
 | 
						|
    }
 | 
						|
    assert(exitingLoop == exitLoop);
 | 
						|
  }
 | 
						|
 | 
						|
  mergeLoopbreakBlock(exitingBlk, exitBlk, landBlk, initReg);
 | 
						|
 | 
						|
} //handleLoopbreak
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::handleLoopcontBlock(BlockT *contingBlk,
 | 
						|
                                                  LoopT *contingLoop,
 | 
						|
                                                 BlockT *contBlk,
 | 
						|
                                                  LoopT *contLoop) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "loopcontPattern cont = BB" << contingBlk->getNumber()
 | 
						|
           << " header = BB" << contBlk->getNumber() << "\n";
 | 
						|
 | 
						|
    errs() << "Trying to continue loop-depth = "
 | 
						|
           << getLoopDepth(contLoop)
 | 
						|
           << " from loop-depth = " << getLoopDepth(contingLoop) << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  RegiT initReg = INVALIDREGNUM;
 | 
						|
  const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
 | 
						|
  if (contingLoop != contLoop) {
 | 
						|
    initReg = static_cast<int>
 | 
						|
      (funcRep->getRegInfo().createVirtualRegister(I32RC));
 | 
						|
    assert(initReg != INVALIDREGNUM);
 | 
						|
    addLoopContInitReg(contLoop, initReg);
 | 
						|
    while (contingLoop && contingLoop->getParentLoop() != contLoop) {
 | 
						|
      addLoopBreakOnReg(contingLoop, initReg);  //not addLoopContOnReg
 | 
						|
      contingLoop = contingLoop->getParentLoop();
 | 
						|
    }
 | 
						|
    assert(contingLoop && contingLoop->getParentLoop() == contLoop);
 | 
						|
    addLoopContOnReg(contingLoop, initReg);
 | 
						|
  }
 | 
						|
 | 
						|
  settleLoopcontBlock(contingBlk, contBlk, initReg);
 | 
						|
} //handleLoopcontBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::mergeSerialBlock(BlockT *dstBlk, BlockT *srcBlk) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "serialPattern BB" << dstBlk->getNumber()
 | 
						|
           << " <= BB" << srcBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
  dstBlk->splice(dstBlk->end(), srcBlk, srcBlk->begin(), srcBlk->end());
 | 
						|
 | 
						|
  dstBlk->removeSuccessor(srcBlk);
 | 
						|
  CFGTraits::cloneSuccessorList(dstBlk, srcBlk);
 | 
						|
 | 
						|
  removeSuccessor(srcBlk);
 | 
						|
  retireBlock(dstBlk, srcBlk);
 | 
						|
} //mergeSerialBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::mergeIfthenelseBlock(InstrT *branchInstr,
 | 
						|
                                                  BlockT *curBlk,
 | 
						|
                                                  BlockT *trueBlk,
 | 
						|
                                                  BlockT *falseBlk,
 | 
						|
                                                  BlockT *landBlk) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "ifPattern BB" << curBlk->getNumber();
 | 
						|
    errs() << "{  ";
 | 
						|
    if (trueBlk) {
 | 
						|
      errs() << "BB" << trueBlk->getNumber();
 | 
						|
    }
 | 
						|
    errs() << "  } else ";
 | 
						|
    errs() << "{  ";
 | 
						|
    if (falseBlk) {
 | 
						|
      errs() << "BB" << falseBlk->getNumber();
 | 
						|
    }
 | 
						|
    errs() << "  }\n ";
 | 
						|
    errs() << "landBlock: ";
 | 
						|
    if (landBlk == NULL) {
 | 
						|
      errs() << "NULL";
 | 
						|
    } else {
 | 
						|
      errs() << "BB" << landBlk->getNumber();
 | 
						|
    }
 | 
						|
    errs() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  int oldOpcode = branchInstr->getOpcode();
 | 
						|
  DebugLoc branchDL = branchInstr->getDebugLoc();
 | 
						|
 | 
						|
//    transform to
 | 
						|
//    if cond
 | 
						|
//       trueBlk
 | 
						|
//    else
 | 
						|
//       falseBlk
 | 
						|
//    endif
 | 
						|
//    landBlk
 | 
						|
 | 
						|
  typename BlockT::iterator branchInstrPos =
 | 
						|
    CFGTraits::getInstrPos(curBlk, branchInstr);
 | 
						|
  CFGTraits::insertCondBranchBefore(branchInstrPos,
 | 
						|
                                    CFGTraits::getBranchNzeroOpcode(oldOpcode),
 | 
						|
                                    passRep,
 | 
						|
                                    branchDL);
 | 
						|
 | 
						|
  if (trueBlk) {
 | 
						|
    curBlk->splice(branchInstrPos, trueBlk, trueBlk->begin(), trueBlk->end());
 | 
						|
    curBlk->removeSuccessor(trueBlk);
 | 
						|
    if (landBlk && trueBlk->succ_size()!=0) {
 | 
						|
      trueBlk->removeSuccessor(landBlk);
 | 
						|
    }
 | 
						|
    retireBlock(curBlk, trueBlk);
 | 
						|
  }
 | 
						|
  CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::ELSE, passRep);
 | 
						|
 | 
						|
  if (falseBlk) {
 | 
						|
    curBlk->splice(branchInstrPos, falseBlk, falseBlk->begin(),
 | 
						|
                   falseBlk->end());
 | 
						|
    curBlk->removeSuccessor(falseBlk);
 | 
						|
    if (landBlk && falseBlk->succ_size() != 0) {
 | 
						|
      falseBlk->removeSuccessor(landBlk);
 | 
						|
    }
 | 
						|
    retireBlock(curBlk, falseBlk);
 | 
						|
  }
 | 
						|
  CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::ENDIF, passRep);
 | 
						|
 | 
						|
  branchInstr->eraseFromParent();
 | 
						|
 | 
						|
  if (landBlk && trueBlk && falseBlk) {
 | 
						|
    curBlk->addSuccessor(landBlk);
 | 
						|
  }
 | 
						|
 | 
						|
} //mergeIfthenelseBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::mergeLooplandBlock(BlockT *dstBlk,
 | 
						|
                                                LoopLandInfo *loopLand) {
 | 
						|
  BlockT *landBlk = loopLand->landBlk;
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "loopPattern header = BB" << dstBlk->getNumber()
 | 
						|
           << " land = BB" << landBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  // Loop contInitRegs are init at the beginning of the loop.
 | 
						|
  for (typename std::set<RegiT>::const_iterator iter =
 | 
						|
         loopLand->contInitRegs.begin(),
 | 
						|
       iterEnd = loopLand->contInitRegs.end(); iter != iterEnd; ++iter) {
 | 
						|
    CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  /* we last inserterd the DebugLoc in the
 | 
						|
   * BREAK_LOGICALZ_i32 or AMDGPU::BREAK_LOGICALNZ statement in the current dstBlk.
 | 
						|
   * search for the DebugLoc in the that statement.
 | 
						|
   * if not found, we have to insert the empty/default DebugLoc */
 | 
						|
  InstrT *loopBreakInstr = CFGTraits::getLoopBreakInstr(dstBlk);
 | 
						|
  DebugLoc DLBreak = (loopBreakInstr) ? loopBreakInstr->getDebugLoc() : DebugLoc();
 | 
						|
 | 
						|
  CFGTraits::insertInstrBefore(dstBlk, AMDGPU::WHILELOOP, passRep, DLBreak);
 | 
						|
  // Loop breakInitRegs are init before entering the loop.
 | 
						|
  for (typename std::set<RegiT>::const_iterator iter =
 | 
						|
         loopLand->breakInitRegs.begin(),
 | 
						|
       iterEnd = loopLand->breakInitRegs.end(); iter != iterEnd; ++iter) {
 | 
						|
    CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
 | 
						|
  }
 | 
						|
  // Loop endbranchInitRegs are init before entering the loop.
 | 
						|
  for (typename std::set<RegiT>::const_iterator iter =
 | 
						|
         loopLand->endbranchInitRegs.begin(),
 | 
						|
       iterEnd = loopLand->endbranchInitRegs.end(); iter != iterEnd; ++iter) {
 | 
						|
    CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  /* we last inserterd the DebugLoc in the continue statement in the current dstBlk
 | 
						|
   * search for the DebugLoc in the continue statement.
 | 
						|
   * if not found, we have to insert the empty/default DebugLoc */
 | 
						|
  InstrT *continueInstr = CFGTraits::getContinueInstr(dstBlk);
 | 
						|
  DebugLoc DLContinue = (continueInstr) ? continueInstr->getDebugLoc() : DebugLoc();
 | 
						|
 | 
						|
  CFGTraits::insertInstrEnd(dstBlk, AMDGPU::ENDLOOP, passRep, DLContinue);
 | 
						|
  // Loop breakOnRegs are check after the ENDLOOP: break the loop outside this
 | 
						|
  // loop.
 | 
						|
  for (typename std::set<RegiT>::const_iterator iter =
 | 
						|
         loopLand->breakOnRegs.begin(),
 | 
						|
       iterEnd = loopLand->breakOnRegs.end(); iter != iterEnd; ++iter) {
 | 
						|
    CFGTraits::insertCondBranchEnd(dstBlk, AMDGPU::PREDICATED_BREAK, passRep,
 | 
						|
                                   *iter);
 | 
						|
  }
 | 
						|
 | 
						|
  // Loop contOnRegs are check after the ENDLOOP: cont the loop outside this
 | 
						|
  // loop.
 | 
						|
  for (std::set<RegiT>::const_iterator iter = loopLand->contOnRegs.begin(),
 | 
						|
       iterEnd = loopLand->contOnRegs.end(); iter != iterEnd; ++iter) {
 | 
						|
    CFGTraits::insertCondBranchEnd(dstBlk, AMDGPU::CONTINUE_LOGICALNZ_i32,
 | 
						|
                                   passRep, *iter);
 | 
						|
  }
 | 
						|
 | 
						|
  dstBlk->splice(dstBlk->end(), landBlk, landBlk->begin(), landBlk->end());
 | 
						|
 | 
						|
  for (typename BlockT::succ_iterator iter = landBlk->succ_begin(),
 | 
						|
       iterEnd = landBlk->succ_end(); iter != iterEnd; ++iter) {
 | 
						|
    dstBlk->addSuccessor(*iter);  // *iter's predecessor is also taken care of.
 | 
						|
  }
 | 
						|
 | 
						|
  removeSuccessor(landBlk);
 | 
						|
  retireBlock(dstBlk, landBlk);
 | 
						|
} //mergeLooplandBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::reversePredicateSetter(typename BlockT::iterator I) {
 | 
						|
  while (I--) {
 | 
						|
    if (I->getOpcode() == AMDGPU::PRED_X) {
 | 
						|
      switch (static_cast<MachineInstr *>(I)->getOperand(2).getImm()) {
 | 
						|
      case OPCODE_IS_ZERO_INT:
 | 
						|
        static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_NOT_ZERO_INT);
 | 
						|
        return;
 | 
						|
      case OPCODE_IS_NOT_ZERO_INT:
 | 
						|
        static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_ZERO_INT);
 | 
						|
        return;
 | 
						|
      case OPCODE_IS_ZERO:
 | 
						|
        static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_NOT_ZERO);
 | 
						|
        return;
 | 
						|
      case OPCODE_IS_NOT_ZERO:
 | 
						|
        static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_ZERO);
 | 
						|
        return;
 | 
						|
      default:
 | 
						|
        assert(0 && "PRED_X Opcode invalid!");
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::mergeLoopbreakBlock(BlockT *exitingBlk,
 | 
						|
                                                 BlockT *exitBlk,
 | 
						|
                                                 BlockT *exitLandBlk,
 | 
						|
                                                 RegiT  setReg) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "loopbreakPattern exiting = BB" << exitingBlk->getNumber()
 | 
						|
           << " exit = BB" << exitBlk->getNumber()
 | 
						|
           << " land = BB" << exitLandBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(exitingBlk);
 | 
						|
  assert(branchInstr && CFGTraits::isCondBranch(branchInstr));
 | 
						|
 | 
						|
  DebugLoc DL = branchInstr->getDebugLoc();
 | 
						|
 | 
						|
  BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr);
 | 
						|
 | 
						|
  //    transform exitingBlk to
 | 
						|
  //    if ( ) {
 | 
						|
  //       exitBlk (if exitBlk != exitLandBlk)
 | 
						|
  //       setReg = 1
 | 
						|
  //       break
 | 
						|
  //    }endif
 | 
						|
  //    successor = {orgSuccessor(exitingBlk) - exitBlk}
 | 
						|
 | 
						|
  typename BlockT::iterator branchInstrPos =
 | 
						|
    CFGTraits::getInstrPos(exitingBlk, branchInstr);
 | 
						|
 | 
						|
  if (exitBlk == exitLandBlk && setReg == INVALIDREGNUM) {
 | 
						|
    //break_logical
 | 
						|
 | 
						|
    if (trueBranch != exitBlk) {
 | 
						|
      reversePredicateSetter(branchInstrPos);
 | 
						|
    }
 | 
						|
    CFGTraits::insertCondBranchBefore(branchInstrPos, AMDGPU::PREDICATED_BREAK, passRep, DL);
 | 
						|
  } else {
 | 
						|
    if (trueBranch != exitBlk) {
 | 
						|
      reversePredicateSetter(branchInstr);
 | 
						|
    }
 | 
						|
    CFGTraits::insertCondBranchBefore(branchInstrPos, AMDGPU::PREDICATED_BREAK, passRep, DL);
 | 
						|
    if (exitBlk != exitLandBlk) {
 | 
						|
      //splice is insert-before ...
 | 
						|
      exitingBlk->splice(branchInstrPos, exitBlk, exitBlk->begin(),
 | 
						|
                         exitBlk->end());
 | 
						|
    }
 | 
						|
    if (setReg != INVALIDREGNUM) {
 | 
						|
      CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1);
 | 
						|
    }
 | 
						|
    CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::BREAK, passRep);
 | 
						|
  } //if_logical
 | 
						|
 | 
						|
  //now branchInst can be erase safely
 | 
						|
  branchInstr->eraseFromParent();
 | 
						|
 | 
						|
  //now take care of successors, retire blocks
 | 
						|
  exitingBlk->removeSuccessor(exitBlk);
 | 
						|
  if (exitBlk != exitLandBlk) {
 | 
						|
    //splice is insert-before ...
 | 
						|
    exitBlk->removeSuccessor(exitLandBlk);
 | 
						|
    retireBlock(exitingBlk, exitBlk);
 | 
						|
  }
 | 
						|
 | 
						|
} //mergeLoopbreakBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::settleLoopcontBlock(BlockT *contingBlk,
 | 
						|
                                                 BlockT *contBlk,
 | 
						|
                                                 RegiT   setReg) {
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "settleLoopcontBlock conting = BB"
 | 
						|
           << contingBlk->getNumber()
 | 
						|
           << ", cont = BB" << contBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(contingBlk);
 | 
						|
  if (branchInstr) {
 | 
						|
    assert(CFGTraits::isCondBranch(branchInstr));
 | 
						|
    typename BlockT::iterator branchInstrPos =
 | 
						|
      CFGTraits::getInstrPos(contingBlk, branchInstr);
 | 
						|
    BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr);
 | 
						|
    int oldOpcode = branchInstr->getOpcode();
 | 
						|
    DebugLoc DL = branchInstr->getDebugLoc();
 | 
						|
 | 
						|
    //    transform contingBlk to
 | 
						|
    //     if () {
 | 
						|
    //          move instr after branchInstr
 | 
						|
    //          continue
 | 
						|
    //        or
 | 
						|
    //          setReg = 1
 | 
						|
    //          break
 | 
						|
    //     }endif
 | 
						|
    //     successor = {orgSuccessor(contingBlk) - loopHeader}
 | 
						|
 | 
						|
    bool useContinueLogical = 
 | 
						|
      (setReg == INVALIDREGNUM && (&*contingBlk->rbegin()) == branchInstr);
 | 
						|
 | 
						|
    if (useContinueLogical == false) {
 | 
						|
      int branchOpcode =
 | 
						|
        trueBranch == contBlk ? CFGTraits::getBranchNzeroOpcode(oldOpcode)
 | 
						|
                              : CFGTraits::getBranchZeroOpcode(oldOpcode);
 | 
						|
 | 
						|
      CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL);
 | 
						|
 | 
						|
      if (setReg != INVALIDREGNUM) {
 | 
						|
        CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1);
 | 
						|
        // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
 | 
						|
        CFGTraits::insertInstrEnd(contingBlk, AMDGPU::BREAK, passRep, DL);
 | 
						|
      } else {
 | 
						|
        // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
 | 
						|
        CFGTraits::insertInstrEnd(contingBlk, AMDGPU::CONTINUE, passRep, DL);
 | 
						|
      }
 | 
						|
 | 
						|
      CFGTraits::insertInstrEnd(contingBlk, AMDGPU::ENDIF, passRep, DL);
 | 
						|
    } else {
 | 
						|
      int branchOpcode =
 | 
						|
        trueBranch == contBlk ? CFGTraits::getContinueNzeroOpcode(oldOpcode)
 | 
						|
                              : CFGTraits::getContinueZeroOpcode(oldOpcode);
 | 
						|
 | 
						|
      CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL);
 | 
						|
    }
 | 
						|
 | 
						|
    branchInstr->eraseFromParent();
 | 
						|
  } else {
 | 
						|
    // if we've arrived here then we've already erased the branch instruction
 | 
						|
    // travel back up the basic block to see the last reference of our debug location
 | 
						|
    // we've just inserted that reference here so it should be representative
 | 
						|
    if (setReg != INVALIDREGNUM) {
 | 
						|
      CFGTraits::insertAssignInstrBefore(contingBlk, passRep, setReg, 1);
 | 
						|
      // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
 | 
						|
      CFGTraits::insertInstrEnd(contingBlk, AMDGPU::BREAK, passRep, CFGTraits::getLastDebugLocInBB(contingBlk));
 | 
						|
    } else {
 | 
						|
      // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
 | 
						|
      CFGTraits::insertInstrEnd(contingBlk, AMDGPU::CONTINUE, passRep, CFGTraits::getLastDebugLocInBB(contingBlk));
 | 
						|
    }
 | 
						|
  } //else
 | 
						|
 | 
						|
} //settleLoopcontBlock
 | 
						|
 | 
						|
// BBs in exitBlkSet are determined as in break-path for loopRep,
 | 
						|
// before we can put code for BBs as inside loop-body for loopRep
 | 
						|
// check whether those BBs are determined as cont-BB for parentLoopRep
 | 
						|
// earlier.
 | 
						|
// If so, generate a new BB newBlk
 | 
						|
//    (1) set newBlk common successor of BBs in exitBlkSet
 | 
						|
//    (2) change the continue-instr in BBs in exitBlkSet to break-instr
 | 
						|
//    (3) generate continue-instr in newBlk
 | 
						|
//
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::relocateLoopcontBlock(LoopT *parentLoopRep,
 | 
						|
                                              LoopT *loopRep,
 | 
						|
                                              std::set<BlockT *> &exitBlkSet,
 | 
						|
                                              BlockT *exitLandBlk) {
 | 
						|
  std::set<BlockT *> endBlkSet;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  for (typename std::set<BlockT *>::const_iterator iter = exitBlkSet.begin(),
 | 
						|
       iterEnd = exitBlkSet.end();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
    BlockT *exitBlk = *iter;
 | 
						|
    BlockT *endBlk = singlePathEnd(exitBlk, exitLandBlk);
 | 
						|
 | 
						|
    if (endBlk == NULL || CFGTraits::getContinueInstr(endBlk) == NULL)
 | 
						|
      return NULL;
 | 
						|
 | 
						|
    endBlkSet.insert(endBlk);
 | 
						|
  }
 | 
						|
 | 
						|
  BlockT *newBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
  funcRep->push_back(newBlk);  //insert to function
 | 
						|
  CFGTraits::insertInstrEnd(newBlk, AMDGPU::CONTINUE, passRep);
 | 
						|
  SHOWNEWBLK(newBlk, "New continue block: ");
 | 
						|
 | 
						|
  for (typename std::set<BlockT*>::const_iterator iter = endBlkSet.begin(),
 | 
						|
       iterEnd = endBlkSet.end();
 | 
						|
       iter != iterEnd; ++iter) {
 | 
						|
      BlockT *endBlk = *iter;
 | 
						|
      InstrT *contInstr = CFGTraits::getContinueInstr(endBlk);
 | 
						|
      if (contInstr) {
 | 
						|
        contInstr->eraseFromParent();
 | 
						|
      }
 | 
						|
      endBlk->addSuccessor(newBlk);
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "Add new continue Block to BB"
 | 
						|
               << endBlk->getNumber() << " successors\n";
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  return newBlk;
 | 
						|
} //relocateLoopcontBlock
 | 
						|
 | 
						|
 | 
						|
// LoopEndbranchBlock is a BB created by the CFGStructurizer to use as
 | 
						|
// LoopLandBlock. This BB branch on the loop endBranchInit register to the
 | 
						|
// pathes corresponding to the loop exiting branches.
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::addLoopEndbranchBlock(LoopT *loopRep,
 | 
						|
                                              BlockTSmallerVector &exitingBlks,
 | 
						|
                                              BlockTSmallerVector &exitBlks) {
 | 
						|
  const AMDGPUInstrInfo *tii =
 | 
						|
             static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
 | 
						|
  const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
 | 
						|
 | 
						|
  RegiT endBranchReg = static_cast<int>
 | 
						|
    (funcRep->getRegInfo().createVirtualRegister(I32RC));
 | 
						|
  assert(endBranchReg >= 0);
 | 
						|
 | 
						|
  // reg = 0 before entering the loop
 | 
						|
  addLoopEndbranchInitReg(loopRep, endBranchReg);
 | 
						|
 | 
						|
  uint32_t numBlks = static_cast<uint32_t>(exitingBlks.size());
 | 
						|
  assert(numBlks >=2 && numBlks == exitBlks.size());
 | 
						|
 | 
						|
  BlockT *preExitingBlk = exitingBlks[0];
 | 
						|
  BlockT *preExitBlk = exitBlks[0];
 | 
						|
  BlockT *preBranchBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
  funcRep->push_back(preBranchBlk);  //insert to function
 | 
						|
  SHOWNEWBLK(preBranchBlk, "New loopEndbranch block: ");
 | 
						|
 | 
						|
  BlockT *newLandBlk = preBranchBlk;
 | 
						|
 | 
						|
      CFGTraits::replaceInstrUseOfBlockWith(preExitingBlk, preExitBlk,
 | 
						|
        newLandBlk);
 | 
						|
  preExitingBlk->removeSuccessor(preExitBlk);
 | 
						|
  preExitingBlk->addSuccessor(newLandBlk);
 | 
						|
 | 
						|
  //it is redundant to add reg = 0 to exitingBlks[0]
 | 
						|
 | 
						|
  // For 1..n th exiting path (the last iteration handles two pathes) create the
 | 
						|
  // branch to the previous path and the current path.
 | 
						|
  for (uint32_t i = 1; i < numBlks; ++i) {
 | 
						|
    BlockT *curExitingBlk = exitingBlks[i];
 | 
						|
    BlockT *curExitBlk = exitBlks[i];
 | 
						|
    BlockT *curBranchBlk;
 | 
						|
 | 
						|
    if (i == numBlks - 1) {
 | 
						|
      curBranchBlk = curExitBlk;
 | 
						|
    } else {
 | 
						|
      curBranchBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
      funcRep->push_back(curBranchBlk);  //insert to function
 | 
						|
      SHOWNEWBLK(curBranchBlk, "New loopEndbranch block: ");
 | 
						|
    }
 | 
						|
 | 
						|
    // Add reg = i to exitingBlks[i].
 | 
						|
    CFGTraits::insertAssignInstrBefore(curExitingBlk, passRep,
 | 
						|
                                       endBranchReg, i);
 | 
						|
 | 
						|
    // Remove the edge (exitingBlks[i] exitBlks[i]) add new edge
 | 
						|
    // (exitingBlks[i], newLandBlk).
 | 
						|
    CFGTraits::replaceInstrUseOfBlockWith(curExitingBlk, curExitBlk,
 | 
						|
                                          newLandBlk);
 | 
						|
    curExitingBlk->removeSuccessor(curExitBlk);
 | 
						|
    curExitingBlk->addSuccessor(newLandBlk);
 | 
						|
 | 
						|
    // add to preBranchBlk the branch instruction:
 | 
						|
    // if (endBranchReg == preVal)
 | 
						|
    //    preExitBlk
 | 
						|
    // else
 | 
						|
    //    curBranchBlk
 | 
						|
    //
 | 
						|
    // preValReg = i - 1
 | 
						|
 | 
						|
  DebugLoc DL;
 | 
						|
  RegiT preValReg = static_cast<int>
 | 
						|
    (funcRep->getRegInfo().createVirtualRegister(I32RC));
 | 
						|
 | 
						|
  preBranchBlk->insert(preBranchBlk->begin(),
 | 
						|
                       tii->getMovImmInstr(preBranchBlk->getParent(), preValReg,
 | 
						|
                       i - 1));
 | 
						|
 | 
						|
  // condResReg = (endBranchReg == preValReg)
 | 
						|
    RegiT condResReg = static_cast<int>
 | 
						|
      (funcRep->getRegInfo().createVirtualRegister(I32RC));
 | 
						|
    BuildMI(preBranchBlk, DL, tii->get(tii->getIEQOpcode()), condResReg)
 | 
						|
      .addReg(endBranchReg).addReg(preValReg);
 | 
						|
 | 
						|
    BuildMI(preBranchBlk, DL, tii->get(AMDGPU::BRANCH_COND_i32))
 | 
						|
      .addMBB(preExitBlk).addReg(condResReg);
 | 
						|
 | 
						|
    preBranchBlk->addSuccessor(preExitBlk);
 | 
						|
    preBranchBlk->addSuccessor(curBranchBlk);
 | 
						|
 | 
						|
    // Update preExitingBlk, preExitBlk, preBranchBlk.
 | 
						|
    preExitingBlk = curExitingBlk;
 | 
						|
    preExitBlk = curExitBlk;
 | 
						|
    preBranchBlk = curBranchBlk;
 | 
						|
 | 
						|
  }  //end for 1 .. n blocks
 | 
						|
 | 
						|
  return newLandBlk;
 | 
						|
} //addLoopEndbranchBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::PathToKind
 | 
						|
CFGStructurizer<PassT>::singlePathTo(BlockT *srcBlk, BlockT *dstBlk,
 | 
						|
                                     bool allowSideEntry) {
 | 
						|
  assert(dstBlk);
 | 
						|
 | 
						|
  if (srcBlk == dstBlk) {
 | 
						|
    return SinglePath_InPath;
 | 
						|
  }
 | 
						|
 | 
						|
  while (srcBlk && srcBlk->succ_size() == 1) {
 | 
						|
    srcBlk = *srcBlk->succ_begin();
 | 
						|
    if (srcBlk == dstBlk) {
 | 
						|
      return SinglePath_InPath;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!allowSideEntry && srcBlk->pred_size() > 1) {
 | 
						|
      return Not_SinglePath;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (srcBlk && srcBlk->succ_size()==0) {
 | 
						|
    return SinglePath_NotInPath;
 | 
						|
  }
 | 
						|
 | 
						|
  return Not_SinglePath;
 | 
						|
} //singlePathTo
 | 
						|
 | 
						|
// If there is a single path from srcBlk to dstBlk, return the last block before
 | 
						|
// dstBlk If there is a single path from srcBlk->end without dstBlk, return the
 | 
						|
// last block in the path Otherwise, return NULL
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::singlePathEnd(BlockT *srcBlk, BlockT *dstBlk,
 | 
						|
                                      bool allowSideEntry) {
 | 
						|
  assert(dstBlk);
 | 
						|
 | 
						|
  if (srcBlk == dstBlk) {
 | 
						|
    return srcBlk;
 | 
						|
  }
 | 
						|
 | 
						|
  if (srcBlk->succ_size() == 0) {
 | 
						|
    return srcBlk;
 | 
						|
  }
 | 
						|
 | 
						|
  while (srcBlk && srcBlk->succ_size() == 1) {
 | 
						|
    BlockT *preBlk = srcBlk;
 | 
						|
 | 
						|
    srcBlk = *srcBlk->succ_begin();
 | 
						|
    if (srcBlk == NULL) {
 | 
						|
      return preBlk;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!allowSideEntry && srcBlk->pred_size() > 1) {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (srcBlk && srcBlk->succ_size()==0) {
 | 
						|
    return srcBlk;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
 | 
						|
} //singlePathEnd
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::cloneOnSideEntryTo(BlockT *preBlk, BlockT *srcBlk,
 | 
						|
                                               BlockT *dstBlk) {
 | 
						|
  int cloned = 0;
 | 
						|
  assert(preBlk->isSuccessor(srcBlk));
 | 
						|
  while (srcBlk && srcBlk != dstBlk) {
 | 
						|
    assert(srcBlk->succ_size() == 1);
 | 
						|
    if (srcBlk->pred_size() > 1) {
 | 
						|
      srcBlk = cloneBlockForPredecessor(srcBlk, preBlk);
 | 
						|
      ++cloned;
 | 
						|
    }
 | 
						|
 | 
						|
    preBlk = srcBlk;
 | 
						|
    srcBlk = *srcBlk->succ_begin();
 | 
						|
  }
 | 
						|
 | 
						|
  return cloned;
 | 
						|
} //cloneOnSideEntryTo
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::cloneBlockForPredecessor(BlockT *curBlk,
 | 
						|
                                                 BlockT *predBlk) {
 | 
						|
  assert(predBlk->isSuccessor(curBlk) &&
 | 
						|
         "succBlk is not a prececessor of curBlk");
 | 
						|
 | 
						|
  BlockT *cloneBlk = CFGTraits::clone(curBlk);  //clone instructions
 | 
						|
  CFGTraits::replaceInstrUseOfBlockWith(predBlk, curBlk, cloneBlk);
 | 
						|
  //srcBlk, oldBlk, newBlk
 | 
						|
 | 
						|
  predBlk->removeSuccessor(curBlk);
 | 
						|
  predBlk->addSuccessor(cloneBlk);
 | 
						|
 | 
						|
  // add all successor to cloneBlk
 | 
						|
  CFGTraits::cloneSuccessorList(cloneBlk, curBlk);
 | 
						|
 | 
						|
  numClonedInstr += curBlk->size();
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Cloned block: " << "BB"
 | 
						|
           << curBlk->getNumber() << "size " << curBlk->size() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  SHOWNEWBLK(cloneBlk, "result of Cloned block: ");
 | 
						|
 | 
						|
  return cloneBlk;
 | 
						|
} //cloneBlockForPredecessor
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::exitingBlock2ExitBlock(LoopT *loopRep,
 | 
						|
                                               BlockT *exitingBlk) {
 | 
						|
  BlockT *exitBlk = NULL;
 | 
						|
 | 
						|
  for (typename BlockT::succ_iterator iterSucc = exitingBlk->succ_begin(),
 | 
						|
       iterSuccEnd = exitingBlk->succ_end();
 | 
						|
       iterSucc != iterSuccEnd; ++iterSucc) {
 | 
						|
    BlockT *curBlk = *iterSucc;
 | 
						|
    if (!loopRep->contains(curBlk)) {
 | 
						|
      assert(exitBlk == NULL);
 | 
						|
      exitBlk = curBlk;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  assert(exitBlk != NULL);
 | 
						|
 | 
						|
  return exitBlk;
 | 
						|
} //exitingBlock2ExitBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::migrateInstruction(BlockT *srcBlk,
 | 
						|
                                                BlockT *dstBlk,
 | 
						|
                                                InstrIterator insertPos) {
 | 
						|
  InstrIterator spliceEnd;
 | 
						|
  //look for the input branchinstr, not the AMDGPU branchinstr
 | 
						|
  InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk);
 | 
						|
  if (branchInstr == NULL) {
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "migrateInstruction don't see branch instr\n" ;
 | 
						|
    }
 | 
						|
    spliceEnd = srcBlk->end();
 | 
						|
  } else {
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "migrateInstruction see branch instr\n" ;
 | 
						|
      branchInstr->dump();
 | 
						|
    }
 | 
						|
    spliceEnd = CFGTraits::getInstrPos(srcBlk, branchInstr);
 | 
						|
  }
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "migrateInstruction before splice dstSize = " << dstBlk->size()
 | 
						|
      << "srcSize = " << srcBlk->size() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  //splice insert before insertPos
 | 
						|
  dstBlk->splice(insertPos, srcBlk, srcBlk->begin(), spliceEnd);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "migrateInstruction after splice dstSize = " << dstBlk->size()
 | 
						|
      << "srcSize = " << srcBlk->size() << "\n";
 | 
						|
  }
 | 
						|
} //migrateInstruction
 | 
						|
 | 
						|
// normalizeInfiniteLoopExit change
 | 
						|
//   B1:
 | 
						|
//        uncond_br LoopHeader
 | 
						|
//
 | 
						|
// to
 | 
						|
//   B1:
 | 
						|
//        cond_br 1 LoopHeader dummyExit
 | 
						|
// and return the newly added dummy exit block
 | 
						|
// 
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::normalizeInfiniteLoopExit(LoopT* LoopRep) {
 | 
						|
  BlockT *loopHeader;
 | 
						|
  BlockT *loopLatch;
 | 
						|
  loopHeader = LoopRep->getHeader();
 | 
						|
  loopLatch = LoopRep->getLoopLatch();
 | 
						|
  BlockT *dummyExitBlk = NULL;
 | 
						|
  const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
 | 
						|
  if (loopHeader!=NULL && loopLatch!=NULL) {
 | 
						|
    InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(loopLatch);
 | 
						|
    if (branchInstr!=NULL && CFGTraits::isUncondBranch(branchInstr)) {
 | 
						|
      dummyExitBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
      funcRep->push_back(dummyExitBlk);  //insert to function
 | 
						|
      SHOWNEWBLK(dummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
 | 
						|
 | 
						|
      if (DEBUGME) errs() << "Old branch instr: " << *branchInstr << "\n";
 | 
						|
 | 
						|
      typename BlockT::iterator insertPos =
 | 
						|
        CFGTraits::getInstrPos(loopLatch, branchInstr);
 | 
						|
      unsigned immReg =
 | 
						|
        funcRep->getRegInfo().createVirtualRegister(I32RC);
 | 
						|
      CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 1);
 | 
						|
      InstrT *newInstr = 
 | 
						|
        CFGTraits::insertInstrBefore(insertPos, AMDGPU::BRANCH_COND_i32, passRep);
 | 
						|
      MachineInstrBuilder MIB(*funcRep, newInstr);
 | 
						|
      MIB.addMBB(loopHeader);
 | 
						|
      MIB.addReg(immReg, false);
 | 
						|
 | 
						|
      SHOWNEWINSTR(newInstr);
 | 
						|
 | 
						|
      branchInstr->eraseFromParent();
 | 
						|
      loopLatch->addSuccessor(dummyExitBlk);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return dummyExitBlk;
 | 
						|
} //normalizeInfiniteLoopExit
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::removeUnconditionalBranch(BlockT *srcBlk) {
 | 
						|
  InstrT *branchInstr;
 | 
						|
 | 
						|
  // I saw two unconditional branch in one basic block in example
 | 
						|
  // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
 | 
						|
  while ((branchInstr = CFGTraits::getLoopendBlockBranchInstr(srcBlk))
 | 
						|
          && CFGTraits::isUncondBranch(branchInstr)) {
 | 
						|
    if (DEBUGME) {
 | 
						|
          errs() << "Removing unconditional branch instruction" ;
 | 
						|
      branchInstr->dump();
 | 
						|
    }
 | 
						|
    branchInstr->eraseFromParent();
 | 
						|
  }
 | 
						|
} //removeUnconditionalBranch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::removeRedundantConditionalBranch(BlockT *srcBlk) {
 | 
						|
  if (srcBlk->succ_size() == 2) {
 | 
						|
    BlockT *blk1 = *srcBlk->succ_begin();
 | 
						|
    BlockT *blk2 = *(++srcBlk->succ_begin());
 | 
						|
 | 
						|
    if (blk1 == blk2) {
 | 
						|
      InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk);
 | 
						|
      assert(branchInstr && CFGTraits::isCondBranch(branchInstr));
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "Removing unneeded conditional branch instruction" ;
 | 
						|
        branchInstr->dump();
 | 
						|
      }
 | 
						|
      branchInstr->eraseFromParent();
 | 
						|
      SHOWNEWBLK(blk1, "Removing redundant successor");
 | 
						|
      srcBlk->removeSuccessor(blk1);
 | 
						|
    }
 | 
						|
  }
 | 
						|
} //removeRedundantConditionalBranch
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addDummyExitBlock(SmallVector<BlockT*,
 | 
						|
                                               DEFAULT_VEC_SLOTS> &retBlks) {
 | 
						|
  BlockT *dummyExitBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
  funcRep->push_back(dummyExitBlk);  //insert to function
 | 
						|
  CFGTraits::insertInstrEnd(dummyExitBlk, AMDGPU::RETURN, passRep);
 | 
						|
 | 
						|
  for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::iterator iter =
 | 
						|
         retBlks.begin(),
 | 
						|
       iterEnd = retBlks.end(); iter != iterEnd; ++iter) {
 | 
						|
    BlockT *curBlk = *iter;
 | 
						|
    InstrT *curInstr = CFGTraits::getReturnInstr(curBlk);
 | 
						|
    if (curInstr) {
 | 
						|
      curInstr->eraseFromParent();
 | 
						|
    }
 | 
						|
    curBlk->addSuccessor(dummyExitBlk);
 | 
						|
    if (DEBUGME) {
 | 
						|
      errs() << "Add dummyExitBlock to BB" << curBlk->getNumber()
 | 
						|
             << " successors\n";
 | 
						|
    }
 | 
						|
  } //for
 | 
						|
 | 
						|
  SHOWNEWBLK(dummyExitBlk, "DummyExitBlock: ");
 | 
						|
} //addDummyExitBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::removeSuccessor(BlockT *srcBlk) {
 | 
						|
  while (srcBlk->succ_size()) {
 | 
						|
    srcBlk->removeSuccessor(*srcBlk->succ_begin());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::recordSccnum(BlockT *srcBlk, int sccNum) {
 | 
						|
  BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk];
 | 
						|
 | 
						|
  if (srcBlkInfo == NULL) {
 | 
						|
    srcBlkInfo = new BlockInfo();
 | 
						|
  }
 | 
						|
 | 
						|
  srcBlkInfo->sccNum = sccNum;
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::getSCCNum(BlockT *srcBlk) {
 | 
						|
  BlockInfo *srcBlkInfo = blockInfoMap[srcBlk];
 | 
						|
  return srcBlkInfo ? srcBlkInfo->sccNum : INVALIDSCCNUM;
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::retireBlock(BlockT *dstBlk, BlockT *srcBlk) {
 | 
						|
  if (DEBUGME) {
 | 
						|
        errs() << "Retiring BB" << srcBlk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk];
 | 
						|
 | 
						|
  if (srcBlkInfo == NULL) {
 | 
						|
    srcBlkInfo = new BlockInfo();
 | 
						|
  }
 | 
						|
 | 
						|
  srcBlkInfo->isRetired = true;
 | 
						|
  assert(srcBlk->succ_size() == 0 && srcBlk->pred_size() == 0
 | 
						|
         && "can't retire block yet");
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::isRetiredBlock(BlockT *srcBlk) {
 | 
						|
  BlockInfo *srcBlkInfo = blockInfoMap[srcBlk];
 | 
						|
  return (srcBlkInfo && srcBlkInfo->isRetired);
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::isActiveLoophead(BlockT *curBlk) {
 | 
						|
  LoopT *loopRep = loopInfo->getLoopFor(curBlk);
 | 
						|
  while (loopRep && loopRep->getHeader() == curBlk) {
 | 
						|
    LoopLandInfo *loopLand = getLoopLandInfo(loopRep);
 | 
						|
 | 
						|
    if(loopLand == NULL)
 | 
						|
      return true;
 | 
						|
 | 
						|
    BlockT *landBlk = loopLand->landBlk;
 | 
						|
    assert(landBlk);
 | 
						|
    if (!isRetiredBlock(landBlk)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    loopRep = loopRep->getParentLoop();
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
} //isActiveLoophead
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::needMigrateBlock(BlockT *blk) {
 | 
						|
  const unsigned blockSizeThreshold = 30;
 | 
						|
  const unsigned cloneInstrThreshold = 100;
 | 
						|
 | 
						|
  bool multiplePreds = blk && (blk->pred_size() > 1);
 | 
						|
 | 
						|
  if(!multiplePreds)
 | 
						|
    return false;
 | 
						|
 | 
						|
  unsigned blkSize = blk->size();
 | 
						|
  return ((blkSize > blockSizeThreshold)
 | 
						|
          && (blkSize * (blk->pred_size() - 1) > cloneInstrThreshold));
 | 
						|
} //needMigrateBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::recordLoopLandBlock(LoopT *loopRep, BlockT *landBlk,
 | 
						|
                                            BlockTSmallerVector &exitBlks,
 | 
						|
                                            std::set<BlockT *> &exitBlkSet) {
 | 
						|
  SmallVector<BlockT *, DEFAULT_VEC_SLOTS> inpathBlks;  //in exit path blocks
 | 
						|
 | 
						|
  for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(),
 | 
						|
       predIterEnd = landBlk->pred_end();
 | 
						|
       predIter != predIterEnd; ++predIter) {
 | 
						|
    BlockT *curBlk = *predIter;
 | 
						|
    if (loopRep->contains(curBlk) || exitBlkSet.count(curBlk)) {
 | 
						|
      inpathBlks.push_back(curBlk);
 | 
						|
    }
 | 
						|
  } //for
 | 
						|
 | 
						|
  //if landBlk has predecessors that are not in the given loop,
 | 
						|
  //create a new block
 | 
						|
  BlockT *newLandBlk = landBlk;
 | 
						|
  if (inpathBlks.size() != landBlk->pred_size()) {
 | 
						|
    newLandBlk = funcRep->CreateMachineBasicBlock();
 | 
						|
    funcRep->push_back(newLandBlk);  //insert to function
 | 
						|
    newLandBlk->addSuccessor(landBlk);
 | 
						|
    for (typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::iterator iter =
 | 
						|
         inpathBlks.begin(),
 | 
						|
         iterEnd = inpathBlks.end(); iter != iterEnd; ++iter) {
 | 
						|
      BlockT *curBlk = *iter;
 | 
						|
      CFGTraits::replaceInstrUseOfBlockWith(curBlk, landBlk, newLandBlk);
 | 
						|
      //srcBlk, oldBlk, newBlk
 | 
						|
      curBlk->removeSuccessor(landBlk);
 | 
						|
      curBlk->addSuccessor(newLandBlk);
 | 
						|
    }
 | 
						|
    for (size_t i = 0, tot = exitBlks.size(); i < tot; ++i) {
 | 
						|
      if (exitBlks[i] == landBlk) {
 | 
						|
        exitBlks[i] = newLandBlk;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    SHOWNEWBLK(newLandBlk, "NewLandingBlock: ");
 | 
						|
  }
 | 
						|
 | 
						|
  setLoopLandBlock(loopRep, newLandBlk);
 | 
						|
 | 
						|
  return newLandBlk;
 | 
						|
} // recordLoopbreakLand
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::setLoopLandBlock(LoopT *loopRep, BlockT *blk) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
  assert(theEntry->landBlk == NULL);
 | 
						|
 | 
						|
  if (blk == NULL) {
 | 
						|
    blk = funcRep->CreateMachineBasicBlock();
 | 
						|
    funcRep->push_back(blk);  //insert to function
 | 
						|
    SHOWNEWBLK(blk, "DummyLandingBlock for loop without break: ");
 | 
						|
  }
 | 
						|
 | 
						|
  theEntry->landBlk = blk;
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "setLoopLandBlock loop-header = BB"
 | 
						|
           << loopRep->getHeader()->getNumber()
 | 
						|
           << "  landing-block = BB" << blk->getNumber() << "\n";
 | 
						|
  }
 | 
						|
} // setLoopLandBlock
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addLoopBreakOnReg(LoopT *loopRep, RegiT regNum) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
 | 
						|
  theEntry->breakOnRegs.insert(regNum);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "addLoopBreakOnReg loop-header = BB"
 | 
						|
           << loopRep->getHeader()->getNumber()
 | 
						|
           << "  regNum = " << regNum << "\n";
 | 
						|
  }
 | 
						|
} // addLoopBreakOnReg
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addLoopContOnReg(LoopT *loopRep, RegiT regNum) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
  theEntry->contOnRegs.insert(regNum);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "addLoopContOnReg loop-header = BB"
 | 
						|
           << loopRep->getHeader()->getNumber()
 | 
						|
           << "  regNum = " << regNum << "\n";
 | 
						|
  }
 | 
						|
} // addLoopContOnReg
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addLoopBreakInitReg(LoopT *loopRep, RegiT regNum) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
  theEntry->breakInitRegs.insert(regNum);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "addLoopBreakInitReg loop-header = BB"
 | 
						|
           << loopRep->getHeader()->getNumber()
 | 
						|
           << "  regNum = " << regNum << "\n";
 | 
						|
  }
 | 
						|
} // addLoopBreakInitReg
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addLoopContInitReg(LoopT *loopRep, RegiT regNum) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
  theEntry->contInitRegs.insert(regNum);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "addLoopContInitReg loop-header = BB"
 | 
						|
           << loopRep->getHeader()->getNumber()
 | 
						|
           << "  regNum = " << regNum << "\n";
 | 
						|
  }
 | 
						|
} // addLoopContInitReg
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
void CFGStructurizer<PassT>::addLoopEndbranchInitReg(LoopT *loopRep,
 | 
						|
                                                     RegiT regNum) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  if (theEntry == NULL) {
 | 
						|
    theEntry = new LoopLandInfo();
 | 
						|
  }
 | 
						|
  theEntry->endbranchInitRegs.insert(regNum);
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
        errs() << "addLoopEndbranchInitReg loop-header = BB"
 | 
						|
      << loopRep->getHeader()->getNumber()
 | 
						|
      << "  regNum = " << regNum << "\n";
 | 
						|
  }
 | 
						|
} // addLoopEndbranchInitReg
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::LoopLandInfo *
 | 
						|
CFGStructurizer<PassT>::getLoopLandInfo(LoopT *loopRep) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  return theEntry;
 | 
						|
} // getLoopLandInfo
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::getLoopLandBlock(LoopT *loopRep) {
 | 
						|
  LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
 | 
						|
 | 
						|
  return theEntry ? theEntry->landBlk : NULL;
 | 
						|
} // getLoopLandBlock
 | 
						|
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
bool CFGStructurizer<PassT>::hasBackEdge(BlockT *curBlk) {
 | 
						|
  LoopT *loopRep = loopInfo->getLoopFor(curBlk);
 | 
						|
  if (loopRep == NULL)
 | 
						|
    return false;
 | 
						|
 | 
						|
  BlockT *loopHeader = loopRep->getHeader();
 | 
						|
 | 
						|
  return curBlk->isSuccessor(loopHeader);
 | 
						|
 | 
						|
} //hasBackEdge
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
unsigned CFGStructurizer<PassT>::getLoopDepth(LoopT *loopRep) {
 | 
						|
  return loopRep ? loopRep->getLoopDepth() : 0;
 | 
						|
} //getLoopDepth
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
int CFGStructurizer<PassT>::countActiveBlock
 | 
						|
(typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::const_iterator iterStart,
 | 
						|
 typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::const_iterator iterEnd) {
 | 
						|
  int count = 0;
 | 
						|
  while (iterStart != iterEnd) {
 | 
						|
    if (!isRetiredBlock(*iterStart)) {
 | 
						|
      ++count;
 | 
						|
    }
 | 
						|
    ++iterStart;
 | 
						|
  }
 | 
						|
 | 
						|
  return count;
 | 
						|
} //countActiveBlock
 | 
						|
 | 
						|
// This is work around solution for findNearestCommonDominator not avaiable to
 | 
						|
// post dom a proper fix should go to Dominators.h.
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT*
 | 
						|
CFGStructurizer<PassT>::findNearestCommonPostDom(BlockT *blk1, BlockT *blk2) {
 | 
						|
 | 
						|
  if (postDomTree->dominates(blk1, blk2)) {
 | 
						|
    return blk1;
 | 
						|
  }
 | 
						|
  if (postDomTree->dominates(blk2, blk1)) {
 | 
						|
    return blk2;
 | 
						|
  }
 | 
						|
 | 
						|
  DomTreeNodeT *node1 = postDomTree->getNode(blk1);
 | 
						|
  DomTreeNodeT *node2 = postDomTree->getNode(blk2);
 | 
						|
 | 
						|
  // Handle newly cloned node.
 | 
						|
  if (node1 == NULL && blk1->succ_size() == 1) {
 | 
						|
    return findNearestCommonPostDom(*blk1->succ_begin(), blk2);
 | 
						|
  }
 | 
						|
  if (node2 == NULL && blk2->succ_size() == 1) {
 | 
						|
    return findNearestCommonPostDom(blk1, *blk2->succ_begin());
 | 
						|
  }
 | 
						|
 | 
						|
  if (node1 == NULL || node2 == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  node1 = node1->getIDom();
 | 
						|
  while (node1) {
 | 
						|
    if (postDomTree->dominates(node1, node2)) {
 | 
						|
      return node1->getBlock();
 | 
						|
    }
 | 
						|
    node1 = node1->getIDom();
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
template<class PassT>
 | 
						|
typename CFGStructurizer<PassT>::BlockT *
 | 
						|
CFGStructurizer<PassT>::findNearestCommonPostDom
 | 
						|
(typename std::set<BlockT *> &blks) {
 | 
						|
  BlockT *commonDom;
 | 
						|
  typename std::set<BlockT *>::const_iterator iter = blks.begin();
 | 
						|
  typename std::set<BlockT *>::const_iterator iterEnd = blks.end();
 | 
						|
  for (commonDom = *iter; iter != iterEnd && commonDom != NULL; ++iter) {
 | 
						|
    BlockT *curBlk = *iter;
 | 
						|
    if (curBlk != commonDom) {
 | 
						|
      commonDom = findNearestCommonPostDom(curBlk, commonDom);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (DEBUGME) {
 | 
						|
    errs() << "Common post dominator for exit blocks is ";
 | 
						|
    if (commonDom) {
 | 
						|
          errs() << "BB" << commonDom->getNumber() << "\n";
 | 
						|
    } else {
 | 
						|
      errs() << "NULL\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return commonDom;
 | 
						|
} //findNearestCommonPostDom
 | 
						|
 | 
						|
} //end namespace llvm
 | 
						|
 | 
						|
//todo: move-end
 | 
						|
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// CFGStructurizer for AMDGPU
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
 | 
						|
using namespace llvmCFGStruct;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
class AMDGPUCFGStructurizer : public MachineFunctionPass {
 | 
						|
public:
 | 
						|
  typedef MachineInstr              InstructionType;
 | 
						|
  typedef MachineFunction           FunctionType;
 | 
						|
  typedef MachineBasicBlock         BlockType;
 | 
						|
  typedef MachineLoopInfo           LoopinfoType;
 | 
						|
  typedef MachineDominatorTree      DominatortreeType;
 | 
						|
  typedef MachinePostDominatorTree  PostDominatortreeType;
 | 
						|
  typedef MachineDomTreeNode        DomTreeNodeType;
 | 
						|
  typedef MachineLoop               LoopType;
 | 
						|
 | 
						|
protected:
 | 
						|
  TargetMachine &TM;
 | 
						|
  const TargetInstrInfo *TII;
 | 
						|
  const AMDGPURegisterInfo *TRI;
 | 
						|
 | 
						|
public:
 | 
						|
  AMDGPUCFGStructurizer(char &pid, TargetMachine &tm);
 | 
						|
  const TargetInstrInfo *getTargetInstrInfo() const;
 | 
						|
 | 
						|
private:
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
} //end of namespace llvm
 | 
						|
AMDGPUCFGStructurizer::AMDGPUCFGStructurizer(char &pid, TargetMachine &tm)
 | 
						|
: MachineFunctionPass(pid), TM(tm), TII(tm.getInstrInfo()),
 | 
						|
  TRI(static_cast<const AMDGPURegisterInfo *>(tm.getRegisterInfo())) {
 | 
						|
}
 | 
						|
 | 
						|
const TargetInstrInfo *AMDGPUCFGStructurizer::getTargetInstrInfo() const {
 | 
						|
  return TII;
 | 
						|
}
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// CFGPrepare
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
 | 
						|
using namespace llvmCFGStruct;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
class AMDGPUCFGPrepare : public AMDGPUCFGStructurizer {
 | 
						|
public:
 | 
						|
  static char ID;
 | 
						|
 | 
						|
public:
 | 
						|
  AMDGPUCFGPrepare(TargetMachine &tm);
 | 
						|
 | 
						|
  virtual const char *getPassName() const;
 | 
						|
  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
 | 
						|
 | 
						|
  bool runOnMachineFunction(MachineFunction &F);
 | 
						|
 | 
						|
private:
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
char AMDGPUCFGPrepare::ID = 0;
 | 
						|
} //end of namespace llvm
 | 
						|
 | 
						|
AMDGPUCFGPrepare::AMDGPUCFGPrepare(TargetMachine &tm)
 | 
						|
  : AMDGPUCFGStructurizer(ID, tm )  {
 | 
						|
}
 | 
						|
const char *AMDGPUCFGPrepare::getPassName() const {
 | 
						|
  return "AMD IL Control Flow Graph Preparation Pass";
 | 
						|
}
 | 
						|
 | 
						|
void AMDGPUCFGPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
 | 
						|
  AU.addPreserved<MachineFunctionAnalysis>();
 | 
						|
  AU.addRequired<MachineFunctionAnalysis>();
 | 
						|
  AU.addRequired<MachineDominatorTree>();
 | 
						|
  AU.addRequired<MachinePostDominatorTree>();
 | 
						|
  AU.addRequired<MachineLoopInfo>();
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// CFGPerform
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
 | 
						|
using namespace llvmCFGStruct;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
class AMDGPUCFGPerform : public AMDGPUCFGStructurizer {
 | 
						|
public:
 | 
						|
  static char ID;
 | 
						|
 | 
						|
public:
 | 
						|
  AMDGPUCFGPerform(TargetMachine &tm);
 | 
						|
  virtual const char *getPassName() const;
 | 
						|
  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
 | 
						|
  bool runOnMachineFunction(MachineFunction &F);
 | 
						|
 | 
						|
private:
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
char AMDGPUCFGPerform::ID = 0;
 | 
						|
} //end of namespace llvm
 | 
						|
 | 
						|
  AMDGPUCFGPerform::AMDGPUCFGPerform(TargetMachine &tm)
 | 
						|
: AMDGPUCFGStructurizer(ID, tm) {
 | 
						|
}
 | 
						|
 | 
						|
const char *AMDGPUCFGPerform::getPassName() const {
 | 
						|
  return "AMD IL Control Flow Graph structurizer Pass";
 | 
						|
}
 | 
						|
 | 
						|
void AMDGPUCFGPerform::getAnalysisUsage(AnalysisUsage &AU) const {
 | 
						|
  AU.addPreserved<MachineFunctionAnalysis>();
 | 
						|
  AU.addRequired<MachineFunctionAnalysis>();
 | 
						|
  AU.addRequired<MachineDominatorTree>();
 | 
						|
  AU.addRequired<MachinePostDominatorTree>();
 | 
						|
  AU.addRequired<MachineLoopInfo>();
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// CFGStructTraits<AMDGPUCFGStructurizer>
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
namespace llvmCFGStruct {
 | 
						|
// this class is tailor to the AMDGPU backend
 | 
						|
template<>
 | 
						|
struct CFGStructTraits<AMDGPUCFGStructurizer> {
 | 
						|
  typedef int RegiT;
 | 
						|
 | 
						|
  static int getBranchNzeroOpcode(int oldOpcode) {
 | 
						|
    switch(oldOpcode) {
 | 
						|
    case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
 | 
						|
    case AMDGPU::BRANCH_COND_i32:
 | 
						|
    case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALNZ_f32;
 | 
						|
    default:
 | 
						|
      assert(0 && "internal error");
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  static int getBranchZeroOpcode(int oldOpcode) {
 | 
						|
    switch(oldOpcode) {
 | 
						|
    case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
 | 
						|
    case AMDGPU::BRANCH_COND_i32:
 | 
						|
    case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALZ_f32;
 | 
						|
    default:
 | 
						|
      assert(0 && "internal error");
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  static int getContinueNzeroOpcode(int oldOpcode) {
 | 
						|
    switch(oldOpcode) {
 | 
						|
    case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALNZ_i32;
 | 
						|
    default:
 | 
						|
      assert(0 && "internal error");
 | 
						|
    };
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  static int getContinueZeroOpcode(int oldOpcode) {
 | 
						|
    switch(oldOpcode) {
 | 
						|
    case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALZ_i32;
 | 
						|
    default:
 | 
						|
      assert(0 && "internal error");
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineBasicBlock *getTrueBranch(MachineInstr *instr) {
 | 
						|
    return instr->getOperand(0).getMBB();
 | 
						|
  }
 | 
						|
 | 
						|
  static void setTrueBranch(MachineInstr *instr, MachineBasicBlock *blk) {
 | 
						|
    instr->getOperand(0).setMBB(blk);
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineBasicBlock *
 | 
						|
  getFalseBranch(MachineBasicBlock *blk, MachineInstr *instr) {
 | 
						|
    assert(blk->succ_size() == 2);
 | 
						|
    MachineBasicBlock *trueBranch = getTrueBranch(instr);
 | 
						|
    MachineBasicBlock::succ_iterator iter = blk->succ_begin();
 | 
						|
    MachineBasicBlock::succ_iterator iterNext = iter;
 | 
						|
    ++iterNext;
 | 
						|
 | 
						|
    return (*iter == trueBranch) ? *iterNext : *iter;
 | 
						|
  }
 | 
						|
 | 
						|
  static bool isCondBranch(MachineInstr *instr) {
 | 
						|
    switch (instr->getOpcode()) {
 | 
						|
      case AMDGPU::JUMP:
 | 
						|
        return instr->getOperand(instr->findFirstPredOperandIdx()).getReg() != 0;
 | 
						|
      case AMDGPU::BRANCH_COND_i32:
 | 
						|
      case AMDGPU::BRANCH_COND_f32:
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  static bool isUncondBranch(MachineInstr *instr) {
 | 
						|
    switch (instr->getOpcode()) {
 | 
						|
    case AMDGPU::JUMP:
 | 
						|
      return instr->getOperand(instr->findFirstPredOperandIdx()).getReg() == 0;
 | 
						|
    case AMDGPU::BRANCH:
 | 
						|
      return true;
 | 
						|
    default:
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  static DebugLoc getLastDebugLocInBB(MachineBasicBlock *blk) {
 | 
						|
    //get DebugLoc from the first MachineBasicBlock instruction with debug info
 | 
						|
    DebugLoc DL;
 | 
						|
    for (MachineBasicBlock::iterator iter = blk->begin(); iter != blk->end(); ++iter) {
 | 
						|
      MachineInstr *instr = &(*iter);
 | 
						|
      if (instr->getDebugLoc().isUnknown() == false) {
 | 
						|
        DL = instr->getDebugLoc();
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return DL;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *blk) {
 | 
						|
    MachineBasicBlock::reverse_iterator iter = blk->rbegin();
 | 
						|
    MachineInstr *instr = &*iter;
 | 
						|
    if (instr && (isCondBranch(instr) || isUncondBranch(instr))) {
 | 
						|
      return instr;
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  // The correct naming for this is getPossibleLoopendBlockBranchInstr.
 | 
						|
  //
 | 
						|
  // BB with backward-edge could have move instructions after the branch
 | 
						|
  // instruction.  Such move instruction "belong to" the loop backward-edge.
 | 
						|
  //
 | 
						|
  static MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *blk) {
 | 
						|
    const AMDGPUInstrInfo * TII = static_cast<const AMDGPUInstrInfo *>(
 | 
						|
                                  blk->getParent()->getTarget().getInstrInfo());
 | 
						|
 | 
						|
    for (MachineBasicBlock::reverse_iterator iter = blk->rbegin(),
 | 
						|
         iterEnd = blk->rend(); iter != iterEnd; ++iter) {
 | 
						|
      // FIXME: Simplify
 | 
						|
      MachineInstr *instr = &*iter;
 | 
						|
      if (instr) {
 | 
						|
        if (isCondBranch(instr) || isUncondBranch(instr)) {
 | 
						|
          return instr;
 | 
						|
        } else if (!TII->isMov(instr->getOpcode())) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineInstr *getReturnInstr(MachineBasicBlock *blk) {
 | 
						|
    MachineBasicBlock::reverse_iterator iter = blk->rbegin();
 | 
						|
    if (iter != blk->rend()) {
 | 
						|
      MachineInstr *instr = &(*iter);
 | 
						|
      if (instr->getOpcode() == AMDGPU::RETURN) {
 | 
						|
        return instr;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineInstr *getContinueInstr(MachineBasicBlock *blk) {
 | 
						|
    MachineBasicBlock::reverse_iterator iter = blk->rbegin();
 | 
						|
    if (iter != blk->rend()) {
 | 
						|
      MachineInstr *instr = &(*iter);
 | 
						|
      if (instr->getOpcode() == AMDGPU::CONTINUE) {
 | 
						|
        return instr;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineInstr *getLoopBreakInstr(MachineBasicBlock *blk) {
 | 
						|
    for (MachineBasicBlock::iterator iter = blk->begin(); (iter != blk->end()); ++iter) {
 | 
						|
      MachineInstr *instr = &(*iter);
 | 
						|
      if (instr->getOpcode() == AMDGPU::PREDICATED_BREAK) {
 | 
						|
        return instr;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  static bool isReturnBlock(MachineBasicBlock *blk) {
 | 
						|
    MachineInstr *instr = getReturnInstr(blk);
 | 
						|
    bool isReturn = (blk->succ_size() == 0);
 | 
						|
    if (instr) {
 | 
						|
      assert(isReturn);
 | 
						|
    } else if (isReturn) {
 | 
						|
      if (DEBUGME) {
 | 
						|
        errs() << "BB" << blk->getNumber()
 | 
						|
               <<" is return block without RETURN instr\n";
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return  isReturn;
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineBasicBlock::iterator
 | 
						|
  getInstrPos(MachineBasicBlock *blk, MachineInstr *instr) {
 | 
						|
    assert(instr->getParent() == blk && "instruction doesn't belong to block");
 | 
						|
    MachineBasicBlock::iterator iter = blk->begin();
 | 
						|
    MachineBasicBlock::iterator iterEnd = blk->end();
 | 
						|
    while (&(*iter) != instr && iter != iterEnd) {
 | 
						|
      ++iter;
 | 
						|
    }
 | 
						|
 | 
						|
    assert(iter != iterEnd);
 | 
						|
    return iter;
 | 
						|
  }//getInstrPos
 | 
						|
 | 
						|
  static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode,
 | 
						|
                                         AMDGPUCFGStructurizer *passRep) {
 | 
						|
    return insertInstrBefore(blk,newOpcode,passRep,DebugLoc());
 | 
						|
  } //insertInstrBefore
 | 
						|
 | 
						|
  static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode,
 | 
						|
                                         AMDGPUCFGStructurizer *passRep, DebugLoc DL) {
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
    MachineInstr *newInstr =
 | 
						|
      blk->getParent()->CreateMachineInstr(tii->get(newOpcode), DL);
 | 
						|
 | 
						|
    MachineBasicBlock::iterator res;
 | 
						|
    if (blk->begin() != blk->end()) {
 | 
						|
      blk->insert(blk->begin(), newInstr);
 | 
						|
    } else {
 | 
						|
      blk->push_back(newInstr);
 | 
						|
    }
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
 | 
						|
    return newInstr;
 | 
						|
  } //insertInstrBefore
 | 
						|
 | 
						|
  static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode,
 | 
						|
                             AMDGPUCFGStructurizer *passRep) {
 | 
						|
    insertInstrEnd(blk,newOpcode,passRep,DebugLoc());
 | 
						|
  } //insertInstrEnd
 | 
						|
 | 
						|
  static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode,
 | 
						|
                             AMDGPUCFGStructurizer *passRep, DebugLoc DL) {
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
   MachineInstr *newInstr = blk->getParent()
 | 
						|
      ->CreateMachineInstr(tii->get(newOpcode), DL);
 | 
						|
 | 
						|
    blk->push_back(newInstr);
 | 
						|
    //assume the instruction doesn't take any reg operand ...
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
  } //insertInstrEnd
 | 
						|
 | 
						|
  static MachineInstr *insertInstrBefore(MachineBasicBlock::iterator instrPos,
 | 
						|
                                         int newOpcode, 
 | 
						|
                                         AMDGPUCFGStructurizer *passRep) {
 | 
						|
    MachineInstr *oldInstr = &(*instrPos);
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
    MachineBasicBlock *blk = oldInstr->getParent();
 | 
						|
    MachineInstr *newInstr =
 | 
						|
      blk->getParent()->CreateMachineInstr(tii->get(newOpcode),
 | 
						|
                                           DebugLoc());
 | 
						|
 | 
						|
    blk->insert(instrPos, newInstr);
 | 
						|
    //assume the instruction doesn't take any reg operand ...
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
    return newInstr;
 | 
						|
  } //insertInstrBefore
 | 
						|
 | 
						|
  static void insertCondBranchBefore(MachineBasicBlock::iterator instrPos,
 | 
						|
                                     int newOpcode,
 | 
						|
                                     AMDGPUCFGStructurizer *passRep,
 | 
						|
                                     DebugLoc DL) {
 | 
						|
    MachineInstr *oldInstr = &(*instrPos);
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
    MachineBasicBlock *blk = oldInstr->getParent();
 | 
						|
    MachineFunction *MF = blk->getParent();
 | 
						|
    MachineInstr *newInstr = MF->CreateMachineInstr(tii->get(newOpcode), DL);
 | 
						|
 | 
						|
    blk->insert(instrPos, newInstr);
 | 
						|
    MachineInstrBuilder MIB(*MF, newInstr);
 | 
						|
    MIB.addReg(oldInstr->getOperand(1).getReg(), false);
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
    //erase later oldInstr->eraseFromParent();
 | 
						|
  } //insertCondBranchBefore
 | 
						|
 | 
						|
  static void insertCondBranchBefore(MachineBasicBlock *blk,
 | 
						|
                                     MachineBasicBlock::iterator insertPos,
 | 
						|
                                     int newOpcode,
 | 
						|
                                     AMDGPUCFGStructurizer *passRep,
 | 
						|
                                     RegiT regNum,
 | 
						|
                                     DebugLoc DL) {
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
    MachineFunction *MF = blk->getParent();
 | 
						|
 | 
						|
    MachineInstr *newInstr = MF->CreateMachineInstr(tii->get(newOpcode), DL);
 | 
						|
 | 
						|
    //insert before
 | 
						|
    blk->insert(insertPos, newInstr);
 | 
						|
    MachineInstrBuilder(*MF, newInstr).addReg(regNum, false);
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
  } //insertCondBranchBefore
 | 
						|
 | 
						|
  static void insertCondBranchEnd(MachineBasicBlock *blk,
 | 
						|
                                  int newOpcode,
 | 
						|
                                  AMDGPUCFGStructurizer *passRep,
 | 
						|
                                  RegiT regNum) {
 | 
						|
    const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
 | 
						|
    MachineFunction *MF = blk->getParent();
 | 
						|
    MachineInstr *newInstr =
 | 
						|
      MF->CreateMachineInstr(tii->get(newOpcode), DebugLoc());
 | 
						|
 | 
						|
    blk->push_back(newInstr);
 | 
						|
    MachineInstrBuilder(*MF, newInstr).addReg(regNum, false);
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
  } //insertCondBranchEnd
 | 
						|
 | 
						|
 | 
						|
  static void insertAssignInstrBefore(MachineBasicBlock::iterator instrPos,
 | 
						|
                                      AMDGPUCFGStructurizer *passRep,
 | 
						|
                                      RegiT regNum, int regVal) {
 | 
						|
    MachineInstr *oldInstr = &(*instrPos);
 | 
						|
    const AMDGPUInstrInfo *tii =
 | 
						|
             static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
 | 
						|
    MachineBasicBlock *blk = oldInstr->getParent();
 | 
						|
    MachineInstr *newInstr = tii->getMovImmInstr(blk->getParent(), regNum,
 | 
						|
                                                 regVal);
 | 
						|
    blk->insert(instrPos, newInstr);
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
  } //insertAssignInstrBefore
 | 
						|
 | 
						|
  static void insertAssignInstrBefore(MachineBasicBlock *blk,
 | 
						|
                                      AMDGPUCFGStructurizer *passRep,
 | 
						|
                                      RegiT regNum, int regVal) {
 | 
						|
    const AMDGPUInstrInfo *tii =
 | 
						|
             static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
 | 
						|
 | 
						|
    MachineInstr *newInstr = tii->getMovImmInstr(blk->getParent(), regNum,
 | 
						|
                                                 regVal);
 | 
						|
    if (blk->begin() != blk->end()) {
 | 
						|
      blk->insert(blk->begin(), newInstr);
 | 
						|
    } else {
 | 
						|
      blk->push_back(newInstr);
 | 
						|
    }
 | 
						|
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
 | 
						|
  } //insertInstrBefore
 | 
						|
 | 
						|
  static void insertCompareInstrBefore(MachineBasicBlock *blk,
 | 
						|
                                       MachineBasicBlock::iterator instrPos,
 | 
						|
                                       AMDGPUCFGStructurizer *passRep,
 | 
						|
                                       RegiT dstReg, RegiT src1Reg,
 | 
						|
                                       RegiT src2Reg) {
 | 
						|
    const AMDGPUInstrInfo *tii =
 | 
						|
             static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
 | 
						|
    MachineFunction *MF = blk->getParent();
 | 
						|
    MachineInstr *newInstr =
 | 
						|
      MF->CreateMachineInstr(tii->get(tii->getIEQOpcode()), DebugLoc());
 | 
						|
 | 
						|
    MachineInstrBuilder MIB(*MF, newInstr);
 | 
						|
    MIB.addReg(dstReg, RegState::Define); //set target
 | 
						|
    MIB.addReg(src1Reg); //set src value
 | 
						|
    MIB.addReg(src2Reg); //set src value
 | 
						|
 | 
						|
    blk->insert(instrPos, newInstr);
 | 
						|
    SHOWNEWINSTR(newInstr);
 | 
						|
 | 
						|
  } //insertCompareInstrBefore
 | 
						|
 | 
						|
  static void cloneSuccessorList(MachineBasicBlock *dstBlk,
 | 
						|
                                 MachineBasicBlock *srcBlk) {
 | 
						|
    for (MachineBasicBlock::succ_iterator iter = srcBlk->succ_begin(),
 | 
						|
         iterEnd = srcBlk->succ_end(); iter != iterEnd; ++iter) {
 | 
						|
      dstBlk->addSuccessor(*iter);  // *iter's predecessor is also taken care of
 | 
						|
    }
 | 
						|
  } //cloneSuccessorList
 | 
						|
 | 
						|
  static MachineBasicBlock *clone(MachineBasicBlock *srcBlk) {
 | 
						|
    MachineFunction *func = srcBlk->getParent();
 | 
						|
    MachineBasicBlock *newBlk = func->CreateMachineBasicBlock();
 | 
						|
    func->push_back(newBlk);  //insert to function
 | 
						|
    for (MachineBasicBlock::iterator iter = srcBlk->begin(),
 | 
						|
         iterEnd = srcBlk->end();
 | 
						|
         iter != iterEnd; ++iter) {
 | 
						|
      MachineInstr *instr = func->CloneMachineInstr(iter);
 | 
						|
      newBlk->push_back(instr);
 | 
						|
    }
 | 
						|
    return newBlk;
 | 
						|
  }
 | 
						|
 | 
						|
  //MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose because
 | 
						|
  //the AMDGPU instruction is not recognized as terminator fix this and retire
 | 
						|
  //this routine
 | 
						|
  static void replaceInstrUseOfBlockWith(MachineBasicBlock *srcBlk,
 | 
						|
                                         MachineBasicBlock *oldBlk,
 | 
						|
                                         MachineBasicBlock *newBlk) {
 | 
						|
    MachineInstr *branchInstr = getLoopendBlockBranchInstr(srcBlk);
 | 
						|
    if (branchInstr && isCondBranch(branchInstr) &&
 | 
						|
        getTrueBranch(branchInstr) == oldBlk) {
 | 
						|
      setTrueBranch(branchInstr, newBlk);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  static void wrapup(MachineBasicBlock *entryBlk) {
 | 
						|
    assert((!entryBlk->getParent()->getJumpTableInfo()
 | 
						|
            || entryBlk->getParent()->getJumpTableInfo()->isEmpty())
 | 
						|
           && "found a jump table");
 | 
						|
 | 
						|
     //collect continue right before endloop
 | 
						|
     SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> contInstr;
 | 
						|
     MachineBasicBlock::iterator pre = entryBlk->begin();
 | 
						|
     MachineBasicBlock::iterator iterEnd = entryBlk->end();
 | 
						|
     MachineBasicBlock::iterator iter = pre;
 | 
						|
     while (iter != iterEnd) {
 | 
						|
       if (pre->getOpcode() == AMDGPU::CONTINUE
 | 
						|
           && iter->getOpcode() == AMDGPU::ENDLOOP) {
 | 
						|
         contInstr.push_back(pre);
 | 
						|
       }
 | 
						|
       pre = iter;
 | 
						|
       ++iter;
 | 
						|
     } //end while
 | 
						|
 | 
						|
     //delete continue right before endloop
 | 
						|
     for (unsigned i = 0; i < contInstr.size(); ++i) {
 | 
						|
        contInstr[i]->eraseFromParent();
 | 
						|
     }
 | 
						|
 | 
						|
     // TODO to fix up jump table so later phase won't be confused.  if
 | 
						|
     // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
 | 
						|
     // there isn't such an interface yet.  alternatively, replace all the other
 | 
						|
     // blocks in the jump table with the entryBlk //}
 | 
						|
 | 
						|
  } //wrapup
 | 
						|
 | 
						|
  static MachineDominatorTree *getDominatorTree(AMDGPUCFGStructurizer &pass) {
 | 
						|
    return &pass.getAnalysis<MachineDominatorTree>();
 | 
						|
  }
 | 
						|
 | 
						|
  static MachinePostDominatorTree*
 | 
						|
  getPostDominatorTree(AMDGPUCFGStructurizer &pass) {
 | 
						|
    return &pass.getAnalysis<MachinePostDominatorTree>();
 | 
						|
  }
 | 
						|
 | 
						|
  static MachineLoopInfo *getLoopInfo(AMDGPUCFGStructurizer &pass) {
 | 
						|
    return &pass.getAnalysis<MachineLoopInfo>();
 | 
						|
  }
 | 
						|
}; // template class CFGStructTraits
 | 
						|
} //end of namespace llvm
 | 
						|
 | 
						|
// createAMDGPUCFGPreparationPass- Returns a pass
 | 
						|
FunctionPass *llvm::createAMDGPUCFGPreparationPass(TargetMachine &tm
 | 
						|
                                                 ) {
 | 
						|
  return new AMDGPUCFGPrepare(tm );
 | 
						|
}
 | 
						|
 | 
						|
bool AMDGPUCFGPrepare::runOnMachineFunction(MachineFunction &func) {
 | 
						|
  return llvmCFGStruct::CFGStructurizer<AMDGPUCFGStructurizer>().prepare(func,
 | 
						|
                                                                        *this,
 | 
						|
                                                                        TRI);
 | 
						|
}
 | 
						|
 | 
						|
// createAMDGPUCFGStructurizerPass- Returns a pass
 | 
						|
FunctionPass *llvm::createAMDGPUCFGStructurizerPass(TargetMachine &tm
 | 
						|
                                                  ) {
 | 
						|
  return new AMDGPUCFGPerform(tm );
 | 
						|
}
 | 
						|
 | 
						|
bool AMDGPUCFGPerform::runOnMachineFunction(MachineFunction &func) {
 | 
						|
  return llvmCFGStruct::CFGStructurizer<AMDGPUCFGStructurizer>().run(func,
 | 
						|
                                                                    *this,
 | 
						|
                                                                    TRI);
 | 
						|
}
 |