28#define DEBUG_TYPE "predicateinfo"
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.");
56 "Not a predicate info type we know how to get a terminator from.");
62std::pair<BasicBlock *, BasicBlock *> getBlockEdge(
const PredicateBase *
PB) {
64 "Not a predicate info type we know how to get an edge from.");
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");
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);
179 assert(VD.
PInfo &&
"No use, and no predicateinfo should not occur");
181 "Middle of block should only occur for assumes");
217 ValueInfo &getOrCreateValueInfo(
Value *);
218 const ValueInfo &getValueInfo(
Value *)
const;
232 Value *Def =
nullptr;
234 StackEntry(
const ValueDFS *V) : V(V) {}
239 Value *materializeStack(
unsigned int &, ValueDFSStack &,
Value *);
240 bool stackIsInScope(
const ValueDFSStack &,
const ValueDFS &)
const;
241 void popStackUntilDFSScope(ValueDFSStack &,
const ValueDFS &);
246 : PI(PI), F(F), DT(DT), AC(AC), Allocator(Allocator) {
248 ValueInfos.resize(1);
254bool PredicateInfoBuilder::stackIsInScope(
const ValueDFSStack &Stack,
256 assert(!Stack.empty() &&
"Should not be called with empty stack");
262 const ValueDFS &Top = *Stack.back().V;
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()) {
295 if (
I->isLifetimeStartOrEnd())
302 IBlock = PN->getIncomingBlock(U);
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(
358 SmallPtrSet<Value *, 4> Visited;
360 while (!Worklist.
empty()) {
380 for (
Value *V : Values) {
382 auto *PA =
new (Allocator) PredicateAssume(V,
II,
Cond);
383 addInfoFor(OpsToRename, V, PA);
391void PredicateInfoBuilder::processBranch(
397 for (BasicBlock *Succ : {FirstBB, SecondBB}) {
398 bool TakenEdge = Succ == FirstBB;
401 if (Succ == BranchBB)
405 SmallPtrSet<Value *, 4> Visited;
407 while (!Worklist.
empty()) {
428 for (
Value *V : Values) {
430 PredicateBase *
PB =
new (Allocator)
431 PredicateBranch(V, BranchBB, Succ,
Cond, TakenEdge);
432 addInfoFor(OpsToRename, V,
PB);
440void PredicateInfoBuilder::processSwitch(
448 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
449 for (BasicBlock *TargetBlock :
successors(BranchBB))
450 ++SwitchEdges[TargetBlock];
453 for (
auto C :
SI->cases()) {
455 if (SwitchEdges.
lookup(TargetBlock) == 1) {
456 PredicateSwitch *PS =
new (Allocator) PredicateSwitch(
457 Op,
SI->getParent(), TargetBlock,
C.getCaseValue(), SI);
458 addInfoFor(OpsToRename,
Op, PS);
465 DT.updateDFSNumbers();
470 if (!DT.isReachableFromEntry(&BB))
479 processBranch(BI, &BB, OpsToRename);
481 processSwitch(
SI, &BB, OpsToRename);
484 for (
auto &Assume : AC.assumptions()) {
486 if (DT.isReachableFromEntry(
II->getParent()))
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;
518 const Twine &Name =
"") {
529 Op->getName() +
"." +
Twine(Counter++));
530 PI.PredicateMap.insert({
PIC, ValInfo});
535 "Should not have gotten here without it being an assume");
538 BitCastInst *
PIC = CreateSSACopy(PAssume->AssumeInst->getNextNode(),
Op);
539 PI.PredicateMap.insert({
PIC, ValInfo});
543 return RenameStack.back().Def;
568 for (
auto *
Op : OpsToRename) {
570 unsigned Counter = 0;
572 const auto &ValueInfo = getValueInfo(
Op);
576 for (
const auto &PossibleCopy : ValueInfo.Infos) {
585 DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
590 VD.
PInfo = 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());
685 ValueInfos.resize(ValueInfos.size() + 1);
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");
694 assert(OINI < ValueInfos.size() &&
695 "Value Info Number greater than size of Value Info Table");
696 return ValueInfos[OINI];
703 Builder.buildPredicateInfo();
710 bool TrueEdge =
true;
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}};
766 const auto *PI = PredInfo.getPredicateInfoFor(&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);
804 if (
const auto *PI = PredInfo->getPredicateInfoFor(
I)) {
805 OS <<
"; Has predicate info\n";
807 OS <<
"; branch predicate info { TrueEdge: " <<
PB->TrueEdge
808 <<
" Comparison:" << *
PB->Condition <<
" Edge: [";
809 PB->From->printAsOperand(OS);
811 PB->To->printAsOperand(OS);
814 OS <<
"; switch predicate info { CaseValue: " << *PS->CaseValue
815 <<
" Switch:" << *PS->Switch <<
" Edge: [";
816 PS->From->printAsOperand(OS);
818 PS->To->printAsOperand(OS);
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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.
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.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
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
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.
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.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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.
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...
friend class PredicateInfo
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.
friend class PredicateInfoAnnotatedWriter
LLVM_ABI void verifyPredicateInfo() const
friend class PredicateInfoBuilder
LLVM_ABI void print(raw_ostream &) const
LLVM_ABI PredicateInfo(Function &, DominatorTree &, AssumptionCache &, BumpPtrAllocator &)
LLVM_ABI void dump() 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.
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...
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
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.
@ BasicBlock
Various leaf nodes.
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.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
void collectCmpOps(CmpInst *Comparison, SmallVectorImpl< Value * > &CmpOperands)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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)
DomTreeNodeBase< BasicBlock > DomTreeNode
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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