67#define DEBUG_TYPE "guard-widening"
69STATISTIC(GuardsEliminated,
"Number of eliminated guards");
70STATISTIC(CondBranchEliminated,
"Number of eliminated conditional branches");
71STATISTIC(FreezeAdded,
"Number of freeze instruction introduced");
75 cl::desc(
"Whether or not we should widen guards "
76 "expressed as branches by widenable conditions"),
84 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
85 "Bad guard intrinsic?");
86 return GI->getArgOperand(0);
93 return cast<BranchInst>(
I)->getCondition();
100 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
101 "Bad guard intrinsic?");
102 GI->setArgOperand(0, NewCond);
105 cast<BranchInst>(
I)->setCondition(NewCond);
125static std::optional<BasicBlock::iterator>
126findInsertionPointForWideCondition(
Instruction *WCOrGuard) {
130 return cast<Instruction>(WC)->getIterator();
134class GuardWideningImpl {
158 bool eliminateInstrViaWidening(
166 WS_IllegalOrNegative,
181 static StringRef scoreTypeToString(WideningScore WS);
185 WideningScore computeWideningScore(
Instruction *DominatedInstr,
194 return canBeHoistedTo(V, InsertPos, Visited);
203 [&](
const Value *V) {
return canBeHoistedTo(V, InsertPos); });
211 for (
Value *V : Checks)
212 makeAvailableAt(V, InsertPos);
222 std::optional<Value *>
225 std::optional<BasicBlock::iterator> InsertPt);
251 void setBase(
const Value *NewBase) {
Base = NewBase; }
254 const Value *getBase()
const {
return Base; }
256 const APInt &getOffsetValue()
const {
return getOffset()->getValue(); }
258 ICmpInst *getCheckInst()
const {
return CheckInst; }
262 Base->printAsOperand(
OS, PrintTypes);
264 Offset->printAsOperand(
OS, PrintTypes);
266 Length->printAsOperand(
OS, PrintTypes);
280 for (
auto CheckCond : ToParse) {
281 if (!parseRangeChecks(CheckCond, Checks))
300 return mergeChecks(ChecksToHoist, ChecksToWiden, std::nullopt)
308 auto InsertPt = findInsertionPointForWideCondition(ToWiden);
309 auto MergedCheck = mergeChecks(ChecksToHoist, ChecksToWiden, InsertPt);
311 : hoistChecks(ChecksToHoist,
312 getCondition(ToWiden), *InsertPt);
318 setCondition(ToWiden, Result);
325 std::function<
bool(
BasicBlock *)> BlockFilter)
326 : DT(DT), PDT(PDT), LI(LI), AC(AC), MSSAU(MSSAU), Root(Root),
327 BlockFilter(BlockFilter) {}
342bool GuardWideningImpl::run() {
344 bool Changed =
false;
347 auto *BB = (*DFI)->getBlock();
348 if (!BlockFilter(BB))
351 auto &CurrentList = GuardsInBlock[BB];
355 CurrentList.push_back(cast<Instruction>(&
I));
357 for (
auto *
II : CurrentList)
358 Changed |= eliminateInstrViaWidening(
II, DFI, GuardsInBlock);
361 assert(EliminatedGuardsAndBranches.
empty() || Changed);
362 for (
auto *
I : EliminatedGuardsAndBranches)
363 if (!WidenedGuards.
count(
I)) {
364 assert(isa<ConstantInt>(getCondition(
I)) &&
"Should be!");
366 eliminateGuard(
I, MSSAU);
369 "Eliminated something other than guard or branch?");
370 ++CondBranchEliminated;
377bool GuardWideningImpl::eliminateInstrViaWidening(
386 if (ChecksToHoist.
empty() ||
387 (ChecksToHoist.
size() == 1 && isa<ConstantInt>(ChecksToHoist.
front())))
391 auto BestScoreSoFar = WS_IllegalOrNegative;
395 for (
unsigned i = 0, e = DFSI.
getPathLength(); i != e; ++i) {
396 auto *CurBB = DFSI.
getPath(i)->getBlock();
397 if (!BlockFilter(CurBB))
399 assert(GuardsInBlock.
count(CurBB) &&
"Must have been populated by now!");
400 const auto &GuardsInCurBB = GuardsInBlock.
find(CurBB)->second;
402 auto I = GuardsInCurBB.begin();
403 auto E =
Instr->getParent() == CurBB ?
find(GuardsInCurBB, Instr)
404 : GuardsInCurBB.
end();
409 for (
auto &
I : *CurBB) {
410 if (
Index == GuardsInCurBB.size())
412 if (GuardsInCurBB[
Index] == &
I)
416 "Guards expected to be in order!");
420 assert((i == (e - 1)) == (
Instr->getParent() == CurBB) &&
"Bad DFS?");
423 auto WideningPoint = findInsertionPointForWideCondition(Candidate);
428 auto Score = computeWideningScore(Instr, Candidate, *WideningPoint,
429 ChecksToHoist, CandidateChecks);
430 LLVM_DEBUG(
dbgs() <<
"Score between " << *Instr <<
" and " << *Candidate
431 <<
" is " << scoreTypeToString(Score) <<
"\n");
432 if (Score > BestScoreSoFar) {
433 BestScoreSoFar = Score;
434 BestSoFar = Candidate;
439 if (BestScoreSoFar == WS_IllegalOrNegative) {
440 LLVM_DEBUG(
dbgs() <<
"Did not eliminate guard " << *Instr <<
"\n");
444 assert(BestSoFar != Instr &&
"Should have never visited same guard!");
447 LLVM_DEBUG(
dbgs() <<
"Widening " << *Instr <<
" into " << *BestSoFar
448 <<
" with score " << scoreTypeToString(BestScoreSoFar)
452 widenGuard(ChecksToHoist, ChecksToWiden, BestSoFar);
454 setCondition(Instr, NewGuardCondition);
455 EliminatedGuardsAndBranches.push_back(Instr);
456 WidenedGuards.
insert(BestSoFar);
460GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
465 Loop *DominatingGuardLoop = LI.
getLoopFor(WideningPoint->getParent());
466 bool HoistingOutOfLoop =
false;
468 if (DominatingGuardLoop != DominatedInstrLoop) {
471 if (DominatingGuardLoop &&
472 !DominatingGuardLoop->
contains(DominatedInstrLoop))
473 return WS_IllegalOrNegative;
475 HoistingOutOfLoop =
true;
478 if (!canBeHoistedTo(ChecksToHoist, WideningPoint))
479 return WS_IllegalOrNegative;
483 if (!canBeHoistedTo(getCondition(ToWiden), WideningPoint))
484 return WS_IllegalOrNegative;
494 if (isWideningCondProfitable(ChecksToHoist, ChecksToWiden))
495 return HoistingOutOfLoop ? WS_VeryPositive : WS_Positive;
497 if (HoistingOutOfLoop)
503 if (
auto *UniqueSucc = BB->getUniqueSuccessor())
505 auto *
Term = BB->getTerminator();
507 const BasicBlock *IfTrue =
nullptr, *IfFalse =
nullptr;
508 using namespace PatternMatch;
513 if (
auto *ConstCond = dyn_cast<ConstantInt>(
Cond))
514 return ConstCond->isAllOnesValue() ? IfTrue : IfFalse;
516 if (IfFalse->getPostdominatingDeoptimizeCall())
529 auto MaybeHoistingToHotterBlock = [&]() {
530 const auto *DominatingBlock = WideningPoint->
getParent();
531 const auto *DominatedBlock = DominatedInstr->
getParent();
536 assert(DT.
dominates(DominatingBlock, DominatedBlock) &&
"No dominance");
537 while (DominatedBlock != DominatingBlock) {
538 auto *LikelySucc = GetLikelySuccessor(DominatingBlock);
545 DominatingBlock = LikelySucc;
549 if (DominatedBlock == DominatingBlock)
553 if (!DT.
dominates(DominatingBlock, DominatedBlock))
558 return !PDT->
dominates(DominatedBlock, DominatingBlock);
561 return MaybeHoistingToHotterBlock() ? WS_IllegalOrNegative : WS_Neutral;
564bool GuardWideningImpl::canBeHoistedTo(
567 auto *Inst = dyn_cast<Instruction>(V);
572 Inst->mayReadFromMemory())
578 assert(!isa<PHINode>(Loc) &&
579 "PHIs should return false for isSafeToSpeculativelyExecute");
581 "We did a DFS from the block entry!");
582 return all_of(Inst->operands(),
583 [&](
Value *
Op) { return canBeHoistedTo(Op, Loc, Visited); });
586void GuardWideningImpl::makeAvailableAt(
Value *V,
588 auto *Inst = dyn_cast<Instruction>(V);
593 !Inst->mayReadFromMemory() &&
594 "Should've checked with canBeHoistedTo!");
596 for (
Value *
Op : Inst->operands())
597 makeAvailableAt(
Op, Loc);
599 Inst->moveBefore(*Loc->getParent(), Loc);
604static std::optional<BasicBlock::iterator>
606 auto *
I = dyn_cast<Instruction>(V);
610 std::optional<BasicBlock::iterator> Res =
I->getInsertionPointAfterDef();
620 Instruction *User = cast<Instruction>(U);
621 return ResInst != User && DT.dominates(I, User) &&
622 !DT.dominates(ResInst, User);
628Value *GuardWideningImpl::freezeAndPush(
Value *Orig,
632 std::optional<BasicBlock::iterator> InsertPtAtDef =
634 if (!InsertPtAtDef) {
639 if (isa<Constant>(Orig) || isa<GlobalValue>(Orig)) {
655 auto handleConstantOrGlobal = [&](
Use &
U) {
657 if (!isa<Constant>(Def) && !isa<GlobalValue>(Def))
660 if (Visited.
insert(Def).second) {
666 CacheOfFreezes[
Def] = FI;
669 if (CacheOfFreezes.
count(Def))
670 U.set(CacheOfFreezes[Def]);
675 while (!Worklist.
empty()) {
677 if (!Visited.
insert(V).second)
692 return isa<Instruction>(Op) && !getFreezeInsertPt(Op, DT);
698 for (
Use &U :
I->operands())
699 if (!handleConstantOrGlobal(U))
703 I->dropPoisonGeneratingAnnotations();
706 for (
Value *V : NeedFreeze) {
709 FI->
insertBefore(*FreezeInsertPt->getParent(), FreezeInsertPt);
713 V->replaceUsesWithIf(
714 FI, [&](
const Use & U)->
bool {
return U.getUser() != FI; });
720std::optional<Value *>
723 std::optional<BasicBlock::iterator> InsertPt) {
734 if (ChecksToWiden.
size() == 1 && ChecksToHoist.
size() == 1 &&
748 if (std::optional<ConstantRange> Intersect =
752 if (Intersect->getEquivalentICmp(Pred, NewRHSAP)) {
755 ConstantInt::get((*InsertPt)->getContext(), NewRHSAP);
756 assert(canBeHoistedTo(LHS, *InsertPt) &&
"must be");
757 makeAvailableAt(LHS, *InsertPt);
768 if (parseRangeChecks(ChecksToWiden, Checks) &&
769 parseRangeChecks(ChecksToHoist, Checks) &&
770 combineRangeChecks(Checks, CombinedChecks)) {
772 for (
auto &RC : CombinedChecks) {
773 makeAvailableAt(RC.getCheckInst(), *InsertPt);
775 Result = BinaryOperator::CreateAnd(RC.getCheckInst(), Result,
"",
778 Result = RC.getCheckInst();
780 assert(Result &&
"Failed to find result value");
781 Result->setName(
"wide.chk");
782 Result = freezeAndPush(Result, *InsertPt);
796 IRBuilder<> Builder(InsertPt->getParent(), InsertPt);
797 makeAvailableAt(ChecksToHoist, InsertPt);
798 makeAvailableAt(OldCondition, InsertPt);
800 Result = freezeAndPush(Result, InsertPt);
801 Result = Builder.CreateAnd(OldCondition, Result);
802 Result->setName(
"wide.chk");
806bool GuardWideningImpl::parseRangeChecks(
810 auto *IC = dyn_cast<ICmpInst>(CheckCond);
811 if (!IC || !IC->getOperand(0)->getType()->isIntegerTy() ||
812 (IC->getPredicate() != ICmpInst::ICMP_ULT &&
813 IC->getPredicate() != ICmpInst::ICMP_UGT))
816 const Value *CmpLHS = IC->getOperand(0), *CmpRHS = IC->getOperand(1);
817 if (IC->getPredicate() == ICmpInst::ICMP_UGT)
820 auto &
DL = IC->getDataLayout();
822 GuardWideningImpl::RangeCheck
Check(
823 CmpLHS, cast<ConstantInt>(ConstantInt::getNullValue(CmpRHS->getType())),
841 auto *BaseInst = dyn_cast<Instruction>(
Check.getBase());
843 "Unreachable instruction?");
847 Check.setBase(OpLHS);
849 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
855 Check.setBase(OpLHS);
857 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
867bool GuardWideningImpl::combineRangeChecks(
870 unsigned OldCount = Checks.
size();
871 while (!Checks.
empty()) {
874 const Value *CurrentBase = Checks.
front().getBase();
875 const Value *CurrentLength = Checks.
front().getLength();
879 auto IsCurrentCheck = [&](GuardWideningImpl::RangeCheck &RC) {
880 return RC.getBase() == CurrentBase && RC.getLength() == CurrentLength;
883 copy_if(Checks, std::back_inserter(CurrentChecks), IsCurrentCheck);
886 assert(CurrentChecks.
size() != 0 &&
"We know we have at least one!");
888 if (CurrentChecks.
size() < 3) {
896 llvm::sort(CurrentChecks, [&](
const GuardWideningImpl::RangeCheck &LHS,
897 const GuardWideningImpl::RangeCheck &RHS) {
898 return LHS.getOffsetValue().slt(
RHS.getOffsetValue());
907 if ((MaxOffset->
getValue() - MinOffset->getValue())
911 APInt MaxDiff = MaxOffset->
getValue() - MinOffset->getValue();
913 auto OffsetOK = [&](
const GuardWideningImpl::RangeCheck &RC) {
914 return (HighOffset - RC.getOffsetValue()).ult(MaxDiff);
959 assert(RangeChecksOut.
size() <= OldCount &&
"We pessimized!");
960 return RangeChecksOut.
size() != OldCount;
964StringRef GuardWideningImpl::scoreTypeToString(WideningScore WS) {
966 case WS_IllegalOrNegative:
967 return "IllegalOrNegative";
972 case WS_VeryPositive:
973 return "VeryPositive";
983 auto *GuardDecl =
F.getParent()->getFunction(
985 bool HasIntrinsicGuards = GuardDecl && !GuardDecl->use_empty();
986 auto *WCDecl =
F.getParent()->getFunction(
988 bool HasWidenableConditions = WCDecl && !WCDecl->use_empty();
989 if (!HasIntrinsicGuards && !HasWidenableConditions)
996 std::unique_ptr<MemorySSAUpdater> MSSAU;
998 MSSAU = std::make_unique<MemorySSAUpdater>(&MSSAA->getMSSA());
999 if (!GuardWideningImpl(DT, &PDT, LI, AC, MSSAU ? MSSAU.get() :
nullptr,
1015 RootBB = L.getHeader();
1017 return BB == RootBB || L.contains(BB);
1019 std::unique_ptr<MemorySSAUpdater> MSSAU;
1021 MSSAU = std::make_unique<MemorySSAUpdater>(AR.
MSSA);
1022 if (!GuardWideningImpl(AR.
DT,
nullptr, AR.
LI, AR.
AC,
1023 MSSAU ? MSSAU.get() :
nullptr, AR.
DT.
getNode(RootBB),
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static cl::opt< bool > WidenBranchGuards("guard-widening-widen-branch-guards", cl::Hidden, cl::desc("Whether or not we should widen guards " "expressed as branches by widenable conditions"), cl::init(true))
static bool isSupportedGuardInstruction(const Instruction *Insn)
static std::optional< BasicBlock::iterator > getFreezeInsertPt(Value *V, const DominatorTree &DT)
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isMinValue() const
Determine if this is the smallest unsigned value.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
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.
InstListType::iterator iterator
Instruction iterators...
const_iterator getFirstNonPHIOrDbgOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const CallInst * getPostdominatingDeoptimizeCall() const
Returns the call instruction calling @llvm.experimental.deoptimize that is present either in current ...
Represents analyses that only rely on functions' control flow.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
const APInt & getValue() const
Return the constant as an APInt value reference.
This class represents a range of values.
static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other)
Produce the exact range such that all values in the returned range satisfy the given predicate with a...
std::optional< ConstantRange > exactIntersectWith(const ConstantRange &CR) const
Intersect the two ranges and return the result if it can be represented exactly, otherwise return std...
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
This class represents a freeze function that returns random concrete value if an operand is either a ...
This instruction compares its operands according to the predicate given to the constructor.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A wrapper class for inspecting calls to intrinsic functions.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
Analysis pass that exposes the LoopInfo for a function.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
An analysis that produces MemorySSA for a function.
void removeMemoryAccess(MemoryAccess *, bool OptimizePhis=false)
Remove a MemoryAccess from MemorySSA, including updating all definitions and uses.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
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.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
LLVMContext & getContext() const
All values hold a context through their type.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
unsigned getPathLength() const
getPathLength - Return the length of the path from the entry node to the current node,...
NodeRef getPath(unsigned n) const
getPath - Return the n'th node in the path from the entry node to the current node.
const ParentTy * getParent() const
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.
StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
CmpClass_match< LHS, RHS, ICmpInst, ICmpInst::Predicate > m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R)
brc_match< Cond_t, bind_ty< BasicBlock >, bind_ty< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
class_match< BasicBlock > m_BasicBlock()
Match an arbitrary basic block value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< InstrNode * > Instr
NodeAddr< DefNode * > Def
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
df_iterator< T > df_begin(const T &G)
Value * extractWidenableCondition(const User *U)
void parseWidenableGuard(const User *U, llvm::SmallVectorImpl< Value * > &Checks)
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void setWidenableBranchCond(BranchInst *WidenableBR, Value *Cond)
Given a branch we know is widenable (defined per Analysis/GuardUtils.h), set it's condition such that...
bool isGuard(const User *U)
Returns true iff U has semantics of a guard expressed in a form of call of llvm.experimental....
bool parseWidenableBranch(const User *U, Value *&Condition, Value *&WidenableCondition, BasicBlock *&IfTrueBB, BasicBlock *&IfFalseBB)
If U is widenable branch looking like: cond = ... wc = call i1 @llvm.experimental....
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool canCreateUndefOrPoison(const Operator *Op, bool ConsiderFlagsAndMetadata=true)
canCreateUndefOrPoison returns true if Op can create undef or poison from non-undef & non-poison oper...
bool isGuardAsWidenableBranch(const User *U)
Returns true iff U has semantics of a guard expressed in a form of a widenable conditional branch to ...
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr unsigned BitWidth
PreservedAnalyses getLoopPassPreservedAnalyses()
Returns the minimum set of Analyses that all loop passes must preserve.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
df_iterator< T > df_end(const T &G)
bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...