#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;
namespace jumpthreading {
using PredValueInfo = SmallVectorImpl<std::pair<Constant *, BasicBlock *>>;
using PredValueInfoTy = SmallVector<std::pair<Constant *, BasicBlock *>, 8>;
enum ConstantPreference { WantInteger, WantBlockAddress };
}
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);
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);
bool doesBlockHaveProfileData(BasicBlock *BB);
};
}
#endif