AMDILCFGStructurizer.cpp revision a75c6163e605f35b14f26930dd9227e4f337ec9e
1//===-- AMDILCFGStructurizer.cpp - CFG Structurizer -----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//==-----------------------------------------------------------------------===// 9 10#define DEBUG_TYPE "structcfg" 11#ifdef DEBUG 12#define DEBUGME (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) 13#else 14#define DEBUGME 0 15#endif 16 17#include "AMDILCompilerErrors.h" 18#include "AMDILMachineFunctionInfo.h" 19#include "AMDILTargetMachine.h" 20#include "AMDILUtilityFunctions.h" 21#include "llvm/ADT/SCCIterator.h" 22#include "llvm/ADT/SmallVector.h" 23#include "llvm/ADT/Statistic.h" 24#include "llvm/CodeGen/MachineDominators.h" 25#include "llvm/CodeGen/MachineFunction.h" 26#include "llvm/CodeGen/MachineFunctionAnalysis.h" 27#include "llvm/CodeGen/MachineFunctionPass.h" 28#include "llvm/CodeGen/MachineJumpTableInfo.h" 29#include "llvm/CodeGen/MachineLoopInfo.h" 30#include "llvm/CodeGen/MachineRegisterInfo.h" 31 32#define FirstNonDebugInstr(A) A->begin() 33using namespace llvm; 34 35// bixia TODO: move this out to analysis lib. Make this work for both target 36// AMDIL and CBackend. 37// TODO: move-begin. 38 39//===----------------------------------------------------------------------===// 40// 41// Statistics for CFGStructurizer. 42// 43//===----------------------------------------------------------------------===// 44 45STATISTIC(numSerialPatternMatch, "CFGStructurizer number of serial pattern " 46 "matched"); 47STATISTIC(numIfPatternMatch, "CFGStructurizer number of if pattern " 48 "matched"); 49STATISTIC(numLoopbreakPatternMatch, "CFGStructurizer number of loop-break " 50 "pattern matched"); 51STATISTIC(numLoopcontPatternMatch, "CFGStructurizer number of loop-continue " 52 "pattern matched"); 53STATISTIC(numLoopPatternMatch, "CFGStructurizer number of loop pattern " 54 "matched"); 55STATISTIC(numClonedBlock, "CFGStructurizer cloned blocks"); 56STATISTIC(numClonedInstr, "CFGStructurizer cloned instructions"); 57 58//===----------------------------------------------------------------------===// 59// 60// Miscellaneous utility for CFGStructurizer. 61// 62//===----------------------------------------------------------------------===// 63namespace llvmCFGStruct 64{ 65#define SHOWNEWINSTR(i) \ 66 if (DEBUGME) errs() << "New instr: " << *i << "\n" 67 68#define SHOWNEWBLK(b, msg) \ 69if (DEBUGME) { \ 70 errs() << msg << "BB" << b->getNumber() << "size " << b->size(); \ 71 errs() << "\n"; \ 72} 73 74#define SHOWBLK_DETAIL(b, msg) \ 75if (DEBUGME) { \ 76 if (b) { \ 77 errs() << msg << "BB" << b->getNumber() << "size " << b->size(); \ 78 b->print(errs()); \ 79 errs() << "\n"; \ 80 } \ 81} 82 83#define INVALIDSCCNUM -1 84#define INVALIDREGNUM 0 85 86template<class LoopinfoT> 87void PrintLoopinfo(const LoopinfoT &LoopInfo, llvm::raw_ostream &OS) { 88 for (typename LoopinfoT::iterator iter = LoopInfo.begin(), 89 iterEnd = LoopInfo.end(); 90 iter != iterEnd; ++iter) { 91 (*iter)->print(OS, 0); 92 } 93} 94 95template<class NodeT> 96void ReverseVector(SmallVector<NodeT *, DEFAULT_VEC_SLOTS> &Src) { 97 size_t sz = Src.size(); 98 for (size_t i = 0; i < sz/2; ++i) { 99 NodeT *t = Src[i]; 100 Src[i] = Src[sz - i - 1]; 101 Src[sz - i - 1] = t; 102 } 103} 104 105} //end namespace llvmCFGStruct 106 107 108//===----------------------------------------------------------------------===// 109// 110// MachinePostDominatorTree 111// 112//===----------------------------------------------------------------------===// 113 114#include "AMDILCompilerErrors.h" 115#include "AMDILMachineFunctionInfo.h" 116#include "AMDILTargetMachine.h" 117#include "AMDILUtilityFunctions.h" 118#include "llvm/ADT/SCCIterator.h" 119#include "llvm/ADT/SmallVector.h" 120#include "llvm/ADT/Statistic.h" 121#include "llvm/Analysis/DominatorInternals.h" 122#include "llvm/Analysis/Dominators.h" 123#include "llvm/CodeGen/MachineDominators.h" 124#include "llvm/CodeGen/MachineDominators.h" 125#include "llvm/CodeGen/MachineFunction.h" 126#include "llvm/CodeGen/MachineFunctionAnalysis.h" 127#include "llvm/CodeGen/MachineFunctionPass.h" 128#include "llvm/CodeGen/MachineFunctionPass.h" 129#include "llvm/CodeGen/MachineJumpTableInfo.h" 130#include "llvm/CodeGen/MachineLoopInfo.h" 131#include "llvm/CodeGen/MachineRegisterInfo.h" 132 133namespace llvm { 134 135/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used 136/// to compute the a post-dominator tree. 137/// 138struct MachinePostDominatorTree : public MachineFunctionPass { 139 static char ID; // Pass identification, replacement for typeid 140 DominatorTreeBase<MachineBasicBlock> *DT; 141 MachinePostDominatorTree() : MachineFunctionPass(ID) 142 { 143 DT = new DominatorTreeBase<MachineBasicBlock>(true); //true indicate 144 // postdominator 145 } 146 147 ~MachinePostDominatorTree(); 148 149 virtual bool runOnMachineFunction(MachineFunction &MF); 150 151 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 152 AU.setPreservesAll(); 153 MachineFunctionPass::getAnalysisUsage(AU); 154 } 155 156 inline const std::vector<MachineBasicBlock *> &getRoots() const { 157 return DT->getRoots(); 158 } 159 160 inline MachineDomTreeNode *getRootNode() const { 161 return DT->getRootNode(); 162 } 163 164 inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { 165 return DT->getNode(BB); 166 } 167 168 inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { 169 return DT->getNode(BB); 170 } 171 172 inline bool dominates(MachineDomTreeNode *A, MachineDomTreeNode *B) const { 173 return DT->dominates(A, B); 174 } 175 176 inline bool dominates(MachineBasicBlock *A, MachineBasicBlock *B) const { 177 return DT->dominates(A, B); 178 } 179 180 inline bool 181 properlyDominates(const MachineDomTreeNode *A, MachineDomTreeNode *B) const { 182 return DT->properlyDominates(A, B); 183 } 184 185 inline bool 186 properlyDominates(MachineBasicBlock *A, MachineBasicBlock *B) const { 187 return DT->properlyDominates(A, B); 188 } 189 190 inline MachineBasicBlock * 191 findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B) { 192 return DT->findNearestCommonDominator(A, B); 193 } 194 195 virtual void print(llvm::raw_ostream &OS, const Module *M = 0) const { 196 DT->print(OS); 197 } 198}; 199} //end of namespace llvm 200 201char MachinePostDominatorTree::ID = 0; 202static RegisterPass<MachinePostDominatorTree> 203machinePostDominatorTreePass("machinepostdomtree", 204 "MachinePostDominator Tree Construction", 205 true, true); 206 207//const PassInfo *const llvm::MachinePostDominatorsID 208//= &machinePostDominatorTreePass; 209 210bool MachinePostDominatorTree::runOnMachineFunction(MachineFunction &F) { 211 DT->recalculate(F); 212 //DEBUG(DT->dump()); 213 return false; 214} 215 216MachinePostDominatorTree::~MachinePostDominatorTree() { 217 delete DT; 218} 219 220//===----------------------------------------------------------------------===// 221// 222// supporting data structure for CFGStructurizer 223// 224//===----------------------------------------------------------------------===// 225 226namespace llvmCFGStruct 227{ 228template<class PassT> 229struct CFGStructTraits { 230}; 231 232template <class InstrT> 233class BlockInformation { 234public: 235 bool isRetired; 236 int sccNum; 237 //SmallVector<InstrT*, DEFAULT_VEC_SLOTS> succInstr; 238 //Instructions defining the corresponding successor. 239 BlockInformation() : isRetired(false), sccNum(INVALIDSCCNUM) {} 240}; 241 242template <class BlockT, class InstrT, class RegiT> 243class LandInformation { 244public: 245 BlockT *landBlk; 246 std::set<RegiT> breakInitRegs; //Registers that need to "reg = 0", before 247 //WHILELOOP(thisloop) init before entering 248 //thisloop. 249 std::set<RegiT> contInitRegs; //Registers that need to "reg = 0", after 250 //WHILELOOP(thisloop) init after entering 251 //thisloop. 252 std::set<RegiT> endbranchInitRegs; //Init before entering this loop, at loop 253 //land block, branch cond on this reg. 254 std::set<RegiT> breakOnRegs; //registers that need to "if (reg) break 255 //endif" after ENDLOOP(thisloop) break 256 //outerLoopOf(thisLoop). 257 std::set<RegiT> contOnRegs; //registers that need to "if (reg) continue 258 //endif" after ENDLOOP(thisloop) continue on 259 //outerLoopOf(thisLoop). 260 LandInformation() : landBlk(NULL) {} 261}; 262 263} //end of namespace llvmCFGStruct 264 265//===----------------------------------------------------------------------===// 266// 267// CFGStructurizer 268// 269//===----------------------------------------------------------------------===// 270 271namespace llvmCFGStruct 272{ 273// bixia TODO: port it to BasicBlock, not just MachineBasicBlock. 274template<class PassT> 275class CFGStructurizer 276{ 277public: 278 typedef enum { 279 Not_SinglePath = 0, 280 SinglePath_InPath = 1, 281 SinglePath_NotInPath = 2 282 } PathToKind; 283 284public: 285 typedef typename PassT::InstructionType InstrT; 286 typedef typename PassT::FunctionType FuncT; 287 typedef typename PassT::DominatortreeType DomTreeT; 288 typedef typename PassT::PostDominatortreeType PostDomTreeT; 289 typedef typename PassT::DomTreeNodeType DomTreeNodeT; 290 typedef typename PassT::LoopinfoType LoopInfoT; 291 292 typedef GraphTraits<FuncT *> FuncGTraits; 293 //typedef FuncGTraits::nodes_iterator BlockIterator; 294 typedef typename FuncT::iterator BlockIterator; 295 296 typedef typename FuncGTraits::NodeType BlockT; 297 typedef GraphTraits<BlockT *> BlockGTraits; 298 typedef GraphTraits<Inverse<BlockT *> > InvBlockGTraits; 299 //typedef BlockGTraits::succ_iterator InstructionIterator; 300 typedef typename BlockT::iterator InstrIterator; 301 302 typedef CFGStructTraits<PassT> CFGTraits; 303 typedef BlockInformation<InstrT> BlockInfo; 304 typedef std::map<BlockT *, BlockInfo *> BlockInfoMap; 305 306 typedef int RegiT; 307 typedef typename PassT::LoopType LoopT; 308 typedef LandInformation<BlockT, InstrT, RegiT> LoopLandInfo; 309 typedef std::map<LoopT *, LoopLandInfo *> LoopLandInfoMap; 310 //landing info for loop break 311 typedef SmallVector<BlockT *, 32> BlockTSmallerVector; 312 313public: 314 CFGStructurizer(); 315 ~CFGStructurizer(); 316 317 /// Perform the CFG structurization 318 bool run(FuncT &Func, PassT &Pass); 319 320 /// Perform the CFG preparation 321 bool prepare(FuncT &Func, PassT &Pass); 322 323private: 324 void orderBlocks(); 325 void printOrderedBlocks(llvm::raw_ostream &OS); 326 int patternMatch(BlockT *CurBlock); 327 int patternMatchGroup(BlockT *CurBlock); 328 329 int serialPatternMatch(BlockT *CurBlock); 330 int ifPatternMatch(BlockT *CurBlock); 331 int switchPatternMatch(BlockT *CurBlock); 332 int loopendPatternMatch(BlockT *CurBlock); 333 int loopPatternMatch(BlockT *CurBlock); 334 335 int loopbreakPatternMatch(LoopT *LoopRep, BlockT *LoopHeader); 336 int loopcontPatternMatch(LoopT *LoopRep, BlockT *LoopHeader); 337 //int loopWithoutBreak(BlockT *); 338 339 void handleLoopbreak (BlockT *ExitingBlock, LoopT *ExitingLoop, 340 BlockT *ExitBlock, LoopT *exitLoop, BlockT *landBlock); 341 void handleLoopcontBlock(BlockT *ContingBlock, LoopT *contingLoop, 342 BlockT *ContBlock, LoopT *contLoop); 343 bool isSameloopDetachedContbreak(BlockT *Src1Block, BlockT *Src2Block); 344 int handleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock, 345 BlockT *FalseBlock); 346 int handleJumpintoIfImp(BlockT *HeadBlock, BlockT *TrueBlock, 347 BlockT *FalseBlock); 348 int improveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock, 349 BlockT *FalseBlock, BlockT **LandBlockPtr); 350 void showImproveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock, 351 BlockT *FalseBlock, BlockT *LandBlock, 352 bool Detail = false); 353 PathToKind singlePathTo(BlockT *SrcBlock, BlockT *DstBlock, 354 bool AllowSideEntry = true); 355 BlockT *singlePathEnd(BlockT *srcBlock, BlockT *DstBlock, 356 bool AllowSideEntry = true); 357 int cloneOnSideEntryTo(BlockT *PreBlock, BlockT *SrcBlock, BlockT *DstBlock); 358 void mergeSerialBlock(BlockT *DstBlock, BlockT *srcBlock); 359 360 void mergeIfthenelseBlock(InstrT *BranchInstr, BlockT *CurBlock, 361 BlockT *TrueBlock, BlockT *FalseBlock, 362 BlockT *LandBlock); 363 void mergeLooplandBlock(BlockT *DstBlock, LoopLandInfo *LoopLand); 364 void mergeLoopbreakBlock(BlockT *ExitingBlock, BlockT *ExitBlock, 365 BlockT *ExitLandBlock, RegiT SetReg); 366 void settleLoopcontBlock(BlockT *ContingBlock, BlockT *ContBlock, 367 RegiT SetReg); 368 BlockT *relocateLoopcontBlock(LoopT *ParentLoopRep, LoopT *LoopRep, 369 std::set<BlockT*> &ExitBlockSet, 370 BlockT *ExitLandBlk); 371 BlockT *addLoopEndbranchBlock(LoopT *LoopRep, 372 BlockTSmallerVector &ExitingBlocks, 373 BlockTSmallerVector &ExitBlocks); 374 BlockT *normalizeInfiniteLoopExit(LoopT *LoopRep); 375 void removeUnconditionalBranch(BlockT *SrcBlock); 376 void removeRedundantConditionalBranch(BlockT *SrcBlock); 377 void addDummyExitBlock(SmallVector<BlockT *, DEFAULT_VEC_SLOTS> &RetBlocks); 378 379 void removeSuccessor(BlockT *SrcBlock); 380 BlockT *cloneBlockForPredecessor(BlockT *CurBlock, BlockT *PredBlock); 381 BlockT *exitingBlock2ExitBlock (LoopT *LoopRep, BlockT *exitingBlock); 382 383 void migrateInstruction(BlockT *SrcBlock, BlockT *DstBlock, 384 InstrIterator InsertPos); 385 386 void recordSccnum(BlockT *SrcBlock, int SCCNum); 387 int getSCCNum(BlockT *srcBlk); 388 389 void retireBlock(BlockT *DstBlock, BlockT *SrcBlock); 390 bool isRetiredBlock(BlockT *SrcBlock); 391 bool isActiveLoophead(BlockT *CurBlock); 392 bool needMigrateBlock(BlockT *Block); 393 394 BlockT *recordLoopLandBlock(LoopT *LoopRep, BlockT *LandBlock, 395 BlockTSmallerVector &exitBlocks, 396 std::set<BlockT*> &ExitBlockSet); 397 void setLoopLandBlock(LoopT *LoopRep, BlockT *Block = NULL); 398 BlockT *getLoopLandBlock(LoopT *LoopRep); 399 LoopLandInfo *getLoopLandInfo(LoopT *LoopRep); 400 401 void addLoopBreakOnReg(LoopT *LoopRep, RegiT RegNum); 402 void addLoopContOnReg(LoopT *LoopRep, RegiT RegNum); 403 void addLoopBreakInitReg(LoopT *LoopRep, RegiT RegNum); 404 void addLoopContInitReg(LoopT *LoopRep, RegiT RegNum); 405 void addLoopEndbranchInitReg(LoopT *LoopRep, RegiT RegNum); 406 407 bool hasBackEdge(BlockT *curBlock); 408 unsigned getLoopDepth (LoopT *LoopRep); 409 int countActiveBlock( 410 typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator IterStart, 411 typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator IterEnd); 412 BlockT *findNearestCommonPostDom(std::set<BlockT *>&); 413 BlockT *findNearestCommonPostDom(BlockT *Block1, BlockT *Block2); 414 415private: 416 DomTreeT *domTree; 417 PostDomTreeT *postDomTree; 418 LoopInfoT *loopInfo; 419 PassT *passRep; 420 FuncT *funcRep; 421 422 BlockInfoMap blockInfoMap; 423 LoopLandInfoMap loopLandInfoMap; 424 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> orderedBlks; 425 426}; //template class CFGStructurizer 427 428template<class PassT> CFGStructurizer<PassT>::CFGStructurizer() 429 : domTree(NULL), postDomTree(NULL), loopInfo(NULL) { 430} 431 432template<class PassT> CFGStructurizer<PassT>::~CFGStructurizer() { 433 for (typename BlockInfoMap::iterator I = blockInfoMap.begin(), 434 E = blockInfoMap.end(); I != E; ++I) { 435 delete I->second; 436 } 437} 438 439template<class PassT> 440bool CFGStructurizer<PassT>::prepare(FuncT &func, PassT &pass) { 441 passRep = &pass; 442 funcRep = &func; 443 444 bool changed = false; 445 //func.RenumberBlocks(); 446 447 //to do, if not reducible flow graph, make it so ??? 448 449 if (DEBUGME) { 450 errs() << "AMDILCFGStructurizer::prepare\n"; 451 //func.viewCFG(); 452 //func.viewCFGOnly(); 453 //func.dump(); 454 } 455 456 //FIXME: gcc complains on this. 457 //domTree = &pass.getAnalysis<DomTreeT>(); 458 //domTree = CFGTraits::getDominatorTree(pass); 459 //if (DEBUGME) { 460 // domTree->print(errs()); 461 //} 462 463 //FIXME: gcc complains on this. 464 //domTree = &pass.getAnalysis<DomTreeT>(); 465 //postDomTree = CFGTraits::getPostDominatorTree(pass); 466 //if (DEBUGME) { 467 // postDomTree->print(errs()); 468 //} 469 470 //FIXME: gcc complains on this. 471 //loopInfo = &pass.getAnalysis<LoopInfoT>(); 472 loopInfo = CFGTraits::getLoopInfo(pass); 473 if (DEBUGME) { 474 errs() << "LoopInfo:\n"; 475 PrintLoopinfo(*loopInfo, errs()); 476 } 477 478 orderBlocks(); 479 if (DEBUGME) { 480 errs() << "Ordered blocks:\n"; 481 printOrderedBlocks(errs()); 482 } 483 484 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> retBlks; 485 486 for (typename LoopInfoT::iterator iter = loopInfo->begin(), 487 iterEnd = loopInfo->end(); 488 iter != iterEnd; ++iter) { 489 LoopT* loopRep = (*iter); 490 BlockTSmallerVector exitingBlks; 491 loopRep->getExitingBlocks(exitingBlks); 492 493 if (exitingBlks.size() == 0) { 494 BlockT* dummyExitBlk = normalizeInfiniteLoopExit(loopRep); 495 if (dummyExitBlk != NULL) 496 retBlks.push_back(dummyExitBlk); 497 } 498 } 499 500 // Remove unconditional branch instr. 501 // Add dummy exit block iff there are multiple returns. 502 503 for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator 504 iterBlk = orderedBlks.begin(), iterEndBlk = orderedBlks.end(); 505 iterBlk != iterEndBlk; 506 ++iterBlk) { 507 BlockT *curBlk = *iterBlk; 508 removeUnconditionalBranch(curBlk); 509 removeRedundantConditionalBranch(curBlk); 510 if (CFGTraits::isReturnBlock(curBlk)) { 511 retBlks.push_back(curBlk); 512 } 513 assert(curBlk->succ_size() <= 2); 514 //assert(curBlk->size() > 0); 515 //removeEmptyBlock(curBlk) ?? 516 } //for 517 518 if (retBlks.size() >= 2) { 519 addDummyExitBlock(retBlks); 520 changed = true; 521 } 522 523 return changed; 524} //CFGStructurizer::prepare 525 526template<class PassT> 527bool CFGStructurizer<PassT>::run(FuncT &func, PassT &pass) { 528 passRep = &pass; 529 funcRep = &func; 530 531 //func.RenumberBlocks(); 532 533 //Assume reducible CFG... 534 if (DEBUGME) { 535 errs() << "AMDILCFGStructurizer::run\n"; 536 //errs() << func.getFunction()->getNameStr() << "\n"; 537 func.viewCFG(); 538 //func.viewCFGOnly(); 539 //func.dump(); 540 } 541 542#if 1 543 //FIXME: gcc complains on this. 544 //domTree = &pass.getAnalysis<DomTreeT>(); 545 domTree = CFGTraits::getDominatorTree(pass); 546 if (DEBUGME) { 547 domTree->print(errs(), (const llvm::Module*)0); 548 } 549#endif 550 551 //FIXME: gcc complains on this. 552 //domTree = &pass.getAnalysis<DomTreeT>(); 553 postDomTree = CFGTraits::getPostDominatorTree(pass); 554 if (DEBUGME) { 555 postDomTree->print(errs()); 556 } 557 558 //FIXME: gcc complains on this. 559 //loopInfo = &pass.getAnalysis<LoopInfoT>(); 560 loopInfo = CFGTraits::getLoopInfo(pass); 561 if (DEBUGME) { 562 errs() << "LoopInfo:\n"; 563 PrintLoopinfo(*loopInfo, errs()); 564 } 565 566 orderBlocks(); 567//#define STRESSTEST 568#ifdef STRESSTEST 569 //Use the worse block ordering to test the algorithm. 570 ReverseVector(orderedBlks); 571#endif 572 573 if (DEBUGME) { 574 errs() << "Ordered blocks:\n"; 575 printOrderedBlocks(errs()); 576 } 577 int numIter = 0; 578 bool finish = false; 579 BlockT *curBlk; 580 bool makeProgress = false; 581 int numRemainedBlk = countActiveBlock(orderedBlks.begin(), 582 orderedBlks.end()); 583 584 do { 585 ++numIter; 586 if (DEBUGME) { 587 errs() << "numIter = " << numIter 588 << ", numRemaintedBlk = " << numRemainedBlk << "\n"; 589 } 590 591 typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator 592 iterBlk = orderedBlks.begin(); 593 typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator 594 iterBlkEnd = orderedBlks.end(); 595 596 typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator 597 sccBeginIter = iterBlk; 598 BlockT *sccBeginBlk = NULL; 599 int sccNumBlk = 0; // The number of active blocks, init to a 600 // maximum possible number. 601 int sccNumIter; // Number of iteration in this SCC. 602 603 while (iterBlk != iterBlkEnd) { 604 curBlk = *iterBlk; 605 606 if (sccBeginBlk == NULL) { 607 sccBeginIter = iterBlk; 608 sccBeginBlk = curBlk; 609 sccNumIter = 0; 610 sccNumBlk = numRemainedBlk; // Init to maximum possible number. 611 if (DEBUGME) { 612 errs() << "start processing SCC" << getSCCNum(sccBeginBlk); 613 errs() << "\n"; 614 } 615 } 616 617 if (!isRetiredBlock(curBlk)) { 618 patternMatch(curBlk); 619 } 620 621 ++iterBlk; 622 623 bool contNextScc = true; 624 if (iterBlk == iterBlkEnd 625 || getSCCNum(sccBeginBlk) != getSCCNum(*iterBlk)) { 626 // Just finish one scc. 627 ++sccNumIter; 628 int sccRemainedNumBlk = countActiveBlock(sccBeginIter, iterBlk); 629 if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= sccNumBlk) { 630 if (DEBUGME) { 631 errs() << "Can't reduce SCC " << getSCCNum(curBlk) 632 << ", sccNumIter = " << sccNumIter; 633 errs() << "doesn't make any progress\n"; 634 } 635 contNextScc = true; 636 } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < sccNumBlk) { 637 sccNumBlk = sccRemainedNumBlk; 638 iterBlk = sccBeginIter; 639 contNextScc = false; 640 if (DEBUGME) { 641 errs() << "repeat processing SCC" << getSCCNum(curBlk) 642 << "sccNumIter = " << sccNumIter << "\n"; 643 func.viewCFG(); 644 //func.viewCFGOnly(); 645 } 646 } else { 647 // Finish the current scc. 648 contNextScc = true; 649 } 650 } else { 651 // Continue on next component in the current scc. 652 contNextScc = false; 653 } 654 655 if (contNextScc) { 656 sccBeginBlk = NULL; 657 } 658 } //while, "one iteration" over the function. 659 660 BlockT *entryBlk = FuncGTraits::nodes_begin(&func); 661 if (entryBlk->succ_size() == 0) { 662 finish = true; 663 if (DEBUGME) { 664 errs() << "Reduce to one block\n"; 665 } 666 } else { 667 int newnumRemainedBlk 668 = countActiveBlock(orderedBlks.begin(), orderedBlks.end()); 669 // consider cloned blocks ?? 670 if (newnumRemainedBlk == 1 || newnumRemainedBlk < numRemainedBlk) { 671 makeProgress = true; 672 numRemainedBlk = newnumRemainedBlk; 673 } else { 674 makeProgress = false; 675 if (DEBUGME) { 676 errs() << "No progress\n"; 677 } 678 } 679 } 680 } while (!finish && makeProgress); 681 682 // Misc wrap up to maintain the consistency of the Function representation. 683 CFGTraits::wrapup(FuncGTraits::nodes_begin(&func)); 684 685 // Detach retired Block, release memory. 686 for (typename BlockInfoMap::iterator iterMap = blockInfoMap.begin(), 687 iterEndMap = blockInfoMap.end(); iterMap != iterEndMap; ++iterMap) { 688 if ((*iterMap).second && (*iterMap).second->isRetired) { 689 assert(((*iterMap).first)->getNumber() != -1); 690 if (DEBUGME) { 691 errs() << "Erase BB" << ((*iterMap).first)->getNumber() << "\n"; 692 } 693 (*iterMap).first->eraseFromParent(); //Remove from the parent Function. 694 } 695 delete (*iterMap).second; 696 } 697 blockInfoMap.clear(); 698 699 // clear loopLandInfoMap 700 for (typename LoopLandInfoMap::iterator iterMap = loopLandInfoMap.begin(), 701 iterEndMap = loopLandInfoMap.end(); iterMap != iterEndMap; ++iterMap) { 702 delete (*iterMap).second; 703 } 704 loopLandInfoMap.clear(); 705 706 if (DEBUGME) { 707 func.viewCFG(); 708 //func.dump(); 709 } 710 711 if (!finish) { 712 MachineFunction *MF = &func; 713 AMDILMachineFunctionInfo *mMFI = 714 MF->getInfo<AMDILMachineFunctionInfo>(); 715 mMFI->addErrorMsg(amd::CompilerErrorMessage[IRREDUCIBLE_CF]); 716 } 717 718 return true; 719} //CFGStructurizer::run 720 721/// Print the ordered Blocks. 722/// 723template<class PassT> 724void CFGStructurizer<PassT>::printOrderedBlocks(llvm::raw_ostream &os) { 725 size_t i = 0; 726 for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::const_iterator 727 iterBlk = orderedBlks.begin(), iterBlkEnd = orderedBlks.end(); 728 iterBlk != iterBlkEnd; 729 ++iterBlk, ++i) { 730 os << "BB" << (*iterBlk)->getNumber(); 731 os << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")"; 732 if (i != 0 && i % 10 == 0) { 733 os << "\n"; 734 } else { 735 os << " "; 736 } 737 } 738} //printOrderedBlocks 739 740/// Compute the reversed DFS post order of Blocks 741/// 742template<class PassT> void CFGStructurizer<PassT>::orderBlocks() { 743 int sccNum = 0; 744 BlockT *bb; 745 for (scc_iterator<FuncT *> sccIter = scc_begin(funcRep), 746 sccEnd = scc_end(funcRep); sccIter != sccEnd; ++sccIter, ++sccNum) { 747 std::vector<BlockT *> &sccNext = *sccIter; 748 for (typename std::vector<BlockT *>::const_iterator 749 blockIter = sccNext.begin(), blockEnd = sccNext.end(); 750 blockIter != blockEnd; ++blockIter) { 751 bb = *blockIter; 752 orderedBlks.push_back(bb); 753 recordSccnum(bb, sccNum); 754 } 755 } 756 757 //walk through all the block in func to check for unreachable 758 for (BlockIterator blockIter1 = FuncGTraits::nodes_begin(funcRep), 759 blockEnd1 = FuncGTraits::nodes_end(funcRep); 760 blockIter1 != blockEnd1; ++blockIter1) { 761 BlockT *bb = &(*blockIter1); 762 sccNum = getSCCNum(bb); 763 if (sccNum == INVALIDSCCNUM) { 764 errs() << "unreachable block BB" << bb->getNumber() << "\n"; 765 } 766 } //end of for 767} //orderBlocks 768 769template<class PassT> int CFGStructurizer<PassT>::patternMatch(BlockT *curBlk) { 770 int numMatch = 0; 771 int curMatch; 772 773 if (DEBUGME) { 774 errs() << "Begin patternMatch BB" << curBlk->getNumber() << "\n"; 775 } 776 777 while ((curMatch = patternMatchGroup(curBlk)) > 0) { 778 numMatch += curMatch; 779 } 780 781 if (DEBUGME) { 782 errs() << "End patternMatch BB" << curBlk->getNumber() 783 << ", numMatch = " << numMatch << "\n"; 784 } 785 786 return numMatch; 787} //patternMatch 788 789template<class PassT> 790int CFGStructurizer<PassT>::patternMatchGroup(BlockT *curBlk) { 791 int numMatch = 0; 792 numMatch += serialPatternMatch(curBlk); 793 numMatch += ifPatternMatch(curBlk); 794 //numMatch += switchPatternMatch(curBlk); 795 numMatch += loopendPatternMatch(curBlk); 796 numMatch += loopPatternMatch(curBlk); 797 return numMatch; 798}//patternMatchGroup 799 800template<class PassT> 801int CFGStructurizer<PassT>::serialPatternMatch(BlockT *curBlk) { 802 if (curBlk->succ_size() != 1) { 803 return 0; 804 } 805 806 BlockT *childBlk = *curBlk->succ_begin(); 807 if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk)) { 808 return 0; 809 } 810 811 mergeSerialBlock(curBlk, childBlk); 812 ++numSerialPatternMatch; 813 return 1; 814} //serialPatternMatch 815 816template<class PassT> 817int CFGStructurizer<PassT>::ifPatternMatch(BlockT *curBlk) { 818 //two edges 819 if (curBlk->succ_size() != 2) { 820 return 0; 821 } 822 823 if (hasBackEdge(curBlk)) { 824 return 0; 825 } 826 827 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(curBlk); 828 if (branchInstr == NULL) { 829 return 0; 830 } 831 832 assert(CFGTraits::isCondBranch(branchInstr)); 833 834 BlockT *trueBlk = CFGTraits::getTrueBranch(branchInstr); 835 BlockT *falseBlk = CFGTraits::getFalseBranch(curBlk, branchInstr); 836 BlockT *landBlk; 837 int cloned = 0; 838 839 // TODO: Simplify 840 if (trueBlk->succ_size() == 1 && falseBlk->succ_size() == 1 841 && *trueBlk->succ_begin() == *falseBlk->succ_begin()) { 842 landBlk = *trueBlk->succ_begin(); 843 } else if (trueBlk->succ_size() == 0 && falseBlk->succ_size() == 0) { 844 landBlk = NULL; 845 } else if (trueBlk->succ_size() == 1 && *trueBlk->succ_begin() == falseBlk) { 846 landBlk = falseBlk; 847 falseBlk = NULL; 848 } else if (falseBlk->succ_size() == 1 849 && *falseBlk->succ_begin() == trueBlk) { 850 landBlk = trueBlk; 851 trueBlk = NULL; 852 } else if (falseBlk->succ_size() == 1 853 && isSameloopDetachedContbreak(trueBlk, falseBlk)) { 854 landBlk = *falseBlk->succ_begin(); 855 } else if (trueBlk->succ_size() == 1 856 && isSameloopDetachedContbreak(falseBlk, trueBlk)) { 857 landBlk = *trueBlk->succ_begin(); 858 } else { 859 return handleJumpintoIf(curBlk, trueBlk, falseBlk); 860 } 861 862 // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the 863 // new BB created for landBlk==NULL may introduce new challenge to the 864 // reduction process. 865 if (landBlk != NULL && 866 ((trueBlk && trueBlk->pred_size() > 1) 867 || (falseBlk && falseBlk->pred_size() > 1))) { 868 cloned += improveSimpleJumpintoIf(curBlk, trueBlk, falseBlk, &landBlk); 869 } 870 871 if (trueBlk && trueBlk->pred_size() > 1) { 872 trueBlk = cloneBlockForPredecessor(trueBlk, curBlk); 873 ++cloned; 874 } 875 876 if (falseBlk && falseBlk->pred_size() > 1) { 877 falseBlk = cloneBlockForPredecessor(falseBlk, curBlk); 878 ++cloned; 879 } 880 881 mergeIfthenelseBlock(branchInstr, curBlk, trueBlk, falseBlk, landBlk); 882 883 ++numIfPatternMatch; 884 885 numClonedBlock += cloned; 886 887 return 1 + cloned; 888} //ifPatternMatch 889 890template<class PassT> 891int CFGStructurizer<PassT>::switchPatternMatch(BlockT *curBlk) { 892 return 0; 893} //switchPatternMatch 894 895template<class PassT> 896int CFGStructurizer<PassT>::loopendPatternMatch(BlockT *curBlk) { 897 LoopT *loopRep = loopInfo->getLoopFor(curBlk); 898 typename std::vector<LoopT *> nestedLoops; 899 while (loopRep) { 900 nestedLoops.push_back(loopRep); 901 loopRep = loopRep->getParentLoop(); 902 } 903 904 if (nestedLoops.size() == 0) { 905 return 0; 906 } 907 908 // Process nested loop outside->inside, so "continue" to a outside loop won't 909 // be mistaken as "break" of the current loop. 910 int num = 0; 911 for (typename std::vector<LoopT *>::reverse_iterator 912 iter = nestedLoops.rbegin(), iterEnd = nestedLoops.rend(); 913 iter != iterEnd; ++iter) { 914 loopRep = *iter; 915 916 if (getLoopLandBlock(loopRep) != NULL) { 917 continue; 918 } 919 920 BlockT *loopHeader = loopRep->getHeader(); 921 922 int numBreak = loopbreakPatternMatch(loopRep, loopHeader); 923 924 if (numBreak == -1) { 925 break; 926 } 927 928 int numCont = loopcontPatternMatch(loopRep, loopHeader); 929 num += numBreak + numCont; 930 } 931 932 return num; 933} //loopendPatternMatch 934 935template<class PassT> 936int CFGStructurizer<PassT>::loopPatternMatch(BlockT *curBlk) { 937 if (curBlk->succ_size() != 0) { 938 return 0; 939 } 940 941 int numLoop = 0; 942 LoopT *loopRep = loopInfo->getLoopFor(curBlk); 943 while (loopRep && loopRep->getHeader() == curBlk) { 944 LoopLandInfo *loopLand = getLoopLandInfo(loopRep); 945 if (loopLand) { 946 BlockT *landBlk = loopLand->landBlk; 947 assert(landBlk); 948 if (!isRetiredBlock(landBlk)) { 949 mergeLooplandBlock(curBlk, loopLand); 950 ++numLoop; 951 } 952 } 953 loopRep = loopRep->getParentLoop(); 954 } 955 956 numLoopPatternMatch += numLoop; 957 958 return numLoop; 959} //loopPatternMatch 960 961template<class PassT> 962int CFGStructurizer<PassT>::loopbreakPatternMatch(LoopT *loopRep, 963 BlockT *loopHeader) { 964 BlockTSmallerVector exitingBlks; 965 loopRep->getExitingBlocks(exitingBlks); 966 967 if (DEBUGME) { 968 errs() << "Loop has " << exitingBlks.size() << " exiting blocks\n"; 969 } 970 971 if (exitingBlks.size() == 0) { 972 setLoopLandBlock(loopRep); 973 return 0; 974 } 975 976 // Compute the corresponding exitBlks and exit block set. 977 BlockTSmallerVector exitBlks; 978 std::set<BlockT *> exitBlkSet; 979 for (typename BlockTSmallerVector::const_iterator iter = exitingBlks.begin(), 980 iterEnd = exitingBlks.end(); iter != iterEnd; ++iter) { 981 BlockT *exitingBlk = *iter; 982 BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk); 983 exitBlks.push_back(exitBlk); 984 exitBlkSet.insert(exitBlk); //non-duplicate insert 985 } 986 987 assert(exitBlkSet.size() > 0); 988 assert(exitBlks.size() == exitingBlks.size()); 989 990 if (DEBUGME) { 991 errs() << "Loop has " << exitBlkSet.size() << " exit blocks\n"; 992 } 993 994 // Find exitLandBlk. 995 BlockT *exitLandBlk = NULL; 996 int numCloned = 0; 997 int numSerial = 0; 998 999 if (exitBlkSet.size() == 1) 1000 { 1001 exitLandBlk = *exitBlkSet.begin(); 1002 } else { 1003 exitLandBlk = findNearestCommonPostDom(exitBlkSet); 1004 1005 if (exitLandBlk == NULL) { 1006 return -1; 1007 } 1008 1009 bool allInPath = true; 1010 bool allNotInPath = true; 1011 for (typename std::set<BlockT*>::const_iterator 1012 iter = exitBlkSet.begin(), 1013 iterEnd = exitBlkSet.end(); 1014 iter != iterEnd; ++iter) { 1015 BlockT *exitBlk = *iter; 1016 1017 PathToKind pathKind = singlePathTo(exitBlk, exitLandBlk, true); 1018 if (DEBUGME) { 1019 errs() << "BB" << exitBlk->getNumber() 1020 << " to BB" << exitLandBlk->getNumber() << " PathToKind=" 1021 << pathKind << "\n"; 1022 } 1023 1024 allInPath = allInPath && (pathKind == SinglePath_InPath); 1025 allNotInPath = allNotInPath && (pathKind == SinglePath_NotInPath); 1026 1027 if (!allInPath && !allNotInPath) { 1028 if (DEBUGME) { 1029 errs() << "singlePath check fail\n"; 1030 } 1031 return -1; 1032 } 1033 } // check all exit blocks 1034 1035 if (allNotInPath) { 1036#if 1 1037 1038 // TODO: Simplify, maybe separate function? 1039 //funcRep->viewCFG(); 1040 LoopT *parentLoopRep = loopRep->getParentLoop(); 1041 BlockT *parentLoopHeader = NULL; 1042 if (parentLoopRep) 1043 parentLoopHeader = parentLoopRep->getHeader(); 1044 1045 if (exitLandBlk == parentLoopHeader && 1046 (exitLandBlk = relocateLoopcontBlock(parentLoopRep, 1047 loopRep, 1048 exitBlkSet, 1049 exitLandBlk)) != NULL) { 1050 if (DEBUGME) { 1051 errs() << "relocateLoopcontBlock success\n"; 1052 } 1053 } else if ((exitLandBlk = addLoopEndbranchBlock(loopRep, 1054 exitingBlks, 1055 exitBlks)) != NULL) { 1056 if (DEBUGME) { 1057 errs() << "insertEndbranchBlock success\n"; 1058 } 1059 } else { 1060 if (DEBUGME) { 1061 errs() << "loop exit fail\n"; 1062 } 1063 return -1; 1064 } 1065#else 1066 return -1; 1067#endif 1068 } 1069 1070 // Handle side entry to exit path. 1071 exitBlks.clear(); 1072 exitBlkSet.clear(); 1073 for (typename BlockTSmallerVector::iterator iterExiting = 1074 exitingBlks.begin(), 1075 iterExitingEnd = exitingBlks.end(); 1076 iterExiting != iterExitingEnd; ++iterExiting) { 1077 BlockT *exitingBlk = *iterExiting; 1078 BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk); 1079 BlockT *newExitBlk = exitBlk; 1080 1081 if (exitBlk != exitLandBlk && exitBlk->pred_size() > 1) { 1082 newExitBlk = cloneBlockForPredecessor(exitBlk, exitingBlk); 1083 ++numCloned; 1084 } 1085 1086 numCloned += cloneOnSideEntryTo(exitingBlk, newExitBlk, exitLandBlk); 1087 1088 exitBlks.push_back(newExitBlk); 1089 exitBlkSet.insert(newExitBlk); 1090 } 1091 1092 for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(), 1093 iterExitEnd = exitBlks.end(); 1094 iterExit != iterExitEnd; ++iterExit) { 1095 BlockT *exitBlk = *iterExit; 1096 numSerial += serialPatternMatch(exitBlk); 1097 } 1098 1099 for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(), 1100 iterExitEnd = exitBlks.end(); 1101 iterExit != iterExitEnd; ++iterExit) { 1102 BlockT *exitBlk = *iterExit; 1103 if (exitBlk->pred_size() > 1) { 1104 if (exitBlk != exitLandBlk) { 1105 return -1; 1106 } 1107 } else { 1108 if (exitBlk != exitLandBlk && 1109 (exitBlk->succ_size() != 1 || 1110 *exitBlk->succ_begin() != exitLandBlk)) { 1111 return -1; 1112 } 1113 } 1114 } 1115 } // else 1116 1117 // LoopT *exitLandLoop = loopInfo->getLoopFor(exitLandBlk); 1118 exitLandBlk = recordLoopLandBlock(loopRep, exitLandBlk, exitBlks, exitBlkSet); 1119 1120 // Fold break into the breaking block. Leverage across level breaks. 1121 assert(exitingBlks.size() == exitBlks.size()); 1122 for (typename BlockTSmallerVector::const_iterator iterExit = exitBlks.begin(), 1123 iterExiting = exitingBlks.begin(), iterExitEnd = exitBlks.end(); 1124 iterExit != iterExitEnd; ++iterExit, ++iterExiting) { 1125 BlockT *exitBlk = *iterExit; 1126 BlockT *exitingBlk = *iterExiting; 1127 assert(exitBlk->pred_size() == 1 || exitBlk == exitLandBlk); 1128 LoopT *exitingLoop = loopInfo->getLoopFor(exitingBlk); 1129 handleLoopbreak(exitingBlk, exitingLoop, exitBlk, loopRep, exitLandBlk); 1130 } 1131 1132 int numBreak = static_cast<int>(exitingBlks.size()); 1133 numLoopbreakPatternMatch += numBreak; 1134 numClonedBlock += numCloned; 1135 return numBreak + numSerial + numCloned; 1136} //loopbreakPatternMatch 1137 1138template<class PassT> 1139int CFGStructurizer<PassT>::loopcontPatternMatch(LoopT *loopRep, 1140 BlockT *loopHeader) { 1141 int numCont = 0; 1142 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> contBlk; 1143 for (typename InvBlockGTraits::ChildIteratorType iter = 1144 InvBlockGTraits::child_begin(loopHeader), 1145 iterEnd = InvBlockGTraits::child_end(loopHeader); 1146 iter != iterEnd; ++iter) { 1147 BlockT *curBlk = *iter; 1148 if (loopRep->contains(curBlk)) { 1149 handleLoopcontBlock(curBlk, loopInfo->getLoopFor(curBlk), 1150 loopHeader, loopRep); 1151 contBlk.push_back(curBlk); 1152 ++numCont; 1153 } 1154 } 1155 1156 for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::iterator 1157 iter = contBlk.begin(), iterEnd = contBlk.end(); 1158 iter != iterEnd; ++iter) { 1159 (*iter)->removeSuccessor(loopHeader); 1160 } 1161 1162 numLoopcontPatternMatch += numCont; 1163 1164 return numCont; 1165} //loopcontPatternMatch 1166 1167 1168template<class PassT> 1169bool CFGStructurizer<PassT>::isSameloopDetachedContbreak(BlockT *src1Blk, 1170 BlockT *src2Blk) { 1171 // return true iff src1Blk->succ_size() == 0 && src1Blk and src2Blk are in the 1172 // same loop with LoopLandInfo without explicitly keeping track of 1173 // loopContBlks and loopBreakBlks, this is a method to get the information. 1174 // 1175 if (src1Blk->succ_size() == 0) { 1176 LoopT *loopRep = loopInfo->getLoopFor(src1Blk); 1177 if (loopRep != NULL && loopRep == loopInfo->getLoopFor(src2Blk)) { 1178 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 1179 if (theEntry != NULL) { 1180 if (DEBUGME) { 1181 errs() << "isLoopContBreakBlock yes src1 = BB" 1182 << src1Blk->getNumber() 1183 << " src2 = BB" << src2Blk->getNumber() << "\n"; 1184 } 1185 return true; 1186 } 1187 } 1188 } 1189 return false; 1190} //isSameloopDetachedContbreak 1191 1192template<class PassT> 1193int CFGStructurizer<PassT>::handleJumpintoIf(BlockT *headBlk, 1194 BlockT *trueBlk, 1195 BlockT *falseBlk) { 1196 int num = handleJumpintoIfImp(headBlk, trueBlk, falseBlk); 1197 if (num == 0) { 1198 if (DEBUGME) { 1199 errs() << "handleJumpintoIf swap trueBlk and FalseBlk" << "\n"; 1200 } 1201 num = handleJumpintoIfImp(headBlk, falseBlk, trueBlk); 1202 } 1203 return num; 1204} 1205 1206template<class PassT> 1207int CFGStructurizer<PassT>::handleJumpintoIfImp(BlockT *headBlk, 1208 BlockT *trueBlk, 1209 BlockT *falseBlk) { 1210 int num = 0; 1211 BlockT *downBlk; 1212 1213 //trueBlk could be the common post dominator 1214 downBlk = trueBlk; 1215 1216 if (DEBUGME) { 1217 errs() << "handleJumpintoIfImp head = BB" << headBlk->getNumber() 1218 << " true = BB" << trueBlk->getNumber() 1219 << ", numSucc=" << trueBlk->succ_size() 1220 << " false = BB" << falseBlk->getNumber() << "\n"; 1221 } 1222 1223 while (downBlk) { 1224 if (DEBUGME) { 1225 errs() << "check down = BB" << downBlk->getNumber(); 1226 } 1227 1228 if (//postDomTree->dominates(downBlk, falseBlk) && 1229 singlePathTo(falseBlk, downBlk) == SinglePath_InPath) { 1230 if (DEBUGME) { 1231 errs() << " working\n"; 1232 } 1233 1234 num += cloneOnSideEntryTo(headBlk, trueBlk, downBlk); 1235 num += cloneOnSideEntryTo(headBlk, falseBlk, downBlk); 1236 1237 numClonedBlock += num; 1238 num += serialPatternMatch(*headBlk->succ_begin()); 1239 num += serialPatternMatch(*(++headBlk->succ_begin())); 1240 num += ifPatternMatch(headBlk); 1241 assert(num > 0); // 1242 1243 break; 1244 } 1245 if (DEBUGME) { 1246 errs() << " not working\n"; 1247 } 1248 downBlk = (downBlk->succ_size() == 1) ? (*downBlk->succ_begin()) : NULL; 1249 } // walk down the postDomTree 1250 1251 return num; 1252} //handleJumpintoIf 1253 1254template<class PassT> 1255void CFGStructurizer<PassT>::showImproveSimpleJumpintoIf(BlockT *headBlk, 1256 BlockT *trueBlk, 1257 BlockT *falseBlk, 1258 BlockT *landBlk, 1259 bool detail) { 1260 errs() << "head = BB" << headBlk->getNumber() 1261 << " size = " << headBlk->size(); 1262 if (detail) { 1263 errs() << "\n"; 1264 headBlk->print(errs()); 1265 errs() << "\n"; 1266 } 1267 1268 if (trueBlk) { 1269 errs() << ", true = BB" << trueBlk->getNumber() << " size = " 1270 << trueBlk->size() << " numPred = " << trueBlk->pred_size(); 1271 if (detail) { 1272 errs() << "\n"; 1273 trueBlk->print(errs()); 1274 errs() << "\n"; 1275 } 1276 } 1277 if (falseBlk) { 1278 errs() << ", false = BB" << falseBlk->getNumber() << " size = " 1279 << falseBlk->size() << " numPred = " << falseBlk->pred_size(); 1280 if (detail) { 1281 errs() << "\n"; 1282 falseBlk->print(errs()); 1283 errs() << "\n"; 1284 } 1285 } 1286 if (landBlk) { 1287 errs() << ", land = BB" << landBlk->getNumber() << " size = " 1288 << landBlk->size() << " numPred = " << landBlk->pred_size(); 1289 if (detail) { 1290 errs() << "\n"; 1291 landBlk->print(errs()); 1292 errs() << "\n"; 1293 } 1294 } 1295 1296 errs() << "\n"; 1297} //showImproveSimpleJumpintoIf 1298 1299template<class PassT> 1300int CFGStructurizer<PassT>::improveSimpleJumpintoIf(BlockT *headBlk, 1301 BlockT *trueBlk, 1302 BlockT *falseBlk, 1303 BlockT **plandBlk) { 1304 bool migrateTrue = false; 1305 bool migrateFalse = false; 1306 1307 BlockT *landBlk = *plandBlk; 1308 1309 assert((trueBlk == NULL || trueBlk->succ_size() <= 1) 1310 && (falseBlk == NULL || falseBlk->succ_size() <= 1)); 1311 1312 if (trueBlk == falseBlk) { 1313 return 0; 1314 } 1315 1316#if 0 1317 if (DEBUGME) { 1318 errs() << "improveSimpleJumpintoIf: "; 1319 showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0); 1320 } 1321#endif 1322 1323 // unsigned landPredSize = landBlk ? landBlk->pred_size() : 0; 1324 // May consider the # landBlk->pred_size() as it represents the number of 1325 // assignment initReg = .. needed to insert. 1326 migrateTrue = needMigrateBlock(trueBlk); 1327 migrateFalse = needMigrateBlock(falseBlk); 1328 1329 if (!migrateTrue && !migrateFalse) { 1330 return 0; 1331 } 1332 1333 // If we need to migrate either trueBlk and falseBlk, migrate the rest that 1334 // have more than one predecessors. without doing this, its predecessor 1335 // rather than headBlk will have undefined value in initReg. 1336 if (!migrateTrue && trueBlk && trueBlk->pred_size() > 1) { 1337 migrateTrue = true; 1338 } 1339 if (!migrateFalse && falseBlk && falseBlk->pred_size() > 1) { 1340 migrateFalse = true; 1341 } 1342 1343 if (DEBUGME) { 1344 errs() << "before improveSimpleJumpintoIf: "; 1345 showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0); 1346 //showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 1); 1347 } 1348 1349 // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk 1350 // 1351 // new: headBlk => if () {initReg = 1; org trueBlk branch} else 1352 // {initReg = 0; org falseBlk branch } 1353 // => landBlk => if (initReg) {org trueBlk} else {org falseBlk} 1354 // => org landBlk 1355 // if landBlk->pred_size() > 2, put the about if-else inside 1356 // if (initReg !=2) {...} 1357 // 1358 // add initReg = initVal to headBlk 1359 unsigned initReg = 1360 funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass); 1361 if (!migrateTrue || !migrateFalse) { 1362 int initVal = migrateTrue ? 0 : 1; 1363 CFGTraits::insertAssignInstrBefore(headBlk, passRep, initReg, initVal); 1364 } 1365 1366 int numNewBlk = 0; 1367 1368 if (landBlk == NULL) { 1369 landBlk = funcRep->CreateMachineBasicBlock(); 1370 funcRep->push_back(landBlk); //insert to function 1371 1372 if (trueBlk) { 1373 trueBlk->addSuccessor(landBlk); 1374 } else { 1375 headBlk->addSuccessor(landBlk); 1376 } 1377 1378 if (falseBlk) { 1379 falseBlk->addSuccessor(landBlk); 1380 } else { 1381 headBlk->addSuccessor(landBlk); 1382 } 1383 1384 numNewBlk ++; 1385 } 1386 1387 bool landBlkHasOtherPred = (landBlk->pred_size() > 2); 1388 1389 //insert AMDIL::ENDIF to avoid special case "input landBlk == NULL" 1390 typename BlockT::iterator insertPos = 1391 CFGTraits::getInstrPos 1392 (landBlk, CFGTraits::insertInstrBefore(landBlk, AMDIL::ENDIF, passRep)); 1393 1394 if (landBlkHasOtherPred) { 1395 unsigned immReg = 1396 funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass); 1397 CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 2); 1398 unsigned cmpResReg = 1399 funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass); 1400 1401 CFGTraits::insertCompareInstrBefore(landBlk, insertPos, passRep, cmpResReg, 1402 initReg, immReg); 1403 CFGTraits::insertCondBranchBefore(landBlk, insertPos, 1404 AMDIL::IF_LOGICALZ_i32, passRep, 1405 cmpResReg, DebugLoc()); 1406 } 1407 1408 CFGTraits::insertCondBranchBefore(landBlk, insertPos, AMDIL::IF_LOGICALNZ_i32, 1409 passRep, initReg, DebugLoc()); 1410 1411 if (migrateTrue) { 1412 migrateInstruction(trueBlk, landBlk, insertPos); 1413 // need to uncondionally insert the assignment to ensure a path from its 1414 // predecessor rather than headBlk has valid value in initReg if 1415 // (initVal != 1). 1416 CFGTraits::insertAssignInstrBefore(trueBlk, passRep, initReg, 1); 1417 } 1418 CFGTraits::insertInstrBefore(insertPos, AMDIL::ELSE, passRep); 1419 1420 if (migrateFalse) { 1421 migrateInstruction(falseBlk, landBlk, insertPos); 1422 // need to uncondionally insert the assignment to ensure a path from its 1423 // predecessor rather than headBlk has valid value in initReg if 1424 // (initVal != 0) 1425 CFGTraits::insertAssignInstrBefore(falseBlk, passRep, initReg, 0); 1426 } 1427 //CFGTraits::insertInstrBefore(insertPos, AMDIL::ENDIF, passRep); 1428 1429 if (landBlkHasOtherPred) { 1430 // add endif 1431 CFGTraits::insertInstrBefore(insertPos, AMDIL::ENDIF, passRep); 1432 1433 // put initReg = 2 to other predecessors of landBlk 1434 for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(), 1435 predIterEnd = landBlk->pred_end(); predIter != predIterEnd; 1436 ++predIter) { 1437 BlockT *curBlk = *predIter; 1438 if (curBlk != trueBlk && curBlk != falseBlk) { 1439 CFGTraits::insertAssignInstrBefore(curBlk, passRep, initReg, 2); 1440 } 1441 } //for 1442 } 1443 if (DEBUGME) { 1444 errs() << "result from improveSimpleJumpintoIf: "; 1445 showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0); 1446 //showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 1); 1447 } 1448 1449 // update landBlk 1450 *plandBlk = landBlk; 1451 1452 return numNewBlk; 1453} //improveSimpleJumpintoIf 1454 1455template<class PassT> 1456void CFGStructurizer<PassT>::handleLoopbreak(BlockT *exitingBlk, 1457 LoopT *exitingLoop, 1458 BlockT *exitBlk, 1459 LoopT *exitLoop, 1460 BlockT *landBlk) { 1461 if (DEBUGME) { 1462 errs() << "Trying to break loop-depth = " << getLoopDepth(exitLoop) 1463 << " from loop-depth = " << getLoopDepth(exitingLoop) << "\n"; 1464 } 1465 1466 RegiT initReg = INVALIDREGNUM; 1467 if (exitingLoop != exitLoop) { 1468 initReg = static_cast<int> 1469 (funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass)); 1470 assert(initReg != INVALIDREGNUM); 1471 addLoopBreakInitReg(exitLoop, initReg); 1472 while (exitingLoop != exitLoop && exitingLoop) { 1473 addLoopBreakOnReg(exitingLoop, initReg); 1474 exitingLoop = exitingLoop->getParentLoop(); 1475 } 1476 assert(exitingLoop == exitLoop); 1477 } 1478 1479 mergeLoopbreakBlock(exitingBlk, exitBlk, landBlk, initReg); 1480 1481} //handleLoopbreak 1482 1483template<class PassT> 1484void CFGStructurizer<PassT>::handleLoopcontBlock(BlockT *contingBlk, 1485 LoopT *contingLoop, 1486 BlockT *contBlk, 1487 LoopT *contLoop) { 1488 if (DEBUGME) { 1489 errs() << "loopcontPattern cont = BB" << contingBlk->getNumber() 1490 << " header = BB" << contBlk->getNumber() << "\n"; 1491 1492 errs() << "Trying to continue loop-depth = " 1493 << getLoopDepth(contLoop) 1494 << " from loop-depth = " << getLoopDepth(contingLoop) << "\n"; 1495 } 1496 1497 RegiT initReg = INVALIDREGNUM; 1498 if (contingLoop != contLoop) { 1499 initReg = static_cast<int> 1500 (funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass)); 1501 assert(initReg != INVALIDREGNUM); 1502 addLoopContInitReg(contLoop, initReg); 1503 while (contingLoop && contingLoop->getParentLoop() != contLoop) { 1504 addLoopBreakOnReg(contingLoop, initReg); //not addLoopContOnReg 1505 contingLoop = contingLoop->getParentLoop(); 1506 } 1507 assert(contingLoop && contingLoop->getParentLoop() == contLoop); 1508 addLoopContOnReg(contingLoop, initReg); 1509 } 1510 1511 settleLoopcontBlock(contingBlk, contBlk, initReg); 1512 //contingBlk->removeSuccessor(loopHeader); 1513} //handleLoopcontBlock 1514 1515template<class PassT> 1516void CFGStructurizer<PassT>::mergeSerialBlock(BlockT *dstBlk, BlockT *srcBlk) { 1517 if (DEBUGME) { 1518 errs() << "serialPattern BB" << dstBlk->getNumber() 1519 << " <= BB" << srcBlk->getNumber() << "\n"; 1520 } 1521 //removeUnconditionalBranch(dstBlk); 1522 dstBlk->splice(dstBlk->end(), srcBlk, FirstNonDebugInstr(srcBlk), srcBlk->end()); 1523 1524 dstBlk->removeSuccessor(srcBlk); 1525 CFGTraits::cloneSuccessorList(dstBlk, srcBlk); 1526 1527 removeSuccessor(srcBlk); 1528 retireBlock(dstBlk, srcBlk); 1529} //mergeSerialBlock 1530 1531template<class PassT> 1532void CFGStructurizer<PassT>::mergeIfthenelseBlock(InstrT *branchInstr, 1533 BlockT *curBlk, 1534 BlockT *trueBlk, 1535 BlockT *falseBlk, 1536 BlockT *landBlk) { 1537 if (DEBUGME) { 1538 errs() << "ifPattern BB" << curBlk->getNumber(); 1539 errs() << "{ "; 1540 if (trueBlk) { 1541 errs() << "BB" << trueBlk->getNumber(); 1542 } 1543 errs() << " } else "; 1544 errs() << "{ "; 1545 if (falseBlk) { 1546 errs() << "BB" << falseBlk->getNumber(); 1547 } 1548 errs() << " }\n "; 1549 errs() << "landBlock: "; 1550 if (landBlk == NULL) { 1551 errs() << "NULL"; 1552 } else { 1553 errs() << "BB" << landBlk->getNumber(); 1554 } 1555 errs() << "\n"; 1556 } 1557 1558 int oldOpcode = branchInstr->getOpcode(); 1559 DebugLoc branchDL = branchInstr->getDebugLoc(); 1560 1561// transform to 1562// if cond 1563// trueBlk 1564// else 1565// falseBlk 1566// endif 1567// landBlk 1568 1569 typename BlockT::iterator branchInstrPos = 1570 CFGTraits::getInstrPos(curBlk, branchInstr); 1571 CFGTraits::insertCondBranchBefore(branchInstrPos, 1572 CFGTraits::getBranchNzeroOpcode(oldOpcode), 1573 passRep, 1574 branchDL); 1575 1576 if (trueBlk) { 1577 curBlk->splice(branchInstrPos, trueBlk, FirstNonDebugInstr(trueBlk), trueBlk->end()); 1578 curBlk->removeSuccessor(trueBlk); 1579 if (landBlk && trueBlk->succ_size()!=0) { 1580 trueBlk->removeSuccessor(landBlk); 1581 } 1582 retireBlock(curBlk, trueBlk); 1583 } 1584 CFGTraits::insertInstrBefore(branchInstrPos, AMDIL::ELSE, passRep); 1585 1586 if (falseBlk) { 1587 curBlk->splice(branchInstrPos, falseBlk, FirstNonDebugInstr(falseBlk), 1588 falseBlk->end()); 1589 curBlk->removeSuccessor(falseBlk); 1590 if (landBlk && falseBlk->succ_size() != 0) { 1591 falseBlk->removeSuccessor(landBlk); 1592 } 1593 retireBlock(curBlk, falseBlk); 1594 } 1595 CFGTraits::insertInstrBefore(branchInstrPos, AMDIL::ENDIF, passRep); 1596 1597 //curBlk->remove(branchInstrPos); 1598 branchInstr->eraseFromParent(); 1599 1600 if (landBlk && trueBlk && falseBlk) { 1601 curBlk->addSuccessor(landBlk); 1602 } 1603 1604} //mergeIfthenelseBlock 1605 1606template<class PassT> 1607void CFGStructurizer<PassT>::mergeLooplandBlock(BlockT *dstBlk, 1608 LoopLandInfo *loopLand) { 1609 BlockT *landBlk = loopLand->landBlk; 1610 1611 if (DEBUGME) { 1612 errs() << "loopPattern header = BB" << dstBlk->getNumber() 1613 << " land = BB" << landBlk->getNumber() << "\n"; 1614 } 1615 1616 // Loop contInitRegs are init at the beginning of the loop. 1617 for (typename std::set<RegiT>::const_iterator iter = 1618 loopLand->contInitRegs.begin(), 1619 iterEnd = loopLand->contInitRegs.end(); iter != iterEnd; ++iter) { 1620 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0); 1621 } 1622 1623 /* we last inserterd the DebugLoc in the 1624 * BREAK_LOGICALZ_i32 or AMDIL::BREAK_LOGICALNZ statement in the current dstBlk. 1625 * search for the DebugLoc in the that statement. 1626 * if not found, we have to insert the empty/default DebugLoc */ 1627 InstrT *loopBreakInstr = CFGTraits::getLoopBreakInstr(dstBlk); 1628 DebugLoc DLBreak = (loopBreakInstr) ? loopBreakInstr->getDebugLoc() : DebugLoc(); 1629 1630 CFGTraits::insertInstrBefore(dstBlk, AMDIL::WHILELOOP, passRep, DLBreak); 1631 // Loop breakInitRegs are init before entering the loop. 1632 for (typename std::set<RegiT>::const_iterator iter = 1633 loopLand->breakInitRegs.begin(), 1634 iterEnd = loopLand->breakInitRegs.end(); iter != iterEnd; ++iter) 1635 { 1636 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0); 1637 } 1638 // Loop endbranchInitRegs are init before entering the loop. 1639 for (typename std::set<RegiT>::const_iterator iter = 1640 loopLand->endbranchInitRegs.begin(), 1641 iterEnd = loopLand->endbranchInitRegs.end(); iter != iterEnd; ++iter) { 1642 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0); 1643 } 1644 1645 /* we last inserterd the DebugLoc in the continue statement in the current dstBlk 1646 * search for the DebugLoc in the continue statement. 1647 * if not found, we have to insert the empty/default DebugLoc */ 1648 InstrT *continueInstr = CFGTraits::getContinueInstr(dstBlk); 1649 DebugLoc DLContinue = (continueInstr) ? continueInstr->getDebugLoc() : DebugLoc(); 1650 1651 CFGTraits::insertInstrEnd(dstBlk, AMDIL::ENDLOOP, passRep, DLContinue); 1652 // Loop breakOnRegs are check after the ENDLOOP: break the loop outside this 1653 // loop. 1654 for (typename std::set<RegiT>::const_iterator iter = 1655 loopLand->breakOnRegs.begin(), 1656 iterEnd = loopLand->breakOnRegs.end(); iter != iterEnd; ++iter) { 1657 CFGTraits::insertCondBranchEnd(dstBlk, AMDIL::BREAK_LOGICALNZ_i32, passRep, 1658 *iter); 1659 } 1660 1661 // Loop contOnRegs are check after the ENDLOOP: cont the loop outside this 1662 // loop. 1663 for (std::set<RegiT>::const_iterator iter = loopLand->contOnRegs.begin(), 1664 iterEnd = loopLand->contOnRegs.end(); iter != iterEnd; ++iter) { 1665 CFGTraits::insertCondBranchEnd(dstBlk, AMDIL::CONTINUE_LOGICALNZ_i32, 1666 passRep, *iter); 1667 } 1668 1669 dstBlk->splice(dstBlk->end(), landBlk, landBlk->begin(), landBlk->end()); 1670 1671 for (typename BlockT::succ_iterator iter = landBlk->succ_begin(), 1672 iterEnd = landBlk->succ_end(); iter != iterEnd; ++iter) { 1673 dstBlk->addSuccessor(*iter); // *iter's predecessor is also taken care of. 1674 } 1675 1676 removeSuccessor(landBlk); 1677 retireBlock(dstBlk, landBlk); 1678} //mergeLooplandBlock 1679 1680template<class PassT> 1681void CFGStructurizer<PassT>::mergeLoopbreakBlock(BlockT *exitingBlk, 1682 BlockT *exitBlk, 1683 BlockT *exitLandBlk, 1684 RegiT setReg) { 1685 if (DEBUGME) { 1686 errs() << "loopbreakPattern exiting = BB" << exitingBlk->getNumber() 1687 << " exit = BB" << exitBlk->getNumber() 1688 << " land = BB" << exitLandBlk->getNumber() << "\n"; 1689 } 1690 1691 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(exitingBlk); 1692 assert(branchInstr && CFGTraits::isCondBranch(branchInstr)); 1693 1694 DebugLoc DL = branchInstr->getDebugLoc(); 1695 1696 BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr); 1697 int oldOpcode = branchInstr->getOpcode(); 1698 1699 // transform exitingBlk to 1700 // if ( ) { 1701 // exitBlk (if exitBlk != exitLandBlk) 1702 // setReg = 1 1703 // break 1704 // }endif 1705 // successor = {orgSuccessor(exitingBlk) - exitBlk} 1706 1707 typename BlockT::iterator branchInstrPos = 1708 CFGTraits::getInstrPos(exitingBlk, branchInstr); 1709 1710 if (exitBlk == exitLandBlk && setReg == INVALIDREGNUM) { 1711 //break_logical 1712 int newOpcode = 1713 (trueBranch == exitBlk) ? CFGTraits::getBreakNzeroOpcode(oldOpcode) 1714 : CFGTraits::getBreakZeroOpcode(oldOpcode); 1715 CFGTraits::insertCondBranchBefore(branchInstrPos, newOpcode, passRep, DL); 1716 } else { 1717 int newOpcode = 1718 (trueBranch == exitBlk) ? CFGTraits::getBranchNzeroOpcode(oldOpcode) 1719 : CFGTraits::getBranchZeroOpcode(oldOpcode); 1720 CFGTraits::insertCondBranchBefore(branchInstrPos, newOpcode, passRep, DL); 1721 if (exitBlk != exitLandBlk) { 1722 //splice is insert-before ... 1723 exitingBlk->splice(branchInstrPos, exitBlk, exitBlk->begin(), 1724 exitBlk->end()); 1725 } 1726 if (setReg != INVALIDREGNUM) { 1727 CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1); 1728 } 1729 CFGTraits::insertInstrBefore(branchInstrPos, AMDIL::BREAK, passRep); 1730 CFGTraits::insertInstrBefore(branchInstrPos, AMDIL::ENDIF, passRep); 1731 } //if_logical 1732 1733 //now branchInst can be erase safely 1734 //exitingBlk->eraseFromParent(branchInstr); 1735 branchInstr->eraseFromParent(); 1736 1737 //now take care of successors, retire blocks 1738 exitingBlk->removeSuccessor(exitBlk); 1739 if (exitBlk != exitLandBlk) { 1740 //splice is insert-before ... 1741 exitBlk->removeSuccessor(exitLandBlk); 1742 retireBlock(exitingBlk, exitBlk); 1743 } 1744 1745} //mergeLoopbreakBlock 1746 1747template<class PassT> 1748void CFGStructurizer<PassT>::settleLoopcontBlock(BlockT *contingBlk, 1749 BlockT *contBlk, 1750 RegiT setReg) { 1751 if (DEBUGME) { 1752 errs() << "settleLoopcontBlock conting = BB" 1753 << contingBlk->getNumber() 1754 << ", cont = BB" << contBlk->getNumber() << "\n"; 1755 } 1756 1757 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(contingBlk); 1758 if (branchInstr) { 1759 assert(CFGTraits::isCondBranch(branchInstr)); 1760 typename BlockT::iterator branchInstrPos = 1761 CFGTraits::getInstrPos(contingBlk, branchInstr); 1762 BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr); 1763 int oldOpcode = branchInstr->getOpcode(); 1764 DebugLoc DL = branchInstr->getDebugLoc(); 1765 1766 // transform contingBlk to 1767 // if () { 1768 // move instr after branchInstr 1769 // continue 1770 // or 1771 // setReg = 1 1772 // break 1773 // }endif 1774 // successor = {orgSuccessor(contingBlk) - loopHeader} 1775 1776 bool useContinueLogical = 1777 (setReg == INVALIDREGNUM && (&*contingBlk->rbegin()) == branchInstr); 1778 1779 if (useContinueLogical == false) 1780 { 1781 int branchOpcode = 1782 trueBranch == contBlk ? CFGTraits::getBranchNzeroOpcode(oldOpcode) 1783 : CFGTraits::getBranchZeroOpcode(oldOpcode); 1784 1785 CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL); 1786 1787 if (setReg != INVALIDREGNUM) { 1788 CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1); 1789 // insertEnd to ensure phi-moves, if exist, go before the continue-instr. 1790 CFGTraits::insertInstrEnd(contingBlk, AMDIL::BREAK, passRep, DL); 1791 } else { 1792 // insertEnd to ensure phi-moves, if exist, go before the continue-instr. 1793 CFGTraits::insertInstrEnd(contingBlk, AMDIL::CONTINUE, passRep, DL); 1794 } 1795 1796 CFGTraits::insertInstrEnd(contingBlk, AMDIL::ENDIF, passRep, DL); 1797 } else { 1798 int branchOpcode = 1799 trueBranch == contBlk ? CFGTraits::getContinueNzeroOpcode(oldOpcode) 1800 : CFGTraits::getContinueZeroOpcode(oldOpcode); 1801 1802 CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL); 1803 } 1804 1805 //contingBlk->eraseFromParent(branchInstr); 1806 branchInstr->eraseFromParent(); 1807 } else { 1808 /* if we've arrived here then we've already erased the branch instruction 1809 * travel back up the basic block to see the last reference of our debug location 1810 * we've just inserted that reference here so it should be representative */ 1811 if (setReg != INVALIDREGNUM) { 1812 CFGTraits::insertAssignInstrBefore(contingBlk, passRep, setReg, 1); 1813 // insertEnd to ensure phi-moves, if exist, go before the continue-instr. 1814 CFGTraits::insertInstrEnd(contingBlk, AMDIL::BREAK, passRep, CFGTraits::getLastDebugLocInBB(contingBlk)); 1815 } else { 1816 // insertEnd to ensure phi-moves, if exist, go before the continue-instr. 1817 CFGTraits::insertInstrEnd(contingBlk, AMDIL::CONTINUE, passRep, CFGTraits::getLastDebugLocInBB(contingBlk)); 1818 } 1819 } //else 1820 1821} //settleLoopcontBlock 1822 1823// BBs in exitBlkSet are determined as in break-path for loopRep, 1824// before we can put code for BBs as inside loop-body for loopRep 1825// check whether those BBs are determined as cont-BB for parentLoopRep 1826// earlier. 1827// If so, generate a new BB newBlk 1828// (1) set newBlk common successor of BBs in exitBlkSet 1829// (2) change the continue-instr in BBs in exitBlkSet to break-instr 1830// (3) generate continue-instr in newBlk 1831// 1832template<class PassT> 1833typename CFGStructurizer<PassT>::BlockT * 1834CFGStructurizer<PassT>::relocateLoopcontBlock(LoopT *parentLoopRep, 1835 LoopT *loopRep, 1836 std::set<BlockT *> &exitBlkSet, 1837 BlockT *exitLandBlk) { 1838 std::set<BlockT *> endBlkSet; 1839 1840// BlockT *parentLoopHead = parentLoopRep->getHeader(); 1841 1842 1843 for (typename std::set<BlockT *>::const_iterator iter = exitBlkSet.begin(), 1844 iterEnd = exitBlkSet.end(); 1845 iter != iterEnd; ++iter) { 1846 BlockT *exitBlk = *iter; 1847 BlockT *endBlk = singlePathEnd(exitBlk, exitLandBlk); 1848 1849 if (endBlk == NULL || CFGTraits::getContinueInstr(endBlk) == NULL) 1850 return NULL; 1851 1852 endBlkSet.insert(endBlk); 1853 } 1854 1855 BlockT *newBlk = funcRep->CreateMachineBasicBlock(); 1856 funcRep->push_back(newBlk); //insert to function 1857 CFGTraits::insertInstrEnd(newBlk, AMDIL::CONTINUE, passRep); 1858 SHOWNEWBLK(newBlk, "New continue block: "); 1859 1860 for (typename std::set<BlockT*>::const_iterator iter = endBlkSet.begin(), 1861 iterEnd = endBlkSet.end(); 1862 iter != iterEnd; ++iter) { 1863 BlockT *endBlk = *iter; 1864 InstrT *contInstr = CFGTraits::getContinueInstr(endBlk); 1865 if (contInstr) { 1866 contInstr->eraseFromParent(); 1867 } 1868 endBlk->addSuccessor(newBlk); 1869 if (DEBUGME) { 1870 errs() << "Add new continue Block to BB" 1871 << endBlk->getNumber() << " successors\n"; 1872 } 1873 } 1874 1875 return newBlk; 1876} //relocateLoopcontBlock 1877 1878 1879// LoopEndbranchBlock is a BB created by the CFGStructurizer to use as 1880// LoopLandBlock. This BB branch on the loop endBranchInit register to the 1881// pathes corresponding to the loop exiting branches. 1882 1883template<class PassT> 1884typename CFGStructurizer<PassT>::BlockT * 1885CFGStructurizer<PassT>::addLoopEndbranchBlock(LoopT *loopRep, 1886 BlockTSmallerVector &exitingBlks, 1887 BlockTSmallerVector &exitBlks) { 1888 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 1889 1890 RegiT endBranchReg = static_cast<int> 1891 (funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass)); 1892 assert(endBranchReg >= 0); 1893 1894 // reg = 0 before entering the loop 1895 addLoopEndbranchInitReg(loopRep, endBranchReg); 1896 1897 uint32_t numBlks = static_cast<uint32_t>(exitingBlks.size()); 1898 assert(numBlks >=2 && numBlks == exitBlks.size()); 1899 1900 BlockT *preExitingBlk = exitingBlks[0]; 1901 BlockT *preExitBlk = exitBlks[0]; 1902 BlockT *preBranchBlk = funcRep->CreateMachineBasicBlock(); 1903 funcRep->push_back(preBranchBlk); //insert to function 1904 SHOWNEWBLK(preBranchBlk, "New loopEndbranch block: "); 1905 1906 BlockT *newLandBlk = preBranchBlk; 1907 1908 CFGTraits::replaceInstrUseOfBlockWith(preExitingBlk, preExitBlk, 1909 newLandBlk); 1910 preExitingBlk->removeSuccessor(preExitBlk); 1911 preExitingBlk->addSuccessor(newLandBlk); 1912 1913 //it is redundant to add reg = 0 to exitingBlks[0] 1914 1915 // For 1..n th exiting path (the last iteration handles two pathes) create the 1916 // branch to the previous path and the current path. 1917 for (uint32_t i = 1; i < numBlks; ++i) { 1918 BlockT *curExitingBlk = exitingBlks[i]; 1919 BlockT *curExitBlk = exitBlks[i]; 1920 BlockT *curBranchBlk; 1921 1922 if (i == numBlks - 1) { 1923 curBranchBlk = curExitBlk; 1924 } else { 1925 curBranchBlk = funcRep->CreateMachineBasicBlock(); 1926 funcRep->push_back(curBranchBlk); //insert to function 1927 SHOWNEWBLK(curBranchBlk, "New loopEndbranch block: "); 1928 } 1929 1930 // Add reg = i to exitingBlks[i]. 1931 CFGTraits::insertAssignInstrBefore(curExitingBlk, passRep, 1932 endBranchReg, i); 1933 1934 // Remove the edge (exitingBlks[i] exitBlks[i]) add new edge 1935 // (exitingBlks[i], newLandBlk). 1936 CFGTraits::replaceInstrUseOfBlockWith(curExitingBlk, curExitBlk, 1937 newLandBlk); 1938 curExitingBlk->removeSuccessor(curExitBlk); 1939 curExitingBlk->addSuccessor(newLandBlk); 1940 1941 // add to preBranchBlk the branch instruction: 1942 // if (endBranchReg == preVal) 1943 // preExitBlk 1944 // else 1945 // curBranchBlk 1946 // 1947 // preValReg = i - 1 1948 1949 DebugLoc DL; 1950 RegiT preValReg = static_cast<int> 1951 (funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass)); 1952 BuildMI(preBranchBlk, DL, tii->get(AMDIL::LOADCONST_i32), preValReg) 1953 .addImm(i - 1); //preVal 1954 1955 // condResReg = (endBranchReg == preValReg) 1956 RegiT condResReg = static_cast<int> 1957 (funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass)); 1958 BuildMI(preBranchBlk, DL, tii->get(AMDIL::IEQ), condResReg) 1959 .addReg(endBranchReg).addReg(preValReg); 1960 1961 BuildMI(preBranchBlk, DL, tii->get(AMDIL::BRANCH_COND_i32)) 1962 .addMBB(preExitBlk).addReg(condResReg); 1963 1964 preBranchBlk->addSuccessor(preExitBlk); 1965 preBranchBlk->addSuccessor(curBranchBlk); 1966 1967 // Update preExitingBlk, preExitBlk, preBranchBlk. 1968 preExitingBlk = curExitingBlk; 1969 preExitBlk = curExitBlk; 1970 preBranchBlk = curBranchBlk; 1971 1972 } //end for 1 .. n blocks 1973 1974 return newLandBlk; 1975} //addLoopEndbranchBlock 1976 1977template<class PassT> 1978typename CFGStructurizer<PassT>::PathToKind 1979CFGStructurizer<PassT>::singlePathTo(BlockT *srcBlk, BlockT *dstBlk, 1980 bool allowSideEntry) { 1981 assert(dstBlk); 1982 1983 if (srcBlk == dstBlk) { 1984 return SinglePath_InPath; 1985 } 1986 1987 while (srcBlk && srcBlk->succ_size() == 1) { 1988 srcBlk = *srcBlk->succ_begin(); 1989 if (srcBlk == dstBlk) { 1990 return SinglePath_InPath; 1991 } 1992 1993 if (!allowSideEntry && srcBlk->pred_size() > 1) { 1994 return Not_SinglePath; 1995 } 1996 } 1997 1998 if (srcBlk && srcBlk->succ_size()==0) { 1999 return SinglePath_NotInPath; 2000 } 2001 2002 return Not_SinglePath; 2003} //singlePathTo 2004 2005// If there is a single path from srcBlk to dstBlk, return the last block before 2006// dstBlk If there is a single path from srcBlk->end without dstBlk, return the 2007// last block in the path Otherwise, return NULL 2008template<class PassT> 2009typename CFGStructurizer<PassT>::BlockT * 2010CFGStructurizer<PassT>::singlePathEnd(BlockT *srcBlk, BlockT *dstBlk, 2011 bool allowSideEntry) { 2012 assert(dstBlk); 2013 2014 if (srcBlk == dstBlk) { 2015 return srcBlk; 2016 } 2017 2018 if (srcBlk->succ_size() == 0) { 2019 return srcBlk; 2020 } 2021 2022 while (srcBlk && srcBlk->succ_size() == 1) { 2023 BlockT *preBlk = srcBlk; 2024 2025 srcBlk = *srcBlk->succ_begin(); 2026 if (srcBlk == NULL) { 2027 return preBlk; 2028 } 2029 2030 if (!allowSideEntry && srcBlk->pred_size() > 1) { 2031 return NULL; 2032 } 2033 } 2034 2035 if (srcBlk && srcBlk->succ_size()==0) { 2036 return srcBlk; 2037 } 2038 2039 return NULL; 2040 2041} //singlePathEnd 2042 2043template<class PassT> 2044int CFGStructurizer<PassT>::cloneOnSideEntryTo(BlockT *preBlk, BlockT *srcBlk, 2045 BlockT *dstBlk) { 2046 int cloned = 0; 2047 assert(preBlk->isSuccessor(srcBlk)); 2048 while (srcBlk && srcBlk != dstBlk) { 2049 assert(srcBlk->succ_size() == 1); 2050 if (srcBlk->pred_size() > 1) { 2051 srcBlk = cloneBlockForPredecessor(srcBlk, preBlk); 2052 ++cloned; 2053 } 2054 2055 preBlk = srcBlk; 2056 srcBlk = *srcBlk->succ_begin(); 2057 } 2058 2059 return cloned; 2060} //cloneOnSideEntryTo 2061 2062template<class PassT> 2063typename CFGStructurizer<PassT>::BlockT * 2064CFGStructurizer<PassT>::cloneBlockForPredecessor(BlockT *curBlk, 2065 BlockT *predBlk) { 2066 assert(predBlk->isSuccessor(curBlk) && 2067 "succBlk is not a prececessor of curBlk"); 2068 2069 BlockT *cloneBlk = CFGTraits::clone(curBlk); //clone instructions 2070 CFGTraits::replaceInstrUseOfBlockWith(predBlk, curBlk, cloneBlk); 2071 //srcBlk, oldBlk, newBlk 2072 2073 predBlk->removeSuccessor(curBlk); 2074 predBlk->addSuccessor(cloneBlk); 2075 2076 // add all successor to cloneBlk 2077 CFGTraits::cloneSuccessorList(cloneBlk, curBlk); 2078 2079 numClonedInstr += curBlk->size(); 2080 2081 if (DEBUGME) { 2082 errs() << "Cloned block: " << "BB" 2083 << curBlk->getNumber() << "size " << curBlk->size() << "\n"; 2084 } 2085 2086 SHOWNEWBLK(cloneBlk, "result of Cloned block: "); 2087 2088 return cloneBlk; 2089} //cloneBlockForPredecessor 2090 2091template<class PassT> 2092typename CFGStructurizer<PassT>::BlockT * 2093CFGStructurizer<PassT>::exitingBlock2ExitBlock(LoopT *loopRep, 2094 BlockT *exitingBlk) { 2095 BlockT *exitBlk = NULL; 2096 2097 for (typename BlockT::succ_iterator iterSucc = exitingBlk->succ_begin(), 2098 iterSuccEnd = exitingBlk->succ_end(); 2099 iterSucc != iterSuccEnd; ++iterSucc) { 2100 BlockT *curBlk = *iterSucc; 2101 if (!loopRep->contains(curBlk)) { 2102 assert(exitBlk == NULL); 2103 exitBlk = curBlk; 2104 } 2105 } 2106 2107 assert(exitBlk != NULL); 2108 2109 return exitBlk; 2110} //exitingBlock2ExitBlock 2111 2112template<class PassT> 2113void CFGStructurizer<PassT>::migrateInstruction(BlockT *srcBlk, 2114 BlockT *dstBlk, 2115 InstrIterator insertPos) { 2116 InstrIterator spliceEnd; 2117 //look for the input branchinstr, not the AMDIL branchinstr 2118 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk); 2119 if (branchInstr == NULL) { 2120 if (DEBUGME) { 2121 errs() << "migrateInstruction don't see branch instr\n" ; 2122 } 2123 spliceEnd = srcBlk->end(); 2124 } else { 2125 if (DEBUGME) { 2126 errs() << "migrateInstruction see branch instr\n" ; 2127 branchInstr->dump(); 2128 } 2129 spliceEnd = CFGTraits::getInstrPos(srcBlk, branchInstr); 2130 } 2131 if (DEBUGME) { 2132 errs() << "migrateInstruction before splice dstSize = " << dstBlk->size() 2133 << "srcSize = " << srcBlk->size() << "\n"; 2134 } 2135 2136 //splice insert before insertPos 2137 dstBlk->splice(insertPos, srcBlk, srcBlk->begin(), spliceEnd); 2138 2139 if (DEBUGME) { 2140 errs() << "migrateInstruction after splice dstSize = " << dstBlk->size() 2141 << "srcSize = " << srcBlk->size() << "\n"; 2142 } 2143} //migrateInstruction 2144 2145// normalizeInfiniteLoopExit change 2146// B1: 2147// uncond_br LoopHeader 2148// 2149// to 2150// B1: 2151// cond_br 1 LoopHeader dummyExit 2152// and return the newly added dummy exit block 2153// 2154template<class PassT> 2155typename CFGStructurizer<PassT>::BlockT * 2156CFGStructurizer<PassT>::normalizeInfiniteLoopExit(LoopT* LoopRep) { 2157 BlockT *loopHeader; 2158 BlockT *loopLatch; 2159 loopHeader = LoopRep->getHeader(); 2160 loopLatch = LoopRep->getLoopLatch(); 2161 BlockT *dummyExitBlk = NULL; 2162 if (loopHeader!=NULL && loopLatch!=NULL) { 2163 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(loopLatch); 2164 if (branchInstr!=NULL && CFGTraits::isUncondBranch(branchInstr)) { 2165 dummyExitBlk = funcRep->CreateMachineBasicBlock(); 2166 funcRep->push_back(dummyExitBlk); //insert to function 2167 SHOWNEWBLK(dummyExitBlk, "DummyExitBlock to normalize infiniteLoop: "); 2168 2169 if (DEBUGME) errs() << "Old branch instr: " << *branchInstr << "\n"; 2170 2171 typename BlockT::iterator insertPos = 2172 CFGTraits::getInstrPos(loopLatch, branchInstr); 2173 unsigned immReg = 2174 funcRep->getRegInfo().createVirtualRegister(&AMDIL::GPRI32RegClass); 2175 CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 1); 2176 InstrT *newInstr = 2177 CFGTraits::insertInstrBefore(insertPos, AMDIL::BRANCH_COND_i32, passRep); 2178 MachineInstrBuilder(newInstr).addMBB(loopHeader).addReg(immReg, false); 2179 2180 SHOWNEWINSTR(newInstr); 2181 2182 branchInstr->eraseFromParent(); 2183 loopLatch->addSuccessor(dummyExitBlk); 2184 } 2185 } 2186 2187 return dummyExitBlk; 2188} //normalizeInfiniteLoopExit 2189 2190template<class PassT> 2191void CFGStructurizer<PassT>::removeUnconditionalBranch(BlockT *srcBlk) { 2192 InstrT *branchInstr; 2193 2194 // I saw two unconditional branch in one basic block in example 2195 // test_fc_do_while_or.c need to fix the upstream on this to remove the loop. 2196 while ((branchInstr = CFGTraits::getLoopendBlockBranchInstr(srcBlk)) 2197 && CFGTraits::isUncondBranch(branchInstr)) { 2198 if (DEBUGME) { 2199 errs() << "Removing unconditional branch instruction" ; 2200 branchInstr->dump(); 2201 } 2202 branchInstr->eraseFromParent(); 2203 } 2204} //removeUnconditionalBranch 2205 2206template<class PassT> 2207void CFGStructurizer<PassT>::removeRedundantConditionalBranch(BlockT *srcBlk) { 2208 if (srcBlk->succ_size() == 2) { 2209 BlockT *blk1 = *srcBlk->succ_begin(); 2210 BlockT *blk2 = *(++srcBlk->succ_begin()); 2211 2212 if (blk1 == blk2) { 2213 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk); 2214 assert(branchInstr && CFGTraits::isCondBranch(branchInstr)); 2215 if (DEBUGME) { 2216 errs() << "Removing unneeded conditional branch instruction" ; 2217 branchInstr->dump(); 2218 } 2219 branchInstr->eraseFromParent(); 2220 SHOWNEWBLK(blk1, "Removing redundant successor"); 2221 srcBlk->removeSuccessor(blk1); 2222 } 2223 } 2224} //removeRedundantConditionalBranch 2225 2226template<class PassT> 2227void CFGStructurizer<PassT>::addDummyExitBlock(SmallVector<BlockT*, 2228 DEFAULT_VEC_SLOTS> &retBlks) { 2229 BlockT *dummyExitBlk = funcRep->CreateMachineBasicBlock(); 2230 funcRep->push_back(dummyExitBlk); //insert to function 2231 CFGTraits::insertInstrEnd(dummyExitBlk, AMDIL::RETURN, passRep); 2232 2233 for (typename SmallVector<BlockT *, DEFAULT_VEC_SLOTS>::iterator iter = 2234 retBlks.begin(), 2235 iterEnd = retBlks.end(); iter != iterEnd; ++iter) { 2236 BlockT *curBlk = *iter; 2237 InstrT *curInstr = CFGTraits::getReturnInstr(curBlk); 2238 if (curInstr) { 2239 curInstr->eraseFromParent(); 2240 } 2241#if 0 2242 if (curBlk->size()==0 && curBlk->pred_size() == 1) { 2243 if (DEBUGME) { 2244 errs() << "Replace empty block BB" << curBlk->getNumber() 2245 << " with dummyExitBlock\n"; 2246 } 2247 BlockT *predb = *curBlk->pred_begin(); 2248 predb->removeSuccessor(curBlk); 2249 curBlk = predb; 2250 } //handle empty curBlk 2251#endif 2252 curBlk->addSuccessor(dummyExitBlk); 2253 if (DEBUGME) { 2254 errs() << "Add dummyExitBlock to BB" << curBlk->getNumber() 2255 << " successors\n"; 2256 } 2257 } //for 2258 2259 SHOWNEWBLK(dummyExitBlk, "DummyExitBlock: "); 2260} //addDummyExitBlock 2261 2262template<class PassT> 2263void CFGStructurizer<PassT>::removeSuccessor(BlockT *srcBlk) { 2264 while (srcBlk->succ_size()) { 2265 srcBlk->removeSuccessor(*srcBlk->succ_begin()); 2266 } 2267} 2268 2269template<class PassT> 2270void CFGStructurizer<PassT>::recordSccnum(BlockT *srcBlk, int sccNum) { 2271 BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk]; 2272 2273 if (srcBlkInfo == NULL) { 2274 srcBlkInfo = new BlockInfo(); 2275 } 2276 2277 srcBlkInfo->sccNum = sccNum; 2278} 2279 2280template<class PassT> 2281int CFGStructurizer<PassT>::getSCCNum(BlockT *srcBlk) { 2282 BlockInfo *srcBlkInfo = blockInfoMap[srcBlk]; 2283 return srcBlkInfo ? srcBlkInfo->sccNum : INVALIDSCCNUM; 2284} 2285 2286template<class PassT> 2287void CFGStructurizer<PassT>::retireBlock(BlockT *dstBlk, BlockT *srcBlk) { 2288 if (DEBUGME) { 2289 errs() << "Retiring BB" << srcBlk->getNumber() << "\n"; 2290 } 2291 2292 BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk]; 2293 2294 if (srcBlkInfo == NULL) { 2295 srcBlkInfo = new BlockInfo(); 2296 } 2297 2298 srcBlkInfo->isRetired = true; 2299 //int i = srcBlk->succ_size(); 2300 //int j = srcBlk->pred_size(); 2301 assert(srcBlk->succ_size() == 0 && srcBlk->pred_size() == 0 2302 && "can't retire block yet"); 2303} 2304 2305template<class PassT> 2306bool CFGStructurizer<PassT>::isRetiredBlock(BlockT *srcBlk) { 2307 BlockInfo *srcBlkInfo = blockInfoMap[srcBlk]; 2308 return (srcBlkInfo && srcBlkInfo->isRetired); 2309} 2310 2311template<class PassT> 2312bool CFGStructurizer<PassT>::isActiveLoophead(BlockT *curBlk) { 2313 LoopT *loopRep = loopInfo->getLoopFor(curBlk); 2314 while (loopRep && loopRep->getHeader() == curBlk) { 2315 LoopLandInfo *loopLand = getLoopLandInfo(loopRep); 2316 2317 if(loopLand == NULL) 2318 return true; 2319 2320 BlockT *landBlk = loopLand->landBlk; 2321 assert(landBlk); 2322 if (!isRetiredBlock(landBlk)) { 2323 return true; 2324 } 2325 2326 loopRep = loopRep->getParentLoop(); 2327 } 2328 2329 return false; 2330} //isActiveLoophead 2331 2332template<class PassT> 2333bool CFGStructurizer<PassT>::needMigrateBlock(BlockT *blk) { 2334 const unsigned blockSizeThreshold = 30; 2335 const unsigned cloneInstrThreshold = 100; 2336 2337 bool multiplePreds = blk && (blk->pred_size() > 1); 2338 2339 if(!multiplePreds) 2340 return false; 2341 2342 unsigned blkSize = blk->size(); 2343 return ((blkSize > blockSizeThreshold) 2344 && (blkSize * (blk->pred_size() - 1) > cloneInstrThreshold)); 2345} //needMigrateBlock 2346 2347template<class PassT> 2348typename CFGStructurizer<PassT>::BlockT * 2349CFGStructurizer<PassT>::recordLoopLandBlock(LoopT *loopRep, BlockT *landBlk, 2350 BlockTSmallerVector &exitBlks, 2351 std::set<BlockT *> &exitBlkSet) { 2352 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> inpathBlks; //in exit path blocks 2353 2354 for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(), 2355 predIterEnd = landBlk->pred_end(); 2356 predIter != predIterEnd; ++predIter) { 2357 BlockT *curBlk = *predIter; 2358 if (loopRep->contains(curBlk) || exitBlkSet.count(curBlk)) { 2359 inpathBlks.push_back(curBlk); 2360 } 2361 } //for 2362 2363 //if landBlk has predecessors that are not in the given loop, 2364 //create a new block 2365 BlockT *newLandBlk = landBlk; 2366 if (inpathBlks.size() != landBlk->pred_size()) { 2367 newLandBlk = funcRep->CreateMachineBasicBlock(); 2368 funcRep->push_back(newLandBlk); //insert to function 2369 newLandBlk->addSuccessor(landBlk); 2370 for (typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::iterator iter = 2371 inpathBlks.begin(), 2372 iterEnd = inpathBlks.end(); iter != iterEnd; ++iter) { 2373 BlockT *curBlk = *iter; 2374 CFGTraits::replaceInstrUseOfBlockWith(curBlk, landBlk, newLandBlk); 2375 //srcBlk, oldBlk, newBlk 2376 curBlk->removeSuccessor(landBlk); 2377 curBlk->addSuccessor(newLandBlk); 2378 } 2379 for (size_t i = 0, tot = exitBlks.size(); i < tot; ++i) { 2380 if (exitBlks[i] == landBlk) { 2381 exitBlks[i] = newLandBlk; 2382 } 2383 } 2384 SHOWNEWBLK(newLandBlk, "NewLandingBlock: "); 2385 } 2386 2387 setLoopLandBlock(loopRep, newLandBlk); 2388 2389 return newLandBlk; 2390} // recordLoopbreakLand 2391 2392template<class PassT> 2393void CFGStructurizer<PassT>::setLoopLandBlock(LoopT *loopRep, BlockT *blk) { 2394 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2395 2396 if (theEntry == NULL) { 2397 theEntry = new LoopLandInfo(); 2398 } 2399 assert(theEntry->landBlk == NULL); 2400 2401 if (blk == NULL) { 2402 blk = funcRep->CreateMachineBasicBlock(); 2403 funcRep->push_back(blk); //insert to function 2404 SHOWNEWBLK(blk, "DummyLandingBlock for loop without break: "); 2405 } 2406 2407 theEntry->landBlk = blk; 2408 2409 if (DEBUGME) { 2410 errs() << "setLoopLandBlock loop-header = BB" 2411 << loopRep->getHeader()->getNumber() 2412 << " landing-block = BB" << blk->getNumber() << "\n"; 2413 } 2414} // setLoopLandBlock 2415 2416template<class PassT> 2417void CFGStructurizer<PassT>::addLoopBreakOnReg(LoopT *loopRep, RegiT regNum) { 2418 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2419 2420 if (theEntry == NULL) { 2421 theEntry = new LoopLandInfo(); 2422 } 2423 2424 theEntry->breakOnRegs.insert(regNum); 2425 2426 if (DEBUGME) { 2427 errs() << "addLoopBreakOnReg loop-header = BB" 2428 << loopRep->getHeader()->getNumber() 2429 << " regNum = " << regNum << "\n"; 2430 } 2431} // addLoopBreakOnReg 2432 2433template<class PassT> 2434void CFGStructurizer<PassT>::addLoopContOnReg(LoopT *loopRep, RegiT regNum) { 2435 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2436 2437 if (theEntry == NULL) { 2438 theEntry = new LoopLandInfo(); 2439 } 2440 theEntry->contOnRegs.insert(regNum); 2441 2442 if (DEBUGME) { 2443 errs() << "addLoopContOnReg loop-header = BB" 2444 << loopRep->getHeader()->getNumber() 2445 << " regNum = " << regNum << "\n"; 2446 } 2447} // addLoopContOnReg 2448 2449template<class PassT> 2450void CFGStructurizer<PassT>::addLoopBreakInitReg(LoopT *loopRep, RegiT regNum) { 2451 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2452 2453 if (theEntry == NULL) { 2454 theEntry = new LoopLandInfo(); 2455 } 2456 theEntry->breakInitRegs.insert(regNum); 2457 2458 if (DEBUGME) { 2459 errs() << "addLoopBreakInitReg loop-header = BB" 2460 << loopRep->getHeader()->getNumber() 2461 << " regNum = " << regNum << "\n"; 2462 } 2463} // addLoopBreakInitReg 2464 2465template<class PassT> 2466void CFGStructurizer<PassT>::addLoopContInitReg(LoopT *loopRep, RegiT regNum) { 2467 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2468 2469 if (theEntry == NULL) { 2470 theEntry = new LoopLandInfo(); 2471 } 2472 theEntry->contInitRegs.insert(regNum); 2473 2474 if (DEBUGME) { 2475 errs() << "addLoopContInitReg loop-header = BB" 2476 << loopRep->getHeader()->getNumber() 2477 << " regNum = " << regNum << "\n"; 2478 } 2479} // addLoopContInitReg 2480 2481template<class PassT> 2482void CFGStructurizer<PassT>::addLoopEndbranchInitReg(LoopT *loopRep, 2483 RegiT regNum) { 2484 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2485 2486 if (theEntry == NULL) { 2487 theEntry = new LoopLandInfo(); 2488 } 2489 theEntry->endbranchInitRegs.insert(regNum); 2490 2491 if (DEBUGME) 2492 { 2493 errs() << "addLoopEndbranchInitReg loop-header = BB" 2494 << loopRep->getHeader()->getNumber() 2495 << " regNum = " << regNum << "\n"; 2496 } 2497} // addLoopEndbranchInitReg 2498 2499template<class PassT> 2500typename CFGStructurizer<PassT>::LoopLandInfo * 2501CFGStructurizer<PassT>::getLoopLandInfo(LoopT *loopRep) { 2502 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2503 2504 return theEntry; 2505} // getLoopLandInfo 2506 2507template<class PassT> 2508typename CFGStructurizer<PassT>::BlockT * 2509CFGStructurizer<PassT>::getLoopLandBlock(LoopT *loopRep) { 2510 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep]; 2511 2512 return theEntry ? theEntry->landBlk : NULL; 2513} // getLoopLandBlock 2514 2515 2516template<class PassT> 2517bool CFGStructurizer<PassT>::hasBackEdge(BlockT *curBlk) { 2518 LoopT *loopRep = loopInfo->getLoopFor(curBlk); 2519 if (loopRep == NULL) 2520 return false; 2521 2522 BlockT *loopHeader = loopRep->getHeader(); 2523 2524 return curBlk->isSuccessor(loopHeader); 2525 2526} //hasBackEdge 2527 2528template<class PassT> 2529unsigned CFGStructurizer<PassT>::getLoopDepth(LoopT *loopRep) { 2530 return loopRep ? loopRep->getLoopDepth() : 0; 2531} //getLoopDepth 2532 2533template<class PassT> 2534int CFGStructurizer<PassT>::countActiveBlock 2535(typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::const_iterator iterStart, 2536 typename SmallVector<BlockT*, DEFAULT_VEC_SLOTS>::const_iterator iterEnd) { 2537 int count = 0; 2538 while (iterStart != iterEnd) { 2539 if (!isRetiredBlock(*iterStart)) { 2540 ++count; 2541 } 2542 ++iterStart; 2543 } 2544 2545 return count; 2546} //countActiveBlock 2547 2548// This is work around solution for findNearestCommonDominator not avaiable to 2549// post dom a proper fix should go to Dominators.h. 2550 2551template<class PassT> 2552typename CFGStructurizer<PassT>::BlockT* 2553CFGStructurizer<PassT>::findNearestCommonPostDom(BlockT *blk1, BlockT *blk2) { 2554 2555 if (postDomTree->dominates(blk1, blk2)) { 2556 return blk1; 2557 } 2558 if (postDomTree->dominates(blk2, blk1)) { 2559 return blk2; 2560 } 2561 2562 DomTreeNodeT *node1 = postDomTree->getNode(blk1); 2563 DomTreeNodeT *node2 = postDomTree->getNode(blk2); 2564 2565 // Handle newly cloned node. 2566 if (node1 == NULL && blk1->succ_size() == 1) { 2567 return findNearestCommonPostDom(*blk1->succ_begin(), blk2); 2568 } 2569 if (node2 == NULL && blk2->succ_size() == 1) { 2570 return findNearestCommonPostDom(blk1, *blk2->succ_begin()); 2571 } 2572 2573 if (node1 == NULL || node2 == NULL) { 2574 return NULL; 2575 } 2576 2577 node1 = node1->getIDom(); 2578 while (node1) { 2579 if (postDomTree->dominates(node1, node2)) { 2580 return node1->getBlock(); 2581 } 2582 node1 = node1->getIDom(); 2583 } 2584 2585 return NULL; 2586} 2587 2588template<class PassT> 2589typename CFGStructurizer<PassT>::BlockT * 2590CFGStructurizer<PassT>::findNearestCommonPostDom 2591(typename std::set<BlockT *> &blks) { 2592 BlockT *commonDom; 2593 typename std::set<BlockT *>::const_iterator iter = blks.begin(); 2594 typename std::set<BlockT *>::const_iterator iterEnd = blks.end(); 2595 for (commonDom = *iter; iter != iterEnd && commonDom != NULL; ++iter) { 2596 BlockT *curBlk = *iter; 2597 if (curBlk != commonDom) { 2598 commonDom = findNearestCommonPostDom(curBlk, commonDom); 2599 } 2600 } 2601 2602 if (DEBUGME) { 2603 errs() << "Common post dominator for exit blocks is "; 2604 if (commonDom) { 2605 errs() << "BB" << commonDom->getNumber() << "\n"; 2606 } else { 2607 errs() << "NULL\n"; 2608 } 2609 } 2610 2611 return commonDom; 2612} //findNearestCommonPostDom 2613 2614} //end namespace llvm 2615 2616//todo: move-end 2617 2618 2619//===----------------------------------------------------------------------===// 2620// 2621// CFGStructurizer for AMDIL 2622// 2623//===----------------------------------------------------------------------===// 2624 2625 2626using namespace llvmCFGStruct; 2627 2628namespace llvm 2629{ 2630class AMDILCFGStructurizer : public MachineFunctionPass 2631{ 2632public: 2633 typedef MachineInstr InstructionType; 2634 typedef MachineFunction FunctionType; 2635 typedef MachineBasicBlock BlockType; 2636 typedef MachineLoopInfo LoopinfoType; 2637 typedef MachineDominatorTree DominatortreeType; 2638 typedef MachinePostDominatorTree PostDominatortreeType; 2639 typedef MachineDomTreeNode DomTreeNodeType; 2640 typedef MachineLoop LoopType; 2641//private: 2642 TargetMachine &TM; 2643 const TargetInstrInfo *TII; 2644 2645//public: 2646// static char ID; 2647 2648public: 2649 AMDILCFGStructurizer(char &pid, TargetMachine &tm AMDIL_OPT_LEVEL_DECL); 2650 const TargetInstrInfo *getTargetInstrInfo() const; 2651 //bool runOnMachineFunction(MachineFunction &F); 2652 2653private: 2654 2655}; //end of class AMDILCFGStructurizer 2656 2657//char AMDILCFGStructurizer::ID = 0; 2658} //end of namespace llvm 2659AMDILCFGStructurizer::AMDILCFGStructurizer(char &pid, TargetMachine &tm 2660 AMDIL_OPT_LEVEL_DECL) 2661: MachineFunctionPass(pid), TM(tm), TII(tm.getInstrInfo()) { 2662} 2663 2664const TargetInstrInfo *AMDILCFGStructurizer::getTargetInstrInfo() const { 2665 return TII; 2666} 2667//===----------------------------------------------------------------------===// 2668// 2669// CFGPrepare 2670// 2671//===----------------------------------------------------------------------===// 2672 2673 2674using namespace llvmCFGStruct; 2675 2676namespace llvm 2677{ 2678class AMDILCFGPrepare : public AMDILCFGStructurizer 2679{ 2680public: 2681 static char ID; 2682 2683public: 2684 AMDILCFGPrepare(TargetMachine &tm AMDIL_OPT_LEVEL_DECL); 2685 2686 virtual const char *getPassName() const; 2687 virtual void getAnalysisUsage(AnalysisUsage &AU) const; 2688 2689 bool runOnMachineFunction(MachineFunction &F); 2690 2691private: 2692 2693}; //end of class AMDILCFGPrepare 2694 2695char AMDILCFGPrepare::ID = 0; 2696} //end of namespace llvm 2697 2698AMDILCFGPrepare::AMDILCFGPrepare(TargetMachine &tm AMDIL_OPT_LEVEL_DECL) 2699 : AMDILCFGStructurizer(ID, tm AMDIL_OPT_LEVEL_VAR) 2700{ 2701} 2702const char *AMDILCFGPrepare::getPassName() const { 2703 return "AMD IL Control Flow Graph Preparation Pass"; 2704} 2705 2706void AMDILCFGPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 2707 AU.addPreserved<MachineFunctionAnalysis>(); 2708 AU.addRequired<MachineFunctionAnalysis>(); 2709 AU.addRequired<MachineDominatorTree>(); 2710 AU.addRequired<MachinePostDominatorTree>(); 2711 AU.addRequired<MachineLoopInfo>(); 2712} 2713 2714//===----------------------------------------------------------------------===// 2715// 2716// CFGPerform 2717// 2718//===----------------------------------------------------------------------===// 2719 2720 2721using namespace llvmCFGStruct; 2722 2723namespace llvm 2724{ 2725class AMDILCFGPerform : public AMDILCFGStructurizer 2726{ 2727public: 2728 static char ID; 2729 2730public: 2731 AMDILCFGPerform(TargetMachine &tm AMDIL_OPT_LEVEL_DECL); 2732 virtual const char *getPassName() const; 2733 virtual void getAnalysisUsage(AnalysisUsage &AU) const; 2734 bool runOnMachineFunction(MachineFunction &F); 2735 2736private: 2737 2738}; //end of class AMDILCFGPerform 2739 2740char AMDILCFGPerform::ID = 0; 2741} //end of namespace llvm 2742 2743 AMDILCFGPerform::AMDILCFGPerform(TargetMachine &tm AMDIL_OPT_LEVEL_DECL) 2744: AMDILCFGStructurizer(ID, tm AMDIL_OPT_LEVEL_VAR) 2745{ 2746} 2747 2748const char *AMDILCFGPerform::getPassName() const { 2749 return "AMD IL Control Flow Graph structurizer Pass"; 2750} 2751 2752void AMDILCFGPerform::getAnalysisUsage(AnalysisUsage &AU) const { 2753 AU.addPreserved<MachineFunctionAnalysis>(); 2754 AU.addRequired<MachineFunctionAnalysis>(); 2755 AU.addRequired<MachineDominatorTree>(); 2756 AU.addRequired<MachinePostDominatorTree>(); 2757 AU.addRequired<MachineLoopInfo>(); 2758} 2759 2760//===----------------------------------------------------------------------===// 2761// 2762// CFGStructTraits<AMDILCFGStructurizer> 2763// 2764//===----------------------------------------------------------------------===// 2765 2766namespace llvmCFGStruct 2767{ 2768// this class is tailor to the AMDIL backend 2769template<> 2770struct CFGStructTraits<AMDILCFGStructurizer> 2771{ 2772 typedef int RegiT; 2773 2774 static int getBreakNzeroOpcode(int oldOpcode) { 2775 switch(oldOpcode) { 2776 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::BREAK_LOGICALNZ); 2777 default: 2778 assert(0 && "internal error"); 2779 }; 2780 return -1; 2781 } 2782 2783 static int getBreakZeroOpcode(int oldOpcode) { 2784 switch(oldOpcode) { 2785 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::BREAK_LOGICALZ); 2786 default: 2787 assert(0 && "internal error"); 2788 }; 2789 return -1; 2790 } 2791 2792 static int getBranchNzeroOpcode(int oldOpcode) { 2793 switch(oldOpcode) { 2794 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::IF_LOGICALNZ); 2795 default: 2796 assert(0 && "internal error"); 2797 }; 2798 return -1; 2799 } 2800 2801 static int getBranchZeroOpcode(int oldOpcode) { 2802 switch(oldOpcode) { 2803 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::IF_LOGICALZ); 2804 default: 2805 assert(0 && "internal error"); 2806 }; 2807 return -1; 2808 } 2809 2810 static int getContinueNzeroOpcode(int oldOpcode) 2811 { 2812 switch(oldOpcode) { 2813 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::CONTINUE_LOGICALNZ); 2814 default: 2815 assert(0 && "internal error"); 2816 }; 2817 return -1; 2818 } 2819 2820 static int getContinueZeroOpcode(int oldOpcode) { 2821 switch(oldOpcode) { 2822 ExpandCaseToAllScalarReturn(AMDIL::BRANCH_COND, AMDIL::CONTINUE_LOGICALZ); 2823 default: 2824 assert(0 && "internal error"); 2825 }; 2826 return -1; 2827 } 2828 2829// the explicitly represented branch target is the true branch target 2830#define getExplicitBranch getTrueBranch 2831#define setExplicitBranch setTrueBranch 2832 2833 static MachineBasicBlock *getTrueBranch(MachineInstr *instr) { 2834 return instr->getOperand(0).getMBB(); 2835 } 2836 2837 static void setTrueBranch(MachineInstr *instr, MachineBasicBlock *blk) { 2838 instr->getOperand(0).setMBB(blk); 2839 } 2840 2841 static MachineBasicBlock * 2842 getFalseBranch(MachineBasicBlock *blk, MachineInstr *instr) { 2843 assert(blk->succ_size() == 2); 2844 MachineBasicBlock *trueBranch = getTrueBranch(instr); 2845 MachineBasicBlock::succ_iterator iter = blk->succ_begin(); 2846 MachineBasicBlock::succ_iterator iterNext = iter; 2847 ++iterNext; 2848 2849 return (*iter == trueBranch) ? *iterNext : *iter; 2850 } 2851 2852 static bool isCondBranch(MachineInstr *instr) { 2853 switch (instr->getOpcode()) { 2854 ExpandCaseToAllScalarTypes(AMDIL::BRANCH_COND); 2855 break; 2856 default: 2857 return false; 2858 } 2859 return true; 2860 } 2861 2862 static bool isUncondBranch(MachineInstr *instr) { 2863 switch (instr->getOpcode()) { 2864 case AMDIL::BRANCH: 2865 break; 2866 default: 2867 return false; 2868 } 2869 return true; 2870 } 2871 2872 static bool isPhimove(MachineInstr *instr) { 2873 switch (instr->getOpcode()) { 2874 ExpandCaseToAllTypes(AMDIL::MOVE); 2875 break; 2876 default: 2877 return false; 2878 } 2879 return true; 2880 } 2881 2882 static DebugLoc getLastDebugLocInBB(MachineBasicBlock *blk) { 2883 //get DebugLoc from the first MachineBasicBlock instruction with debug info 2884 DebugLoc DL; 2885 for (MachineBasicBlock::iterator iter = blk->begin(); iter != blk->end(); ++iter) { 2886 MachineInstr *instr = &(*iter); 2887 if (instr->getDebugLoc().isUnknown() == false) { 2888 DL = instr->getDebugLoc(); 2889 } 2890 } 2891 return DL; 2892 } 2893 2894 static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *blk) { 2895 MachineBasicBlock::reverse_iterator iter = blk->rbegin(); 2896 MachineInstr *instr = &*iter; 2897 if (instr && (isCondBranch(instr) || isUncondBranch(instr))) { 2898 return instr; 2899 } 2900 return NULL; 2901 } 2902 2903 // The correct naming for this is getPossibleLoopendBlockBranchInstr. 2904 // 2905 // BB with backward-edge could have move instructions after the branch 2906 // instruction. Such move instruction "belong to" the loop backward-edge. 2907 // 2908 static MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *blk) { 2909 for (MachineBasicBlock::reverse_iterator iter = blk->rbegin(), 2910 iterEnd = blk->rend(); iter != iterEnd; ++iter) { 2911 // FIXME: Simplify 2912 MachineInstr *instr = &*iter; 2913 if (instr) { 2914 if (isCondBranch(instr) || isUncondBranch(instr)) { 2915 return instr; 2916 } else if (!isPhimove(instr)) { 2917 break; 2918 } 2919 } 2920 } 2921 return NULL; 2922 } 2923 2924 static MachineInstr *getReturnInstr(MachineBasicBlock *blk) { 2925 MachineBasicBlock::reverse_iterator iter = blk->rbegin(); 2926 if (iter != blk->rend()) { 2927 MachineInstr *instr = &(*iter); 2928 if (instr->getOpcode() == AMDIL::RETURN) { 2929 return instr; 2930 } 2931 } 2932 return NULL; 2933 } 2934 2935 static MachineInstr *getContinueInstr(MachineBasicBlock *blk) { 2936 MachineBasicBlock::reverse_iterator iter = blk->rbegin(); 2937 if (iter != blk->rend()) { 2938 MachineInstr *instr = &(*iter); 2939 if (instr->getOpcode() == AMDIL::CONTINUE) { 2940 return instr; 2941 } 2942 } 2943 return NULL; 2944 } 2945 2946 static MachineInstr *getLoopBreakInstr(MachineBasicBlock *blk) { 2947 for (MachineBasicBlock::iterator iter = blk->begin(); (iter != blk->end()); ++iter) { 2948 MachineInstr *instr = &(*iter); 2949 if ((instr->getOpcode() == AMDIL::BREAK_LOGICALNZ_i32) || (instr->getOpcode() == AMDIL::BREAK_LOGICALZ_i32)) { 2950 return instr; 2951 } 2952 } 2953 return NULL; 2954 } 2955 2956 static bool isReturnBlock(MachineBasicBlock *blk) { 2957 MachineInstr *instr = getReturnInstr(blk); 2958 bool isReturn = (blk->succ_size() == 0); 2959 if (instr) { 2960 assert(isReturn); 2961 } else if (isReturn) { 2962 if (DEBUGME) { 2963 errs() << "BB" << blk->getNumber() 2964 <<" is return block without RETURN instr\n"; 2965 } 2966 } 2967 2968 return isReturn; 2969 } 2970 2971 static MachineBasicBlock::iterator 2972 getInstrPos(MachineBasicBlock *blk, MachineInstr *instr) { 2973 assert(instr->getParent() == blk && "instruction doesn't belong to block"); 2974 MachineBasicBlock::iterator iter = blk->begin(); 2975 MachineBasicBlock::iterator iterEnd = blk->end(); 2976 while (&(*iter) != instr && iter != iterEnd) { 2977 ++iter; 2978 } 2979 2980 assert(iter != iterEnd); 2981 return iter; 2982 }//getInstrPos 2983 2984 static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode, 2985 AMDILCFGStructurizer *passRep) { 2986 return insertInstrBefore(blk,newOpcode,passRep,DebugLoc()); 2987 } //insertInstrBefore 2988 2989 static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode, 2990 AMDILCFGStructurizer *passRep, DebugLoc DL) { 2991 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 2992 MachineInstr *newInstr = 2993 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), DL); 2994 2995 MachineBasicBlock::iterator res; 2996 if (blk->begin() != blk->end()) { 2997 blk->insert(blk->begin(), newInstr); 2998 } else { 2999 blk->push_back(newInstr); 3000 } 3001 3002 SHOWNEWINSTR(newInstr); 3003 3004 return newInstr; 3005 } //insertInstrBefore 3006 3007 static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode, 3008 AMDILCFGStructurizer *passRep) { 3009 insertInstrEnd(blk,newOpcode,passRep,DebugLoc()); 3010 } //insertInstrEnd 3011 3012 static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode, 3013 AMDILCFGStructurizer *passRep, DebugLoc DL) { 3014 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3015 MachineInstr *newInstr = blk->getParent() 3016 ->CreateMachineInstr(tii->get(newOpcode), DL); 3017 3018 blk->push_back(newInstr); 3019 //assume the instruction doesn't take any reg operand ... 3020 3021 SHOWNEWINSTR(newInstr); 3022 } //insertInstrEnd 3023 3024 static MachineInstr *insertInstrBefore(MachineBasicBlock::iterator instrPos, 3025 int newOpcode, 3026 AMDILCFGStructurizer *passRep) { 3027 MachineInstr *oldInstr = &(*instrPos); 3028 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3029 MachineBasicBlock *blk = oldInstr->getParent(); 3030 MachineInstr *newInstr = 3031 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), 3032 DebugLoc()); 3033 3034 blk->insert(instrPos, newInstr); 3035 //assume the instruction doesn't take any reg operand ... 3036 3037 SHOWNEWINSTR(newInstr); 3038 return newInstr; 3039 } //insertInstrBefore 3040 3041 static void insertCondBranchBefore(MachineBasicBlock::iterator instrPos, 3042 int newOpcode, 3043 AMDILCFGStructurizer *passRep, 3044 DebugLoc DL) { 3045 MachineInstr *oldInstr = &(*instrPos); 3046 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3047 MachineBasicBlock *blk = oldInstr->getParent(); 3048 MachineInstr *newInstr = 3049 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), 3050 DL); 3051 3052 blk->insert(instrPos, newInstr); 3053 MachineInstrBuilder(newInstr).addReg(oldInstr->getOperand(1).getReg(), 3054 false); 3055 3056 SHOWNEWINSTR(newInstr); 3057 //erase later oldInstr->eraseFromParent(); 3058 } //insertCondBranchBefore 3059 3060 static void insertCondBranchBefore(MachineBasicBlock *blk, 3061 MachineBasicBlock::iterator insertPos, 3062 int newOpcode, 3063 AMDILCFGStructurizer *passRep, 3064 RegiT regNum, 3065 DebugLoc DL) { 3066 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3067 3068 MachineInstr *newInstr = 3069 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), DL); 3070 3071 //insert before 3072 blk->insert(insertPos, newInstr); 3073 MachineInstrBuilder(newInstr).addReg(regNum, false); 3074 3075 SHOWNEWINSTR(newInstr); 3076 } //insertCondBranchBefore 3077 3078 static void insertCondBranchEnd(MachineBasicBlock *blk, 3079 int newOpcode, 3080 AMDILCFGStructurizer *passRep, 3081 RegiT regNum) { 3082 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3083 MachineInstr *newInstr = 3084 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), DebugLoc()); 3085 3086 blk->push_back(newInstr); 3087 MachineInstrBuilder(newInstr).addReg(regNum, false); 3088 3089 SHOWNEWINSTR(newInstr); 3090 } //insertCondBranchEnd 3091 3092 3093 static void insertAssignInstrBefore(MachineBasicBlock::iterator instrPos, 3094 AMDILCFGStructurizer *passRep, 3095 RegiT regNum, int regVal) { 3096 MachineInstr *oldInstr = &(*instrPos); 3097 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3098 MachineBasicBlock *blk = oldInstr->getParent(); 3099 MachineInstr *newInstr = 3100 blk->getParent()->CreateMachineInstr(tii->get(AMDIL::LOADCONST_i32), 3101 DebugLoc()); 3102 MachineInstrBuilder(newInstr).addReg(regNum, RegState::Define); //set target 3103 MachineInstrBuilder(newInstr).addImm(regVal); //set src value 3104 3105 blk->insert(instrPos, newInstr); 3106 3107 SHOWNEWINSTR(newInstr); 3108 } //insertAssignInstrBefore 3109 3110 static void insertAssignInstrBefore(MachineBasicBlock *blk, 3111 AMDILCFGStructurizer *passRep, 3112 RegiT regNum, int regVal) { 3113 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3114 3115 MachineInstr *newInstr = 3116 blk->getParent()->CreateMachineInstr(tii->get(AMDIL::LOADCONST_i32), 3117 DebugLoc()); 3118 MachineInstrBuilder(newInstr).addReg(regNum, RegState::Define); //set target 3119 MachineInstrBuilder(newInstr).addImm(regVal); //set src value 3120 3121 if (blk->begin() != blk->end()) { 3122 blk->insert(blk->begin(), newInstr); 3123 } else { 3124 blk->push_back(newInstr); 3125 } 3126 3127 SHOWNEWINSTR(newInstr); 3128 3129 } //insertInstrBefore 3130 3131 static void insertCompareInstrBefore(MachineBasicBlock *blk, 3132 MachineBasicBlock::iterator instrPos, 3133 AMDILCFGStructurizer *passRep, 3134 RegiT dstReg, RegiT src1Reg, 3135 RegiT src2Reg) { 3136 const TargetInstrInfo *tii = passRep->getTargetInstrInfo(); 3137 MachineInstr *newInstr = 3138 blk->getParent()->CreateMachineInstr(tii->get(AMDIL::IEQ), DebugLoc()); 3139 3140 MachineInstrBuilder(newInstr).addReg(dstReg, RegState::Define); //set target 3141 MachineInstrBuilder(newInstr).addReg(src1Reg); //set src value 3142 MachineInstrBuilder(newInstr).addReg(src2Reg); //set src value 3143 3144 blk->insert(instrPos, newInstr); 3145 SHOWNEWINSTR(newInstr); 3146 3147 } //insertCompareInstrBefore 3148 3149 static void cloneSuccessorList(MachineBasicBlock *dstBlk, 3150 MachineBasicBlock *srcBlk) { 3151 for (MachineBasicBlock::succ_iterator iter = srcBlk->succ_begin(), 3152 iterEnd = srcBlk->succ_end(); iter != iterEnd; ++iter) { 3153 dstBlk->addSuccessor(*iter); // *iter's predecessor is also taken care of 3154 } 3155 } //cloneSuccessorList 3156 3157 static MachineBasicBlock *clone(MachineBasicBlock *srcBlk) { 3158 MachineFunction *func = srcBlk->getParent(); 3159 MachineBasicBlock *newBlk = func->CreateMachineBasicBlock(); 3160 func->push_back(newBlk); //insert to function 3161 //newBlk->setNumber(srcBlk->getNumber()); 3162 for (MachineBasicBlock::iterator iter = srcBlk->begin(), 3163 iterEnd = srcBlk->end(); 3164 iter != iterEnd; ++iter) { 3165 MachineInstr *instr = func->CloneMachineInstr(iter); 3166 // This is a workaround for LLVM bugzilla 8420 because CloneMachineInstr 3167 // does not clone the AsmPrinterFlags. 3168 instr->setAsmPrinterFlag( 3169 (llvm::MachineInstr::CommentFlag)iter->getAsmPrinterFlags()); 3170 newBlk->push_back(instr); 3171 } 3172 return newBlk; 3173 } 3174 3175 //MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose because 3176 //the AMDIL instruction is not recognized as terminator fix this and retire 3177 //this routine 3178 static void replaceInstrUseOfBlockWith(MachineBasicBlock *srcBlk, 3179 MachineBasicBlock *oldBlk, 3180 MachineBasicBlock *newBlk) { 3181 MachineInstr *branchInstr = getLoopendBlockBranchInstr(srcBlk); 3182 if (branchInstr && isCondBranch(branchInstr) && 3183 getExplicitBranch(branchInstr) == oldBlk) { 3184 setExplicitBranch(branchInstr, newBlk); 3185 } 3186 } 3187 3188 static void wrapup(MachineBasicBlock *entryBlk) { 3189 assert((!entryBlk->getParent()->getJumpTableInfo() 3190 || entryBlk->getParent()->getJumpTableInfo()->isEmpty()) 3191 && "found a jump table"); 3192 3193 //collect continue right before endloop 3194 SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> contInstr; 3195 MachineBasicBlock::iterator pre = entryBlk->begin(); 3196 MachineBasicBlock::iterator iterEnd = entryBlk->end(); 3197 MachineBasicBlock::iterator iter = pre; 3198 while (iter != iterEnd) { 3199 if (pre->getOpcode() == AMDIL::CONTINUE 3200 && iter->getOpcode() == AMDIL::ENDLOOP) { 3201 contInstr.push_back(pre); 3202 } 3203 pre = iter; 3204 ++iter; 3205 } //end while 3206 3207 //delete continue right before endloop 3208 for (unsigned i = 0; i < contInstr.size(); ++i) { 3209 contInstr[i]->eraseFromParent(); 3210 } 3211 3212 // TODO to fix up jump table so later phase won't be confused. if 3213 // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but 3214 // there isn't such an interface yet. alternatively, replace all the other 3215 // blocks in the jump table with the entryBlk //} 3216 3217 } //wrapup 3218 3219 static MachineDominatorTree *getDominatorTree(AMDILCFGStructurizer &pass) { 3220 return &pass.getAnalysis<MachineDominatorTree>(); 3221 } 3222 3223 static MachinePostDominatorTree* 3224 getPostDominatorTree(AMDILCFGStructurizer &pass) { 3225 return &pass.getAnalysis<MachinePostDominatorTree>(); 3226 } 3227 3228 static MachineLoopInfo *getLoopInfo(AMDILCFGStructurizer &pass) { 3229 return &pass.getAnalysis<MachineLoopInfo>(); 3230 } 3231}; // template class CFGStructTraits 3232} //end of namespace llvm 3233 3234// createAMDILCFGPreparationPass- Returns a pass 3235FunctionPass *llvm::createAMDILCFGPreparationPass(TargetMachine &tm 3236 AMDIL_OPT_LEVEL_DECL) { 3237 return new AMDILCFGPrepare(tm AMDIL_OPT_LEVEL_VAR); 3238} 3239 3240bool AMDILCFGPrepare::runOnMachineFunction(MachineFunction &func) { 3241 return llvmCFGStruct::CFGStructurizer<AMDILCFGStructurizer>().prepare(func, 3242 *this); 3243} 3244 3245// createAMDILCFGStructurizerPass- Returns a pass 3246FunctionPass *llvm::createAMDILCFGStructurizerPass(TargetMachine &tm 3247 AMDIL_OPT_LEVEL_DECL) { 3248 return new AMDILCFGPerform(tm AMDIL_OPT_LEVEL_VAR); 3249} 3250 3251bool AMDILCFGPerform::runOnMachineFunction(MachineFunction &func) { 3252 return llvmCFGStruct::CFGStructurizer<AMDILCFGStructurizer>().run(func, 3253 *this); 3254} 3255 3256//end of file newline goes below 3257 3258