1 //===- LowerConstantIntrinsics.cpp - Lower constant intrinsic calls -------===//
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
7 //===----------------------------------------------------------------------===//
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"
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
,
51 bool HasDeadBlocks
= false;
52 SmallSetVector
<Instruction
*, 8> Worklist
;
53 replaceAndRecursivelySimplify(II
, NewValue
, nullptr, nullptr, nullptr,
55 for (auto I
: Worklist
) {
56 BranchInst
*BI
= dyn_cast
<BranchInst
>(I
);
59 if (BI
->isUnconditional())
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);
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
))
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
);
96 switch (II
->getIntrinsicID()) {
99 case Intrinsic::is_constant
:
100 case Intrinsic::objectsize
:
101 Worklist
.push_back(WeakTrackingVH(&I
));
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.
112 IntrinsicInst
*II
= dyn_cast
<IntrinsicInst
>(&*VH
);
116 switch (II
->getIntrinsicID()) {
119 case Intrinsic::is_constant
:
120 NewValue
= lowerIsConstantIntrinsic(II
);
121 IsConstantIntrinsicsHandled
++;
123 case Intrinsic::objectsize
:
124 NewValue
= lowerObjectSizeCall(II
, DL
, TLI
, true);
125 ObjectSizeIntrinsicsHandled
++;
128 HasDeadBlocks
|= replaceConditionalBranchesOnConstant(II
, NewValue
);
131 removeUnreachableBlocks(F
);
132 return !Worklist
.empty();
136 LowerConstantIntrinsicsPass::run(Function
&F
, FunctionAnalysisManager
&AM
) {
137 if (lowerConstantIntrinsics(F
, AM
.getCachedResult
<TargetLibraryAnalysis
>(F
)))
138 return PreservedAnalyses::none();
140 return PreservedAnalyses::all();
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
{
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
);
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();