//===- JumpThreading.h - thread control through conditional BBs -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// See the comments on JumpThreadingPass. // //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H #define LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/IR/ValueHandle.h" #include #include namespace llvm { class AAResults; class BasicBlock; class BinaryOperator; class BranchInst; class CmpInst; class Constant; class DomTreeUpdater; class Function; class Instruction; class IntrinsicInst; class LazyValueInfo; class LoadInst; class PHINode; class SelectInst; class SwitchInst; class TargetLibraryInfo; class Value; /// A private "module" namespace for types and utilities used by /// JumpThreading. /// These are implementation details and should not be used by clients. namespace jumpthreading { // These are at global scope so static functions can use them too. using PredValueInfo = SmallVectorImpl>; using PredValueInfoTy = SmallVector, 8>; // This is used to keep track of what kind of constant we're currently hoping // to find. enum ConstantPreference { WantInteger, WantBlockAddress }; } // end namespace jumpthreading /// This pass performs 'jump threading', which looks at blocks that have /// multiple predecessors and multiple successors. If one or more of the /// predecessors of the block can be proven to always jump to one of the /// successors, we forward the edge from the predecessor to the successor by /// duplicating the contents of this block. /// /// An example of when this can occur is code like this: /// /// if () { ... /// X = 4; /// } /// if (X < 3) { /// /// In this case, the unconditional branch at the end of the first if can be /// revectored to the false side of the second if. class JumpThreadingPass : public PassInfoMixin { TargetLibraryInfo *TLI; LazyValueInfo *LVI; AAResults *AA; DomTreeUpdater *DTU; std::unique_ptr BFI; std::unique_ptr BPI; bool HasProfileData = false; bool HasGuards = false; #ifdef NDEBUG SmallPtrSet LoopHeaders; #else SmallSet, 16> LoopHeaders; #endif unsigned BBDupThreshold; unsigned DefaultBBDupThreshold; bool InsertFreezeWhenUnfoldingSelect; public: JumpThreadingPass(bool InsertFreezeWhenUnfoldingSelect = false, int T = -1); // Glue for old PM. bool runImpl(Function &F, TargetLibraryInfo *TLI, LazyValueInfo *LVI, AAResults *AA, DomTreeUpdater *DTU, bool HasProfileData, std::unique_ptr BFI, std::unique_ptr BPI); PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); void releaseMemory() { BFI.reset(); BPI.reset(); } void findLoopHeaders(Function &F); bool processBlock(BasicBlock *BB); bool maybeMergeBasicBlockIntoOnlyPred(BasicBlock *BB); void updateSSA(BasicBlock *BB, BasicBlock *NewBB, DenseMap &ValueMapping); DenseMap cloneInstructions(BasicBlock::iterator BI, BasicBlock::iterator BE, BasicBlock *NewBB, BasicBlock *PredBB); bool tryThreadEdge(BasicBlock *BB, const SmallVectorImpl &PredBBs, BasicBlock *SuccBB); void threadEdge(BasicBlock *BB, const SmallVectorImpl &PredBBs, BasicBlock *SuccBB); bool duplicateCondBranchOnPHIIntoPred( BasicBlock *BB, const SmallVectorImpl &PredBBs); bool computeValueKnownInPredecessorsImpl( Value *V, BasicBlock *BB, jumpthreading::PredValueInfo &Result, jumpthreading::ConstantPreference Preference, DenseSet &RecursionSet, Instruction *CxtI = nullptr); bool computeValueKnownInPredecessors(Value *V, BasicBlock *BB, jumpthreading::PredValueInfo &Result, jumpthreading::ConstantPreference Preference, Instruction *CxtI = nullptr) { DenseSet RecursionSet; return computeValueKnownInPredecessorsImpl(V, BB, Result, Preference, RecursionSet, CxtI); } Constant *evaluateOnPredecessorEdge(BasicBlock *BB, BasicBlock *PredPredBB, Value *cond); bool maybethreadThroughTwoBasicBlocks(BasicBlock *BB, Value *Cond); void threadThroughTwoBasicBlocks(BasicBlock *PredPredBB, BasicBlock *PredBB, BasicBlock *BB, BasicBlock *SuccBB); bool processThreadableEdges(Value *Cond, BasicBlock *BB, jumpthreading::ConstantPreference Preference, Instruction *CxtI = nullptr); bool processBranchOnPHI(PHINode *PN); bool processBranchOnXOR(BinaryOperator *BO); bool processImpliedCondition(BasicBlock *BB); bool simplifyPartiallyRedundantLoad(LoadInst *LI); void unfoldSelectInstr(BasicBlock *Pred, BasicBlock *BB, SelectInst *SI, PHINode *SIUse, unsigned Idx); bool tryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB); bool tryToUnfoldSelect(SwitchInst *SI, BasicBlock *BB); bool tryToUnfoldSelectInCurrBB(BasicBlock *BB); bool processGuards(BasicBlock *BB); bool threadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI); private: BasicBlock *splitBlockPreds(BasicBlock *BB, ArrayRef Preds, const char *Suffix); void updateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BasicBlock *BB, BasicBlock *NewBB, BasicBlock *SuccBB); /// Check if the block has profile metadata for its outgoing edges. bool doesBlockHaveProfileData(BasicBlock *BB); }; } // end namespace llvm #endif // LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H