DxilRemoveDeadBlocks.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 "dxc/DXIL/DxilUtil.h"
  21. #include <unordered_set>
  22. using namespace llvm;
  23. static void RemoveIncomingValueFrom(BasicBlock *SuccBB, BasicBlock *BB) {
  24. for (auto inst_it = SuccBB->begin(); inst_it != SuccBB->end();) {
  25. Instruction *I = &*(inst_it++);
  26. if (PHINode *PN = dyn_cast<PHINode>(I))
  27. PN->removeIncomingValue(BB, true);
  28. else
  29. break;
  30. }
  31. }
  32. static bool EraseDeadBlocks(Function &F, DxilValueCache *DVC) {
  33. std::unordered_set<BasicBlock *> Seen;
  34. std::vector<BasicBlock *> WorkList;
  35. bool Changed = false;
  36. auto Add = [&WorkList, &Seen](BasicBlock *BB) {
  37. if (!Seen.count(BB)) {
  38. WorkList.push_back(BB);
  39. Seen.insert(BB);
  40. }
  41. };
  42. Add(&F.getEntryBlock());
  43. // Go through blocks
  44. while (WorkList.size()) {
  45. BasicBlock *BB = WorkList.back();
  46. WorkList.pop_back();
  47. if (BranchInst *Br = dyn_cast<BranchInst>(BB->getTerminator())) {
  48. if (Br->isUnconditional()) {
  49. BasicBlock *Succ = Br->getSuccessor(0);
  50. Add(Succ);
  51. }
  52. else {
  53. if (ConstantInt *C = DVC->GetConstInt(Br->getCondition())) {
  54. bool IsTrue = C->getLimitedValue() != 0;
  55. BasicBlock *Succ = Br->getSuccessor(IsTrue ? 0 : 1);
  56. BasicBlock *NotSucc = Br->getSuccessor(!IsTrue ? 0 : 1);
  57. Add(Succ);
  58. // Rewrite conditional branch as unconditional branch if
  59. // we don't have structural information that needs it to
  60. // be alive.
  61. if (!Br->getMetadata(hlsl::DXIL::kDxBreakMDName)) {
  62. BranchInst *NewBr = BranchInst::Create(Succ, BB);
  63. hlsl::DxilMDHelper::CopyMetadata(*NewBr, *Br);
  64. RemoveIncomingValueFrom(NotSucc, BB);
  65. Br->eraseFromParent();
  66. Br = nullptr;
  67. Changed = true;
  68. }
  69. }
  70. else {
  71. Add(Br->getSuccessor(0));
  72. Add(Br->getSuccessor(1));
  73. }
  74. }
  75. }
  76. else if (SwitchInst *Switch = dyn_cast<SwitchInst>(BB->getTerminator())) {
  77. Value *Cond = Switch->getCondition();
  78. BasicBlock *Succ = nullptr;
  79. if (ConstantInt *ConstCond = DVC->GetConstInt(Cond)) {
  80. Succ = hlsl::dxilutil::GetSwitchSuccessorForCond(Switch, ConstCond);
  81. }
  82. if (Succ) {
  83. Add(Succ);
  84. BranchInst *NewBr = BranchInst::Create(Succ, BB);
  85. hlsl::DxilMDHelper::CopyMetadata(*NewBr, *Switch);
  86. for (unsigned i = 0; i < Switch->getNumSuccessors(); i++) {
  87. BasicBlock *NotSucc = Switch->getSuccessor(i);
  88. if (NotSucc != Succ) {
  89. RemoveIncomingValueFrom(NotSucc, BB);
  90. }
  91. }
  92. Switch->eraseFromParent();
  93. Switch = nullptr;
  94. Changed = true;
  95. }
  96. else {
  97. for (unsigned i = 0; i < Switch->getNumSuccessors(); i++) {
  98. Add(Switch->getSuccessor(i));
  99. }
  100. }
  101. }
  102. }
  103. if (Seen.size() == F.size())
  104. return Changed;
  105. std::vector<BasicBlock *> DeadBlocks;
  106. // Reconnect edges and everything
  107. for (auto it = F.begin(); it != F.end();) {
  108. BasicBlock *BB = &*(it++);
  109. if (Seen.count(BB))
  110. continue;
  111. DeadBlocks.push_back(BB);
  112. // Make predecessors branch somewhere else and fix the phi nodes
  113. for (auto pred_it = pred_begin(BB); pred_it != pred_end(BB);) {
  114. BasicBlock *PredBB = *(pred_it++);
  115. if (!Seen.count(PredBB)) // Don't bother fixing it if it's gonna get deleted anyway
  116. continue;
  117. TerminatorInst *TI = PredBB->getTerminator();
  118. if (!TI) continue;
  119. BranchInst *Br = dyn_cast<BranchInst>(TI);
  120. if (!Br || Br->isUnconditional()) continue;
  121. BasicBlock *Other = Br->getSuccessor(0) == BB ?
  122. Br->getSuccessor(1) : Br->getSuccessor(0);
  123. BranchInst *NewBr = BranchInst::Create(Other, Br);
  124. hlsl::DxilMDHelper::CopyMetadata(*NewBr, *Br);
  125. Br->eraseFromParent();
  126. }
  127. // Fix phi nodes in successors
  128. for (auto succ_it = succ_begin(BB); succ_it != succ_end(BB); succ_it++) {
  129. BasicBlock *SuccBB = *succ_it;
  130. if (!Seen.count(SuccBB)) continue; // Don't bother fixing it if it's gonna get deleted anyway
  131. RemoveIncomingValueFrom(SuccBB, BB);
  132. }
  133. // Erase all instructions in block
  134. while (BB->size()) {
  135. Instruction *I = &BB->back();
  136. if (!I->getType()->isVoidTy())
  137. I->replaceAllUsesWith(UndefValue::get(I->getType()));
  138. I->eraseFromParent();
  139. }
  140. }
  141. for (BasicBlock *BB : DeadBlocks) {
  142. BB->eraseFromParent();
  143. }
  144. DVC->ResetUnknowns();
  145. return true;
  146. }
  147. namespace {
  148. struct DxilRemoveDeadBlocks : public FunctionPass {
  149. static char ID;
  150. DxilRemoveDeadBlocks() : FunctionPass(ID) {
  151. initializeDxilRemoveDeadBlocksPass(*PassRegistry::getPassRegistry());
  152. }
  153. void getAnalysisUsage(AnalysisUsage &AU) const override {
  154. AU.addRequired<DxilValueCache>();
  155. }
  156. bool runOnFunction(Function &F) override {
  157. DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
  158. return EraseDeadBlocks(F, DVC);
  159. }
  160. };
  161. }
  162. char DxilRemoveDeadBlocks::ID;
  163. Pass *llvm::createDxilRemoveDeadBlocksPass() {
  164. return new DxilRemoveDeadBlocks();
  165. }
  166. INITIALIZE_PASS_BEGIN(DxilRemoveDeadBlocks, "dxil-remove-dead-blocks", "DXIL Remove Dead Blocks", false, false)
  167. INITIALIZE_PASS_DEPENDENCY(DxilValueCache)
  168. INITIALIZE_PASS_END(DxilRemoveDeadBlocks, "dxil-remove-dead-blocks", "DXIL Remove Dead Blocks", false, false)