28#define DEBUG_TYPE "predicateinfo"
30using namespace PatternMatch;
34 cl::desc(
"Verify PredicateInfo in legacy printer pass."));
36 "Controls which variables are renamed with predicateinfo");
47 "Only branches and switches should have PHIOnly defs that "
48 "require branch blocks.");
49 return cast<PredicateWithEdge>(
PB)->From;
56 "Not a predicate info type we know how to get a terminator from.");
57 return cast<PredicateWithEdge>(
PB)->From->getTerminator();
62std::pair<BasicBlock *, BasicBlock *> getBlockEdge(
const PredicateBase *
PB) {
64 "Not a predicate info type we know how to get an edge from.");
65 const auto *PEdge = cast<PredicateWithEdge>(
PB);
66 return std::make_pair(PEdge->From, PEdge->To);
103 if (
A.DFSIn !=
B.DFSIn)
104 return A.DFSIn <
B.DFSIn;
106 "Equal DFS-in numbers imply equal out numbers");
109 if (
A.LocalNum !=
B.LocalNum)
110 return A.LocalNum <
B.LocalNum;
126 assert(
A.PInfo &&
B.PInfo &&
"Must be predicate info def");
133 auto *
PHI = cast<PHINode>(VD.
U->getUser());
134 return std::make_pair(
PHI->getIncomingBlock(*VD.
U),
PHI->getParent());
137 return ::getBlockEdge(VD.
PInfo);
151 "DFS numbers for A should match the ones of the source block");
153 "DFS numbers for B should match the ones of the source block");
154 assert(
A.DFSIn ==
B.DFSIn &&
"Values must be in the same block");
167 assert((!
A.PInfo || !
A.U) && (!
B.PInfo || !
B.U) &&
168 "Def and U cannot be set at the same time");
170 return std::tie(AIn, isAUse) < std::tie(BIn, isBUse);
175 return cast<Instruction>(VD.
U->getUser());
179 assert(VD.
PInfo &&
"No use, and no predicateinfo should not occur");
181 "Middle of block should only occur for assumes");
182 return cast<PredicateAssume>(VD.
PInfo)->AssumeInst->getNextNode();
232 Value *Def =
nullptr;
234 StackEntry(
const ValueDFS *V) : V(V) {}
254bool PredicateInfoBuilder::stackIsInScope(
const ValueDFSStack &Stack,
256 assert(!Stack.empty() &&
"Should not be called with empty stack");
262 const ValueDFS &Top = *Stack.back().V;
266 auto *
PHI = dyn_cast<PHINode>(VDUse.
U->getUser());
271 if (EdgePred != getBranchBlock(Top.
PInfo))
281void PredicateInfoBuilder::popStackUntilDFSScope(ValueDFSStack &Stack,
283 while (!
Stack.empty() && !stackIsInScope(Stack, VD))
289void PredicateInfoBuilder::convertUsesToDFSOrdered(
291 for (
auto &U :
Op->uses()) {
292 if (
auto *
I = dyn_cast<Instruction>(
U.getUser())) {
295 if (
I->isLifetimeStartOrEnd())
301 if (
auto *PN = dyn_cast<PHINode>(
I)) {
302 IBlock = PN->getIncomingBlock(U);
309 IBlock =
I->getParent();
328 return (isa<Instruction>(V) || isa<Argument>(V)) && !V->hasOneUse();
334 auto *Op0 = Comparison->getOperand(0);
335 auto *Op1 = Comparison->getOperand(1);
346 auto &OperandInfo = getOrCreateValueInfo(
Op);
347 if (OperandInfo.Infos.empty())
349 OperandInfo.Infos.push_back(
PB);
354void PredicateInfoBuilder::processAssume(
360 while (!Worklist.
empty()) {
375 if (
auto *Cmp = dyn_cast<CmpInst>(
Cond))
380 for (
Value *V : Values) {
383 addInfoFor(OpsToRename, V, PA);
391void PredicateInfoBuilder::processBranch(
397 for (
BasicBlock *Succ : {FirstBB, SecondBB}) {
398 bool TakenEdge = Succ == FirstBB;
401 if (Succ == BranchBB)
407 while (!Worklist.
empty()) {
423 if (
auto *Cmp = dyn_cast<CmpInst>(
Cond))
428 for (
Value *V : Values) {
432 addInfoFor(OpsToRename, V,
PB);
440void PredicateInfoBuilder::processSwitch(
444 if ((!isa<Instruction>(
Op) && !isa<Argument>(
Op)) ||
Op->hasOneUse())
450 ++SwitchEdges[TargetBlock];
453 for (
auto C :
SI->cases()) {
455 if (SwitchEdges.
lookup(TargetBlock) == 1) {
457 Op,
SI->getParent(), TargetBlock,
C.getCaseValue(),
SI);
458 addInfoFor(OpsToRename,
Op, PS);
473 if (
auto *BI = dyn_cast<BranchInst>(BB.getTerminator())) {
479 processBranch(BI, &BB, OpsToRename);
480 }
else if (
auto *SI = dyn_cast<SwitchInst>(BB.getTerminator())) {
481 processSwitch(SI, &BB, OpsToRename);
485 if (
auto *
II = dyn_cast_or_null<IntrinsicInst>(Assume))
487 processAssume(
II,
II->getParent(), OpsToRename);
490 renameUses(OpsToRename);
495Value *PredicateInfoBuilder::materializeStack(
unsigned int &Counter,
496 ValueDFSStack &RenameStack,
499 auto RevIter = RenameStack.rbegin();
500 for (; RevIter != RenameStack.rend(); ++RevIter)
504 size_t Start = RevIter - RenameStack.rbegin();
508 for (
auto RenameIter = RenameStack.end() - Start;
509 RenameIter != RenameStack.end(); ++RenameIter) {
511 RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def;
512 StackEntry &Result = *RenameIter;
513 auto *ValInfo = Result.V->PInfo;
514 ValInfo->RenamedOp = (RenameStack.end() - Start) == RenameStack.begin()
516 : (RenameStack.end() - Start - 1)->Def;
527 if (isa<PredicateWithEdge>(ValInfo)) {
529 Op->getName() +
"." +
Twine(Counter++));
530 PI.PredicateMap.insert({
PIC, ValInfo});
533 auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
535 "Should not have gotten here without it being an assume");
539 PI.PredicateMap.insert({
PIC, ValInfo});
543 return RenameStack.back().Def;
568 for (
auto *
Op : OpsToRename) {
570 unsigned Counter = 0;
576 for (
const auto &PossibleCopy :
ValueInfo.Infos) {
583 if (
const auto *PAssume = dyn_cast<PredicateAssume>(PossibleCopy)) {
590 VD.
PInfo = PossibleCopy;
592 }
else if (isa<PredicateWithEdge>(PossibleCopy)) {
596 auto BlockEdge = getBlockEdge(PossibleCopy);
597 if (!BlockEdge.second->getSinglePredecessor()) {
599 auto *DomNode = DT.
getNode(BlockEdge.first);
603 VD.
PInfo = PossibleCopy;
611 auto *DomNode = DT.
getNode(BlockEdge.second);
615 VD.
PInfo = PossibleCopy;
622 convertUsesToDFSOrdered(
Op, OrderedUses);
632 for (
const ValueDFS &VD : OrderedUses) {
635 if (RenameStack.
empty()) {
639 << RenameStack.
back().V->DFSIn <<
","
640 << RenameStack.
back().V->DFSOut <<
")\n");
647 popStackUntilDFSScope(RenameStack, VD);
656 if (RenameStack.
empty())
659 LLVM_DEBUG(
dbgs() <<
"Skipping execution due to debug counter\n");
668 Result.Def = materializeStack(Counter, RenameStack,
Op);
671 << *VD.
U->get() <<
" in " << *(VD.
U->getUser())
674 "Predicateinfo def should have dominated this use");
680PredicateInfoBuilder::ValueInfo &
681PredicateInfoBuilder::getOrCreateValueInfo(
Value *Operand) {
682 auto Res = ValueInfoNums.try_emplace(Operand, ValueInfos.
size());
687 return ValueInfos[Res.first->second];
690const PredicateInfoBuilder::ValueInfo &
691PredicateInfoBuilder::getValueInfo(
Value *Operand)
const {
692 auto OINI = ValueInfoNums.lookup(Operand);
693 assert(OINI != 0 &&
"Operand was not really in the Value Info Numbers");
695 "Value Info Number greater than size of Value Info Table");
696 return ValueInfos[OINI];
710 bool TrueEdge =
true;
711 if (
auto *PBranch = dyn_cast<PredicateBranch>(
this))
712 TrueEdge = PBranch->TrueEdge;
734 Pred = Cmp->getPredicate();
735 OtherOp = Cmp->getOperand(1);
736 }
else if (Cmp->getOperand(1) ==
RenamedOp) {
737 Pred = Cmp->getSwappedPredicate();
738 OtherOp = Cmp->getOperand(0);
748 return {{Pred, OtherOp}};
770 assert(isa<BitCastInst>(Inst) &&
771 Inst.getType() == Inst.getOperand(0)->getType());
772 Inst.replaceAllUsesWith(Inst.getOperand(0));
773 Inst.eraseFromParent();
781 OS <<
"PredicateInfo for function: " <<
F.getName() <<
"\n";
783 auto PredInfo = std::make_unique<PredicateInfo>(
F, DT, AC,
Allocator);
805 OS <<
"; Has predicate info\n";
806 if (
const auto *
PB = dyn_cast<PredicateBranch>(PI)) {
807 OS <<
"; branch predicate info { TrueEdge: " <<
PB->TrueEdge
808 <<
" Comparison:" << *
PB->Condition <<
" Edge: [";
809 PB->From->printAsOperand(
OS);
811 PB->To->printAsOperand(
OS);
813 }
else if (
const auto *PS = dyn_cast<PredicateSwitch>(PI)) {
814 OS <<
"; switch predicate info { CaseValue: " << *PS->CaseValue
815 <<
" Switch:" << *PS->Switch <<
" Edge: [";
816 PS->From->printAsOperand(
OS);
818 PS->To->printAsOperand(
OS);
820 }
else if (
const auto *PA = dyn_cast<PredicateAssume>(PI)) {
821 OS <<
"; assume predicate info {"
822 <<
" Comparison:" << *PA->Condition;
824 OS <<
", RenamedOp: ";
825 PI->RenamedOp->printAsOperand(
OS,
false);
833 F.print(
OS, &Writer);
838 F.print(
dbgs(), &Writer);
846 std::make_unique<PredicateInfo>(
F, DT, AC,
Allocator)->verifyPredicateInfo();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
uint64_t IntrinsicInst * II
PassInstrumentationCallbacks PIC
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
static cl::opt< bool > VerifyPredicateInfo("verify-predicateinfo", cl::init(false), cl::Hidden, cl::desc("Verify PredicateInfo in legacy printer pass."))
static const unsigned MaxCondsPerBranch
This file implements the PredicateInfo analysis, which creates an Extended SSA form for operations us...
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallPtrSet class.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
MutableArrayRef< ResultElem > assumptions()
Access the list of assumption handles currently tracked for this function.
LLVM Basic Block Representation.
This class represents a no-op cast from one type to another.
Conditional or Unconditional Branch instruction.
bool isConditional() const
BasicBlock * getSuccessor(unsigned i) const
Value * getCondition() const
Allocate memory in an ever growing pool, as if by bump-pointer.
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This class represents an Operation in the Expression.
static bool shouldExecute(unsigned CounterName)
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...
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
unsigned getDFSNumOut() const
Analysis pass which computes a DominatorTree.
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
A wrapper class for inspecting calls to intrinsic functions.
LLVM_ABI std::optional< PredicateConstraint > getConstraint() const
Fetch condition in the form of PredicateConstraint, if possible.
An assembly annotator class to print PredicateInfo information in comments.
PredicateInfoAnnotatedWriter(const PredicateInfo *M)
void emitInstructionAnnot(const Instruction *I, formatted_raw_ostream &OS) override
emitInstructionAnnot - This may be implemented to emit a string right before an instruction is emitte...
void emitBasicBlockStartAnnot(const BasicBlock *BB, formatted_raw_ostream &OS) override
emitBasicBlockStartAnnot - This may be implemented to emit a string right after the basic block label...
PredicateInfoBuilder(PredicateInfo &PI, Function &F, DominatorTree &DT, AssumptionCache &AC, BumpPtrAllocator &Allocator)
void buildPredicateInfo()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Encapsulates PredicateInfo, including all data associated with memory accesses.
LLVM_ABI void verifyPredicateInfo() const
LLVM_ABI void print(raw_ostream &) const
LLVM_ABI PredicateInfo(Function &, DominatorTree &, AssumptionCache &, BumpPtrAllocator &)
LLVM_ABI void dump() const
const PredicateBase * getPredicateInfoFor(const Value *V) const
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)
Matches trunc nuw.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
void collectCmpOps(CmpInst *Comparison, SmallVectorImpl< Value * > &CmpOperands)
auto successors(const MachineBasicBlock *BB)
static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool shouldRename(Value *V)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
std::pair< BasicBlock *, BasicBlock * > getBlockEdge(const ValueDFS &VD) const
bool operator()(const ValueDFS &A, const ValueDFS &B) const
const Instruction * getDefOrUser(const ValueDFS &VD) const
bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const
ValueDFS_Compare(DominatorTree &DT)
bool localComesBefore(const ValueDFS &A, const ValueDFS &B) const
Struct that holds a reference to a particular GUID in a global value summary.