DxilRemoveDeadBlocks.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilRemoveDeadBlocks.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Pass to use value tracker to remove dead blocks. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "llvm/Pass.h"
  12. #include "llvm/IR/Function.h"
  13. #include "llvm/IR/Instruction.h"
  14. #include "llvm/IR/Instructions.h"
  15. #include "llvm/IR/Constants.h"
  16. #include "llvm/IR/CFG.h"
  17. #include "llvm/Transforms/Scalar.h"
  18. #include "llvm/Analysis/DxilValueCache.h"
  19. #include "dxc/DXIL/DxilMetadataHelper.h"
  20. #include <unordered_set>
  21. using namespace llvm;
  22. static bool EraseDeadBlocks(Function &F, DxilValueCache *DVC) {
  23. std::unordered_set<BasicBlock *> Seen;
  24. std::vector<BasicBlock *> WorkList;
  25. auto Add = [&WorkList, &Seen](BasicBlock *BB) {
  26. if (!Seen.count(BB)) {
  27. WorkList.push_back(BB);
  28. Seen.insert(BB);
  29. }
  30. };
  31. Add(&F.getEntryBlock());
  32. // Go through blocks
  33. while (WorkList.size()) {
  34. BasicBlock *BB = WorkList.back();
  35. WorkList.pop_back();
  36. if (BranchInst *Br = dyn_cast<BranchInst>(BB->getTerminator())) {
  37. if (Br->isUnconditional()) {
  38. BasicBlock *Succ = Br->getSuccessor(0);
  39. Add(Succ);
  40. }
  41. else {
  42. bool IsConstant = false;
  43. if (Value *V = DVC->GetValue(Br->getCondition())) {
  44. if (ConstantInt *C = dyn_cast<ConstantInt>(V)) {
  45. bool IsTrue = C->getLimitedValue() != 0;
  46. BasicBlock *Succ = IsTrue ?
  47. Br->getSuccessor(0) : Br->getSuccessor(1);
  48. Add(Succ);
  49. IsConstant = true;
  50. }
  51. }
  52. if (!IsConstant) {
  53. Add(Br->getSuccessor(0));
  54. Add(Br->getSuccessor(1));
  55. }
  56. }
  57. }
  58. else if (SwitchInst *Switch = dyn_cast<SwitchInst>(BB->getTerminator())) {
  59. for (unsigned i = 0; i < Switch->getNumSuccessors(); i++) {
  60. Add(Switch->getSuccessor(i));
  61. }
  62. }
  63. }
  64. if (Seen.size() == F.size())
  65. return false;
  66. std::vector<BasicBlock *> DeadBlocks;
  67. // Reconnect edges and everything
  68. for (auto it = F.begin(); it != F.end();) {
  69. BasicBlock *BB = &*(it++);
  70. if (Seen.count(BB))
  71. continue;
  72. DeadBlocks.push_back(BB);
  73. // Make predecessors branch somewhere else and fix the phi nodes
  74. for (auto pred_it = pred_begin(BB); pred_it != pred_end(BB);) {
  75. BasicBlock *PredBB = *(pred_it++);
  76. if (!Seen.count(PredBB))
  77. continue;
  78. TerminatorInst *TI = PredBB->getTerminator();
  79. if (!TI) continue;
  80. BranchInst *Br = dyn_cast<BranchInst>(TI);
  81. if (!Br || Br->isUnconditional()) continue;
  82. BasicBlock *Other = Br->getSuccessor(0) == BB ?
  83. Br->getSuccessor(1) : Br->getSuccessor(0);
  84. BranchInst *NewBr = BranchInst::Create(Other, Br);
  85. hlsl::DxilMDHelper::CopyMetadata(*NewBr, *Br);
  86. Br->eraseFromParent();
  87. }
  88. // Fix phi nodes in successors
  89. for (auto succ_it = succ_begin(BB); succ_it != succ_end(BB); succ_it++) {
  90. BasicBlock *SuccBB = *succ_it;
  91. if (!Seen.count(SuccBB)) continue;
  92. for (auto inst_it = SuccBB->begin(); inst_it != SuccBB->end();) {
  93. Instruction *I = &*(inst_it++);
  94. if (PHINode *PN = dyn_cast<PHINode>(I))
  95. PN->removeIncomingValue(BB, true);
  96. else
  97. break;
  98. }
  99. }
  100. // Erase all instructions in block
  101. while (BB->size()) {
  102. Instruction *I = &BB->back();
  103. if (!I->getType()->isVoidTy())
  104. I->replaceAllUsesWith(UndefValue::get(I->getType()));
  105. I->eraseFromParent();
  106. }
  107. }
  108. for (BasicBlock *BB : DeadBlocks) {
  109. BB->eraseFromParent();
  110. }
  111. return true;
  112. }
  113. namespace {
  114. struct DxilRemoveDeadBlocks : public FunctionPass {
  115. static char ID;
  116. DxilRemoveDeadBlocks() : FunctionPass(ID) {
  117. initializeDxilRemoveDeadBlocksPass(*PassRegistry::getPassRegistry());
  118. }
  119. void getAnalysisUsage(AnalysisUsage &AU) const override {
  120. AU.addRequired<DxilValueCache>();
  121. }
  122. bool runOnFunction(Function &F) override {
  123. DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
  124. return EraseDeadBlocks(F, DVC);
  125. }
  126. };
  127. }
  128. char DxilRemoveDeadBlocks::ID;
  129. Pass *llvm::createDxilRemoveDeadBlocksPass() {
  130. return new DxilRemoveDeadBlocks();
  131. }
  132. INITIALIZE_PASS_BEGIN(DxilRemoveDeadBlocks, "dxil-remove-dead-blocks", "DXIL Remove Dead Blocks", false, false)
  133. INITIALIZE_PASS_DEPENDENCY(DxilValueCache)
  134. INITIALIZE_PASS_END(DxilRemoveDeadBlocks, "dxil-remove-dead-blocks", "DXIL Remove Dead Blocks", false, false)