ReduceBasicBlocks.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //===- ReduceBasicBlocks.cpp - Specialized Delta Pass ---------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements a function which calls the Generic Delta pass in order
  10. // to reduce uninteresting BasicBlocks from defined functions.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "ReduceBasicBlocks.h"
  14. #include "Utils.h"
  15. #include "llvm/ADT/DenseSet.h"
  16. #include "llvm/IR/BasicBlock.h"
  17. #include "llvm/IR/Constants.h"
  18. #include "llvm/IR/Instruction.h"
  19. #include "llvm/IR/Instructions.h"
  20. #include "llvm/IR/LLVMContext.h"
  21. #include "llvm/IR/Value.h"
  22. #include "llvm/Support/Casting.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. #include "llvm/Transforms/Utils/BasicBlockUtils.h"
  25. #include "llvm/Transforms/Utils/Local.h"
  26. #include <vector>
  27. #define DEBUG_TYPE "llvm-reduce"
  28. using namespace llvm;
  29. /// Replaces BB Terminator with one that only contains Chunk BBs
  30. static void replaceBranchTerminator(BasicBlock &BB,
  31. const DenseSet<BasicBlock *> &BBsToDelete) {
  32. auto *Term = BB.getTerminator();
  33. std::vector<BasicBlock *> ChunkSuccessors;
  34. for (auto *Succ : successors(&BB)) {
  35. if (!BBsToDelete.count(Succ))
  36. ChunkSuccessors.push_back(Succ);
  37. }
  38. // BB only references Chunk BBs
  39. if (ChunkSuccessors.size() == Term->getNumSuccessors())
  40. return;
  41. bool IsBranch = isa<BranchInst>(Term);
  42. if (InvokeInst *Invoke = dyn_cast<InvokeInst>(Term)) {
  43. LandingPadInst *LP = Invoke->getLandingPadInst();
  44. // Remove landingpad instruction if the containing block isn't used by other
  45. // invokes.
  46. if (none_of(LP->getParent()->users(), [Invoke](User *U) {
  47. return U != Invoke && isa<InvokeInst>(U);
  48. })) {
  49. LP->replaceAllUsesWith(getDefaultValue(LP->getType()));
  50. LP->eraseFromParent();
  51. } else if (!ChunkSuccessors.empty() &&
  52. ChunkSuccessors[0] == LP->getParent()) {
  53. // If the selected successor is the landing pad, clear the chunk
  54. // successors to avoid creating a regular branch to the landing pad which
  55. // would result in invalid IR.
  56. ChunkSuccessors.clear();
  57. }
  58. IsBranch = true;
  59. }
  60. Value *Address = nullptr;
  61. if (auto *IndBI = dyn_cast<IndirectBrInst>(Term))
  62. Address = IndBI->getAddress();
  63. Term->replaceAllUsesWith(getDefaultValue(Term->getType()));
  64. Term->eraseFromParent();
  65. if (ChunkSuccessors.empty()) {
  66. // If that fails then resort to replacing with a ret.
  67. auto *FnRetTy = BB.getParent()->getReturnType();
  68. ReturnInst::Create(BB.getContext(),
  69. FnRetTy->isVoidTy() ? nullptr : getDefaultValue(FnRetTy),
  70. &BB);
  71. return;
  72. }
  73. if (IsBranch)
  74. BranchInst::Create(ChunkSuccessors[0], &BB);
  75. if (Address) {
  76. auto *NewIndBI =
  77. IndirectBrInst::Create(Address, ChunkSuccessors.size(), &BB);
  78. for (auto *Dest : ChunkSuccessors)
  79. NewIndBI->addDestination(Dest);
  80. }
  81. }
  82. /// Removes uninteresting BBs from switch, if the default case ends up being
  83. /// uninteresting, the switch is replaced with a void return (since it has to be
  84. /// replace with something)
  85. static void
  86. removeUninterestingBBsFromSwitch(SwitchInst &SwInst,
  87. const DenseSet<BasicBlock *> &BBsToDelete) {
  88. for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
  89. auto Case = SwInst.case_begin() + I;
  90. if (BBsToDelete.count(Case->getCaseSuccessor())) {
  91. SwInst.removeCase(Case);
  92. --I;
  93. --E;
  94. }
  95. }
  96. if (BBsToDelete.count(SwInst.getDefaultDest())) {
  97. if (SwInst.getNumCases() == 0) {
  98. auto *FnRetTy = SwInst.getParent()->getParent()->getReturnType();
  99. Value *RetValue =
  100. FnRetTy->isVoidTy() ? nullptr : getDefaultValue(FnRetTy);
  101. ReturnInst::Create(SwInst.getContext(), RetValue, SwInst.getParent());
  102. SwInst.eraseFromParent();
  103. return;
  104. }
  105. // Replace the default dest with one of the other cases
  106. auto Case = SwInst.case_begin();
  107. BasicBlock *NewDefault = Case->getCaseSuccessor();
  108. SwInst.setDefaultDest(NewDefault);
  109. for (PHINode &SuccPHI : NewDefault->phis()) {
  110. SuccPHI.addIncoming(SuccPHI.getIncomingValueForBlock(SwInst.getParent()),
  111. SwInst.getParent());
  112. }
  113. }
  114. }
  115. /// Removes out-of-chunk arguments from functions, and modifies their calls
  116. /// accordingly. It also removes allocations of out-of-chunk arguments.
  117. static void extractBasicBlocksFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
  118. DenseSet<BasicBlock *> BBsToDelete;
  119. df_iterator_default_set<BasicBlock *> Reachable;
  120. for (auto &F : WorkItem.getModule()) {
  121. if (F.empty())
  122. continue;
  123. BasicBlock &Entry = F.getEntryBlock();
  124. for (auto *BB : depth_first_ext(&Entry, Reachable))
  125. (void)BB;
  126. // Skip any function with unreachable blocks. It's somewhat difficult to
  127. // avoid producing invalid IR without deleting them.
  128. //
  129. // We also do not want to unconditionally delete them, as doing so would
  130. // break the invariant of changing the number of chunks during counting.
  131. const bool HasUnreachableBlocks = Reachable.size() != F.size();
  132. Reachable.clear();
  133. if (HasUnreachableBlocks) {
  134. LLVM_DEBUG(dbgs() << "Skipping function with unreachable blocks\n");
  135. continue;
  136. }
  137. for (BasicBlock &BB : F) {
  138. if (&BB != &Entry && !O.shouldKeep())
  139. BBsToDelete.insert(&BB);
  140. }
  141. // Replace terminators that reference out-of-chunk BBs
  142. for (BasicBlock &BB : F) {
  143. if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator()))
  144. removeUninterestingBBsFromSwitch(*SwInst, BBsToDelete);
  145. else
  146. replaceBranchTerminator(BB, BBsToDelete);
  147. }
  148. // Cleanup any blocks that are now dead after eliminating this set. This
  149. // will likely be larger than the number of blocks the oracle told us to
  150. // delete.
  151. EliminateUnreachableBlocks(F);
  152. BBsToDelete.clear();
  153. }
  154. }
  155. void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
  156. runDeltaPass(Test, extractBasicBlocksFromModule, "Reducing Basic Blocks");
  157. }
  158. static void removeUnreachableBasicBlocksFromModule(Oracle &O,
  159. ReducerWorkItem &WorkItem) {
  160. std::vector<BasicBlock *> DeadBlocks;
  161. df_iterator_default_set<BasicBlock *> Reachable;
  162. for (Function &F : WorkItem.getModule()) {
  163. if (F.empty())
  164. continue;
  165. // Mark all reachable blocks.
  166. for (BasicBlock *BB : depth_first_ext(&F, Reachable))
  167. (void)BB;
  168. if (Reachable.size() != F.size() && !O.shouldKeep()) {
  169. for (BasicBlock &BB : F) {
  170. if (!Reachable.count(&BB))
  171. DeadBlocks.push_back(&BB);
  172. }
  173. // Delete the dead blocks.
  174. DeleteDeadBlocks(DeadBlocks, nullptr, /*KeepOneInputPHIs*/ false);
  175. DeadBlocks.clear();
  176. }
  177. Reachable.clear();
  178. }
  179. }
  180. void llvm::reduceUnreachableBasicBlocksDeltaPass(TestRunner &Test) {
  181. runDeltaPass(Test, removeUnreachableBasicBlocksFromModule,
  182. "Removing Unreachable Basic Blocks");
  183. }