|
| 1 | +//===- JumpThreading.h - thread control through conditional BBs -*- C++ -*-===// |
| 2 | +// |
| 3 | +// The LLVM Compiler Infrastructure |
| 4 | +// |
| 5 | +// This file is distributed under the University of Illinois Open Source |
| 6 | +// License. See LICENSE.TXT for details. |
| 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/DenseSet.h" |
| 18 | +#include "llvm/ADT/SmallPtrSet.h" |
| 19 | +#include "llvm/ADT/SmallSet.h" |
| 20 | +#include "llvm/Analysis/BlockFrequencyInfo.h" |
| 21 | +#include "llvm/Analysis/BranchProbabilityInfo.h" |
| 22 | +#include "llvm/Analysis/LazyValueInfo.h" |
| 23 | +#include "llvm/Analysis/TargetLibraryInfo.h" |
| 24 | +#include "llvm/IR/Instructions.h" |
| 25 | +#include "llvm/IR/ValueHandle.h" |
| 26 | + |
| 27 | +namespace llvm { |
| 28 | + |
| 29 | +/// A private "module" namespace for types and utilities used by |
| 30 | +/// JumpThreading. |
| 31 | +/// These are implementation details and should not be used by clients. |
| 32 | +namespace jumpthreading { |
| 33 | +// These are at global scope so static functions can use them too. |
| 34 | +typedef SmallVectorImpl<std::pair<Constant *, BasicBlock *>> PredValueInfo; |
| 35 | +typedef SmallVector<std::pair<Constant *, BasicBlock *>, 8> PredValueInfoTy; |
| 36 | + |
| 37 | +// This is used to keep track of what kind of constant we're currently hoping |
| 38 | +// to find. |
| 39 | +enum ConstantPreference { WantInteger, WantBlockAddress }; |
| 40 | +} |
| 41 | + |
| 42 | +/// This pass performs 'jump threading', which looks at blocks that have |
| 43 | +/// multiple predecessors and multiple successors. If one or more of the |
| 44 | +/// predecessors of the block can be proven to always jump to one of the |
| 45 | +/// successors, we forward the edge from the predecessor to the successor by |
| 46 | +/// duplicating the contents of this block. |
| 47 | +/// |
| 48 | +/// An example of when this can occur is code like this: |
| 49 | +/// |
| 50 | +/// if () { ... |
| 51 | +/// X = 4; |
| 52 | +/// } |
| 53 | +/// if (X < 3) { |
| 54 | +/// |
| 55 | +/// In this case, the unconditional branch at the end of the first if can be |
| 56 | +/// revectored to the false side of the second if. |
| 57 | +/// |
| 58 | +class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> { |
| 59 | + TargetLibraryInfo *TLI; |
| 60 | + LazyValueInfo *LVI; |
| 61 | + std::unique_ptr<BlockFrequencyInfo> BFI; |
| 62 | + std::unique_ptr<BranchProbabilityInfo> BPI; |
| 63 | + bool HasProfileData; |
| 64 | +#ifdef NDEBUG |
| 65 | + SmallPtrSet<const BasicBlock *, 16> LoopHeaders; |
| 66 | +#else |
| 67 | + SmallSet<AssertingVH<const BasicBlock>, 16> LoopHeaders; |
| 68 | +#endif |
| 69 | + DenseSet<std::pair<Value *, BasicBlock *>> RecursionSet; |
| 70 | + |
| 71 | + unsigned BBDupThreshold; |
| 72 | + |
| 73 | + // RAII helper for updating the recursion stack. |
| 74 | + struct RecursionSetRemover { |
| 75 | + DenseSet<std::pair<Value *, BasicBlock *>> &TheSet; |
| 76 | + std::pair<Value *, BasicBlock *> ThePair; |
| 77 | + |
| 78 | + RecursionSetRemover(DenseSet<std::pair<Value *, BasicBlock *>> &S, |
| 79 | + std::pair<Value *, BasicBlock *> P) |
| 80 | + : TheSet(S), ThePair(P) {} |
| 81 | + |
| 82 | + ~RecursionSetRemover() { TheSet.erase(ThePair); } |
| 83 | + }; |
| 84 | + |
| 85 | +public: |
| 86 | + JumpThreadingPass(int T = -1); |
| 87 | + // Hack for MSVC 2013 which seems like it can't synthesize this. |
| 88 | + JumpThreadingPass(JumpThreadingPass &&Other) |
| 89 | + : TLI(Other.TLI), LVI(Other.LVI), BFI(std::move(Other.BFI)), |
| 90 | + BPI(std::move(Other.BPI)), HasProfileData(Other.HasProfileData), |
| 91 | + LoopHeaders(std::move(Other.LoopHeaders)), |
| 92 | + RecursionSet(std::move(Other.RecursionSet)), |
| 93 | + BBDupThreshold(Other.BBDupThreshold) {} |
| 94 | + |
| 95 | + // Glue for old PM. |
| 96 | + bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_, |
| 97 | + bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_, |
| 98 | + std::unique_ptr<BranchProbabilityInfo> BPI_); |
| 99 | + |
| 100 | + PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM); |
| 101 | + |
| 102 | + void releaseMemory() { |
| 103 | + BFI.reset(); |
| 104 | + BPI.reset(); |
| 105 | + } |
| 106 | + |
| 107 | + void FindLoopHeaders(Function &F); |
| 108 | + bool ProcessBlock(BasicBlock *BB); |
| 109 | + bool ThreadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs, |
| 110 | + BasicBlock *SuccBB); |
| 111 | + bool DuplicateCondBranchOnPHIIntoPred( |
| 112 | + BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs); |
| 113 | + |
| 114 | + bool |
| 115 | + ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB, |
| 116 | + jumpthreading::PredValueInfo &Result, |
| 117 | + jumpthreading::ConstantPreference Preference, |
| 118 | + Instruction *CxtI = nullptr); |
| 119 | + bool ProcessThreadableEdges(Value *Cond, BasicBlock *BB, |
| 120 | + jumpthreading::ConstantPreference Preference, |
| 121 | + Instruction *CxtI = nullptr); |
| 122 | + |
| 123 | + bool ProcessBranchOnPHI(PHINode *PN); |
| 124 | + bool ProcessBranchOnXOR(BinaryOperator *BO); |
| 125 | + bool ProcessImpliedCondition(BasicBlock *BB); |
| 126 | + |
| 127 | + bool SimplifyPartiallyRedundantLoad(LoadInst *LI); |
| 128 | + bool TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB); |
| 129 | + bool TryToUnfoldSelectInCurrBB(BasicBlock *BB); |
| 130 | + |
| 131 | +private: |
| 132 | + BasicBlock *SplitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds, |
| 133 | + const char *Suffix); |
| 134 | + void UpdateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BasicBlock *BB, |
| 135 | + BasicBlock *NewBB, BasicBlock *SuccBB); |
| 136 | +}; |
| 137 | + |
| 138 | +} // end namespace llvm |
| 139 | + |
| 140 | +#endif |
0 commit comments