1 | //===- JumpThreading.h - thread control through conditional BBs -*- C++ -*-===// |
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 | /// \file |
10 | /// See the comments on JumpThreadingPass. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H |
15 | #define LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H |
16 | |
17 | #include "llvm/ADT/ArrayRef.h" |
18 | #include "llvm/ADT/DenseSet.h" |
19 | #include "llvm/ADT/SmallSet.h" |
20 | #include "llvm/ADT/SmallVector.h" |
21 | #include "llvm/Analysis/BlockFrequencyInfo.h" |
22 | #include "llvm/Analysis/BranchProbabilityInfo.h" |
23 | #include "llvm/Analysis/DomTreeUpdater.h" |
24 | #include "llvm/IR/ValueHandle.h" |
25 | #include "llvm/Transforms/Utils/ValueMapper.h" |
26 | #include <optional> |
27 | #include <utility> |
28 | |
29 | namespace llvm { |
30 | |
31 | class AAResults; |
32 | class BasicBlock; |
33 | class BinaryOperator; |
34 | class BranchInst; |
35 | class CmpInst; |
36 | class Constant; |
37 | class Function; |
38 | class Instruction; |
39 | class IntrinsicInst; |
40 | class LazyValueInfo; |
41 | class LoadInst; |
42 | class PHINode; |
43 | class SelectInst; |
44 | class SwitchInst; |
45 | class TargetLibraryInfo; |
46 | class TargetTransformInfo; |
47 | class Value; |
48 | |
49 | /// A private "module" namespace for types and utilities used by |
50 | /// JumpThreading. |
51 | /// These are implementation details and should not be used by clients. |
52 | namespace jumpthreading { |
53 | |
54 | // These are at global scope so static functions can use them too. |
55 | using PredValueInfo = SmallVectorImpl<std::pair<Constant *, BasicBlock *>>; |
56 | using PredValueInfoTy = SmallVector<std::pair<Constant *, BasicBlock *>, 8>; |
57 | |
58 | // This is used to keep track of what kind of constant we're currently hoping |
59 | // to find. |
60 | enum ConstantPreference { WantInteger, WantBlockAddress }; |
61 | |
62 | } // end namespace jumpthreading |
63 | |
64 | /// This pass performs 'jump threading', which looks at blocks that have |
65 | /// multiple predecessors and multiple successors. If one or more of the |
66 | /// predecessors of the block can be proven to always jump to one of the |
67 | /// successors, we forward the edge from the predecessor to the successor by |
68 | /// duplicating the contents of this block. |
69 | /// |
70 | /// An example of when this can occur is code like this: |
71 | /// |
72 | /// if () { ... |
73 | /// X = 4; |
74 | /// } |
75 | /// if (X < 3) { |
76 | /// |
77 | /// In this case, the unconditional branch at the end of the first if can be |
78 | /// revectored to the false side of the second if. |
79 | class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> { |
80 | Function *F = nullptr; |
81 | FunctionAnalysisManager *FAM = nullptr; |
82 | TargetLibraryInfo *TLI = nullptr; |
83 | TargetTransformInfo *TTI = nullptr; |
84 | LazyValueInfo *LVI = nullptr; |
85 | AAResults *AA = nullptr; |
86 | std::unique_ptr<DomTreeUpdater> DTU; |
87 | std::optional<BlockFrequencyInfo *> BFI; |
88 | std::optional<BranchProbabilityInfo *> BPI; |
89 | bool ChangedSinceLastAnalysisUpdate = false; |
90 | bool HasGuards = false; |
91 | #ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS |
92 | SmallPtrSet<const BasicBlock *, 16> LoopHeaders; |
93 | #else |
94 | SmallSet<AssertingVH<const BasicBlock>, 16> ; |
95 | #endif |
96 | |
97 | unsigned BBDupThreshold; |
98 | unsigned DefaultBBDupThreshold; |
99 | |
100 | public: |
101 | JumpThreadingPass(int T = -1); |
102 | |
103 | // Glue for old PM. |
104 | bool runImpl(Function &F, FunctionAnalysisManager *FAM, |
105 | TargetLibraryInfo *TLI, TargetTransformInfo *TTI, |
106 | LazyValueInfo *LVI, AAResults *AA, |
107 | std::unique_ptr<DomTreeUpdater> DTU, |
108 | std::optional<BlockFrequencyInfo *> BFI, |
109 | std::optional<BranchProbabilityInfo *> BPI); |
110 | |
111 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
112 | |
113 | DomTreeUpdater *getDomTreeUpdater() const { return DTU.get(); } |
114 | void (Function &F); |
115 | bool processBlock(BasicBlock *BB); |
116 | bool maybeMergeBasicBlockIntoOnlyPred(BasicBlock *BB); |
117 | void updateSSA(BasicBlock *BB, BasicBlock *NewBB, |
118 | ValueToValueMapTy &ValueMapping); |
119 | void cloneInstructions(ValueToValueMapTy &ValueMapping, |
120 | BasicBlock::iterator BI, BasicBlock::iterator BE, |
121 | BasicBlock *NewBB, BasicBlock *PredBB); |
122 | bool tryThreadEdge(BasicBlock *BB, |
123 | const SmallVectorImpl<BasicBlock *> &PredBBs, |
124 | BasicBlock *SuccBB); |
125 | void threadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs, |
126 | BasicBlock *SuccBB); |
127 | bool duplicateCondBranchOnPHIIntoPred( |
128 | BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs); |
129 | |
130 | bool computeValueKnownInPredecessorsImpl( |
131 | Value *V, BasicBlock *BB, jumpthreading::PredValueInfo &Result, |
132 | jumpthreading::ConstantPreference Preference, |
133 | SmallPtrSet<Value *, 4> &RecursionSet, Instruction *CxtI = nullptr); |
134 | bool |
135 | computeValueKnownInPredecessors(Value *V, BasicBlock *BB, |
136 | jumpthreading::PredValueInfo &Result, |
137 | jumpthreading::ConstantPreference Preference, |
138 | Instruction *CxtI = nullptr) { |
139 | SmallPtrSet<Value *, 4> RecursionSet; |
140 | return computeValueKnownInPredecessorsImpl(V, BB, Result, Preference, |
141 | RecursionSet, CxtI); |
142 | } |
143 | |
144 | Constant *evaluateOnPredecessorEdge(BasicBlock *BB, BasicBlock *PredPredBB, |
145 | Value *cond, const DataLayout &DL); |
146 | bool maybethreadThroughTwoBasicBlocks(BasicBlock *BB, Value *Cond); |
147 | void threadThroughTwoBasicBlocks(BasicBlock *PredPredBB, BasicBlock *PredBB, |
148 | BasicBlock *BB, BasicBlock *SuccBB); |
149 | bool processThreadableEdges(Value *Cond, BasicBlock *BB, |
150 | jumpthreading::ConstantPreference Preference, |
151 | Instruction *CxtI = nullptr); |
152 | |
153 | bool processBranchOnPHI(PHINode *PN); |
154 | bool processBranchOnXOR(BinaryOperator *BO); |
155 | bool processImpliedCondition(BasicBlock *BB); |
156 | |
157 | bool simplifyPartiallyRedundantLoad(LoadInst *LI); |
158 | void unfoldSelectInstr(BasicBlock *Pred, BasicBlock *BB, SelectInst *SI, |
159 | PHINode *SIUse, unsigned Idx); |
160 | |
161 | bool tryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB); |
162 | bool tryToUnfoldSelect(SwitchInst *SI, BasicBlock *BB); |
163 | bool tryToUnfoldSelectInCurrBB(BasicBlock *BB); |
164 | |
165 | bool processGuards(BasicBlock *BB); |
166 | bool threadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI); |
167 | |
168 | private: |
169 | BasicBlock *splitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds, |
170 | const char *Suffix); |
171 | void updateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BasicBlock *BB, |
172 | BasicBlock *NewBB, BasicBlock *SuccBB, |
173 | BlockFrequencyInfo *BFI, |
174 | BranchProbabilityInfo *BPI, |
175 | bool HasProfile); |
176 | /// Check if the block has profile metadata for its outgoing edges. |
177 | bool doesBlockHaveProfileData(BasicBlock *BB); |
178 | |
179 | /// Returns analysis preserved by the pass. |
180 | PreservedAnalyses getPreservedAnalysis() const; |
181 | |
182 | /// Helper function to run "external" analysis in the middle of JumpThreading. |
183 | /// It takes care of updating/invalidating other existing analysis |
184 | /// before/after running the "external" one. |
185 | template <typename AnalysisT> |
186 | typename AnalysisT::Result *runExternalAnalysis(); |
187 | |
188 | /// Returns an existing instance of BPI if any, otherwise nullptr. By |
189 | /// "existing" we mean either cached result provided by FunctionAnalysisManger |
190 | /// or created by preceding call to 'getOrCreateBPI'. |
191 | BranchProbabilityInfo *getBPI(); |
192 | |
193 | /// Returns an existing instance of BFI if any, otherwise nullptr. By |
194 | /// "existing" we mean either cached result provided by FunctionAnalysisManger |
195 | /// or created by preceding call to 'getOrCreateBFI'. |
196 | BlockFrequencyInfo *getBFI(); |
197 | |
198 | /// Returns an existing instance of BPI if any, otherwise: |
199 | /// if 'HasProfile' is true creates new instance through |
200 | /// FunctionAnalysisManager, otherwise nullptr. |
201 | BranchProbabilityInfo *getOrCreateBPI(bool Force = false); |
202 | |
203 | /// Returns an existing instance of BFI if any, otherwise: |
204 | /// if 'HasProfile' is true creates new instance through |
205 | /// FunctionAnalysisManager, otherwise nullptr. |
206 | BlockFrequencyInfo *getOrCreateBFI(bool Force = false); |
207 | }; |
208 | |
209 | } // end namespace llvm |
210 | |
211 | #endif // LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H |
212 | |