Home | History | Annotate | Line # | Download | only in Scalar
      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/SmallPtrSet.h"
     20 #include "llvm/ADT/SmallSet.h"
     21 #include "llvm/ADT/SmallVector.h"
     22 #include "llvm/Analysis/BlockFrequencyInfo.h"
     23 #include "llvm/Analysis/BranchProbabilityInfo.h"
     24 #include "llvm/Analysis/DomTreeUpdater.h"
     25 #include "llvm/IR/ValueHandle.h"
     26 #include <memory>
     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 DomTreeUpdater;
     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 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   TargetLibraryInfo *TLI;
     81   LazyValueInfo *LVI;
     82   AAResults *AA;
     83   DomTreeUpdater *DTU;
     84   std::unique_ptr<BlockFrequencyInfo> BFI;
     85   std::unique_ptr<BranchProbabilityInfo> BPI;
     86   bool HasProfileData = false;
     87   bool HasGuards = false;
     88 #ifdef NDEBUG
     89   SmallPtrSet<const BasicBlock *, 16> LoopHeaders;
     90 #else
     91   SmallSet<AssertingVH<const BasicBlock>, 16> LoopHeaders;
     92 #endif
     93 
     94   unsigned BBDupThreshold;
     95   unsigned DefaultBBDupThreshold;
     96   bool InsertFreezeWhenUnfoldingSelect;
     97 
     98 public:
     99   JumpThreadingPass(bool InsertFreezeWhenUnfoldingSelect = false, int T = -1);
    100 
    101   // Glue for old PM.
    102   bool runImpl(Function &F, TargetLibraryInfo *TLI, LazyValueInfo *LVI,
    103                AAResults *AA, DomTreeUpdater *DTU, bool HasProfileData,
    104                std::unique_ptr<BlockFrequencyInfo> BFI,
    105                std::unique_ptr<BranchProbabilityInfo> BPI);
    106 
    107   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
    108 
    109   void releaseMemory() {
    110     BFI.reset();
    111     BPI.reset();
    112   }
    113 
    114   void findLoopHeaders(Function &F);
    115   bool processBlock(BasicBlock *BB);
    116   bool maybeMergeBasicBlockIntoOnlyPred(BasicBlock *BB);
    117   void updateSSA(BasicBlock *BB, BasicBlock *NewBB,
    118                  DenseMap<Instruction *, Value *> &ValueMapping);
    119   DenseMap<Instruction *, Value *> cloneInstructions(BasicBlock::iterator BI,
    120                                                      BasicBlock::iterator BE,
    121                                                      BasicBlock *NewBB,
    122                                                      BasicBlock *PredBB);
    123   bool tryThreadEdge(BasicBlock *BB,
    124                      const SmallVectorImpl<BasicBlock *> &PredBBs,
    125                      BasicBlock *SuccBB);
    126   void threadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs,
    127                   BasicBlock *SuccBB);
    128   bool duplicateCondBranchOnPHIIntoPred(
    129       BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs);
    130 
    131   bool computeValueKnownInPredecessorsImpl(
    132       Value *V, BasicBlock *BB, jumpthreading::PredValueInfo &Result,
    133       jumpthreading::ConstantPreference Preference,
    134       DenseSet<Value *> &RecursionSet, Instruction *CxtI = nullptr);
    135   bool
    136   computeValueKnownInPredecessors(Value *V, BasicBlock *BB,
    137                                   jumpthreading::PredValueInfo &Result,
    138                                   jumpthreading::ConstantPreference Preference,
    139                                   Instruction *CxtI = nullptr) {
    140     DenseSet<Value *> RecursionSet;
    141     return computeValueKnownInPredecessorsImpl(V, BB, Result, Preference,
    142                                                RecursionSet, CxtI);
    143   }
    144 
    145   Constant *evaluateOnPredecessorEdge(BasicBlock *BB, BasicBlock *PredPredBB,
    146                                       Value *cond);
    147   bool maybethreadThroughTwoBasicBlocks(BasicBlock *BB, Value *Cond);
    148   void threadThroughTwoBasicBlocks(BasicBlock *PredPredBB, BasicBlock *PredBB,
    149                                    BasicBlock *BB, BasicBlock *SuccBB);
    150   bool processThreadableEdges(Value *Cond, BasicBlock *BB,
    151                               jumpthreading::ConstantPreference Preference,
    152                               Instruction *CxtI = nullptr);
    153 
    154   bool processBranchOnPHI(PHINode *PN);
    155   bool processBranchOnXOR(BinaryOperator *BO);
    156   bool processImpliedCondition(BasicBlock *BB);
    157 
    158   bool simplifyPartiallyRedundantLoad(LoadInst *LI);
    159   void unfoldSelectInstr(BasicBlock *Pred, BasicBlock *BB, SelectInst *SI,
    160                          PHINode *SIUse, unsigned Idx);
    161 
    162   bool tryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB);
    163   bool tryToUnfoldSelect(SwitchInst *SI, BasicBlock *BB);
    164   bool tryToUnfoldSelectInCurrBB(BasicBlock *BB);
    165 
    166   bool processGuards(BasicBlock *BB);
    167   bool threadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI);
    168 
    169 private:
    170   BasicBlock *splitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
    171                               const char *Suffix);
    172   void updateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BasicBlock *BB,
    173                                     BasicBlock *NewBB, BasicBlock *SuccBB);
    174   /// Check if the block has profile metadata for its outgoing edges.
    175   bool doesBlockHaveProfileData(BasicBlock *BB);
    176 };
    177 
    178 } // end namespace llvm
    179 
    180 #endif // LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H
    181