//===- 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/SmallSet.h"
 
#include "llvm/ADT/SmallVector.h"
 
#include "llvm/Analysis/BlockFrequencyInfo.h"
 
#include "llvm/Analysis/BranchProbabilityInfo.h"
 
#include "llvm/IR/ValueHandle.h"
 
#include <utility>
 
 
 
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 TargetTransformInfo;
 
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<std::pair<Constant *, BasicBlock *>>;
 
using PredValueInfoTy = SmallVector<std::pair<Constant *, BasicBlock *>, 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<JumpThreadingPass> {
 
  TargetLibraryInfo *TLI;
 
  TargetTransformInfo *TTI;
 
  LazyValueInfo *LVI;
 
  AAResults *AA;
 
  DomTreeUpdater *DTU;
 
  std::unique_ptr<BlockFrequencyInfo> BFI;
 
  std::unique_ptr<BranchProbabilityInfo> BPI;
 
  bool HasProfileData = false;
 
  bool HasGuards = false;
 
#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
 
  SmallPtrSet<const BasicBlock *, 16> LoopHeaders;
 
#else
 
  SmallSet<AssertingVH<const BasicBlock>, 16> LoopHeaders;
 
#endif
 
 
 
  unsigned BBDupThreshold;
 
  unsigned DefaultBBDupThreshold;
 
 
 
public:
 
  JumpThreadingPass(int T = -1);
 
 
 
  // Glue for old PM.
 
  bool runImpl(Function &F, TargetLibraryInfo *TLI, TargetTransformInfo *TTI,
 
               LazyValueInfo *LVI, AAResults *AA, DomTreeUpdater *DTU,
 
               bool HasProfileData, std::unique_ptr<BlockFrequencyInfo> BFI,
 
               std::unique_ptr<BranchProbabilityInfo> 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<Instruction *, Value *> &ValueMapping);
 
  DenseMap<Instruction *, Value *> cloneInstructions(BasicBlock::iterator BI,
 
                                                     BasicBlock::iterator BE,
 
                                                     BasicBlock *NewBB,
 
                                                     BasicBlock *PredBB);
 
  bool tryThreadEdge(BasicBlock *BB,
 
                     const SmallVectorImpl<BasicBlock *> &PredBBs,
 
                     BasicBlock *SuccBB);
 
  void threadEdge(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs,
 
                  BasicBlock *SuccBB);
 
  bool duplicateCondBranchOnPHIIntoPred(
 
      BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &PredBBs);
 
 
 
  bool computeValueKnownInPredecessorsImpl(
 
      Value *V, BasicBlock *BB, jumpthreading::PredValueInfo &Result,
 
      jumpthreading::ConstantPreference Preference,
 
      DenseSet<Value *> &RecursionSet, Instruction *CxtI = nullptr);
 
  bool
 
  computeValueKnownInPredecessors(Value *V, BasicBlock *BB,
 
                                  jumpthreading::PredValueInfo &Result,
 
                                  jumpthreading::ConstantPreference Preference,
 
                                  Instruction *CxtI = nullptr) {
 
    DenseSet<Value *> 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<BasicBlock *> 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