66#define DEBUG_TYPE "guard-widening"
68STATISTIC(GuardsEliminated,
"Number of eliminated guards");
69STATISTIC(CondBranchEliminated,
"Number of eliminated conditional branches");
70STATISTIC(FreezeAdded,
"Number of freeze instruction introduced");
74 cl::desc(
"Whether or not we should widen guards "
75 "expressed as branches by widenable conditions"),
83 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
84 "Bad guard intrinsic?");
85 return GI->getArgOperand(0);
92 return cast<BranchInst>(
I)->getCondition();
99 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&
100 "Bad guard intrinsic?");
101 GI->setArgOperand(0, NewCond);
104 cast<BranchInst>(
I)->setCondition(NewCond);
124static std::optional<BasicBlock::iterator>
125findInsertionPointForWideCondition(
Instruction *WCOrGuard) {
129 return cast<Instruction>(WC)->getIterator();
133class GuardWideningImpl {
157 bool eliminateInstrViaWidening(
165 WS_IllegalOrNegative,
180 static StringRef scoreTypeToString(WideningScore WS);
184 WideningScore computeWideningScore(
Instruction *DominatedInstr,
193 return canBeHoistedTo(V, InsertPos, Visited);
202 [&](
const Value *V) {
return canBeHoistedTo(V, InsertPos); });
210 for (
Value *V : Checks)
211 makeAvailableAt(V, InsertPos);
221 std::optional<Value *>
224 std::optional<BasicBlock::iterator> InsertPt);
250 void setBase(
const Value *NewBase) {
Base = NewBase; }
253 const Value *getBase()
const {
return Base; }
255 const APInt &getOffsetValue()
const {
return getOffset()->getValue(); }
257 ICmpInst *getCheckInst()
const {
return CheckInst; }
261 Base->printAsOperand(
OS, PrintTypes);
263 Offset->printAsOperand(
OS, PrintTypes);
265 Length->printAsOperand(
OS, PrintTypes);
279 for (
auto CheckCond : ToParse) {
280 if (!parseRangeChecks(CheckCond, Checks))
299 return mergeChecks(ChecksToHoist, ChecksToWiden, std::nullopt)
307 auto InsertPt = findInsertionPointForWideCondition(ToWiden);
308 auto MergedCheck = mergeChecks(ChecksToHoist, ChecksToWiden, InsertPt);
310 : hoistChecks(ChecksToHoist,
311 getCondition(ToWiden), *InsertPt);
317 setCondition(ToWiden, Result);
324 std::function<
bool(
BasicBlock *)> BlockFilter)
325 : DT(DT), PDT(PDT), LI(LI), AC(AC), MSSAU(MSSAU), Root(Root),
326 BlockFilter(BlockFilter) {}
341bool GuardWideningImpl::run() {
343 bool Changed =
false;
346 auto *BB = (*DFI)->getBlock();
347 if (!BlockFilter(BB))
350 auto &CurrentList = GuardsInBlock[BB];
354 CurrentList.push_back(cast<Instruction>(&
I));
356 for (
auto *
II : CurrentList)
357 Changed |= eliminateInstrViaWidening(
II, DFI, GuardsInBlock);
360 assert(EliminatedGuardsAndBranches.
empty() || Changed);
361 for (
auto *
I : EliminatedGuardsAndBranches)
362 if (!WidenedGuards.
count(
I)) {
363 assert(isa<ConstantInt>(getCondition(
I)) &&
"Should be!");
365 eliminateGuard(
I, MSSAU);
368 "Eliminated something other than guard or branch?");
369 ++CondBranchEliminated;
376bool GuardWideningImpl::eliminateInstrViaWidening(
385 if (ChecksToHoist.
empty() ||
386 (ChecksToHoist.
size() == 1 && isa<ConstantInt>(ChecksToHoist.
front())))
390 auto BestScoreSoFar = WS_IllegalOrNegative;
394 for (
unsigned i = 0, e = DFSI.
getPathLength(); i != e; ++i) {
395 auto *CurBB = DFSI.
getPath(i)->getBlock();
396 if (!BlockFilter(CurBB))
398 assert(GuardsInBlock.
count(CurBB) &&
"Must have been populated by now!");
399 const auto &GuardsInCurBB = GuardsInBlock.
find(CurBB)->second;
401 auto I = GuardsInCurBB.begin();
402 auto E =
Instr->getParent() == CurBB ?
find(GuardsInCurBB, Instr)
403 : GuardsInCurBB.
end();
408 for (
auto &
I : *CurBB) {
409 if (Index == GuardsInCurBB.size())
411 if (GuardsInCurBB[Index] == &
I)
414 assert(Index == GuardsInCurBB.size() &&
415 "Guards expected to be in order!");
419 assert((i == (e - 1)) == (
Instr->getParent() == CurBB) &&
"Bad DFS?");
422 auto WideningPoint = findInsertionPointForWideCondition(Candidate);
427 auto Score = computeWideningScore(Instr, Candidate, *WideningPoint,
428 ChecksToHoist, CandidateChecks);
429 LLVM_DEBUG(
dbgs() <<
"Score between " << *Instr <<
" and " << *Candidate
430 <<
" is " << scoreTypeToString(Score) <<
"\n");
431 if (Score > BestScoreSoFar) {
432 BestScoreSoFar = Score;
433 BestSoFar = Candidate;
438 if (BestScoreSoFar == WS_IllegalOrNegative) {
439 LLVM_DEBUG(
dbgs() <<
"Did not eliminate guard " << *Instr <<
"\n");
443 assert(BestSoFar != Instr &&
"Should have never visited same guard!");
446 LLVM_DEBUG(
dbgs() <<
"Widening " << *Instr <<
" into " << *BestSoFar
447 <<
" with score " << scoreTypeToString(BestScoreSoFar)
451 widenGuard(ChecksToHoist, ChecksToWiden, BestSoFar);
453 setCondition(Instr, NewGuardCondition);
454 EliminatedGuardsAndBranches.push_back(Instr);
455 WidenedGuards.
insert(BestSoFar);
459GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
464 Loop *DominatingGuardLoop = LI.
getLoopFor(WideningPoint->getParent());
465 bool HoistingOutOfLoop =
false;
467 if (DominatingGuardLoop != DominatedInstrLoop) {
470 if (DominatingGuardLoop &&
471 !DominatingGuardLoop->
contains(DominatedInstrLoop))
472 return WS_IllegalOrNegative;
474 HoistingOutOfLoop =
true;
477 if (!canBeHoistedTo(ChecksToHoist, WideningPoint))
478 return WS_IllegalOrNegative;
482 if (!canBeHoistedTo(getCondition(ToWiden), WideningPoint))
483 return WS_IllegalOrNegative;
493 if (isWideningCondProfitable(ChecksToHoist, ChecksToWiden))
494 return HoistingOutOfLoop ? WS_VeryPositive : WS_Positive;
496 if (HoistingOutOfLoop)
502 if (
auto *UniqueSucc = BB->getUniqueSuccessor())
504 auto *
Term = BB->getTerminator();
506 const BasicBlock *IfTrue =
nullptr, *IfFalse =
nullptr;
507 using namespace PatternMatch;
512 if (
auto *ConstCond = dyn_cast<ConstantInt>(
Cond))
513 return ConstCond->isAllOnesValue() ? IfTrue : IfFalse;
515 if (IfFalse->getPostdominatingDeoptimizeCall())
528 auto MaybeHoistingToHotterBlock = [&]() {
529 const auto *DominatingBlock = WideningPoint->
getParent();
530 const auto *DominatedBlock = DominatedInstr->
getParent();
535 assert(DT.
dominates(DominatingBlock, DominatedBlock) &&
"No dominance");
536 while (DominatedBlock != DominatingBlock) {
537 auto *LikelySucc = GetLikelySuccessor(DominatingBlock);
544 DominatingBlock = LikelySucc;
548 if (DominatedBlock == DominatingBlock)
552 if (!DT.
dominates(DominatingBlock, DominatedBlock))
557 return !PDT->
dominates(DominatedBlock, DominatingBlock);
560 return MaybeHoistingToHotterBlock() ? WS_IllegalOrNegative : WS_Neutral;
563bool GuardWideningImpl::canBeHoistedTo(
566 auto *Inst = dyn_cast<Instruction>(V);
571 Inst->mayReadFromMemory())
577 assert(!isa<PHINode>(Loc) &&
578 "PHIs should return false for isSafeToSpeculativelyExecute");
580 "We did a DFS from the block entry!");
581 return all_of(Inst->operands(),
582 [&](
Value *
Op) { return canBeHoistedTo(Op, Loc, Visited); });
585void GuardWideningImpl::makeAvailableAt(
Value *V,
587 auto *Inst = dyn_cast<Instruction>(V);
592 !Inst->mayReadFromMemory() &&
593 "Should've checked with canBeHoistedTo!");
595 for (
Value *
Op : Inst->operands())
596 makeAvailableAt(
Op, Loc);
598 Inst->moveBefore(*Loc->getParent(), Loc);
603static std::optional<BasicBlock::iterator>
605 auto *
I = dyn_cast<Instruction>(V);
609 std::optional<BasicBlock::iterator> Res =
I->getInsertionPointAfterDef();
619 Instruction *User = cast<Instruction>(U);
620 return ResInst != User && DT.dominates(I, User) &&
621 !DT.dominates(ResInst, User);
627Value *GuardWideningImpl::freezeAndPush(
Value *Orig,
631 std::optional<BasicBlock::iterator> InsertPtAtDef =
633 if (!InsertPtAtDef) {
638 if (isa<Constant>(Orig) || isa<GlobalValue>(Orig)) {
654 auto handleConstantOrGlobal = [&](
Use &
U) {
656 if (!isa<Constant>(Def) && !isa<GlobalValue>(Def))
659 if (Visited.
insert(Def).second) {
665 CacheOfFreezes[
Def] = FI;
668 if (CacheOfFreezes.
count(Def))
669 U.set(CacheOfFreezes[Def]);
674 while (!Worklist.
empty()) {
676 if (!Visited.
insert(V).second)
691 return isa<Instruction>(Op) && !getFreezeInsertPt(Op, DT);
697 for (
Use &U :
I->operands())
698 if (!handleConstantOrGlobal(U))
702 I->dropPoisonGeneratingAnnotations();
705 for (
Value *V : NeedFreeze) {
708 FI->
insertBefore(*FreezeInsertPt->getParent(), FreezeInsertPt);
712 V->replaceUsesWithIf(
713 FI, [&](
const Use & U)->
bool {
return U.getUser() != FI; });
719std::optional<Value *>
722 std::optional<BasicBlock::iterator> InsertPt) {
733 if (ChecksToWiden.
size() == 1 && ChecksToHoist.
size() == 1 &&
747 if (std::optional<ConstantRange> Intersect =
751 if (Intersect->getEquivalentICmp(Pred, NewRHSAP)) {
754 ConstantInt::get((*InsertPt)->getContext(), NewRHSAP);
755 assert(canBeHoistedTo(LHS, *InsertPt) &&
"must be");
756 makeAvailableAt(LHS, *InsertPt);
767 if (parseRangeChecks(ChecksToWiden, Checks) &&
768 parseRangeChecks(ChecksToHoist, Checks) &&
769 combineRangeChecks(Checks, CombinedChecks)) {
771 for (
auto &RC : CombinedChecks) {
772 makeAvailableAt(RC.getCheckInst(), *InsertPt);
774 Result = BinaryOperator::CreateAnd(RC.getCheckInst(), Result,
"",
777 Result = RC.getCheckInst();
779 assert(Result &&
"Failed to find result value");
780 Result->setName(
"wide.chk");
781 Result = freezeAndPush(Result, *InsertPt);
795 IRBuilder<> Builder(InsertPt->getParent(), InsertPt);
796 makeAvailableAt(ChecksToHoist, InsertPt);
797 makeAvailableAt(OldCondition, InsertPt);
799 Result = freezeAndPush(Result, InsertPt);
800 Result = Builder.CreateAnd(OldCondition, Result);
801 Result->setName(
"wide.chk");
805bool GuardWideningImpl::parseRangeChecks(
809 auto *IC = dyn_cast<ICmpInst>(CheckCond);
810 if (!IC || !IC->getOperand(0)->getType()->isIntegerTy() ||
811 (IC->getPredicate() != ICmpInst::ICMP_ULT &&
812 IC->getPredicate() != ICmpInst::ICMP_UGT))
815 const Value *CmpLHS = IC->getOperand(0), *CmpRHS = IC->getOperand(1);
816 if (IC->getPredicate() == ICmpInst::ICMP_UGT)
819 auto &
DL = IC->getDataLayout();
821 GuardWideningImpl::RangeCheck
Check(
822 CmpLHS, cast<ConstantInt>(ConstantInt::getNullValue(CmpRHS->getType())),
840 auto *BaseInst = dyn_cast<Instruction>(
Check.getBase());
842 "Unreachable instruction?");
846 Check.setBase(OpLHS);
848 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
854 Check.setBase(OpLHS);
856 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
866bool GuardWideningImpl::combineRangeChecks(
869 unsigned OldCount = Checks.
size();
870 while (!Checks.
empty()) {
873 const Value *CurrentBase = Checks.
front().getBase();
874 const Value *CurrentLength = Checks.
front().getLength();
878 auto IsCurrentCheck = [&](GuardWideningImpl::RangeCheck &RC) {
879 return RC.getBase() == CurrentBase && RC.getLength() == CurrentLength;
882 copy_if(Checks, std::back_inserter(CurrentChecks), IsCurrentCheck);
885 assert(CurrentChecks.
size() != 0 &&
"We know we have at least one!");
887 if (CurrentChecks.
size() < 3) {
895 llvm::sort(CurrentChecks, [&](
const GuardWideningImpl::RangeCheck &LHS,
896 const GuardWideningImpl::RangeCheck &RHS) {
897 return LHS.getOffsetValue().slt(
RHS.getOffsetValue());
906 if ((MaxOffset->
getValue() - MinOffset->getValue())
910 APInt MaxDiff = MaxOffset->
getValue() - MinOffset->getValue();
912 auto OffsetOK = [&](
const GuardWideningImpl::RangeCheck &RC) {
913 return (HighOffset - RC.getOffsetValue()).ult(MaxDiff);
958 assert(RangeChecksOut.
size() <= OldCount &&
"We pessimized!");
959 return RangeChecksOut.
size() != OldCount;
963StringRef GuardWideningImpl::scoreTypeToString(WideningScore WS) {
965 case WS_IllegalOrNegative:
966 return "IllegalOrNegative";
971 case WS_VeryPositive:
972 return "VeryPositive";
983 F.getParent(), Intrinsic::experimental_guard);
984 bool HasIntrinsicGuards = GuardDecl && !GuardDecl->use_empty();
986 F.getParent(), Intrinsic::experimental_widenable_condition);
987 bool HasWidenableConditions = WCDecl && !WCDecl->use_empty();
988 if (!HasIntrinsicGuards && !HasWidenableConditions)
995 std::unique_ptr<MemorySSAUpdater> MSSAU;
997 MSSAU = std::make_unique<MemorySSAUpdater>(&MSSAA->getMSSA());
998 if (!GuardWideningImpl(DT, &PDT, LI, AC, MSSAU ? MSSAU.get() :
nullptr,
1014 RootBB = L.getHeader();
1016 return BB == RootBB || L.contains(BB);
1018 std::unique_ptr<MemorySSAUpdater> MSSAU;
1020 MSSAU = std::make_unique<MemorySSAUpdater>(AR.
MSSA);
1021 if (!GuardWideningImpl(AR.
DT,
nullptr, AR.
LI, AR.
AC,
1022 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)
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.
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
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.
Function * getDeclarationIfExists(Module *M, ID id, ArrayRef< Type * > Tys, FunctionType *FT=nullptr)
This version supports overloaded intrinsics.
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.
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.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
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...