39 #define DEBUG_TYPE "predicateinfo" 45 "PredicateInfo Printer",
false,
false)
54 "Controls which variables are renamed with predicateinfo");
60 assert(isa<PredicateWithEdge>(PB) &&
61 "Only branches and switches should have PHIOnly defs that " 62 "require branch blocks.");
63 return cast<PredicateWithEdge>(PB)->
From;
69 assert(isa<PredicateWithEdge>(PB) &&
70 "Not a predicate info type we know how to get a terminator from.");
71 return cast<PredicateWithEdge>(PB)->
From->getTerminator();
76 const std::pair<BasicBlock *, BasicBlock *>
78 assert(isa<PredicateWithEdge>(PB) &&
79 "Not a predicate info type we know how to get an edge from.");
80 const auto *PEdge = cast<PredicateWithEdge>(PB);
81 return std::make_pair(PEdge->From, PEdge->To);
86 namespace PredicateInfoClasses {
108 bool EdgeOnly =
false;
114 auto *ArgA = dyn_cast_or_null<Argument>(A);
115 auto *ArgB = dyn_cast_or_null<Argument>(
B);
121 return ArgA->getArgNo() < ArgB->getArgNo();
122 return OI.
dfsBefore(cast<Instruction>(A), cast<Instruction>(B));
147 return comparePHIRelated(A, B);
152 return localComesBefore(A, B);
156 const std::pair<BasicBlock *, BasicBlock *>
158 if (!VD.
Def && VD.
U) {
159 auto *PHI = cast<PHINode>(VD.
U->getUser());
160 return std::make_pair(PHI->getIncomingBlock(*VD.
U), PHI->getParent());
163 return ::getBlockEdge(VD.
PInfo);
168 auto &ABlockEdge = getBlockEdge(A);
169 auto &BBlockEdge = getBlockEdge(B);
171 return std::tie(ABlockEdge, A.
Def, A.
U) < std::tie(BBlockEdge, B.
Def, B.
U);
186 "No def, no use, and no predicateinfo should not occur");
188 "Middle of block should only occur for assumes");
189 return cast<PredicateAssume>(VD.
PInfo)->AssumeInst;
198 return cast<Instruction>(
Def);
199 return cast<Instruction>(U->getUser());
205 auto *ADef = getMiddleDef(A);
206 auto *BDef = getMiddleDef(B);
211 auto *ArgA = dyn_cast_or_null<Argument>(ADef);
212 auto *ArgB = dyn_cast_or_null<Argument>(BDef);
217 auto *AInst = getDefOrUser(ADef, A.
U);
218 auto *BInst = getDefOrUser(BDef, B.
U);
225 bool PredicateInfo::stackIsInScope(
const ValueDFSStack &Stack,
234 if (Stack.back().EdgeOnly) {
241 BasicBlock *EdgePred = PHI->getIncomingBlock(*VDUse.
U);
242 if (EdgePred != getBranchBlock(Stack.back().PInfo))
246 return DT.dominates(getBlockEdge(Stack.back().PInfo), *VDUse.
U);
249 return (VDUse.
DFSIn >= Stack.back().DFSIn &&
250 VDUse.
DFSOut <= Stack.back().DFSOut);
253 void PredicateInfo::popStackUntilDFSScope(ValueDFSStack &Stack,
255 while (!Stack.empty() && !stackIsInScope(Stack, VD))
261 void PredicateInfo::convertUsesToDFSOrdered(
263 for (
auto &U : Op->
uses()) {
264 if (
auto *
I = dyn_cast<Instruction>(U.getUser())) {
268 if (
auto *PN = dyn_cast<PHINode>(
I)) {
269 IBlock = PN->getIncomingBlock(U);
276 IBlock =
I->getParent();
303 if ((isa<Instruction>(Op0) || isa<Argument>(Op0)) && !Op0->hasOneUse())
305 if ((isa<Instruction>(Op1) || isa<Argument>(Op1)) && !Op1->hasOneUse())
313 auto &OperandInfo = getOrCreateValueInfo(Op);
314 AllInfos.push_back(PB);
315 OperandInfo.Infos.push_back(PB);
330 ConditionsToProcess.
push_back(cast<BinaryOperator>(Operand)->getOperand(0));
331 ConditionsToProcess.
push_back(cast<BinaryOperator>(Operand)->getOperand(1));
333 }
else if (isa<CmpInst>(Operand)) {
337 for (
auto Cond : ConditionsToProcess) {
338 if (
auto *Cmp = dyn_cast<CmpInst>(Cond)) {
341 for (
auto *Op : CmpOperands) {
343 addInfoFor(OpsToRename, Op, PA);
346 }
else if (
auto *BinOp = dyn_cast<BinaryOperator>(Cond)) {
348 assert(BinOp->getOpcode() == Instruction::And &&
349 "Should have been an AND");
351 addInfoFor(OpsToRename, BinOp, PA);
369 auto InsertHelper = [&](
Value *
Op,
bool isAnd,
bool isOr,
Value *Cond) {
370 for (
auto *Succ : SuccsToProcess) {
373 if (Succ == BranchBB)
375 bool TakenEdge = (Succ == FirstBB);
378 if ((isAnd && !TakenEdge) || (isOr && TakenEdge))
382 addInfoFor(OpsToRename, Op, PB);
383 if (!Succ->getSinglePredecessor())
384 EdgeUsesOnly.insert({BranchBB, Succ});
398 if (BinOp->getOpcode() == Instruction::And)
400 else if (BinOp->getOpcode() == Instruction::Or)
402 ConditionsToProcess.
push_back(BinOp->getOperand(0));
403 ConditionsToProcess.
push_back(BinOp->getOperand(1));
408 for (
auto Cond : ConditionsToProcess) {
409 if (
auto *Cmp = dyn_cast<CmpInst>(Cond)) {
412 for (
auto *Op : CmpOperands)
413 InsertHelper(Op, isAnd, isOr, Cmp);
414 }
else if (
auto *BinOp = dyn_cast<BinaryOperator>(Cond)) {
416 assert((BinOp->getOpcode() == Instruction::And ||
417 BinOp->getOpcode() == Instruction::Or) &&
418 "Should have been an AND or an OR");
421 InsertHelper(BinOp,
false,
false, BinOp);
433 if ((!isa<Instruction>(Op) && !isa<Argument>(Op)) || Op->
hasOneUse())
440 ++SwitchEdges[TargetBlock];
444 for (
auto C : SI->
cases()) {
446 if (SwitchEdges.
lookup(TargetBlock) == 1) {
448 Op, SI->
getParent(), TargetBlock,
C.getCaseValue(),
SI);
449 addInfoFor(OpsToRename, Op, PS);
451 EdgeUsesOnly.insert({BranchBB, TargetBlock});
457 void PredicateInfo::buildPredicateInfo() {
458 DT.updateDFSNumbers();
464 if (
auto *BI = dyn_cast<BranchInst>(BranchBB->
getTerminator())) {
470 processBranch(BI, BranchBB, OpsToRename);
471 }
else if (
auto *SI = dyn_cast<SwitchInst>(BranchBB->
getTerminator())) {
475 for (
auto &Assume : AC.assumptions()) {
476 if (
auto *II = dyn_cast_or_null<IntrinsicInst>(Assume))
477 processAssume(II, II->
getParent(), OpsToRename);
480 renameUses(OpsToRename);
491 std::string
Name =
"llvm.ssa.copy." +
utostr((uintptr_t) Ty);
498 Value *PredicateInfo::materializeStack(
unsigned int &Counter,
499 ValueDFSStack &RenameStack,
502 auto RevIter = RenameStack.rbegin();
503 for (; RevIter != RenameStack.rend(); ++RevIter)
507 size_t Start = RevIter - RenameStack.rbegin();
511 for (
auto RenameIter = RenameStack.end() - Start;
512 RenameIter != RenameStack.end(); ++RenameIter) {
514 RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->
Def;
516 auto *ValInfo = Result.
PInfo;
522 if (isa<PredicateWithEdge>(ValInfo)) {
526 CreatedDeclarations.insert(IF);
529 PredicateMap.insert({PIC, ValInfo});
534 "Should not have gotten here without it being an assume");
538 CreatedDeclarations.insert(IF);
540 PredicateMap.insert({PIC, ValInfo});
544 return RenameStack.back().Def;
569 auto Comparator = [&](
const Value *A,
const Value *
B) {
575 for (
auto *Op : OpsToRename) {
577 unsigned Counter = 0;
579 const auto &
ValueInfo = getValueInfo(Op);
583 for (
auto &PossibleCopy :
ValueInfo.Infos) {
590 if (
const auto *PAssume = dyn_cast<PredicateAssume>(PossibleCopy)) {
592 DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
597 VD.
PInfo = PossibleCopy;
599 }
else if (isa<PredicateWithEdge>(PossibleCopy)) {
603 auto BlockEdge = getBlockEdge(PossibleCopy);
604 if (EdgeUsesOnly.count(BlockEdge)) {
606 auto *DomNode = DT.getNode(BlockEdge.first);
608 VD.
DFSIn = DomNode->getDFSNumIn();
609 VD.
DFSOut = DomNode->getDFSNumOut();
610 VD.
PInfo = PossibleCopy;
619 auto *DomNode = DT.getNode(BlockEdge.second);
621 VD.
DFSIn = DomNode->getDFSNumIn();
622 VD.
DFSOut = DomNode->getDFSNumOut();
623 VD.
PInfo = PossibleCopy;
630 convertUsesToDFSOrdered(Op, OrderedUses);
640 for (
auto &VD : OrderedUses) {
643 bool PossibleCopy = VD.
PInfo !=
nullptr;
644 if (RenameStack.empty()) {
648 << RenameStack.back().DFSIn <<
"," 649 << RenameStack.back().DFSOut <<
")\n");
655 bool ShouldPush = (VD.
Def || PossibleCopy);
656 bool OutOfScope = !stackIsInScope(RenameStack, VD);
657 if (OutOfScope || ShouldPush) {
659 popStackUntilDFSScope(RenameStack, VD);
661 RenameStack.push_back(VD);
666 if (RenameStack.empty())
669 if (VD.
Def || PossibleCopy)
672 LLVM_DEBUG(
dbgs() <<
"Skipping execution due to debug counter\n");
675 ValueDFS &Result = RenameStack.back();
681 Result.
Def = materializeStack(Counter, RenameStack, Op);
684 << *VD.
U->get() <<
" in " << *(VD.
U->getUser())
686 assert(DT.dominates(cast<Instruction>(Result.
Def), *VD.
U) &&
687 "Predicateinfo def should have dominated this use");
688 VD.
U->set(Result.
Def);
693 PredicateInfo::ValueInfo &PredicateInfo::getOrCreateValueInfo(
Value *Operand) {
694 auto OIN = ValueInfoNums.find(Operand);
695 if (OIN == ValueInfoNums.end()) {
697 ValueInfos.resize(ValueInfos.size() + 1);
699 auto InsertResult = ValueInfoNums.insert({Operand, ValueInfos.size() - 1});
700 assert(InsertResult.second &&
"Value info number already existed?");
701 return ValueInfos[InsertResult.first->second];
703 return ValueInfos[OIN->second];
706 const PredicateInfo::ValueInfo &
707 PredicateInfo::getValueInfo(
Value *Operand)
const {
708 auto OINI = ValueInfoNums.lookup(Operand);
709 assert(OINI != 0 &&
"Operand was not really in the Value Info Numbers");
710 assert(OINI < ValueInfos.size() &&
711 "Value Info Number greater than size of Value Info Table");
712 return ValueInfos[OINI];
717 : F(F), DT(DT), AC(AC), OI(&DT) {
720 buildPredicateInfo();
729 for (
auto &F : CreatedDeclarations)
731 CreatedDeclarations.clear();
735 "PredicateInfo consumer did not remove all SSA copies.");
771 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
772 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
773 auto PredInfo = make_unique<PredicateInfo>(
F, DT, AC);
774 PredInfo->print(
dbgs());
776 PredInfo->verifyPredicateInfo();
786 OS <<
"PredicateInfo for function: " << F.
getName() <<
"\n";
787 auto PredInfo = make_unique<PredicateInfo>(
F, DT, AC);
809 OS <<
"; Has predicate info\n";
810 if (
const auto *PB = dyn_cast<PredicateBranch>(PI)) {
811 OS <<
"; branch predicate info { TrueEdge: " << PB->TrueEdge
812 <<
" Comparison:" << *PB->Condition <<
" Edge: [";
813 PB->From->printAsOperand(OS);
815 PB->To->printAsOperand(OS);
817 }
else if (
const auto *PS = dyn_cast<PredicateSwitch>(PI)) {
818 OS <<
"; switch predicate info { CaseValue: " << *PS->CaseValue
819 <<
" Switch:" << *PS->Switch <<
" Edge: [";
820 PS->From->printAsOperand(OS);
822 PS->To->printAsOperand(OS);
824 }
else if (
const auto *PA = dyn_cast<PredicateAssume>(PI)) {
825 OS <<
"; assume predicate info {" 826 <<
" Comparison:" << *PA->Condition <<
" }\n";
834 F.print(OS, &Writer);
839 F.print(
dbgs(), &Writer);
846 make_unique<PredicateInfo>(
F, DT, AC)->verifyPredicateInfo();
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
Safe Stack instrumentation pass
This class is the base class for the comparison instructions.
iterator_range< use_iterator > uses()
class_match< CmpInst > m_Cmp()
Matches any compare instruction and ignore it.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
iterator_range< CaseIt > cases()
Iteration adapter for range-for loops.
bool operator()(const ValueDFS &A, const ValueDFS &B) const
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
A Module instance is used to store all the information related to an LLVM module. ...
static Function * getCopyDeclaration(Module *M, Type *Ty)
void verifyPredicateInfo() const
void push_back(const T &Elt)
PredicateInfo(Function &, DominatorTree &, AssumptionCache &)
This class represents a function call, abstracting a target machine's calling convention.
An immutable pass that tracks lazily created AssumptionCache objects.
Value * getCondition() const
void collectCmpOps(CmpInst *Comparison, SmallVectorImpl< Value *> &CmpOperands)
A cache of @llvm.assume calls within a function.
const std::pair< BasicBlock *, BasicBlock * > getBlockEdge(const ValueDFS &VD) const
PredicateInfoPrinterLegacyPass()
BasicBlock * getSuccessor(unsigned i) const
Analysis pass which computes a DominatorTree.
Value * getCondition() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, formatted_raw_ostream &OS)
emitBasicBlockStartAnnot - This may be implemented to emit a string right after the basic block label...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static bool valueComesBefore(OrderedInstructions &OI, const Value *A, const Value *B)
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
amdgpu Simplify well known AMD library false Value Value const Twine & Name
inst_iterator inst_begin(Function *F)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVMContext & getContext() const
Get the global data context.
A Use represents the edge between a Value definition and its users.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This file provides an implementation of debug counters.
PredicateInfoAnnotatedWriter(const PredicateInfo *M)
void initializePredicateInfoPrinterLegacyPassPass(PassRegistry &)
Type * getType() const
All values are typed, get the type of this value.
ppc ctr loops PowerPC CTR Loops Verify
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
print PredicateInfo static false cl::opt< bool > VerifyPredicateInfo("verify-predicateinfo", cl::init(false), cl::Hidden, cl::desc("Verify PredicateInfo in legacy printer pass."))
unsigned getNumSuccessors() const
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
BasicBlock * getSuccessor(unsigned idx) const
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Value * getOperand(unsigned i) const
bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const
bool localComesBefore(const ValueDFS &A, const ValueDFS &B) const
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree...
initializer< Ty > init(const Ty &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A set of analyses that are preserved following a run of a transformation pass.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
Conditional or Unconditional Branch instruction.
INITIALIZE_PASS_BEGIN(PredicateInfoPrinterLegacyPass, "print-predicateinfo", "PredicateInfo Printer", false, false) INITIALIZE_PASS_END(PredicateInfoPrinterLegacyPass
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
bool dfsBefore(const Instruction *, const Instruction *) const
Return true if the first instruction comes before the second in the dominator tree DFS traversal if t...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
FunctionPass class - This class is used to implement most global optimizations.
unsigned getDFSNumOut() const
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static bool shouldExecute(unsigned CounterName)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static wasm::ValType getType(const TargetRegisterClass *RC)
This file implements the PredicateInfo analysis, which creates an Extended SSA form for operations us...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool verify(const TargetRegisterInfo &TRI) const
Check that information hold by this instance make sense for the given TRI.
void sort(IteratorTy Start, IteratorTy End)
Struct that holds a reference to a particular GUID in a global value summary.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
A function analysis which provides an AssumptionCache.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
BlockVerifier::State From
Module.h This file contains the declarations for the Module class.
bool isConditional() const
std::string utostr(uint64_t X, bool isNeg=false)
static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Encapsulates PredicateInfo, including all data associated with memory accesses.
const PredicateBase * getPredicateInfoFor(const Value *V) const
void setPreservesAll()
Set by analyses that do not transform their input at all.
iterator_range< user_iterator > users()
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
print PredicateInfo Printer
ValueDFS_Compare(OrderedInstructions &OI)
StringRef getName() const
Return a constant reference to the value's name.
static void rename(GlobalValue *GV)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
An assembly annotator class to print PredicateInfo information in comments.
AnalysisUsage & addRequiredTransitive()
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream...
bool hasOneUse() const
Return true if there is exactly one user of this value.
inst_iterator inst_end(Function *F)
A container for analyses that lazily runs them and caches their results.
void print(raw_ostream &) const
Legacy analysis pass which computes a DominatorTree.
DEBUG_COUNTER(RenameCounter, "predicateinfo-rename", "Controls which variables are renamed with predicateinfo")
bool runOnFunction(Function &) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass...
Value * getMiddleDef(const ValueDFS &VD) const
A wrapper class for inspecting calls to intrinsic functions.
const BasicBlock * getParent() const
const Instruction * getDefOrUser(const Value *Def, const Use *U) const
virtual void emitInstructionAnnot(const Instruction *I, formatted_raw_ostream &OS)
emitInstructionAnnot - This may be implemented to emit a string right before an instruction is emitte...