File indexing completed on 2026-05-10 08:44:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_TRANSFORMS_SCALAR_GVN_H
0016 #define LLVM_TRANSFORMS_SCALAR_GVN_H
0017
0018 #include "llvm/ADT/DenseMap.h"
0019 #include "llvm/ADT/MapVector.h"
0020 #include "llvm/ADT/SetVector.h"
0021 #include "llvm/ADT/SmallVector.h"
0022 #include "llvm/IR/Dominators.h"
0023 #include "llvm/IR/InstrTypes.h"
0024 #include "llvm/IR/PassManager.h"
0025 #include "llvm/IR/ValueHandle.h"
0026 #include "llvm/Support/Allocator.h"
0027 #include "llvm/Support/Compiler.h"
0028 #include <cstdint>
0029 #include <optional>
0030 #include <utility>
0031 #include <vector>
0032
0033 namespace llvm {
0034
0035 class AAResults;
0036 class AssumeInst;
0037 class AssumptionCache;
0038 class BasicBlock;
0039 class BranchInst;
0040 class CallInst;
0041 class ExtractValueInst;
0042 class Function;
0043 class FunctionPass;
0044 class GetElementPtrInst;
0045 class ImplicitControlFlowTracking;
0046 class LoadInst;
0047 class LoopInfo;
0048 class MemDepResult;
0049 class MemoryDependenceResults;
0050 class MemorySSA;
0051 class MemorySSAUpdater;
0052 class NonLocalDepResult;
0053 class OptimizationRemarkEmitter;
0054 class PHINode;
0055 class TargetLibraryInfo;
0056 class Value;
0057
0058
0059 namespace LLVM_LIBRARY_VISIBILITY_NAMESPACE gvn {
0060
0061 struct AvailableValue;
0062 struct AvailableValueInBlock;
0063 class GVNLegacyPass;
0064
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074 struct GVNOptions {
0075 std::optional<bool> AllowPRE;
0076 std::optional<bool> AllowLoadPRE;
0077 std::optional<bool> AllowLoadInLoopPRE;
0078 std::optional<bool> AllowLoadPRESplitBackedge;
0079 std::optional<bool> AllowMemDep;
0080 std::optional<bool> AllowMemorySSA;
0081
0082 GVNOptions() = default;
0083
0084
0085 GVNOptions &setPRE(bool PRE) {
0086 AllowPRE = PRE;
0087 return *this;
0088 }
0089
0090
0091 GVNOptions &setLoadPRE(bool LoadPRE) {
0092 AllowLoadPRE = LoadPRE;
0093 return *this;
0094 }
0095
0096 GVNOptions &setLoadInLoopPRE(bool LoadInLoopPRE) {
0097 AllowLoadInLoopPRE = LoadInLoopPRE;
0098 return *this;
0099 }
0100
0101
0102 GVNOptions &setLoadPRESplitBackedge(bool LoadPRESplitBackedge) {
0103 AllowLoadPRESplitBackedge = LoadPRESplitBackedge;
0104 return *this;
0105 }
0106
0107
0108 GVNOptions &setMemDep(bool MemDep) {
0109 AllowMemDep = MemDep;
0110 return *this;
0111 }
0112
0113
0114 GVNOptions &setMemorySSA(bool MemSSA) {
0115 AllowMemorySSA = MemSSA;
0116 return *this;
0117 }
0118 };
0119
0120
0121
0122
0123
0124 class GVNPass : public PassInfoMixin<GVNPass> {
0125 GVNOptions Options;
0126
0127 public:
0128 struct Expression;
0129
0130 GVNPass(GVNOptions Options = {}) : Options(Options) {}
0131
0132
0133 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0134
0135 void printPipeline(raw_ostream &OS,
0136 function_ref<StringRef(StringRef)> MapClassName2PassName);
0137
0138
0139
0140 void markInstructionForDeletion(Instruction *I) {
0141 VN.erase(I);
0142 InstrsToErase.push_back(I);
0143 }
0144
0145 DominatorTree &getDominatorTree() const { return *DT; }
0146 AAResults *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
0147 MemoryDependenceResults &getMemDep() const { return *MD; }
0148
0149 bool isPREEnabled() const;
0150 bool isLoadPREEnabled() const;
0151 bool isLoadInLoopPREEnabled() const;
0152 bool isLoadPRESplitBackedgeEnabled() const;
0153 bool isMemDepEnabled() const;
0154 bool isMemorySSAEnabled() const;
0155
0156
0157
0158
0159 class ValueTable {
0160 DenseMap<Value *, uint32_t> valueNumbering;
0161 DenseMap<Expression, uint32_t> expressionNumbering;
0162
0163
0164
0165
0166
0167 uint32_t nextExprNumber = 0;
0168
0169 std::vector<Expression> Expressions;
0170 std::vector<uint32_t> ExprIdx;
0171
0172
0173 DenseMap<uint32_t, PHINode *> NumberingPhi;
0174
0175
0176 using PhiTranslateMap =
0177 DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>;
0178 PhiTranslateMap PhiTranslateTable;
0179
0180 AAResults *AA = nullptr;
0181 MemoryDependenceResults *MD = nullptr;
0182 DominatorTree *DT = nullptr;
0183
0184 uint32_t nextValueNumber = 1;
0185
0186 Expression createExpr(Instruction *I);
0187 Expression createCmpExpr(unsigned Opcode, CmpInst::Predicate Predicate,
0188 Value *LHS, Value *RHS);
0189 Expression createExtractvalueExpr(ExtractValueInst *EI);
0190 Expression createGEPExpr(GetElementPtrInst *GEP);
0191 uint32_t lookupOrAddCall(CallInst *C);
0192 uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
0193 uint32_t Num, GVNPass &Gvn);
0194 bool areCallValsEqual(uint32_t Num, uint32_t NewNum, const BasicBlock *Pred,
0195 const BasicBlock *PhiBlock, GVNPass &Gvn);
0196 std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
0197 bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVNPass &Gvn);
0198
0199 public:
0200 ValueTable();
0201 ValueTable(const ValueTable &Arg);
0202 ValueTable(ValueTable &&Arg);
0203 ~ValueTable();
0204 ValueTable &operator=(const ValueTable &Arg);
0205
0206 uint32_t lookupOrAdd(Value *V);
0207 uint32_t lookup(Value *V, bool Verify = true) const;
0208 uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
0209 Value *LHS, Value *RHS);
0210 uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
0211 uint32_t Num, GVNPass &Gvn);
0212 void eraseTranslateCacheEntry(uint32_t Num, const BasicBlock &CurrBlock);
0213 bool exists(Value *V) const;
0214 void add(Value *V, uint32_t num);
0215 void clear();
0216 void erase(Value *v);
0217 void setAliasAnalysis(AAResults *A) { AA = A; }
0218 AAResults *getAliasAnalysis() const { return AA; }
0219 void setMemDep(MemoryDependenceResults *M) { MD = M; }
0220 void setDomTree(DominatorTree *D) { DT = D; }
0221 uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
0222 void verifyRemoved(const Value *) const;
0223 };
0224
0225 private:
0226 friend class gvn::GVNLegacyPass;
0227 friend struct DenseMapInfo<Expression>;
0228
0229 MemoryDependenceResults *MD = nullptr;
0230 DominatorTree *DT = nullptr;
0231 const TargetLibraryInfo *TLI = nullptr;
0232 AssumptionCache *AC = nullptr;
0233 SetVector<BasicBlock *> DeadBlocks;
0234 OptimizationRemarkEmitter *ORE = nullptr;
0235 ImplicitControlFlowTracking *ICF = nullptr;
0236 LoopInfo *LI = nullptr;
0237 MemorySSAUpdater *MSSAU = nullptr;
0238
0239 ValueTable VN;
0240
0241
0242
0243 class LeaderMap {
0244 public:
0245 struct LeaderTableEntry {
0246 Value *Val;
0247 const BasicBlock *BB;
0248 };
0249
0250 private:
0251 struct LeaderListNode {
0252 LeaderTableEntry Entry;
0253 LeaderListNode *Next;
0254 };
0255 DenseMap<uint32_t, LeaderListNode> NumToLeaders;
0256 BumpPtrAllocator TableAllocator;
0257
0258 public:
0259 class leader_iterator {
0260 const LeaderListNode *Current;
0261
0262 public:
0263 using iterator_category = std::forward_iterator_tag;
0264 using value_type = const LeaderTableEntry;
0265 using difference_type = std::ptrdiff_t;
0266 using pointer = value_type *;
0267 using reference = value_type &;
0268
0269 leader_iterator(const LeaderListNode *C) : Current(C) {}
0270 leader_iterator &operator++() {
0271 assert(Current && "Dereferenced end of leader list!");
0272 Current = Current->Next;
0273 return *this;
0274 }
0275 bool operator==(const leader_iterator &Other) const {
0276 return Current == Other.Current;
0277 }
0278 bool operator!=(const leader_iterator &Other) const {
0279 return Current != Other.Current;
0280 }
0281 reference operator*() const { return Current->Entry; }
0282 };
0283
0284 iterator_range<leader_iterator> getLeaders(uint32_t N) {
0285 auto I = NumToLeaders.find(N);
0286 if (I == NumToLeaders.end()) {
0287 return iterator_range(leader_iterator(nullptr),
0288 leader_iterator(nullptr));
0289 }
0290
0291 return iterator_range(leader_iterator(&I->second),
0292 leader_iterator(nullptr));
0293 }
0294
0295 void insert(uint32_t N, Value *V, const BasicBlock *BB);
0296 void erase(uint32_t N, Instruction *I, const BasicBlock *BB);
0297 void verifyRemoved(const Value *Inst) const;
0298 void clear() {
0299 NumToLeaders.clear();
0300 TableAllocator.Reset();
0301 }
0302 };
0303 LeaderMap LeaderTable;
0304
0305
0306
0307
0308 SmallMapVector<Value *, Value *, 4> ReplaceOperandsWithMap;
0309 SmallVector<Instruction *, 8> InstrsToErase;
0310
0311
0312
0313 DenseMap<AssertingVH<BasicBlock>, uint32_t> BlockRPONumber;
0314
0315
0316
0317
0318 bool InvalidBlockRPONumbers = true;
0319
0320 using LoadDepVect = SmallVector<NonLocalDepResult, 64>;
0321 using AvailValInBlkVect = SmallVector<gvn::AvailableValueInBlock, 64>;
0322 using UnavailBlkVect = SmallVector<BasicBlock *, 64>;
0323
0324 bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
0325 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
0326 MemoryDependenceResults *RunMD, LoopInfo &LI,
0327 OptimizationRemarkEmitter *ORE, MemorySSA *MSSA = nullptr);
0328
0329
0330 SmallVector<std::pair<Instruction *, unsigned>, 4> toSplit;
0331
0332
0333 bool processLoad(LoadInst *L);
0334 bool processNonLocalLoad(LoadInst *L);
0335 bool processAssumeIntrinsic(AssumeInst *II);
0336
0337
0338
0339 std::optional<gvn::AvailableValue>
0340 AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo, Value *Address);
0341
0342
0343
0344
0345 void AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
0346 AvailValInBlkVect &ValuesPerBlock,
0347 UnavailBlkVect &UnavailableBlocks);
0348
0349
0350
0351 LoadInst *findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
0352 LoadInst *Load);
0353
0354 bool PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
0355 UnavailBlkVect &UnavailableBlocks);
0356
0357
0358
0359
0360 bool performLoopLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
0361 UnavailBlkVect &UnavailableBlocks);
0362
0363
0364
0365 void eliminatePartiallyRedundantLoad(
0366 LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
0367 MapVector<BasicBlock *, Value *> &AvailableLoads,
0368 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad);
0369
0370
0371 bool processInstruction(Instruction *I);
0372 bool processBlock(BasicBlock *BB);
0373 void dump(DenseMap<uint32_t, Value *> &d) const;
0374 bool iterateOnFunction(Function &F);
0375 bool performPRE(Function &F);
0376 bool performScalarPRE(Instruction *I);
0377 bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
0378 BasicBlock *Curr, unsigned int ValNo);
0379 Value *findLeader(const BasicBlock *BB, uint32_t num);
0380 void cleanupGlobalSets();
0381 void removeInstruction(Instruction *I);
0382 void verifyRemoved(const Instruction *I) const;
0383 bool splitCriticalEdges();
0384 BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);
0385 bool replaceOperandsForInBlockEquality(Instruction *I) const;
0386 bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root,
0387 bool DominatesByEdge);
0388 bool processFoldableCondBr(BranchInst *BI);
0389 void addDeadBlock(BasicBlock *BB);
0390 void assignValNumForDeadCode();
0391 void assignBlockRPONumber(Function &F);
0392 };
0393
0394
0395 FunctionPass *createGVNPass();
0396
0397
0398
0399 struct GVNHoistPass : PassInfoMixin<GVNHoistPass> {
0400
0401 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0402 };
0403
0404
0405
0406 struct GVNSinkPass : PassInfoMixin<GVNSinkPass> {
0407
0408 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0409 };
0410
0411 }
0412
0413 #endif