LowerConstantIntrinsics.cpp 7.0 KB

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