#ifndef LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
#define LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Transforms/Utils/OrderedInstructions.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <utility>
namespace llvm {
class DominatorTree;
class Function;
class Instruction;
class MemoryAccess;
class LLVMContext;
class raw_ostream;
enum PredicateType { PT_Branch, PT_Assume, PT_Switch };
class PredicateBase : public ilist_node<PredicateBase> {
public:
PredicateType Type;
Value *OriginalOp;
PredicateBase(const PredicateBase &) = delete;
PredicateBase &operator=(const PredicateBase &) = delete;
PredicateBase() = delete;
virtual ~PredicateBase() = default;
protected:
PredicateBase(PredicateType PT, Value *Op) : Type(PT), OriginalOp(Op) {}
};
class PredicateWithCondition : public PredicateBase {
public:
Value *Condition;
static bool classof(const PredicateBase *PB) {
return PB->Type == PT_Assume || PB->Type == PT_Branch ||
PB->Type == PT_Switch;
}
protected:
PredicateWithCondition(PredicateType PT, Value *Op, Value *Condition)
: PredicateBase(PT, Op), Condition(Condition) {}
};
class PredicateAssume : public PredicateWithCondition {
public:
IntrinsicInst *AssumeInst;
PredicateAssume(Value *Op, IntrinsicInst *AssumeInst, Value *Condition)
: PredicateWithCondition(PT_Assume, Op, Condition),
AssumeInst(AssumeInst) {}
PredicateAssume() = delete;
static bool classof(const PredicateBase *PB) {
return PB->Type == PT_Assume;
}
};
class PredicateWithEdge : public PredicateWithCondition {
public:
BasicBlock *From;
BasicBlock *To;
PredicateWithEdge() = delete;
static bool classof(const PredicateBase *PB) {
return PB->Type == PT_Branch || PB->Type == PT_Switch;
}
protected:
PredicateWithEdge(PredicateType PType, Value *Op, BasicBlock *From,
BasicBlock *To, Value *Cond)
: PredicateWithCondition(PType, Op, Cond), From(From), To(To) {}
};
class PredicateBranch : public PredicateWithEdge {
public:
bool TrueEdge;
PredicateBranch(Value *Op, BasicBlock *BranchBB, BasicBlock *SplitBB,
Value *Condition, bool TakenEdge)
: PredicateWithEdge(PT_Branch, Op, BranchBB, SplitBB, Condition),
TrueEdge(TakenEdge) {}
PredicateBranch() = delete;
static bool classof(const PredicateBase *PB) {
return PB->Type == PT_Branch;
}
};
class PredicateSwitch : public PredicateWithEdge {
public:
Value *CaseValue;
SwitchInst *Switch;
PredicateSwitch(Value *Op, BasicBlock *SwitchBB, BasicBlock *TargetBB,
Value *CaseValue, SwitchInst *SI)
: PredicateWithEdge(PT_Switch, Op, SwitchBB, TargetBB,
SI->getCondition()),
CaseValue(CaseValue), Switch(SI) {}
PredicateSwitch() = delete;
static bool classof(const PredicateBase *PB) {
return PB->Type == PT_Switch;
}
};
namespace PredicateInfoClasses {
struct ValueDFS;
}
class PredicateInfo {
private:
struct ValueInfo {
SmallVector<PredicateBase *, 4> Infos;
SmallVector<PredicateBase *, 4> UninsertedInfos;
};
iplist<PredicateBase> AllInfos;
public:
PredicateInfo(Function &, DominatorTree &, AssumptionCache &);
~PredicateInfo();
void verifyPredicateInfo() const;
void dump() const;
void print(raw_ostream &) const;
const PredicateBase *getPredicateInfoFor(const Value *V) const {
return PredicateMap.lookup(V);
}
protected:
friend class PredicateInfoAnnotatedWriter;
friend class PredicateInfoPrinterLegacyPass;
private:
void buildPredicateInfo();
void processAssume(IntrinsicInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
void processBranch(BranchInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
void processSwitch(SwitchInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
void renameUses(SmallPtrSetImpl<Value *> &);
using ValueDFS = PredicateInfoClasses::ValueDFS;
typedef SmallVectorImpl<ValueDFS> ValueDFSStack;
void convertUsesToDFSOrdered(Value *, SmallVectorImpl<ValueDFS> &);
Value *materializeStack(unsigned int &, ValueDFSStack &, Value *);
bool stackIsInScope(const ValueDFSStack &, const ValueDFS &) const;
void popStackUntilDFSScope(ValueDFSStack &, const ValueDFS &);
ValueInfo &getOrCreateValueInfo(Value *);
void addInfoFor(SmallPtrSetImpl<Value *> &OpsToRename, Value *Op,
PredicateBase *PB);
const ValueInfo &getValueInfo(Value *) const;
Function &F;
DominatorTree &DT;
AssumptionCache &AC;
OrderedInstructions OI;
DenseMap<const Value *, const PredicateBase *> PredicateMap;
SmallVector<ValueInfo, 32> ValueInfos;
DenseMap<Value *, unsigned int> ValueInfoNums;
DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly;
SmallSet<AssertingVH<Function>, 20> CreatedDeclarations;
};
class PredicateInfoPrinterLegacyPass : public FunctionPass {
public:
PredicateInfoPrinterLegacyPass();
static char ID;
bool runOnFunction(Function &) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
class PredicateInfoPrinterPass
: public PassInfoMixin<PredicateInfoPrinterPass> {
raw_ostream &OS;
public:
explicit PredicateInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
struct PredicateInfoVerifierPass : PassInfoMixin<PredicateInfoVerifierPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
}
#endif