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;
263 assert(Top.
PInfo &&
"RenameStack should only contain predicate infos (defs)");
266 assert(VDUse.
PInfo &&
"A non-use VDUse should have a predicate info");
271 getBlockEdge(Top.
PInfo) == getBlockEdge(VDUse.
PInfo);
278 if (EdgePred != getBranchBlock(Top.
PInfo))
282 return DT.dominates(getBlockEdge(Top.
PInfo), *VDUse.
U);
288void PredicateInfoBuilder::popStackUntilDFSScope(ValueDFSStack &Stack,
290 while (!
Stack.empty() && !stackIsInScope(Stack, VD))
296void PredicateInfoBuilder::convertUsesToDFSOrdered(
298 for (
auto &U :
Op->uses()) {
302 if (
I->isLifetimeStartOrEnd())
309 IBlock = PN->getIncomingBlock(U);
341 auto *Op0 = Comparison->getOperand(0);
342 auto *Op1 = Comparison->getOperand(1);
353 auto &OperandInfo = getOrCreateValueInfo(
Op);
354 if (OperandInfo.Infos.empty())
356 OperandInfo.Infos.push_back(
PB);
361void PredicateInfoBuilder::processAssume(
365 SmallPtrSet<Value *, 4> Visited;
367 while (!Worklist.
empty()) {
387 for (
Value *V : Values) {
389 auto *PA =
new (Allocator) PredicateAssume(V,
II,
Cond);
390 addInfoFor(OpsToRename, V, PA);
398void PredicateInfoBuilder::processBranch(
404 for (BasicBlock *Succ : {FirstBB, SecondBB}) {
405 bool TakenEdge = Succ == FirstBB;
408 if (Succ == BranchBB)
412 SmallPtrSet<Value *, 4> Visited;
414 while (!Worklist.
empty()) {
435 for (
Value *V : Values) {
437 PredicateBase *
PB =
new (Allocator)
438 PredicateBranch(V, BranchBB, Succ,
Cond, TakenEdge);
439 addInfoFor(OpsToRename, V,
PB);
447void PredicateInfoBuilder::processSwitch(
455 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
456 for (BasicBlock *TargetBlock :
successors(BranchBB))
457 ++SwitchEdges[TargetBlock];
460 for (
auto C :
SI->cases()) {
462 if (SwitchEdges.
lookup(TargetBlock) == 1) {
463 PredicateSwitch *PS =
new (Allocator) PredicateSwitch(
464 Op,
SI->getParent(), TargetBlock,
C.getCaseValue(), SI);
465 addInfoFor(OpsToRename,
Op, PS);
472 DT.updateDFSNumbers();
477 if (!DT.isReachableFromEntry(&BB))
486 processBranch(BI, &BB, OpsToRename);
488 processSwitch(
SI, &BB, OpsToRename);
491 for (
auto &Assume : AC.assumptions()) {
493 if (DT.isReachableFromEntry(
II->getParent()))
494 processAssume(
II,
II->getParent(), OpsToRename);
497 renameUses(OpsToRename);
502Value *PredicateInfoBuilder::materializeStack(
unsigned int &Counter,
503 ValueDFSStack &RenameStack,
506 auto RevIter = RenameStack.rbegin();
507 for (; RevIter != RenameStack.rend(); ++RevIter)
511 size_t Start = RevIter - RenameStack.rbegin();
515 for (
auto RenameIter = RenameStack.end() - Start;
516 RenameIter != RenameStack.end(); ++RenameIter) {
518 RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def;
519 StackEntry &Result = *RenameIter;
520 auto *ValInfo = Result.V->PInfo;
521 ValInfo->RenamedOp = (RenameStack.end() - Start) == RenameStack.begin()
523 : (RenameStack.end() - Start - 1)->Def;
525 const Twine &Name =
"") {
536 Op->getName() +
"." +
Twine(Counter++));
537 PI.PredicateMap.insert({
PIC, ValInfo});
542 "Should not have gotten here without it being an assume");
545 BitCastInst *
PIC = CreateSSACopy(PAssume->AssumeInst->getNextNode(),
Op);
546 PI.PredicateMap.insert({
PIC, ValInfo});
550 return RenameStack.back().Def;
575 for (
auto *
Op : OpsToRename) {
577 unsigned Counter = 0;
579 const auto &ValueInfo = getValueInfo(
Op);
583 for (
const auto &PossibleCopy : ValueInfo.Infos) {
592 DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
597 VD.
PInfo = PossibleCopy;
603 auto BlockEdge = getBlockEdge(PossibleCopy);
604 if (!BlockEdge.second->getSinglePredecessor()) {
606 auto *DomNode = DT.getNode(BlockEdge.first);
610 VD.
PInfo = PossibleCopy;
618 auto *DomNode = DT.getNode(BlockEdge.second);
622 VD.
PInfo = PossibleCopy;
629 convertUsesToDFSOrdered(
Op, OrderedUses);
639 for (
const ValueDFS &VD : OrderedUses) {
642 if (RenameStack.
empty()) {
646 << RenameStack.
back().V->DFSIn <<
","
647 << RenameStack.
back().V->DFSOut <<
")\n");
654 popStackUntilDFSScope(RenameStack, VD);
663 if (RenameStack.
empty())
666 LLVM_DEBUG(
dbgs() <<
"Skipping execution due to debug counter\n");
675 Result.Def = materializeStack(Counter, RenameStack,
Op);
678 << *VD.
U->get() <<
" in " << *(VD.
U->getUser())
681 "Predicateinfo def should have dominated this use");
687PredicateInfoBuilder::ValueInfo &
688PredicateInfoBuilder::getOrCreateValueInfo(
Value *Operand) {
689 auto Res = ValueInfoNums.try_emplace(Operand, ValueInfos.size());
692 ValueInfos.resize(ValueInfos.size() + 1);
694 return ValueInfos[Res.first->second];
697const PredicateInfoBuilder::ValueInfo &
698PredicateInfoBuilder::getValueInfo(
Value *Operand)
const {
699 auto OINI = ValueInfoNums.lookup(Operand);
700 assert(OINI != 0 &&
"Operand was not really in the Value Info Numbers");
701 assert(OINI < ValueInfos.size() &&
702 "Value Info Number greater than size of Value Info Table");
703 return ValueInfos[OINI];
710 Builder.buildPredicateInfo();
717 bool TrueEdge =
true;
719 TrueEdge = PBranch->TrueEdge;
741 Pred = Cmp->getPredicate();
742 OtherOp = Cmp->getOperand(1);
743 }
else if (Cmp->getOperand(1) ==
RenamedOp) {
744 Pred = Cmp->getSwappedPredicate();
745 OtherOp = Cmp->getOperand(0);
755 return {{Pred, OtherOp}};
773 const auto *PI = PredInfo.getPredicateInfoFor(&Inst);
778 Inst.getType() == Inst.getOperand(0)->getType());
779 Inst.replaceAllUsesWith(Inst.getOperand(0));
780 Inst.eraseFromParent();
788 OS <<
"PredicateInfo for function: " <<
F.getName() <<
"\n";
790 auto PredInfo = std::make_unique<PredicateInfo>(
F, DT, AC, Allocator);
811 if (
const auto *PI = PredInfo->getPredicateInfoFor(
I)) {
813 OS <<
"; branch predicate info { TrueEdge: " <<
PB->TrueEdge
814 <<
" Comparison:" << *
PB->Condition <<
" Edge: [";
815 PB->From->printAsOperand(OS);
817 PB->To->printAsOperand(OS);
820 OS <<
"; switch predicate info { CaseValue: " << *PS->CaseValue
822 PS->From->printAsOperand(OS);
824 PS->To->printAsOperand(OS);
827 OS <<
"; assume predicate info {"
828 <<
" Comparison:" << *PA->Condition;
830 OS <<
", RenamedOp: ";
831 PI->RenamedOp->printAsOperand(OS,
false);
839 F.print(OS, &Writer);
844 F.print(
dbgs(), &Writer);
852 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 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