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