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