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/SetVector.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/Analysis/DomTreeUpdater.h"
19 #include "llvm/Analysis/GlobalsModRef.h"
20 #include "llvm/Analysis/InstructionSimplify.h"
21 #include "llvm/Analysis/MemoryBuiltins.h"
22 #include "llvm/Analysis/TargetLibraryInfo.h"
23 #include "llvm/IR/BasicBlock.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/Dominators.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/IntrinsicInst.h"
29 #include "llvm/IR/PatternMatch.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Transforms/Scalar.h"
33 #include "llvm/Transforms/Utils/Local.h"
37 using namespace llvm::PatternMatch
;
39 #define DEBUG_TYPE "lower-is-constant-intrinsic"
41 STATISTIC(IsConstantIntrinsicsHandled
,
42 "Number of 'is.constant' intrinsic calls handled");
43 STATISTIC(ObjectSizeIntrinsicsHandled
,
44 "Number of 'objectsize' intrinsic calls handled");
46 static Value
*lowerIsConstantIntrinsic(IntrinsicInst
*II
) {
47 if (auto *C
= dyn_cast
<Constant
>(II
->getOperand(0)))
48 if (C
->isManifestConstant())
49 return ConstantInt::getTrue(II
->getType());
50 return ConstantInt::getFalse(II
->getType());
53 static bool replaceConditionalBranchesOnConstant(Instruction
*II
,
55 DomTreeUpdater
*DTU
) {
56 bool HasDeadBlocks
= false;
57 SmallSetVector
<Instruction
*, 8> UnsimplifiedUsers
;
58 replaceAndRecursivelySimplify(II
, NewValue
, nullptr, nullptr, nullptr,
60 // UnsimplifiedUsers can contain PHI nodes that may be removed when
61 // replacing the branch instructions, so use a value handle worklist
62 // to handle those possibly removed instructions.
63 SmallVector
<WeakVH
, 8> Worklist(UnsimplifiedUsers
.begin(),
64 UnsimplifiedUsers
.end());
66 for (auto &VH
: Worklist
) {
67 BranchInst
*BI
= dyn_cast_or_null
<BranchInst
>(VH
);
70 if (BI
->isUnconditional())
73 BasicBlock
*Target
, *Other
;
74 if (match(BI
->getOperand(0), m_Zero())) {
75 Target
= BI
->getSuccessor(1);
76 Other
= BI
->getSuccessor(0);
77 } else if (match(BI
->getOperand(0), m_One())) {
78 Target
= BI
->getSuccessor(0);
79 Other
= BI
->getSuccessor(1);
84 if (Target
&& Target
!= Other
) {
85 BasicBlock
*Source
= BI
->getParent();
86 Other
->removePredecessor(Source
);
88 Instruction
*NewBI
= BranchInst::Create(Target
, Source
);
89 NewBI
->setDebugLoc(BI
->getDebugLoc());
90 BI
->eraseFromParent();
93 DTU
->applyUpdates({{DominatorTree::Delete
, Source
, Other
}});
94 if (pred_empty(Other
))
101 bool llvm::lowerConstantIntrinsics(Function
&F
, const TargetLibraryInfo
&TLI
,
103 std::optional
<DomTreeUpdater
> DTU
;
105 DTU
.emplace(DT
, DomTreeUpdater::UpdateStrategy::Lazy
);
107 bool HasDeadBlocks
= false;
108 const auto &DL
= F
.getDataLayout();
109 SmallVector
<WeakTrackingVH
, 8> Worklist
;
111 ReversePostOrderTraversal
<Function
*> RPOT(&F
);
112 for (BasicBlock
*BB
: RPOT
) {
113 for (Instruction
&I
: *BB
) {
114 IntrinsicInst
*II
= dyn_cast
<IntrinsicInst
>(&I
);
117 switch (II
->getIntrinsicID()) {
120 case Intrinsic::is_constant
:
121 case Intrinsic::objectsize
:
122 Worklist
.push_back(WeakTrackingVH(&I
));
127 for (WeakTrackingVH
&VH
: Worklist
) {
128 // Items on the worklist can be mutated by earlier recursive replaces.
129 // This can remove the intrinsic as dead (VH == null), but also replace
130 // the intrinsic in place.
133 IntrinsicInst
*II
= dyn_cast
<IntrinsicInst
>(&*VH
);
137 switch (II
->getIntrinsicID()) {
140 case Intrinsic::is_constant
:
141 NewValue
= lowerIsConstantIntrinsic(II
);
142 LLVM_DEBUG(dbgs() << "Folding " << *II
<< " to " << *NewValue
<< "\n");
143 IsConstantIntrinsicsHandled
++;
145 case Intrinsic::objectsize
:
146 NewValue
= lowerObjectSizeCall(II
, DL
, &TLI
, true);
147 LLVM_DEBUG(dbgs() << "Folding " << *II
<< " to " << *NewValue
<< "\n");
148 ObjectSizeIntrinsicsHandled
++;
151 HasDeadBlocks
|= replaceConditionalBranchesOnConstant(
152 II
, NewValue
, DTU
? &*DTU
: nullptr);
155 removeUnreachableBlocks(F
, DTU
? &*DTU
: nullptr);
156 return !Worklist
.empty();
160 LowerConstantIntrinsicsPass::run(Function
&F
, FunctionAnalysisManager
&AM
) {
161 if (lowerConstantIntrinsics(F
, AM
.getResult
<TargetLibraryAnalysis
>(F
),
162 AM
.getCachedResult
<DominatorTreeAnalysis
>(F
))) {
163 PreservedAnalyses PA
;
164 PA
.preserve
<DominatorTreeAnalysis
>();
168 return PreservedAnalyses::all();