LowerConstantIntrinsics.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //===- LowerConstantIntrinsics.cpp - Lower constant intrinsic calls -------===//
  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 pass lowers all remaining 'objectsize' 'is.constant' intrinsic calls
  10. // and provides constant propagation and basic CFG cleanup on the result.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
  14. #include "llvm/ADT/PostOrderIterator.h"
  15. #include "llvm/ADT/SetVector.h"
  16. #include "llvm/ADT/Statistic.h"
  17. #include "llvm/Analysis/DomTreeUpdater.h"
  18. #include "llvm/Analysis/GlobalsModRef.h"
  19. #include "llvm/Analysis/InstructionSimplify.h"
  20. #include "llvm/Analysis/MemoryBuiltins.h"
  21. #include "llvm/Analysis/TargetLibraryInfo.h"
  22. #include "llvm/IR/BasicBlock.h"
  23. #include "llvm/IR/Constants.h"
  24. #include "llvm/IR/Dominators.h"
  25. #include "llvm/IR/Function.h"
  26. #include "llvm/IR/Instructions.h"
  27. #include "llvm/IR/IntrinsicInst.h"
  28. #include "llvm/IR/Intrinsics.h"
  29. #include "llvm/IR/PatternMatch.h"
  30. #include "llvm/InitializePasses.h"
  31. #include "llvm/Pass.h"
  32. #include "llvm/Support/Debug.h"
  33. #include "llvm/Transforms/Scalar.h"
  34. #include "llvm/Transforms/Utils/Local.h"
  35. using namespace llvm;
  36. using namespace llvm::PatternMatch;
  37. #define DEBUG_TYPE "lower-is-constant-intrinsic"
  38. STATISTIC(IsConstantIntrinsicsHandled,
  39. "Number of 'is.constant' intrinsic calls handled");
  40. STATISTIC(ObjectSizeIntrinsicsHandled,
  41. "Number of 'objectsize' intrinsic calls handled");
  42. static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {
  43. if (auto *C = dyn_cast<Constant>(II->getOperand(0)))
  44. if (C->isManifestConstant())
  45. return ConstantInt::getTrue(II->getType());
  46. return ConstantInt::getFalse(II->getType());
  47. }
  48. static bool replaceConditionalBranchesOnConstant(Instruction *II,
  49. Value *NewValue,
  50. DomTreeUpdater *DTU) {
  51. bool HasDeadBlocks = false;
  52. SmallSetVector<Instruction *, 8> UnsimplifiedUsers;
  53. replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr,
  54. &UnsimplifiedUsers);
  55. // UnsimplifiedUsers can contain PHI nodes that may be removed when
  56. // replacing the branch instructions, so use a value handle worklist
  57. // to handle those possibly removed instructions.
  58. SmallVector<WeakVH, 8> Worklist(UnsimplifiedUsers.begin(),
  59. UnsimplifiedUsers.end());
  60. for (auto &VH : Worklist) {
  61. BranchInst *BI = dyn_cast_or_null<BranchInst>(VH);
  62. if (!BI)
  63. continue;
  64. if (BI->isUnconditional())
  65. continue;
  66. BasicBlock *Target, *Other;
  67. if (match(BI->getOperand(0), m_Zero())) {
  68. Target = BI->getSuccessor(1);
  69. Other = BI->getSuccessor(0);
  70. } else if (match(BI->getOperand(0), m_One())) {
  71. Target = BI->getSuccessor(0);
  72. Other = BI->getSuccessor(1);
  73. } else {
  74. Target = nullptr;
  75. Other = nullptr;
  76. }
  77. if (Target && Target != Other) {
  78. BasicBlock *Source = BI->getParent();
  79. Other->removePredecessor(Source);
  80. BI->eraseFromParent();
  81. BranchInst::Create(Target, Source);
  82. if (DTU)
  83. DTU->applyUpdates({{DominatorTree::Delete, Source, Other}});
  84. if (pred_empty(Other))
  85. HasDeadBlocks = true;
  86. }
  87. }
  88. return HasDeadBlocks;
  89. }
  90. static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo *TLI,
  91. DominatorTree *DT) {
  92. Optional<DomTreeUpdater> DTU;
  93. if (DT)
  94. DTU.emplace(DT, DomTreeUpdater::UpdateStrategy::Lazy);
  95. bool HasDeadBlocks = false;
  96. const auto &DL = F.getParent()->getDataLayout();
  97. SmallVector<WeakTrackingVH, 8> Worklist;
  98. ReversePostOrderTraversal<Function *> RPOT(&F);
  99. for (BasicBlock *BB : RPOT) {
  100. for (Instruction &I: *BB) {
  101. IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
  102. if (!II)
  103. continue;
  104. switch (II->getIntrinsicID()) {
  105. default:
  106. break;
  107. case Intrinsic::is_constant:
  108. case Intrinsic::objectsize:
  109. Worklist.push_back(WeakTrackingVH(&I));
  110. break;
  111. }
  112. }
  113. }
  114. for (WeakTrackingVH &VH: Worklist) {
  115. // Items on the worklist can be mutated by earlier recursive replaces.
  116. // This can remove the intrinsic as dead (VH == null), but also replace
  117. // the intrinsic in place.
  118. if (!VH)
  119. continue;
  120. IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*VH);
  121. if (!II)
  122. continue;
  123. Value *NewValue;
  124. switch (II->getIntrinsicID()) {
  125. default:
  126. continue;
  127. case Intrinsic::is_constant:
  128. NewValue = lowerIsConstantIntrinsic(II);
  129. IsConstantIntrinsicsHandled++;
  130. break;
  131. case Intrinsic::objectsize:
  132. NewValue = lowerObjectSizeCall(II, DL, TLI, true);
  133. ObjectSizeIntrinsicsHandled++;
  134. break;
  135. }
  136. HasDeadBlocks |= replaceConditionalBranchesOnConstant(
  137. II, NewValue, DTU.hasValue() ? DTU.getPointer() : nullptr);
  138. }
  139. if (HasDeadBlocks)
  140. removeUnreachableBlocks(F, DTU.hasValue() ? DTU.getPointer() : nullptr);
  141. return !Worklist.empty();
  142. }
  143. PreservedAnalyses
  144. LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) {
  145. if (lowerConstantIntrinsics(F, AM.getCachedResult<TargetLibraryAnalysis>(F),
  146. AM.getCachedResult<DominatorTreeAnalysis>(F))) {
  147. PreservedAnalyses PA;
  148. PA.preserve<DominatorTreeAnalysis>();
  149. return PA;
  150. }
  151. return PreservedAnalyses::all();
  152. }
  153. namespace {
  154. /// Legacy pass for lowering is.constant intrinsics out of the IR.
  155. ///
  156. /// When this pass is run over a function it converts is.constant intrinsics
  157. /// into 'true' or 'false'. This complements the normal constant folding
  158. /// to 'true' as part of Instruction Simplify passes.
  159. class LowerConstantIntrinsics : public FunctionPass {
  160. public:
  161. static char ID;
  162. LowerConstantIntrinsics() : FunctionPass(ID) {
  163. initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry());
  164. }
  165. bool runOnFunction(Function &F) override {
  166. auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
  167. const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI(F) : nullptr;
  168. DominatorTree *DT = nullptr;
  169. if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
  170. DT = &DTWP->getDomTree();
  171. return lowerConstantIntrinsics(F, TLI, DT);
  172. }
  173. void getAnalysisUsage(AnalysisUsage &AU) const override {
  174. AU.addPreserved<GlobalsAAWrapperPass>();
  175. AU.addPreserved<DominatorTreeWrapperPass>();
  176. }
  177. };
  178. } // namespace
  179. char LowerConstantIntrinsics::ID = 0;
  180. INITIALIZE_PASS_BEGIN(LowerConstantIntrinsics, "lower-constant-intrinsics",
  181. "Lower constant intrinsics", false, false)
  182. INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
  183. INITIALIZE_PASS_END(LowerConstantIntrinsics, "lower-constant-intrinsics",
  184. "Lower constant intrinsics", false, false)
  185. FunctionPass *llvm::createLowerConstantIntrinsicsPass() {
  186. return new LowerConstantIntrinsics();
  187. }