LowerConstantIntrinsics.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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/Statistic.h"
  16. #include "llvm/Analysis/InstructionSimplify.h"
  17. #include "llvm/Analysis/MemoryBuiltins.h"
  18. #include "llvm/Analysis/TargetLibraryInfo.h"
  19. #include "llvm/IR/BasicBlock.h"
  20. #include "llvm/IR/Constants.h"
  21. #include "llvm/IR/Function.h"
  22. #include "llvm/IR/Instructions.h"
  23. #include "llvm/IR/IntrinsicInst.h"
  24. #include "llvm/IR/Intrinsics.h"
  25. #include "llvm/IR/PatternMatch.h"
  26. #include "llvm/Pass.h"
  27. #include "llvm/Support/Debug.h"
  28. #include "llvm/Transforms/Scalar.h"
  29. #include "llvm/Transforms/Utils/Local.h"
  30. using namespace llvm;
  31. using namespace llvm::PatternMatch;
  32. #define DEBUG_TYPE "lower-is-constant-intrinsic"
  33. STATISTIC(IsConstantIntrinsicsHandled,
  34. "Number of 'is.constant' intrinsic calls handled");
  35. STATISTIC(ObjectSizeIntrinsicsHandled,
  36. "Number of 'objectsize' intrinsic calls handled");
  37. static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) {
  38. Value *Op = II->getOperand(0);
  39. return isa<Constant>(Op) ? ConstantInt::getTrue(II->getType())
  40. : ConstantInt::getFalse(II->getType());
  41. }
  42. static bool replaceConditionalBranchesOnConstant(Instruction *II,
  43. Value *NewValue) {
  44. bool HasDeadBlocks = false;
  45. SmallSetVector<Instruction *, 8> Worklist;
  46. replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr,
  47. &Worklist);
  48. for (auto I : Worklist) {
  49. BranchInst *BI = dyn_cast<BranchInst>(I);
  50. if (!BI)
  51. continue;
  52. if (BI->isUnconditional())
  53. continue;
  54. BasicBlock *Target, *Other;
  55. if (match(BI->getOperand(0), m_Zero())) {
  56. Target = BI->getSuccessor(1);
  57. Other = BI->getSuccessor(0);
  58. } else if (match(BI->getOperand(0), m_One())) {
  59. Target = BI->getSuccessor(0);
  60. Other = BI->getSuccessor(1);
  61. } else {
  62. Target = nullptr;
  63. Other = nullptr;
  64. }
  65. if (Target && Target != Other) {
  66. BasicBlock *Source = BI->getParent();
  67. Other->removePredecessor(Source);
  68. BI->eraseFromParent();
  69. BranchInst::Create(Target, Source);
  70. if (pred_begin(Other) == pred_end(Other))
  71. HasDeadBlocks = true;
  72. }
  73. }
  74. return HasDeadBlocks;
  75. }
  76. static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo *TLI) {
  77. bool HasDeadBlocks = false;
  78. const auto &DL = F.getParent()->getDataLayout();
  79. SmallVector<WeakTrackingVH, 8> Worklist;
  80. ReversePostOrderTraversal<Function *> RPOT(&F);
  81. for (BasicBlock *BB : RPOT) {
  82. for (Instruction &I: *BB) {
  83. IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
  84. if (!II)
  85. continue;
  86. switch (II->getIntrinsicID()) {
  87. default:
  88. break;
  89. case Intrinsic::is_constant:
  90. case Intrinsic::objectsize:
  91. Worklist.push_back(WeakTrackingVH(&I));
  92. break;
  93. }
  94. }
  95. }
  96. for (WeakTrackingVH &VH: Worklist) {
  97. // Items on the worklist can be mutated by earlier recursive replaces.
  98. // This can remove the intrinsic as dead (VH == null), but also replace
  99. // the intrinsic in place.
  100. if (!VH)
  101. continue;
  102. IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*VH);
  103. if (!II)
  104. continue;
  105. Value *NewValue;
  106. switch (II->getIntrinsicID()) {
  107. default:
  108. continue;
  109. case Intrinsic::is_constant:
  110. NewValue = lowerIsConstantIntrinsic(II);
  111. IsConstantIntrinsicsHandled++;
  112. break;
  113. case Intrinsic::objectsize:
  114. NewValue = lowerObjectSizeCall(II, DL, TLI, true);
  115. ObjectSizeIntrinsicsHandled++;
  116. break;
  117. }
  118. HasDeadBlocks |= replaceConditionalBranchesOnConstant(II, NewValue);
  119. }
  120. if (HasDeadBlocks)
  121. removeUnreachableBlocks(F);
  122. return !Worklist.empty();
  123. }
  124. PreservedAnalyses
  125. LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) {
  126. if (lowerConstantIntrinsics(F, AM.getCachedResult<TargetLibraryAnalysis>(F)))
  127. return PreservedAnalyses::none();
  128. return PreservedAnalyses::all();
  129. }
  130. namespace {
  131. /// Legacy pass for lowering is.constant intrinsics out of the IR.
  132. ///
  133. /// When this pass is run over a function it converts is.constant intrinsics
  134. /// into 'true' or 'false'. This is completements the normal constand folding
  135. /// to 'true' as part of Instruction Simplify passes.
  136. class LowerConstantIntrinsics : public FunctionPass {
  137. public:
  138. static char ID;
  139. LowerConstantIntrinsics() : FunctionPass(ID) {
  140. initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry());
  141. }
  142. bool runOnFunction(Function &F) override {
  143. auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
  144. const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI(F) : nullptr;
  145. return lowerConstantIntrinsics(F, TLI);
  146. }
  147. };
  148. } // namespace
  149. char LowerConstantIntrinsics::ID = 0;
  150. INITIALIZE_PASS(LowerConstantIntrinsics, "lower-constant-intrinsics",
  151. "Lower constant intrinsics", false, false)
  152. FunctionPass *llvm::createLowerConstantIntrinsicsPass() {
  153. return new LowerConstantIntrinsics();
  154. }