Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
ConstraintElimination.cpp
Go to the documentation of this file.
1//===-- ConstraintElimination.cpp - Eliminate conds using constraints. ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Eliminate conditions based on constraints collected from dominating
10// conditions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Transforms/Scalar/ConstraintElimination.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/ScopeExit.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/Statistic.h"
19#include "llvm/Analysis/ConstraintSystem.h"
20#include "llvm/Analysis/GlobalsModRef.h"
21#include "llvm/Analysis/LoopInfo.h"
22#include "llvm/Analysis/OptimizationRemarkEmitter.h"
23#include "llvm/Analysis/ScalarEvolution.h"
24#include "llvm/Analysis/ScalarEvolutionExpressions.h"
25#include "llvm/Analysis/ValueTracking.h"
26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/Dominators.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/IRBuilder.h"
30#include "llvm/IR/InstrTypes.h"
31#include "llvm/IR/Instructions.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IR/PatternMatch.h"
34#include "llvm/IR/Verifier.h"
35#include "llvm/Pass.h"
36#include "llvm/Support/CommandLine.h"
37#include "llvm/Support/Debug.h"
38#include "llvm/Support/DebugCounter.h"
39#include "llvm/Support/MathExtras.h"
40#include "llvm/Transforms/Utils/Cloning.h"
41#include "llvm/Transforms/Utils/ValueMapper.h"
42
43#include <cmath>
44#include <optional>
45#include <string>
46
47using namespacellvm;
48using namespacePatternMatch;
49
50#define DEBUG_TYPE "constraint-elimination"
51
52STATISTIC(NumCondsRemoved,"Number of instructions removed");
53DEBUG_COUNTER(EliminatedCounter,"conds-eliminated",
54"Controls which conditions are eliminated");
55
56staticcl::opt<unsigned>
57MaxRows("constraint-elimination-max-rows",cl::init(500),cl::Hidden,
58cl::desc("Maximum number of rows to keep in constraint system"));
59
60staticcl::opt<bool>DumpReproducers(
61"constraint-elimination-dump-reproducers",cl::init(false),cl::Hidden,
62cl::desc("Dump IR to reproduce successful transformations."));
63
64static int64_tMaxConstraintValue = std::numeric_limits<int64_t>::max();
65static int64_tMinSignedConstraintValue = std::numeric_limits<int64_t>::min();
66
67// A helper to multiply 2 signed integers where overflowing is allowed.
68static int64_tmultiplyWithOverflow(int64_tA, int64_tB) {
69 int64_t Result;
70MulOverflow(A,B, Result);
71return Result;
72}
73
74// A helper to add 2 signed integers where overflowing is allowed.
75static int64_taddWithOverflow(int64_tA, int64_tB) {
76 int64_t Result;
77AddOverflow(A,B, Result);
78return Result;
79}
80
81staticInstruction *getContextInstForUse(Use &U) {
82Instruction *UserI = cast<Instruction>(U.getUser());
83if (auto *Phi = dyn_cast<PHINode>(UserI))
84 UserI = Phi->getIncomingBlock(U)->getTerminator();
85return UserI;
86}
87
88namespace{
89/// Struct to express a condition of the form %Op0 Pred %Op1.
90structConditionTy {
91CmpPredicate Pred;
92Value *Op0 =nullptr;
93Value *Op1 =nullptr;
94
95ConditionTy() =default;
96ConditionTy(CmpPredicate Pred,Value *Op0,Value *Op1)
97 : Pred(Pred), Op0(Op0), Op1(Op1) {}
98};
99
100/// Represents either
101/// * a condition that holds on entry to a block (=condition fact)
102/// * an assume (=assume fact)
103/// * a use of a compare instruction to simplify.
104/// It also tracks the Dominator DFS in and out numbers for each entry.
105structFactOrCheck {
106enum class EntryTy {
107 ConditionFact,/// A condition that holds on entry to a block.
108 InstFact,/// A fact that holds after Inst executed (e.g. an assume or
109 /// min/mix intrinsic.
110 InstCheck,/// An instruction to simplify (e.g. an overflow math
111 /// intrinsics).
112 UseCheck/// An use of a compare instruction to simplify.
113 };
114
115union{
116Instruction *Inst;
117Use *U;
118ConditionTyCond;
119 };
120
121 /// A pre-condition that must hold for the current fact to be added to the
122 /// system.
123ConditionTy DoesHold;
124
125unsigned NumIn;
126unsigned NumOut;
127 EntryTy Ty;
128
129 FactOrCheck(EntryTy Ty,DomTreeNode *DTN,Instruction *Inst)
130 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
131 Ty(Ty) {}
132
133 FactOrCheck(DomTreeNode *DTN,Use *U)
134 :U(U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
135 Ty(EntryTy::UseCheck) {}
136
137 FactOrCheck(DomTreeNode *DTN,CmpPredicate Pred,Value *Op0,Value *Op1,
138 ConditionTy Precond = {})
139 :Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
140 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
141
142static FactOrCheck getConditionFact(DomTreeNode *DTN,CmpPredicate Pred,
143Value *Op0,Value *Op1,
144 ConditionTy Precond = {}) {
145return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
146 }
147
148static FactOrCheck getInstFact(DomTreeNode *DTN,Instruction *Inst) {
149return FactOrCheck(EntryTy::InstFact, DTN, Inst);
150 }
151
152static FactOrCheck getCheck(DomTreeNode *DTN,Use *U) {
153return FactOrCheck(DTN, U);
154 }
155
156static FactOrCheck getCheck(DomTreeNode *DTN,CallInst *CI) {
157return FactOrCheck(EntryTy::InstCheck, DTN, CI);
158 }
159
160bool isCheck() const{
161return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
162 }
163
164Instruction *getContextInst() const{
165assert(!isConditionFact());
166if (Ty == EntryTy::UseCheck)
167returngetContextInstForUse(*U);
168return Inst;
169 }
170
171Instruction *getInstructionToSimplify() const{
172assert(isCheck());
173if (Ty == EntryTy::InstCheck)
174return Inst;
175// The use may have been simplified to a constant already.
176return dyn_cast<Instruction>(*U);
177 }
178
179bool isConditionFact() const{return Ty == EntryTy::ConditionFact; }
180};
181
182/// Keep state required to build worklist.
183structState {
184DominatorTree &DT;
185LoopInfo &LI;
186ScalarEvolution &SE;
187SmallVector<FactOrCheck, 64> WorkList;
188
189 State(DominatorTree &DT,LoopInfo &LI,ScalarEvolution &SE)
190 : DT(DT), LI(LI), SE(SE) {}
191
192 /// Process block \p BB and add known facts to work-list.
193void addInfoFor(BasicBlock &BB);
194
195 /// Try to add facts for loop inductions (AddRecs) in EQ/NE compares
196 /// controlling the loop header.
197void addInfoForInductions(BasicBlock &BB);
198
199 /// Returns true if we can add a known condition from BB to its successor
200 /// block Succ.
201bool canAddSuccessor(BasicBlock &BB,BasicBlock *Succ) const{
202return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
203 }
204};
205
206classConstraintInfo;
207
208structStackEntry {
209unsigned NumIn;
210unsigned NumOut;
211bool IsSigned =false;
212 /// Variables that can be removed from the system once the stack entry gets
213 /// removed.
214SmallVector<Value *, 2> ValuesToRelease;
215
216 StackEntry(unsigned NumIn,unsigned NumOut,bool IsSigned,
217SmallVector<Value *, 2> ValuesToRelease)
218 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
219 ValuesToRelease(std::move(ValuesToRelease)) {}
220};
221
222structConstraintTy {
223SmallVector<int64_t, 8> Coefficients;
224SmallVector<ConditionTy, 2> Preconditions;
225
226SmallVector<SmallVector<int64_t, 8>> ExtraInfo;
227
228bool IsSigned =false;
229
230 ConstraintTy() =default;
231
232 ConstraintTy(SmallVector<int64_t, 8> Coefficients,bool IsSigned,bool IsEq,
233bool IsNe)
234 : Coefficients(std::move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
235 IsNe(IsNe) {}
236
237unsignedsize() const{return Coefficients.size(); }
238
239unsigned empty() const{return Coefficients.empty(); }
240
241 /// Returns true if all preconditions for this list of constraints are
242 /// satisfied given \p CS and the corresponding \p Value2Index mapping.
243boolisValid(const ConstraintInfo &Info)const;
244
245bool isEq() const{return IsEq; }
246
247bool isNe() const{return IsNe; }
248
249 /// Check if the current constraint is implied by the given ConstraintSystem.
250 ///
251 /// \return true or false if the constraint is proven to be respectively true,
252 /// or false. When the constraint cannot be proven to be either true or false,
253 /// std::nullopt is returned.
254 std::optional<bool> isImpliedBy(constConstraintSystem &CS)const;
255
256private:
257bool IsEq =false;
258bool IsNe =false;
259};
260
261/// Wrapper encapsulating separate constraint systems and corresponding value
262/// mappings for both unsigned and signed information. Facts are added to and
263/// conditions are checked against the corresponding system depending on the
264/// signed-ness of their predicates. While the information is kept separate
265/// based on signed-ness, certain conditions can be transferred between the two
266/// systems.
267classConstraintInfo {
268
269ConstraintSystem UnsignedCS;
270ConstraintSystem SignedCS;
271
272constDataLayout &DL;
273
274public:
275 ConstraintInfo(constDataLayout &DL,ArrayRef<Value *> FunctionArgs)
276 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs),DL(DL) {
277auto &Value2Index = getValue2Index(false);
278// Add Arg > -1 constraints to unsigned system for all function arguments.
279for (Value *Arg : FunctionArgs) {
280 ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
281false,false,false);
282 VarPos.Coefficients[Value2Index[Arg]] = -1;
283 UnsignedCS.addVariableRow(VarPos.Coefficients);
284 }
285 }
286
287DenseMap<Value *, unsigned> &getValue2Index(boolSigned) {
288returnSigned ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
289 }
290constDenseMap<Value *, unsigned> &getValue2Index(boolSigned) const{
291returnSigned ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
292 }
293
294ConstraintSystem &getCS(boolSigned) {
295returnSigned ? SignedCS : UnsignedCS;
296 }
297constConstraintSystem &getCS(boolSigned) const{
298returnSigned ? SignedCS : UnsignedCS;
299 }
300
301void popLastConstraint(boolSigned) { getCS(Signed).popLastConstraint(); }
302void popLastNVariables(boolSigned,unsignedN) {
303 getCS(Signed).popLastNVariables(N);
304 }
305
306bool doesHold(CmpInst::Predicate Pred,Value *A,Value *B)const;
307
308void addFact(CmpInst::Predicate Pred,Value *A,Value *B,unsigned NumIn,
309unsigned NumOut,SmallVectorImpl<StackEntry> &DFSInStack);
310
311 /// Turn a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
312 /// constraints, using indices from the corresponding constraint system.
313 /// New variables that need to be added to the system are collected in
314 /// \p NewVariables.
315 ConstraintTy getConstraint(CmpInst::Predicate Pred,Value *Op0,Value *Op1,
316SmallVectorImpl<Value *> &NewVariables,
317bool ForceSignedSystem =false)const;
318
319 /// Turns a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
320 /// constraints using getConstraint. Returns an empty constraint if the result
321 /// cannot be used to query the existing constraint system, e.g. because it
322 /// would require adding new variables. Also tries to convert signed
323 /// predicates to unsigned ones if possible to allow using the unsigned system
324 /// which increases the effectiveness of the signed <-> unsigned transfer
325 /// logic.
326 ConstraintTy getConstraintForSolving(CmpInst::Predicate Pred,Value *Op0,
327Value *Op1)const;
328
329 /// Try to add information from \p A \p Pred \p B to the unsigned/signed
330 /// system if \p Pred is signed/unsigned.
331void transferToOtherSystem(CmpInst::Predicate Pred,Value *A,Value *B,
332unsigned NumIn,unsigned NumOut,
333SmallVectorImpl<StackEntry> &DFSInStack);
334
335private:
336 /// Adds facts into constraint system. \p ForceSignedSystem can be set when
337 /// the \p Pred is eq/ne, and signed constraint system is used when it's
338 /// specified.
339void addFactImpl(CmpInst::Predicate Pred,Value *A,Value *B,unsigned NumIn,
340unsigned NumOut,SmallVectorImpl<StackEntry> &DFSInStack,
341bool ForceSignedSystem);
342};
343
344/// Represents a (Coefficient * Variable) entry after IR decomposition.
345structDecompEntry {
346 int64_t Coefficient;
347Value *Variable;
348 /// True if the variable is known positive in the current constraint.
349bool IsKnownNonNegative;
350
351 DecompEntry(int64_t Coefficient,Value *Variable,
352bool IsKnownNonNegative =false)
353 : Coefficient(Coefficient), Variable(Variable),
354 IsKnownNonNegative(IsKnownNonNegative) {}
355};
356
357/// Represents an Offset + Coefficient1 * Variable1 + ... decomposition.
358structDecomposition {
359 int64_tOffset = 0;
360SmallVector<DecompEntry, 3> Vars;
361
362 Decomposition(int64_t Offset) :Offset(Offset) {}
363 Decomposition(Value *V,bool IsKnownNonNegative =false) {
364 Vars.emplace_back(1, V, IsKnownNonNegative);
365 }
366 Decomposition(int64_t Offset,ArrayRef<DecompEntry> Vars)
367 :Offset(Offset), Vars(Vars) {}
368
369voidadd(int64_t OtherOffset) {
370Offset =addWithOverflow(Offset, OtherOffset);
371 }
372
373voidadd(const Decomposition &Other) {
374add(Other.Offset);
375append_range(Vars,Other.Vars);
376 }
377
378voidsub(const Decomposition &Other) {
379 Decomposition Tmp =Other;
380 Tmp.mul(-1);
381add(Tmp.Offset);
382append_range(Vars, Tmp.Vars);
383 }
384
385void mul(int64_t Factor) {
386Offset =multiplyWithOverflow(Offset, Factor);
387for (auto &Var : Vars)
388 Var.Coefficient =multiplyWithOverflow(Var.Coefficient, Factor);
389 }
390};
391
392// Variable and constant offsets for a chain of GEPs, with base pointer BasePtr.
393structOffsetResult {
394Value *BasePtr;
395APInt ConstantOffset;
396SmallMapVector<Value *, APInt, 4> VariableOffsets;
397GEPNoWrapFlags NW;
398
399 OffsetResult() :BasePtr(nullptr), ConstantOffset(0,uint64_t(0)) {}
400
401 OffsetResult(GEPOperator &GEP,constDataLayout &DL)
402 :BasePtr(GEP.getPointerOperand()), NW(GEP.getNoWrapFlags()) {
403 ConstantOffset =APInt(DL.getIndexTypeSizeInBits(BasePtr->getType()), 0);
404 }
405};
406}// namespace
407
408// Try to collect variable and constant offsets for \p GEP, partly traversing
409// nested GEPs. Returns an OffsetResult with nullptr as BasePtr of collecting
410// the offset fails.
411static OffsetResultcollectOffsets(GEPOperator &GEP,constDataLayout &DL) {
412 OffsetResult Result(GEP,DL);
413unsignedBitWidth = Result.ConstantOffset.getBitWidth();
414if (!GEP.collectOffset(DL,BitWidth, Result.VariableOffsets,
415 Result.ConstantOffset))
416return {};
417
418// If we have a nested GEP, check if we can combine the constant offset of the
419// inner GEP with the outer GEP.
420if (auto *InnerGEP = dyn_cast<GetElementPtrInst>(Result.BasePtr)) {
421SmallMapVector<Value *, APInt, 4> VariableOffsets2;
422APInt ConstantOffset2(BitWidth, 0);
423bool CanCollectInner = InnerGEP->collectOffset(
424DL,BitWidth, VariableOffsets2, ConstantOffset2);
425// TODO: Support cases with more than 1 variable offset.
426if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
427 VariableOffsets2.size() > 1 ||
428 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.size() >= 1)) {
429// More than 1 variable index, use outer result.
430return Result;
431 }
432 Result.BasePtr = InnerGEP->getPointerOperand();
433 Result.ConstantOffset += ConstantOffset2;
434if (Result.VariableOffsets.size() == 0 && VariableOffsets2.size() == 1)
435 Result.VariableOffsets = VariableOffsets2;
436 Result.NW &= InnerGEP->getNoWrapFlags();
437 }
438return Result;
439}
440
441static Decompositiondecompose(Value *V,
442SmallVectorImpl<ConditionTy> &Preconditions,
443bool IsSigned,constDataLayout &DL);
444
445staticboolcanUseSExt(ConstantInt *CI) {
446constAPInt &Val = CI->getValue();
447return Val.sgt(MinSignedConstraintValue) && Val.slt(MaxConstraintValue);
448}
449
450static DecompositiondecomposeGEP(GEPOperator &GEP,
451SmallVectorImpl<ConditionTy> &Preconditions,
452bool IsSigned,constDataLayout &DL) {
453// Do not reason about pointers where the index size is larger than 64 bits,
454// as the coefficients used to encode constraints are 64 bit integers.
455if (DL.getIndexTypeSizeInBits(GEP.getPointerOperand()->getType()) > 64)
456return &GEP;
457
458assert(!IsSigned &&"The logic below only supports decomposition for "
459"unsigned predicates at the moment.");
460constauto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
461collectOffsets(GEP,DL);
462// We support either plain gep nuw, or gep nusw with non-negative offset,
463// which implies gep nuw.
464if (!BasePtr || NW ==GEPNoWrapFlags::none())
465return &GEP;
466
467 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
468for (auto [Index, Scale] : VariableOffsets) {
469auto IdxResult =decompose(Index, Preconditions, IsSigned,DL);
470 IdxResult.mul(Scale.getSExtValue());
471 Result.add(IdxResult);
472
473if (!NW.hasNoUnsignedWrap()) {
474// Try to prove nuw from nusw and nneg.
475assert(NW.hasNoUnsignedSignedWrap() &&"Must have nusw flag");
476if (!isKnownNonNegative(Index,DL))
477 Preconditions.emplace_back(CmpInst::ICMP_SGE, Index,
478 ConstantInt::get(Index->getType(), 0));
479 }
480 }
481return Result;
482}
483
484// Decomposes \p V into a constant offset + list of pairs { Coefficient,
485// Variable } where Coefficient * Variable. The sum of the constant offset and
486// pairs equals \p V.
487static Decompositiondecompose(Value *V,
488SmallVectorImpl<ConditionTy> &Preconditions,
489bool IsSigned,constDataLayout &DL) {
490
491auto MergeResults = [&Preconditions, IsSigned, &DL](Value *A,Value *B,
492bool IsSignedB) {
493auto ResA =decompose(A, Preconditions, IsSigned,DL);
494auto ResB =decompose(B, Preconditions, IsSignedB,DL);
495 ResA.add(ResB);
496return ResA;
497 };
498
499Type *Ty = V->getType()->getScalarType();
500if (Ty->isPointerTy() && !IsSigned) {
501if (auto *GEP = dyn_cast<GEPOperator>(V))
502returndecomposeGEP(*GEP, Preconditions, IsSigned,DL);
503if (isa<ConstantPointerNull>(V))
504return int64_t(0);
505
506return V;
507 }
508
509// Don't handle integers > 64 bit. Our coefficients are 64-bit large, so
510// coefficient add/mul may wrap, while the operation in the full bit width
511// would not.
512if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
513return V;
514
515bool IsKnownNonNegative =false;
516
517// Decompose \p V used with a signed predicate.
518if (IsSigned) {
519if (auto *CI = dyn_cast<ConstantInt>(V)) {
520if (canUseSExt(CI))
521return CI->getSExtValue();
522 }
523Value *Op0;
524Value *Op1;
525
526if (match(V,m_SExt(m_Value(Op0))))
527 V = Op0;
528elseif (match(V,m_NNegZExt(m_Value(Op0)))) {
529 V = Op0;
530 IsKnownNonNegative =true;
531 }elseif (match(V,m_NSWTrunc(m_Value(Op0)))) {
532if (Op0->getType()->getScalarSizeInBits() <= 64)
533 V = Op0;
534 }
535
536if (match(V,m_NSWAdd(m_Value(Op0),m_Value(Op1))))
537return MergeResults(Op0, Op1, IsSigned);
538
539if (match(V,m_NSWSub(m_Value(Op0),m_Value(Op1)))) {
540auto ResA =decompose(Op0, Preconditions, IsSigned,DL);
541auto ResB =decompose(Op1, Preconditions, IsSigned,DL);
542 ResA.sub(ResB);
543return ResA;
544 }
545
546ConstantInt *CI;
547if (match(V,m_NSWMul(m_Value(Op0),m_ConstantInt(CI))) &&canUseSExt(CI)) {
548auto Result =decompose(Op0, Preconditions, IsSigned,DL);
549 Result.mul(CI->getSExtValue());
550return Result;
551 }
552
553// (shl nsw x, shift) is (mul nsw x, (1<<shift)), with the exception of
554// shift == bw-1.
555if (match(V,m_NSWShl(m_Value(Op0),m_ConstantInt(CI)))) {
556uint64_t Shift = CI->getValue().getLimitedValue();
557if (Shift < Ty->getIntegerBitWidth() - 1) {
558assert(Shift < 64 &&"Would overflow");
559auto Result =decompose(Op0, Preconditions, IsSigned,DL);
560 Result.mul(int64_t(1) << Shift);
561return Result;
562 }
563 }
564
565return {V, IsKnownNonNegative};
566 }
567
568if (auto *CI = dyn_cast<ConstantInt>(V)) {
569if (CI->uge(MaxConstraintValue))
570return V;
571return int64_t(CI->getZExtValue());
572 }
573
574Value *Op0;
575if (match(V,m_ZExt(m_Value(Op0)))) {
576 IsKnownNonNegative =true;
577 V = Op0;
578 }elseif (match(V,m_SExt(m_Value(Op0)))) {
579 V = Op0;
580 Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0,
581 ConstantInt::get(Op0->getType(), 0));
582 }elseif (auto *Trunc = dyn_cast<TruncInst>(V)) {
583if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
584if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
585 V = Trunc->getOperand(0);
586if (!Trunc->hasNoUnsignedWrap())
587 Preconditions.emplace_back(CmpInst::ICMP_SGE, V,
588 ConstantInt::get(V->getType(), 0));
589 }
590 }
591 }
592
593Value *Op1;
594ConstantInt *CI;
595if (match(V,m_NUWAdd(m_Value(Op0),m_Value(Op1)))) {
596return MergeResults(Op0, Op1, IsSigned);
597 }
598if (match(V,m_NSWAdd(m_Value(Op0),m_Value(Op1)))) {
599if (!isKnownNonNegative(Op0,DL))
600 Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0,
601 ConstantInt::get(Op0->getType(), 0));
602if (!isKnownNonNegative(Op1,DL))
603 Preconditions.emplace_back(CmpInst::ICMP_SGE, Op1,
604 ConstantInt::get(Op1->getType(), 0));
605
606return MergeResults(Op0, Op1, IsSigned);
607 }
608
609if (match(V,m_Add(m_Value(Op0),m_ConstantInt(CI))) && CI->isNegative() &&
610canUseSExt(CI)) {
611 Preconditions.emplace_back(
612CmpInst::ICMP_UGE, Op0,
613 ConstantInt::get(Op0->getType(), CI->getSExtValue() * -1));
614return MergeResults(Op0, CI,true);
615 }
616
617// Decompose or as an add if there are no common bits between the operands.
618if (match(V,m_DisjointOr(m_Value(Op0),m_ConstantInt(CI))))
619return MergeResults(Op0, CI, IsSigned);
620
621if (match(V,m_NUWShl(m_Value(Op1),m_ConstantInt(CI))) &&canUseSExt(CI)) {
622if (CI->getSExtValue() < 0 || CI->getSExtValue() >= 64)
623return {V, IsKnownNonNegative};
624auto Result =decompose(Op1, Preconditions, IsSigned,DL);
625 Result.mul(int64_t{1} << CI->getSExtValue());
626return Result;
627 }
628
629if (match(V,m_NUWMul(m_Value(Op1),m_ConstantInt(CI))) &&canUseSExt(CI) &&
630 (!CI->isNegative())) {
631auto Result =decompose(Op1, Preconditions, IsSigned,DL);
632 Result.mul(CI->getSExtValue());
633return Result;
634 }
635
636if (match(V,m_NUWSub(m_Value(Op0),m_Value(Op1)))) {
637auto ResA =decompose(Op0, Preconditions, IsSigned,DL);
638auto ResB =decompose(Op1, Preconditions, IsSigned,DL);
639 ResA.sub(ResB);
640return ResA;
641 }
642
643return {V, IsKnownNonNegative};
644}
645
646ConstraintTy
647ConstraintInfo::getConstraint(CmpInst::Predicate Pred,Value *Op0,Value *Op1,
648SmallVectorImpl<Value *> &NewVariables,
649bool ForceSignedSystem) const{
650assert(NewVariables.empty() &&"NewVariables must be empty when passed in");
651assert((!ForceSignedSystem ||CmpInst::isEquality(Pred)) &&
652"signed system can only be forced on eq/ne");
653
654bool IsEq =false;
655bool IsNe =false;
656
657// Try to convert Pred to one of ULE/SLT/SLE/SLT.
658switch (Pred) {
659caseCmpInst::ICMP_UGT:
660caseCmpInst::ICMP_UGE:
661caseCmpInst::ICMP_SGT:
662caseCmpInst::ICMP_SGE: {
663 Pred =CmpInst::getSwappedPredicate(Pred);
664std::swap(Op0, Op1);
665break;
666 }
667caseCmpInst::ICMP_EQ:
668if (!ForceSignedSystem &&match(Op1,m_Zero())) {
669 Pred =CmpInst::ICMP_ULE;
670 }else {
671 IsEq =true;
672 Pred =CmpInst::ICMP_ULE;
673 }
674break;
675caseCmpInst::ICMP_NE:
676if (!ForceSignedSystem &&match(Op1,m_Zero())) {
677 Pred =CmpInst::getSwappedPredicate(CmpInst::ICMP_UGT);
678std::swap(Op0, Op1);
679 }else {
680 IsNe =true;
681 Pred =CmpInst::ICMP_ULE;
682 }
683break;
684default:
685break;
686 }
687
688if (Pred !=CmpInst::ICMP_ULE && Pred !=CmpInst::ICMP_ULT &&
689 Pred !=CmpInst::ICMP_SLE && Pred !=CmpInst::ICMP_SLT)
690return {};
691
692SmallVector<ConditionTy, 4> Preconditions;
693bool IsSigned = ForceSignedSystem ||CmpInst::isSigned(Pred);
694auto &Value2Index = getValue2Index(IsSigned);
695auto ADec =decompose(Op0->stripPointerCastsSameRepresentation(),
696 Preconditions, IsSigned,DL);
697auto BDec =decompose(Op1->stripPointerCastsSameRepresentation(),
698 Preconditions, IsSigned,DL);
699 int64_t Offset1 = ADec.Offset;
700 int64_t Offset2 = BDec.Offset;
701 Offset1 *= -1;
702
703auto &VariablesA = ADec.Vars;
704auto &VariablesB = BDec.Vars;
705
706// First try to look up \p V in Value2Index and NewVariables. Otherwise add a
707// new entry to NewVariables.
708SmallDenseMap<Value *, unsigned> NewIndexMap;
709auto GetOrAddIndex = [&Value2Index, &NewVariables,
710 &NewIndexMap](Value *V) ->unsigned {
711auto V2I = Value2Index.find(V);
712if (V2I != Value2Index.end())
713return V2I->second;
714auto Insert =
715 NewIndexMap.insert({V, Value2Index.size() + NewVariables.size() + 1});
716if (Insert.second)
717 NewVariables.push_back(V);
718returnInsert.first->second;
719 };
720
721// Make sure all variables have entries in Value2Index or NewVariables.
722for (constauto &KV : concat<DecompEntry>(VariablesA, VariablesB))
723 GetOrAddIndex(KV.Variable);
724
725// Build result constraint, by first adding all coefficients from A and then
726// subtracting all coefficients from B.
727 ConstraintTy Res(
728SmallVector<int64_t, 8>(Value2Index.size() + NewVariables.size() + 1, 0),
729 IsSigned, IsEq, IsNe);
730// Collect variables that are known to be positive in all uses in the
731// constraint.
732SmallDenseMap<Value *, bool> KnownNonNegativeVariables;
733auto &R = Res.Coefficients;
734for (constauto &KV : VariablesA) {
735R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
736autoI =
737 KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative});
738I.first->second &= KV.IsKnownNonNegative;
739 }
740
741for (constauto &KV : VariablesB) {
742auto &Coeff =R[GetOrAddIndex(KV.Variable)];
743if (SubOverflow(Coeff, KV.Coefficient, Coeff))
744return {};
745autoI =
746 KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative});
747I.first->second &= KV.IsKnownNonNegative;
748 }
749
750 int64_t OffsetSum;
751if (AddOverflow(Offset1, Offset2, OffsetSum))
752return {};
753if (Pred ==CmpInst::ICMP_SLT || Pred ==CmpInst::ICMP_ULT)
754if (AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
755return {};
756R[0] = OffsetSum;
757 Res.Preconditions = std::move(Preconditions);
758
759// Remove any (Coefficient, Variable) entry where the Coefficient is 0 for new
760// variables.
761while (!NewVariables.empty()) {
762 int64_tLast =R.back();
763if (Last != 0)
764break;
765R.pop_back();
766Value *RemovedV = NewVariables.pop_back_val();
767 NewIndexMap.erase(RemovedV);
768 }
769
770// Add extra constraints for variables that are known positive.
771for (auto &KV : KnownNonNegativeVariables) {
772if (!KV.second ||
773 (!Value2Index.contains(KV.first) && !NewIndexMap.contains(KV.first)))
774continue;
775auto &C = Res.ExtraInfo.emplace_back(
776 Value2Index.size() + NewVariables.size() + 1, 0);
777C[GetOrAddIndex(KV.first)] = -1;
778 }
779return Res;
780}
781
782ConstraintTy ConstraintInfo::getConstraintForSolving(CmpInst::Predicate Pred,
783Value *Op0,
784Value *Op1) const{
785Constant *NullC =Constant::getNullValue(Op0->getType());
786// Handle trivially true compares directly to avoid adding V UGE 0 constraints
787// for all variables in the unsigned system.
788if ((Pred ==CmpInst::ICMP_ULE && Op0 == NullC) ||
789 (Pred ==CmpInst::ICMP_UGE && Op1 == NullC)) {
790auto &Value2Index = getValue2Index(false);
791// Return constraint that's trivially true.
792return ConstraintTy(SmallVector<int64_t, 8>(Value2Index.size(), 0),false,
793false,false);
794 }
795
796// If both operands are known to be non-negative, change signed predicates to
797// unsigned ones. This increases the reasoning effectiveness in combination
798// with the signed <-> unsigned transfer logic.
799if (CmpInst::isSigned(Pred) &&
800isKnownNonNegative(Op0,DL,/*Depth=*/MaxAnalysisRecursionDepth - 1) &&
801isKnownNonNegative(Op1,DL,/*Depth=*/MaxAnalysisRecursionDepth - 1))
802 Pred =ICmpInst::getUnsignedPredicate(Pred);
803
804SmallVector<Value *> NewVariables;
805 ConstraintTyR = getConstraint(Pred, Op0, Op1, NewVariables);
806if (!NewVariables.empty())
807return {};
808returnR;
809}
810
811bool ConstraintTy::isValid(const ConstraintInfo &Info) const{
812return Coefficients.size() > 0 &&
813all_of(Preconditions, [&Info](const ConditionTy &C) {
814returnInfo.doesHold(C.Pred,C.Op0,C.Op1);
815 });
816}
817
818std::optional<bool>
819ConstraintTy::isImpliedBy(constConstraintSystem &CS) const{
820bool IsConditionImplied = CS.isConditionImplied(Coefficients);
821
822if (IsEq || IsNe) {
823auto NegatedOrEqual =ConstraintSystem::negateOrEqual(Coefficients);
824bool IsNegatedOrEqualImplied =
825 !NegatedOrEqual.empty() && CS.isConditionImplied(NegatedOrEqual);
826
827// In order to check that `%a == %b` is true (equality), both conditions `%a
828// >= %b` and `%a <= %b` must hold true. When checking for equality (`IsEq`
829// is true), we return true if they both hold, false in the other cases.
830if (IsConditionImplied && IsNegatedOrEqualImplied)
831return IsEq;
832
833auto Negated =ConstraintSystem::negate(Coefficients);
834bool IsNegatedImplied = !Negated.empty() && CS.isConditionImplied(Negated);
835
836auto StrictLessThan =ConstraintSystem::toStrictLessThan(Coefficients);
837bool IsStrictLessThanImplied =
838 !StrictLessThan.empty() && CS.isConditionImplied(StrictLessThan);
839
840// In order to check that `%a != %b` is true (non-equality), either
841// condition `%a > %b` or `%a < %b` must hold true. When checking for
842// non-equality (`IsNe` is true), we return true if one of the two holds,
843// false in the other cases.
844if (IsNegatedImplied || IsStrictLessThanImplied)
845return IsNe;
846
847return std::nullopt;
848 }
849
850if (IsConditionImplied)
851returntrue;
852
853auto Negated =ConstraintSystem::negate(Coefficients);
854auto IsNegatedImplied = !Negated.empty() && CS.isConditionImplied(Negated);
855if (IsNegatedImplied)
856returnfalse;
857
858// Neither the condition nor its negated holds, did not prove anything.
859return std::nullopt;
860}
861
862bool ConstraintInfo::doesHold(CmpInst::Predicate Pred,Value *A,
863Value *B) const{
864autoR = getConstraintForSolving(Pred,A,B);
865returnR.isValid(*this) &&
866 getCS(R.IsSigned).isConditionImplied(R.Coefficients);
867}
868
869void ConstraintInfo::transferToOtherSystem(
870CmpInst::Predicate Pred,Value *A,Value *B,unsigned NumIn,
871unsigned NumOut,SmallVectorImpl<StackEntry> &DFSInStack) {
872auto IsKnownNonNegative = [this](Value *V) {
873return doesHold(CmpInst::ICMP_SGE, V, ConstantInt::get(V->getType(), 0)) ||
874isKnownNonNegative(V,DL,/*Depth=*/MaxAnalysisRecursionDepth - 1);
875 };
876// Check if we can combine facts from the signed and unsigned systems to
877// derive additional facts.
878if (!A->getType()->isIntegerTy())
879return;
880// FIXME: This currently depends on the order we add facts. Ideally we
881// would first add all known facts and only then try to add additional
882// facts.
883switch (Pred) {
884default:
885break;
886caseCmpInst::ICMP_ULT:
887caseCmpInst::ICMP_ULE:
888// If B is a signed positive constant, then A >=s 0 and A <s (or <=s) B.
889if (IsKnownNonNegative(B)) {
890 addFact(CmpInst::ICMP_SGE,A, ConstantInt::get(B->getType(), 0), NumIn,
891 NumOut, DFSInStack);
892 addFact(ICmpInst::getSignedPredicate(Pred),A,B, NumIn, NumOut,
893 DFSInStack);
894 }
895break;
896caseCmpInst::ICMP_UGE:
897caseCmpInst::ICMP_UGT:
898// If A is a signed positive constant, then B >=s 0 and A >s (or >=s) B.
899if (IsKnownNonNegative(A)) {
900 addFact(CmpInst::ICMP_SGE,B, ConstantInt::get(B->getType(), 0), NumIn,
901 NumOut, DFSInStack);
902 addFact(ICmpInst::getSignedPredicate(Pred),A,B, NumIn, NumOut,
903 DFSInStack);
904 }
905break;
906caseCmpInst::ICMP_SLT:
907if (IsKnownNonNegative(A))
908 addFact(CmpInst::ICMP_ULT,A,B, NumIn, NumOut, DFSInStack);
909break;
910caseCmpInst::ICMP_SGT: {
911if (doesHold(CmpInst::ICMP_SGE,B,Constant::getAllOnesValue(B->getType())))
912 addFact(CmpInst::ICMP_UGE,A, ConstantInt::get(B->getType(), 0), NumIn,
913 NumOut, DFSInStack);
914if (IsKnownNonNegative(B))
915 addFact(CmpInst::ICMP_UGT,A,B, NumIn, NumOut, DFSInStack);
916
917break;
918 }
919caseCmpInst::ICMP_SGE:
920if (IsKnownNonNegative(B))
921 addFact(CmpInst::ICMP_UGE,A,B, NumIn, NumOut, DFSInStack);
922break;
923 }
924}
925
926#ifndef NDEBUG
927
928staticvoiddumpConstraint(ArrayRef<int64_t>C,
929constDenseMap<Value *, unsigned> &Value2Index) {
930ConstraintSystem CS(Value2Index);
931 CS.addVariableRowFill(C);
932 CS.dump();
933}
934#endif
935
936void State::addInfoForInductions(BasicBlock &BB) {
937auto *L = LI.getLoopFor(&BB);
938if (!L ||L->getHeader() != &BB)
939return;
940
941Value *A;
942Value *B;
943CmpPredicate Pred;
944
945if (!match(BB.getTerminator(),
946m_Br(m_ICmp(Pred,m_Value(A),m_Value(B)),m_Value(),m_Value())))
947return;
948PHINode *PN = dyn_cast<PHINode>(A);
949if (!PN) {
950 Pred =CmpInst::getSwappedPredicate(Pred);
951std::swap(A,B);
952 PN = dyn_cast<PHINode>(A);
953 }
954
955if (!PN || PN->getParent() != &BB || PN->getNumIncomingValues() != 2 ||
956 !SE.isSCEVable(PN->getType()))
957return;
958
959BasicBlock *InLoopSucc =nullptr;
960if (Pred ==CmpInst::ICMP_NE)
961 InLoopSucc = cast<BranchInst>(BB.getTerminator())->getSuccessor(0);
962elseif (Pred ==CmpInst::ICMP_EQ)
963 InLoopSucc = cast<BranchInst>(BB.getTerminator())->getSuccessor(1);
964else
965return;
966
967if (!L->contains(InLoopSucc) || !L->isLoopExiting(&BB) || InLoopSucc == &BB)
968return;
969
970auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.getSCEV(PN));
971BasicBlock *LoopPred =L->getLoopPredecessor();
972if (!AR || AR->getLoop() != L || !LoopPred)
973return;
974
975constSCEV *StartSCEV = AR->getStart();
976Value *StartValue =nullptr;
977if (auto *C = dyn_cast<SCEVConstant>(StartSCEV)) {
978 StartValue =C->getValue();
979 }else {
980 StartValue = PN->getIncomingValueForBlock(LoopPred);
981assert(SE.getSCEV(StartValue) == StartSCEV &&"inconsistent start value");
982 }
983
984DomTreeNode *DTN = DT.getNode(InLoopSucc);
985auto IncUnsigned = SE.getMonotonicPredicateType(AR,CmpInst::ICMP_UGT);
986auto IncSigned = SE.getMonotonicPredicateType(AR,CmpInst::ICMP_SGT);
987bool MonotonicallyIncreasingUnsigned =
988 IncUnsigned && *IncUnsigned ==ScalarEvolution::MonotonicallyIncreasing;
989bool MonotonicallyIncreasingSigned =
990 IncSigned && *IncSigned ==ScalarEvolution::MonotonicallyIncreasing;
991// If SCEV guarantees that AR does not wrap, PN >= StartValue can be added
992// unconditionally.
993if (MonotonicallyIncreasingUnsigned)
994 WorkList.push_back(
995 FactOrCheck::getConditionFact(DTN,CmpInst::ICMP_UGE, PN, StartValue));
996if (MonotonicallyIncreasingSigned)
997 WorkList.push_back(
998 FactOrCheck::getConditionFact(DTN,CmpInst::ICMP_SGE, PN, StartValue));
999
1000APInt StepOffset;
1001if (auto *C = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE)))
1002 StepOffset =C->getAPInt();
1003else
1004return;
1005
1006// Make sure the bound B is loop-invariant.
1007if (!L->isLoopInvariant(B))
1008return;
1009
1010// Handle negative steps.
1011if (StepOffset.isNegative()) {
1012// TODO: Extend to allow steps > -1.
1013if (!(-StepOffset).isOne())
1014return;
1015
1016// AR may wrap.
1017// Add StartValue >= PN conditional on B <= StartValue which guarantees that
1018// the loop exits before wrapping with a step of -1.
1019 WorkList.push_back(FactOrCheck::getConditionFact(
1020 DTN,CmpInst::ICMP_UGE, StartValue, PN,
1021ConditionTy(CmpInst::ICMP_ULE,B, StartValue)));
1022 WorkList.push_back(FactOrCheck::getConditionFact(
1023 DTN,CmpInst::ICMP_SGE, StartValue, PN,
1024ConditionTy(CmpInst::ICMP_SLE,B, StartValue)));
1025// Add PN > B conditional on B <= StartValue which guarantees that the loop
1026// exits when reaching B with a step of -1.
1027 WorkList.push_back(FactOrCheck::getConditionFact(
1028 DTN,CmpInst::ICMP_UGT, PN,B,
1029ConditionTy(CmpInst::ICMP_ULE,B, StartValue)));
1030 WorkList.push_back(FactOrCheck::getConditionFact(
1031 DTN,CmpInst::ICMP_SGT, PN,B,
1032ConditionTy(CmpInst::ICMP_SLE,B, StartValue)));
1033return;
1034 }
1035
1036// Make sure AR either steps by 1 or that the value we compare against is a
1037// GEP based on the same start value and all offsets are a multiple of the
1038// step size, to guarantee that the induction will reach the value.
1039if (StepOffset.isZero() || StepOffset.isNegative())
1040return;
1041
1042if (!StepOffset.isOne()) {
1043// Check whether B-Start is known to be a multiple of StepOffset.
1044constSCEV *BMinusStart = SE.getMinusSCEV(SE.getSCEV(B), StartSCEV);
1045if (isa<SCEVCouldNotCompute>(BMinusStart) ||
1046 !SE.getConstantMultiple(BMinusStart).urem(StepOffset).isZero())
1047return;
1048 }
1049
1050// AR may wrap. Add PN >= StartValue conditional on StartValue <= B which
1051// guarantees that the loop exits before wrapping in combination with the
1052// restrictions on B and the step above.
1053if (!MonotonicallyIncreasingUnsigned)
1054 WorkList.push_back(FactOrCheck::getConditionFact(
1055 DTN,CmpInst::ICMP_UGE, PN, StartValue,
1056ConditionTy(CmpInst::ICMP_ULE, StartValue,B)));
1057if (!MonotonicallyIncreasingSigned)
1058 WorkList.push_back(FactOrCheck::getConditionFact(
1059 DTN,CmpInst::ICMP_SGE, PN, StartValue,
1060ConditionTy(CmpInst::ICMP_SLE, StartValue,B)));
1061
1062 WorkList.push_back(FactOrCheck::getConditionFact(
1063 DTN,CmpInst::ICMP_ULT, PN,B,
1064ConditionTy(CmpInst::ICMP_ULE, StartValue,B)));
1065 WorkList.push_back(FactOrCheck::getConditionFact(
1066 DTN,CmpInst::ICMP_SLT, PN,B,
1067ConditionTy(CmpInst::ICMP_SLE, StartValue,B)));
1068
1069// Try to add condition from header to the dedicated exit blocks. When exiting
1070// either with EQ or NE in the header, we know that the induction value must
1071// be u<= B, as other exits may only exit earlier.
1072assert(!StepOffset.isNegative() &&"induction must be increasing");
1073assert((Pred ==CmpInst::ICMP_EQ || Pred ==CmpInst::ICMP_NE) &&
1074"unsupported predicate");
1075ConditionTy Precond = {CmpInst::ICMP_ULE, StartValue,B};
1076SmallVector<BasicBlock *> ExitBBs;
1077L->getExitBlocks(ExitBBs);
1078for (BasicBlock *EB : ExitBBs) {
1079// Bail out on non-dedicated exits.
1080if (DT.dominates(&BB, EB)) {
1081 WorkList.emplace_back(FactOrCheck::getConditionFact(
1082 DT.getNode(EB),CmpInst::ICMP_ULE,A,B, Precond));
1083 }
1084 }
1085}
1086
1087void State::addInfoFor(BasicBlock &BB) {
1088 addInfoForInductions(BB);
1089
1090// True as long as long as the current instruction is guaranteed to execute.
1091bool GuaranteedToExecute =true;
1092// Queue conditions and assumes.
1093for (Instruction &I : BB) {
1094if (auto Cmp = dyn_cast<ICmpInst>(&I)) {
1095for (Use &U :Cmp->uses()) {
1096auto *UserI =getContextInstForUse(U);
1097auto *DTN = DT.getNode(UserI->getParent());
1098if (!DTN)
1099continue;
1100 WorkList.push_back(FactOrCheck::getCheck(DTN, &U));
1101 }
1102continue;
1103 }
1104
1105auto *II = dyn_cast<IntrinsicInst>(&I);
1106Intrinsic::IDID =II ?II->getIntrinsicID() :Intrinsic::not_intrinsic;
1107switch (ID) {
1108case Intrinsic::assume: {
1109Value *A, *B;
1110CmpPredicate Pred;
1111if (!match(I.getOperand(0),m_ICmp(Pred,m_Value(A),m_Value(B))))
1112break;
1113if (GuaranteedToExecute) {
1114// The assume is guaranteed to execute when BB is entered, hence Cond
1115// holds on entry to BB.
1116 WorkList.emplace_back(FactOrCheck::getConditionFact(
1117 DT.getNode(I.getParent()), Pred,A,B));
1118 }else {
1119 WorkList.emplace_back(
1120 FactOrCheck::getInstFact(DT.getNode(I.getParent()), &I));
1121 }
1122break;
1123 }
1124// Enqueue ssub_with_overflow for simplification.
1125case Intrinsic::ssub_with_overflow:
1126case Intrinsic::ucmp:
1127case Intrinsic::scmp:
1128 WorkList.push_back(
1129 FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
1130break;
1131// Enqueue the intrinsics to add extra info.
1132case Intrinsic::umin:
1133case Intrinsic::umax:
1134case Intrinsic::smin:
1135case Intrinsic::smax:
1136// TODO: handle llvm.abs as well
1137 WorkList.push_back(
1138 FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
1139// TODO: Check if it is possible to instead only added the min/max facts
1140// when simplifying uses of the min/max intrinsics.
1141if (!isGuaranteedNotToBePoison(&I))
1142break;
1143 [[fallthrough]];
1144case Intrinsic::abs:
1145 WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I));
1146break;
1147 }
1148
1149 GuaranteedToExecute &=isGuaranteedToTransferExecutionToSuccessor(&I);
1150 }
1151
1152if (auto *Switch = dyn_cast<SwitchInst>(BB.getTerminator())) {
1153for (auto &Case :Switch->cases()) {
1154BasicBlock *Succ = Case.getCaseSuccessor();
1155Value *V = Case.getCaseValue();
1156if (!canAddSuccessor(BB, Succ))
1157continue;
1158 WorkList.emplace_back(FactOrCheck::getConditionFact(
1159 DT.getNode(Succ),CmpInst::ICMP_EQ,Switch->getCondition(), V));
1160 }
1161return;
1162 }
1163
1164auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
1165if (!Br || !Br->isConditional())
1166return;
1167
1168Value *Cond = Br->getCondition();
1169
1170// If the condition is a chain of ORs/AND and the successor only has the
1171// current block as predecessor, queue conditions for the successor.
1172Value *Op0, *Op1;
1173if (match(Cond,m_LogicalOr(m_Value(Op0),m_Value(Op1))) ||
1174match(Cond,m_LogicalAnd(m_Value(Op0),m_Value(Op1)))) {
1175bool IsOr =match(Cond,m_LogicalOr());
1176bool IsAnd =match(Cond,m_LogicalAnd());
1177// If there's a select that matches both AND and OR, we need to commit to
1178// one of the options. Arbitrarily pick OR.
1179if (IsOr && IsAnd)
1180 IsAnd =false;
1181
1182BasicBlock *Successor = Br->getSuccessor(IsOr ? 1 : 0);
1183if (canAddSuccessor(BB,Successor)) {
1184SmallVector<Value *> CondWorkList;
1185SmallPtrSet<Value *, 8> SeenCond;
1186auto QueueValue = [&CondWorkList, &SeenCond](Value *V) {
1187if (SeenCond.insert(V).second)
1188 CondWorkList.push_back(V);
1189 };
1190 QueueValue(Op1);
1191 QueueValue(Op0);
1192while (!CondWorkList.empty()) {
1193Value *Cur = CondWorkList.pop_back_val();
1194if (auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
1195 WorkList.emplace_back(FactOrCheck::getConditionFact(
1196 DT.getNode(Successor),
1197 IsOr ?Cmp->getInverseCmpPredicate() :Cmp->getCmpPredicate(),
1198Cmp->getOperand(0),Cmp->getOperand(1)));
1199continue;
1200 }
1201if (IsOr &&match(Cur,m_LogicalOr(m_Value(Op0),m_Value(Op1)))) {
1202 QueueValue(Op1);
1203 QueueValue(Op0);
1204continue;
1205 }
1206if (IsAnd &&match(Cur,m_LogicalAnd(m_Value(Op0),m_Value(Op1)))) {
1207 QueueValue(Op1);
1208 QueueValue(Op0);
1209continue;
1210 }
1211 }
1212 }
1213return;
1214 }
1215
1216auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
1217if (!CmpI)
1218return;
1219if (canAddSuccessor(BB, Br->getSuccessor(0)))
1220 WorkList.emplace_back(FactOrCheck::getConditionFact(
1221 DT.getNode(Br->getSuccessor(0)), CmpI->getCmpPredicate(),
1222 CmpI->getOperand(0), CmpI->getOperand(1)));
1223if (canAddSuccessor(BB, Br->getSuccessor(1)))
1224 WorkList.emplace_back(FactOrCheck::getConditionFact(
1225 DT.getNode(Br->getSuccessor(1)), CmpI->getInverseCmpPredicate(),
1226 CmpI->getOperand(0), CmpI->getOperand(1)));
1227}
1228
1229#ifndef NDEBUG
1230staticvoiddumpUnpackedICmp(raw_ostream &OS,ICmpInst::Predicate Pred,
1231Value *LHS,Value *RHS) {
1232OS <<"icmp " << Pred <<' ';
1233LHS->printAsOperand(OS,/*PrintType=*/true);
1234OS <<", ";
1235RHS->printAsOperand(OS,/*PrintType=*/false);
1236}
1237#endif
1238
1239namespace{
1240/// Helper to keep track of a condition and if it should be treated as negated
1241/// for reproducer construction.
1242/// Pred == Predicate::BAD_ICMP_PREDICATE indicates that this entry is a
1243/// placeholder to keep the ReproducerCondStack in sync with DFSInStack.
1244structReproducerEntry {
1245ICmpInst::Predicate Pred;
1246Value *LHS;
1247Value *RHS;
1248
1249 ReproducerEntry(ICmpInst::Predicate Pred,Value *LHS,Value *RHS)
1250 : Pred(Pred),LHS(LHS),RHS(RHS) {}
1251};
1252}// namespace
1253
1254/// Helper function to generate a reproducer function for simplifying \p Cond.
1255/// The reproducer function contains a series of @llvm.assume calls, one for
1256/// each condition in \p Stack. For each condition, the operand instruction are
1257/// cloned until we reach operands that have an entry in \p Value2Index. Those
1258/// will then be added as function arguments. \p DT is used to order cloned
1259/// instructions. The reproducer function will get added to \p M, if it is
1260/// non-null. Otherwise no reproducer function is generated.
1261staticvoidgenerateReproducer(CmpInst *Cond,Module *M,
1262ArrayRef<ReproducerEntry> Stack,
1263 ConstraintInfo &Info,DominatorTree &DT) {
1264if (!M)
1265return;
1266
1267LLVMContext &Ctx =Cond->getContext();
1268
1269LLVM_DEBUG(dbgs() <<"Creating reproducer for " << *Cond <<"\n");
1270
1271ValueToValueMapTy Old2New;
1272SmallVector<Value *> Args;
1273SmallPtrSet<Value *, 8> Seen;
1274// Traverse Cond and its operands recursively until we reach a value that's in
1275// Value2Index or not an instruction, or not a operation that
1276// ConstraintElimination can decompose. Such values will be considered as
1277// external inputs to the reproducer, they are collected and added as function
1278// arguments later.
1279auto CollectArguments = [&](ArrayRef<Value *> Ops,bool IsSigned) {
1280auto &Value2Index =Info.getValue2Index(IsSigned);
1281SmallVector<Value *, 4> WorkList(Ops);
1282while (!WorkList.empty()) {
1283Value *V = WorkList.pop_back_val();
1284if (!Seen.insert(V).second)
1285continue;
1286if (Old2New.find(V) != Old2New.end())
1287continue;
1288if (isa<Constant>(V))
1289continue;
1290
1291auto *I = dyn_cast<Instruction>(V);
1292if (Value2Index.contains(V) || !I ||
1293 !isa<CmpInst, BinaryOperator, GEPOperator, CastInst>(V)) {
1294 Old2New[V] = V;
1295 Args.push_back(V);
1296LLVM_DEBUG(dbgs() <<" found external input " << *V <<"\n");
1297 }else {
1298append_range(WorkList,I->operands());
1299 }
1300 }
1301 };
1302
1303for (auto &Entry : Stack)
1304if (Entry.Pred != ICmpInst::BAD_ICMP_PREDICATE)
1305 CollectArguments({Entry.LHS, Entry.RHS}, ICmpInst::isSigned(Entry.Pred));
1306 CollectArguments(Cond, ICmpInst::isSigned(Cond->getPredicate()));
1307
1308SmallVector<Type *> ParamTys;
1309for (auto *P : Args)
1310 ParamTys.push_back(P->getType());
1311
1312FunctionType *FTy = FunctionType::get(Cond->getType(), ParamTys,
1313/*isVarArg=*/false);
1314Function *F =Function::Create(FTy, Function::ExternalLinkage,
1315Cond->getModule()->getName() +
1316Cond->getFunction()->getName() +"repro",
1317 M);
1318// Add arguments to the reproducer function for each external value collected.
1319for (unsignedI = 0;I < Args.size(); ++I) {
1320F->getArg(I)->setName(Args[I]->getName());
1321 Old2New[Args[I]] =F->getArg(I);
1322 }
1323
1324BasicBlock *Entry =BasicBlock::Create(Ctx,"entry",F);
1325IRBuilder<> Builder(Entry);
1326 Builder.CreateRet(Builder.getTrue());
1327 Builder.SetInsertPoint(Entry->getTerminator());
1328
1329// Clone instructions in \p Ops and their operands recursively until reaching
1330// an value in Value2Index (external input to the reproducer). Update Old2New
1331// mapping for the original and cloned instructions. Sort instructions to
1332// clone by dominance, then insert the cloned instructions in the function.
1333auto CloneInstructions = [&](ArrayRef<Value *> Ops,bool IsSigned) {
1334SmallVector<Value *, 4> WorkList(Ops);
1335SmallVector<Instruction *> ToClone;
1336auto &Value2Index =Info.getValue2Index(IsSigned);
1337while (!WorkList.empty()) {
1338Value *V = WorkList.pop_back_val();
1339if (Old2New.find(V) != Old2New.end())
1340continue;
1341
1342auto *I = dyn_cast<Instruction>(V);
1343if (!Value2Index.contains(V) &&I) {
1344 Old2New[V] =nullptr;
1345 ToClone.push_back(I);
1346append_range(WorkList,I->operands());
1347 }
1348 }
1349
1350sort(ToClone,
1351 [&DT](Instruction *A,Instruction *B) {return DT.dominates(A,B); });
1352for (Instruction *I : ToClone) {
1353Instruction *Cloned =I->clone();
1354 Old2New[I] = Cloned;
1355 Old2New[I]->setName(I->getName());
1356 Cloned->insertBefore(Builder.GetInsertPoint());
1357 Cloned->dropUnknownNonDebugMetadata();
1358 Cloned->setDebugLoc({});
1359 }
1360 };
1361
1362// Materialize the assumptions for the reproducer using the entries in Stack.
1363// That is, first clone the operands of the condition recursively until we
1364// reach an external input to the reproducer and add them to the reproducer
1365// function. Then add an ICmp for the condition (with the inverse predicate if
1366// the entry is negated) and an assert using the ICmp.
1367for (auto &Entry : Stack) {
1368if (Entry.Pred == ICmpInst::BAD_ICMP_PREDICATE)
1369continue;
1370
1371LLVM_DEBUG(dbgs() <<" Materializing assumption ";
1372dumpUnpackedICmp(dbgs(), Entry.Pred, Entry.LHS, Entry.RHS);
1373dbgs() <<"\n");
1374 CloneInstructions({Entry.LHS, Entry.RHS},CmpInst::isSigned(Entry.Pred));
1375
1376auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1377 Builder.CreateAssumption(Cmp);
1378 }
1379
1380// Finally, clone the condition to reproduce and remap instruction operands in
1381// the reproducer using Old2New.
1382 CloneInstructions(Cond,CmpInst::isSigned(Cond->getPredicate()));
1383 Entry->getTerminator()->setOperand(0,Cond);
1384remapInstructionsInBlocks({Entry}, Old2New);
1385
1386assert(!verifyFunction(*F, &dbgs()));
1387}
1388
1389static std::optional<bool>checkCondition(CmpInst::Predicate Pred,Value *A,
1390Value *B,Instruction *CheckInst,
1391 ConstraintInfo &Info) {
1392LLVM_DEBUG(dbgs() <<"Checking " << *CheckInst <<"\n");
1393
1394auto R =Info.getConstraintForSolving(Pred,A,B);
1395if (R.empty() || !R.isValid(Info)){
1396LLVM_DEBUG(dbgs() <<" failed to decompose condition\n");
1397return std::nullopt;
1398 }
1399
1400auto &CSToUse =Info.getCS(R.IsSigned);
1401
1402// If there was extra information collected during decomposition, apply
1403// it now and remove it immediately once we are done with reasoning
1404// about the constraint.
1405for (auto &Row : R.ExtraInfo)
1406 CSToUse.addVariableRow(Row);
1407auto InfoRestorer =make_scope_exit([&]() {
1408for (unsignedI = 0;I < R.ExtraInfo.size(); ++I)
1409 CSToUse.popLastConstraint();
1410 });
1411
1412if (auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1413if (!DebugCounter::shouldExecute(EliminatedCounter))
1414return std::nullopt;
1415
1416LLVM_DEBUG({
1417dbgs() <<"Condition ";
1418dumpUnpackedICmp(
1419dbgs(), *ImpliedCondition ? Pred :CmpInst::getInversePredicate(Pred),
1420A,B);
1421dbgs() <<" implied by dominating constraints\n";
1422 CSToUse.dump();
1423 });
1424return ImpliedCondition;
1425 }
1426
1427return std::nullopt;
1428}
1429
1430staticboolcheckAndReplaceCondition(
1431CmpInst *Cmp, ConstraintInfo &Info,unsigned NumIn,unsigned NumOut,
1432Instruction *ContextInst,Module *ReproducerModule,
1433ArrayRef<ReproducerEntry> ReproducerCondStack,DominatorTree &DT,
1434SmallVectorImpl<Instruction *> &ToRemove) {
1435auto ReplaceCmpWithConstant = [&](CmpInst *Cmp,bool IsTrue) {
1436generateReproducer(Cmp, ReproducerModule, ReproducerCondStack,Info, DT);
1437Constant *ConstantC =ConstantInt::getBool(
1438CmpInst::makeCmpResultType(Cmp->getType()), IsTrue);
1439 Cmp->replaceUsesWithIf(ConstantC, [&DT, NumIn, NumOut,
1440 ContextInst](Use &U) {
1441auto *UserI =getContextInstForUse(U);
1442auto *DTN = DT.getNode(UserI->getParent());
1443if (!DTN || DTN->getDFSNumIn() < NumIn || DTN->getDFSNumOut() > NumOut)
1444returnfalse;
1445if (UserI->getParent() == ContextInst->getParent() &&
1446 UserI->comesBefore(ContextInst))
1447returnfalse;
1448
1449// Conditions in an assume trivially simplify to true. Skip uses
1450// in assume calls to not destroy the available information.
1451auto *II = dyn_cast<IntrinsicInst>(U.getUser());
1452return !II ||II->getIntrinsicID() != Intrinsic::assume;
1453 });
1454 NumCondsRemoved++;
1455if (Cmp->use_empty())
1456ToRemove.push_back(Cmp);
1457returntrue;
1458 };
1459
1460if (auto ImpliedCondition =
1461checkCondition(Cmp->getPredicate(), Cmp->getOperand(0),
1462 Cmp->getOperand(1), Cmp,Info))
1463return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1464returnfalse;
1465}
1466
1467staticboolcheckAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info,
1468SmallVectorImpl<Instruction *> &ToRemove) {
1469auto ReplaceMinMaxWithOperand = [&](MinMaxIntrinsic *MinMax,bool UseLHS) {
1470// TODO: generate reproducer for min/max.
1471MinMax->replaceAllUsesWith(MinMax->getOperand(UseLHS ? 0 : 1));
1472ToRemove.push_back(MinMax);
1473returntrue;
1474 };
1475
1476ICmpInst::Predicate Pred =
1477 ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
1478if (auto ImpliedCondition =checkCondition(
1479 Pred,MinMax->getOperand(0),MinMax->getOperand(1),MinMax,Info))
1480return ReplaceMinMaxWithOperand(MinMax, *ImpliedCondition);
1481if (auto ImpliedCondition =checkCondition(
1482 Pred,MinMax->getOperand(1),MinMax->getOperand(0),MinMax,Info))
1483return ReplaceMinMaxWithOperand(MinMax, !*ImpliedCondition);
1484returnfalse;
1485}
1486
1487staticboolcheckAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
1488SmallVectorImpl<Instruction *> &ToRemove) {
1489Value *LHS =I->getOperand(0);
1490Value *RHS =I->getOperand(1);
1491if (checkCondition(I->getGTPredicate(),LHS,RHS,I,Info).value_or(false)) {
1492I->replaceAllUsesWith(ConstantInt::get(I->getType(), 1));
1493ToRemove.push_back(I);
1494returntrue;
1495 }
1496if (checkCondition(I->getLTPredicate(),LHS,RHS,I,Info).value_or(false)) {
1497I->replaceAllUsesWith(ConstantInt::getSigned(I->getType(), -1));
1498ToRemove.push_back(I);
1499returntrue;
1500 }
1501if (checkCondition(ICmpInst::ICMP_EQ,LHS,RHS,I,Info).value_or(false)) {
1502I->replaceAllUsesWith(ConstantInt::get(I->getType(), 0));
1503ToRemove.push_back(I);
1504returntrue;
1505 }
1506returnfalse;
1507}
1508
1509staticvoid
1510removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
1511Module *ReproducerModule,
1512SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1513SmallVectorImpl<StackEntry> &DFSInStack) {
1514Info.popLastConstraint(E.IsSigned);
1515// Remove variables in the system that went out of scope.
1516auto &Mapping =Info.getValue2Index(E.IsSigned);
1517for (Value *V : E.ValuesToRelease)
1518 Mapping.erase(V);
1519Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
1520 DFSInStack.pop_back();
1521if (ReproducerModule)
1522 ReproducerCondStack.pop_back();
1523}
1524
1525/// Check if either the first condition of an AND or OR is implied by the
1526/// (negated in case of OR) second condition or vice versa.
1527staticboolcheckOrAndOpImpliedByOther(
1528 FactOrCheck &CB, ConstraintInfo &Info,Module *ReproducerModule,
1529SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
1530SmallVectorImpl<StackEntry> &DFSInStack) {
1531Instruction *JoinOp = CB.getContextInst();
1532CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
1533unsigned OtherOpIdx = JoinOp->getOperand(0) == CmpToCheck ? 1 : 0;
1534
1535// Don't try to simplify the first condition of a select by the second, as
1536// this may make the select more poisonous than the original one.
1537// TODO: check if the first operand may be poison.
1538if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
1539returnfalse;
1540
1541unsigned OldSize = DFSInStack.size();
1542auto InfoRestorer =make_scope_exit([&]() {
1543// Remove entries again.
1544while (OldSize < DFSInStack.size()) {
1545 StackEntry E = DFSInStack.back();
1546 removeEntryFromStack(E, Info, ReproducerModule, ReproducerCondStack,
1547 DFSInStack);
1548 }
1549 });
1550bool IsOr =match(JoinOp,m_LogicalOr());
1551SmallVector<Value *, 4> Worklist({JoinOp->getOperand(OtherOpIdx)});
1552// Do a traversal of the AND/OR tree to add facts from leaf compares.
1553while (!Worklist.empty()) {
1554Value *Val = Worklist.pop_back_val();
1555Value *LHS, *RHS;
1556CmpPredicate Pred;
1557if (match(Val,m_ICmp(Pred,m_Value(LHS),m_Value(RHS)))) {
1558// For OR, check if the negated condition implies CmpToCheck.
1559if (IsOr)
1560 Pred =CmpInst::getInversePredicate(Pred);
1561// Optimistically add fact from the other compares in the AND/OR.
1562Info.addFact(Pred,LHS,RHS, CB.NumIn, CB.NumOut, DFSInStack);
1563continue;
1564 }
1565if (IsOr ?match(Val,m_LogicalOr(m_Value(LHS),m_Value(RHS)))
1566 :match(Val,m_LogicalAnd(m_Value(LHS),m_Value(RHS)))) {
1567 Worklist.push_back(LHS);
1568 Worklist.push_back(RHS);
1569 }
1570 }
1571if (OldSize == DFSInStack.size())
1572returnfalse;
1573
1574// Check if the second condition can be simplified now.
1575if (auto ImpliedCondition =
1576checkCondition(CmpToCheck->getPredicate(), CmpToCheck->getOperand(0),
1577 CmpToCheck->getOperand(1), CmpToCheck,Info)) {
1578if (IsOr && isa<SelectInst>(JoinOp)) {
1579 JoinOp->setOperand(
1580 OtherOpIdx == 0 ? 2 : 0,
1581ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
1582 }else
1583 JoinOp->setOperand(
1584 1 - OtherOpIdx,
1585ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
1586
1587returntrue;
1588 }
1589
1590returnfalse;
1591}
1592
1593void ConstraintInfo::addFact(CmpInst::Predicate Pred,Value *A,Value *B,
1594unsigned NumIn,unsigned NumOut,
1595SmallVectorImpl<StackEntry> &DFSInStack) {
1596 addFactImpl(Pred,A,B, NumIn, NumOut, DFSInStack,false);
1597// If the Pred is eq/ne, also add the fact to signed system.
1598if (CmpInst::isEquality(Pred))
1599 addFactImpl(Pred,A,B, NumIn, NumOut, DFSInStack,true);
1600}
1601
1602void ConstraintInfo::addFactImpl(CmpInst::Predicate Pred,Value *A,Value *B,
1603unsigned NumIn,unsigned NumOut,
1604SmallVectorImpl<StackEntry> &DFSInStack,
1605bool ForceSignedSystem) {
1606// If the constraint has a pre-condition, skip the constraint if it does not
1607// hold.
1608SmallVector<Value *> NewVariables;
1609autoR = getConstraint(Pred,A,B, NewVariables, ForceSignedSystem);
1610
1611// TODO: Support non-equality for facts as well.
1612if (!R.isValid(*this) ||R.isNe())
1613return;
1614
1615LLVM_DEBUG(dbgs() <<"Adding '";dumpUnpackedICmp(dbgs(), Pred,A,B);
1616dbgs() <<"'\n");
1617auto &CSToUse = getCS(R.IsSigned);
1618if (R.Coefficients.empty())
1619return;
1620
1621boolAdded = CSToUse.addVariableRowFill(R.Coefficients);
1622if (!Added)
1623return;
1624
1625// If R has been added to the system, add the new variables and queue it for
1626// removal once it goes out-of-scope.
1627SmallVector<Value *, 2> ValuesToRelease;
1628auto &Value2Index = getValue2Index(R.IsSigned);
1629for (Value *V : NewVariables) {
1630 Value2Index.insert({V, Value2Index.size() + 1});
1631 ValuesToRelease.push_back(V);
1632 }
1633
1634LLVM_DEBUG({
1635dbgs() <<" constraint: ";
1636dumpConstraint(R.Coefficients, getValue2Index(R.IsSigned));
1637dbgs() <<"\n";
1638 });
1639
1640 DFSInStack.emplace_back(NumIn, NumOut,R.IsSigned,
1641 std::move(ValuesToRelease));
1642
1643if (!R.IsSigned) {
1644for (Value *V : NewVariables) {
1645 ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
1646false,false,false);
1647 VarPos.Coefficients[Value2Index[V]] = -1;
1648 CSToUse.addVariableRow(VarPos.Coefficients);
1649 DFSInStack.emplace_back(NumIn, NumOut,R.IsSigned,
1650SmallVector<Value *, 2>());
1651 }
1652 }
1653
1654if (R.isEq()) {
1655// Also add the inverted constraint for equality constraints.
1656for (auto &Coeff :R.Coefficients)
1657 Coeff *= -1;
1658 CSToUse.addVariableRowFill(R.Coefficients);
1659
1660 DFSInStack.emplace_back(NumIn, NumOut,R.IsSigned,
1661SmallVector<Value *, 2>());
1662 }
1663}
1664
1665staticboolreplaceSubOverflowUses(IntrinsicInst *II,Value *A,Value *B,
1666SmallVectorImpl<Instruction *> &ToRemove) {
1667bool Changed =false;
1668IRBuilder<> Builder(II->getParent(),II->getIterator());
1669Value *Sub =nullptr;
1670for (User *U :make_early_inc_range(II->users())) {
1671if (match(U, m_ExtractValue<0>(m_Value()))) {
1672if (!Sub)
1673 Sub = Builder.CreateSub(A,B);
1674 U->replaceAllUsesWith(Sub);
1675 Changed =true;
1676 }elseif (match(U, m_ExtractValue<1>(m_Value()))) {
1677 U->replaceAllUsesWith(Builder.getFalse());
1678 Changed =true;
1679 }else
1680continue;
1681
1682if (U->use_empty()) {
1683auto *I = cast<Instruction>(U);
1684ToRemove.push_back(I);
1685I->setOperand(0,PoisonValue::get(II->getType()));
1686 Changed =true;
1687 }
1688 }
1689
1690if (II->use_empty()) {
1691II->eraseFromParent();
1692 Changed =true;
1693 }
1694return Changed;
1695}
1696
1697staticbool
1698tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
1699SmallVectorImpl<Instruction *> &ToRemove) {
1700auto DoesConditionHold = [](CmpInst::Predicate Pred,Value *A,Value *B,
1701 ConstraintInfo &Info) {
1702auto R =Info.getConstraintForSolving(Pred,A,B);
1703if (R.size() < 2 || !R.isValid(Info))
1704returnfalse;
1705
1706auto &CSToUse =Info.getCS(R.IsSigned);
1707return CSToUse.isConditionImplied(R.Coefficients);
1708 };
1709
1710bool Changed =false;
1711if (II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1712// If A s>= B && B s>= 0, ssub.with.overflow(a, b) should not overflow and
1713// can be simplified to a regular sub.
1714Value *A =II->getArgOperand(0);
1715Value *B =II->getArgOperand(1);
1716if (!DoesConditionHold(CmpInst::ICMP_SGE,A,B,Info) ||
1717 !DoesConditionHold(CmpInst::ICMP_SGE,B,
1718 ConstantInt::get(A->getType(), 0),Info))
1719returnfalse;
1720 Changed =replaceSubOverflowUses(II,A,B,ToRemove);
1721 }
1722return Changed;
1723}
1724
1725staticbooleliminateConstraints(Function &F,DominatorTree &DT,LoopInfo &LI,
1726ScalarEvolution &SE,
1727OptimizationRemarkEmitter &ORE) {
1728bool Changed =false;
1729 DT.updateDFSNumbers();
1730SmallVector<Value *> FunctionArgs;
1731for (Value &Arg :F.args())
1732 FunctionArgs.push_back(&Arg);
1733 ConstraintInfoInfo(F.getDataLayout(), FunctionArgs);
1734 State S(DT, LI, SE);
1735 std::unique_ptr<Module> ReproducerModule(
1736DumpReproducers ?newModule(F.getName(),F.getContext()) :nullptr);
1737
1738// First, collect conditions implied by branches and blocks with their
1739// Dominator DFS in and out numbers.
1740for (BasicBlock &BB :F) {
1741if (!DT.getNode(&BB))
1742continue;
1743 S.addInfoFor(BB);
1744 }
1745
1746// Next, sort worklist by dominance, so that dominating conditions to check
1747// and facts come before conditions and facts dominated by them. If a
1748// condition to check and a fact have the same numbers, conditional facts come
1749// first. Assume facts and checks are ordered according to their relative
1750// order in the containing basic block. Also make sure conditions with
1751// constant operands come before conditions without constant operands. This
1752// increases the effectiveness of the current signed <-> unsigned fact
1753// transfer logic.
1754stable_sort(S.WorkList, [](const FactOrCheck &A,const FactOrCheck &B) {
1755 auto HasNoConstOp = [](const FactOrCheck &B) {
1756 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1757 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1758 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1759 };
1760// If both entries have the same In numbers, conditional facts come first.
1761// Otherwise use the relative order in the basic block.
1762if (A.NumIn ==B.NumIn) {
1763 if (A.isConditionFact() && B.isConditionFact()) {
1764 bool NoConstOpA = HasNoConstOp(A);
1765 bool NoConstOpB = HasNoConstOp(B);
1766 return NoConstOpA < NoConstOpB;
1767 }
1768if (A.isConditionFact())
1769returntrue;
1770if (B.isConditionFact())
1771returnfalse;
1772auto *InstA =A.getContextInst();
1773auto *InstB =B.getContextInst();
1774return InstA->comesBefore(InstB);
1775 }
1776returnA.NumIn <B.NumIn;
1777 });
1778
1779SmallVector<Instruction *>ToRemove;
1780
1781// Finally, process ordered worklist and eliminate implied conditions.
1782SmallVector<StackEntry, 16> DFSInStack;
1783SmallVector<ReproducerEntry> ReproducerCondStack;
1784for (FactOrCheck &CB : S.WorkList) {
1785// First, pop entries from the stack that are out-of-scope for CB. Remove
1786// the corresponding entry from the constraint system.
1787while (!DFSInStack.empty()) {
1788auto &E = DFSInStack.back();
1789LLVM_DEBUG(dbgs() <<"Top of stack : " << E.NumIn <<" " << E.NumOut
1790 <<"\n");
1791LLVM_DEBUG(dbgs() <<"CB: " << CB.NumIn <<" " << CB.NumOut <<"\n");
1792assert(E.NumIn <= CB.NumIn);
1793if (CB.NumOut <= E.NumOut)
1794break;
1795LLVM_DEBUG({
1796dbgs() <<"Removing ";
1797dumpConstraint(Info.getCS(E.IsSigned).getLastConstraint(),
1798Info.getValue2Index(E.IsSigned));
1799dbgs() <<"\n";
1800 });
1801removeEntryFromStack(E, Info, ReproducerModule.get(), ReproducerCondStack,
1802 DFSInStack);
1803 }
1804
1805// For a block, check if any CmpInsts become known based on the current set
1806// of constraints.
1807if (CB.isCheck()) {
1808Instruction *Inst = CB.getInstructionToSimplify();
1809if (!Inst)
1810continue;
1811LLVM_DEBUG(dbgs() <<"Processing condition to simplify: " << *Inst
1812 <<"\n");
1813if (auto *II = dyn_cast<WithOverflowInst>(Inst)) {
1814 Changed |=tryToSimplifyOverflowMath(II, Info,ToRemove);
1815 }elseif (auto *Cmp = dyn_cast<ICmpInst>(Inst)) {
1816boolSimplified =checkAndReplaceCondition(
1817 Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
1818 ReproducerModule.get(), ReproducerCondStack, S.DT,ToRemove);
1819if (!Simplified &&
1820match(CB.getContextInst(),m_LogicalOp(m_Value(),m_Value()))) {
1821Simplified =
1822checkOrAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
1823 ReproducerCondStack, DFSInStack);
1824 }
1825 Changed |=Simplified;
1826 }elseif (auto *MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
1827 Changed |=checkAndReplaceMinMax(MinMax, Info,ToRemove);
1828 }elseif (auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
1829 Changed |=checkAndReplaceCmp(CmpIntr, Info,ToRemove);
1830 }
1831continue;
1832 }
1833
1834auto AddFact = [&](CmpPredicate Pred,Value *A,Value *B) {
1835LLVM_DEBUG(dbgs() <<"Processing fact to add to the system: ";
1836dumpUnpackedICmp(dbgs(), Pred,A,B);dbgs() <<"\n");
1837if (Info.getCS(CmpInst::isSigned(Pred)).size() >MaxRows) {
1838LLVM_DEBUG(
1839dbgs()
1840 <<"Skip adding constraint because system has too many rows.\n");
1841return;
1842 }
1843
1844Info.addFact(Pred,A,B, CB.NumIn, CB.NumOut, DFSInStack);
1845if (ReproducerModule && DFSInStack.size() > ReproducerCondStack.size())
1846 ReproducerCondStack.emplace_back(Pred,A,B);
1847
1848if (ICmpInst::isRelational(Pred)) {
1849// If samesign is present on the ICmp, simply flip the sign of the
1850// predicate, transferring the information from the signed system to the
1851// unsigned system, and viceversa.
1852if (Pred.hasSameSign())
1853Info.addFact(ICmpInst::getFlippedSignednessPredicate(Pred),A,B,
1854 CB.NumIn, CB.NumOut, DFSInStack);
1855else
1856Info.transferToOtherSystem(Pred,A,B, CB.NumIn, CB.NumOut,
1857 DFSInStack);
1858 }
1859
1860if (ReproducerModule && DFSInStack.size() > ReproducerCondStack.size()) {
1861// Add dummy entries to ReproducerCondStack to keep it in sync with
1862// DFSInStack.
1863for (unsignedI = 0,
1864 E = (DFSInStack.size() - ReproducerCondStack.size());
1865I < E; ++I) {
1866 ReproducerCondStack.emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
1867nullptr,nullptr);
1868 }
1869 }
1870 };
1871
1872CmpPredicate Pred;
1873if (!CB.isConditionFact()) {
1874Value *X;
1875if (match(CB.Inst, m_Intrinsic<Intrinsic::abs>(m_Value(X)))) {
1876// If is_int_min_poison is true then we may assume llvm.abs >= 0.
1877if (cast<ConstantInt>(CB.Inst->getOperand(1))->isOne())
1878 AddFact(CmpInst::ICMP_SGE, CB.Inst,
1879 ConstantInt::get(CB.Inst->getType(), 0));
1880 AddFact(CmpInst::ICMP_SGE, CB.Inst,X);
1881continue;
1882 }
1883
1884if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
1885 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
1886 AddFact(Pred,MinMax,MinMax->getLHS());
1887 AddFact(Pred,MinMax,MinMax->getRHS());
1888continue;
1889 }
1890 }
1891
1892Value *A =nullptr, *B =nullptr;
1893if (CB.isConditionFact()) {
1894 Pred = CB.Cond.Pred;
1895A = CB.Cond.Op0;
1896B = CB.Cond.Op1;
1897if (CB.DoesHold.Pred !=CmpInst::BAD_ICMP_PREDICATE &&
1898 !Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
1899LLVM_DEBUG({
1900dbgs() <<"Not adding fact ";
1901dumpUnpackedICmp(dbgs(), Pred,A,B);
1902dbgs() <<" because precondition ";
1903dumpUnpackedICmp(dbgs(), CB.DoesHold.Pred, CB.DoesHold.Op0,
1904 CB.DoesHold.Op1);
1905dbgs() <<" does not hold.\n";
1906 });
1907continue;
1908 }
1909 }else {
1910bool Matched =match(CB.Inst, m_Intrinsic<Intrinsic::assume>(
1911m_ICmp(Pred,m_Value(A),m_Value(B))));
1912 (void)Matched;
1913assert(Matched &&"Must have an assume intrinsic with a icmp operand");
1914 }
1915 AddFact(Pred,A,B);
1916 }
1917
1918if (ReproducerModule && !ReproducerModule->functions().empty()) {
1919 std::string S;
1920raw_string_ostream StringS(S);
1921 ReproducerModule->print(StringS,nullptr);
1922OptimizationRemark Rem(DEBUG_TYPE,"Reproducer", &F);
1923 Rem <<ore::NV("module") << S;
1924 ORE.emit(Rem);
1925 }
1926
1927#ifndef NDEBUG
1928unsigned SignedEntries =
1929count_if(DFSInStack, [](const StackEntry &E) {return E.IsSigned; });
1930assert(Info.getCS(false).size() - FunctionArgs.size() ==
1931 DFSInStack.size() - SignedEntries &&
1932"updates to CS and DFSInStack are out of sync");
1933assert(Info.getCS(true).size() == SignedEntries &&
1934"updates to CS and DFSInStack are out of sync");
1935#endif
1936
1937for (Instruction *I :ToRemove)
1938I->eraseFromParent();
1939return Changed;
1940}
1941
1942PreservedAnalysesConstraintEliminationPass::run(Function &F,
1943FunctionAnalysisManager &AM) {
1944auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
1945auto &LI = AM.getResult<LoopAnalysis>(F);
1946auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
1947auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
1948if (!eliminateConstraints(F, DT, LI, SE, ORE))
1949returnPreservedAnalyses::all();
1950
1951PreservedAnalyses PA;
1952 PA.preserve<DominatorTreeAnalysis>();
1953 PA.preserve<LoopAnalysis>();
1954 PA.preserve<ScalarEvolutionAnalysis>();
1955 PA.preserveSet<CFGAnalyses>();
1956return PA;
1957}
ToRemove
ReachingDefAnalysis InstSet & ToRemove
Definition:ARMLowOverheadLoops.cpp:531
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition:ARMSLSHardening.cpp:73
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Info
Analysis containing CSE Info
Definition:CSEInfo.cpp:27
ConditionTy
std::pair< ICmpInst *, unsigned > ConditionTy
Definition:CallSiteSplitting.cpp:124
Cloning.h
CommandLine.h
MaxConstraintValue
static int64_t MaxConstraintValue
Definition:ConstraintElimination.cpp:64
MinSignedConstraintValue
static int64_t MinSignedConstraintValue
Definition:ConstraintElimination.cpp:65
getContextInstForUse
static Instruction * getContextInstForUse(Use &U)
Definition:ConstraintElimination.cpp:81
decomposeGEP
static Decomposition decomposeGEP(GEPOperator &GEP, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
Definition:ConstraintElimination.cpp:450
canUseSExt
static bool canUseSExt(ConstantInt *CI)
Definition:ConstraintElimination.cpp:445
multiplyWithOverflow
static int64_t multiplyWithOverflow(int64_t A, int64_t B)
Definition:ConstraintElimination.cpp:68
dumpConstraint
static void dumpConstraint(ArrayRef< int64_t > C, const DenseMap< Value *, unsigned > &Value2Index)
Definition:ConstraintElimination.cpp:928
removeEntryFromStack
static void removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
Definition:ConstraintElimination.cpp:1510
checkCondition
static std::optional< bool > checkCondition(CmpInst::Predicate Pred, Value *A, Value *B, Instruction *CheckInst, ConstraintInfo &Info)
Definition:ConstraintElimination.cpp:1389
MaxRows
static cl::opt< unsigned > MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden, cl::desc("Maximum number of rows to keep in constraint system"))
eliminateConstraints
static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE)
Definition:ConstraintElimination.cpp:1725
addWithOverflow
static int64_t addWithOverflow(int64_t A, int64_t B)
Definition:ConstraintElimination.cpp:75
DumpReproducers
static cl::opt< bool > DumpReproducers("constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden, cl::desc("Dump IR to reproduce successful transformations."))
collectOffsets
static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL)
Definition:ConstraintElimination.cpp:411
checkAndReplaceMinMax
static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
Definition:ConstraintElimination.cpp:1467
generateReproducer
static void generateReproducer(CmpInst *Cond, Module *M, ArrayRef< ReproducerEntry > Stack, ConstraintInfo &Info, DominatorTree &DT)
Helper function to generate a reproducer function for simplifying Cond.
Definition:ConstraintElimination.cpp:1261
dumpUnpackedICmp
static void dumpUnpackedICmp(raw_ostream &OS, ICmpInst::Predicate Pred, Value *LHS, Value *RHS)
Definition:ConstraintElimination.cpp:1230
checkOrAndOpImpliedByOther
static bool checkOrAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
Check if either the first condition of an AND or OR is implied by the (negated in case of OR) second ...
Definition:ConstraintElimination.cpp:1527
decompose
static Decomposition decompose(Value *V, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
Definition:ConstraintElimination.cpp:487
replaceSubOverflowUses
static bool replaceSubOverflowUses(IntrinsicInst *II, Value *A, Value *B, SmallVectorImpl< Instruction * > &ToRemove)
Definition:ConstraintElimination.cpp:1665
tryToSimplifyOverflowMath
static bool tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
Definition:ConstraintElimination.cpp:1698
DEBUG_TYPE
#define DEBUG_TYPE
Definition:ConstraintElimination.cpp:50
checkAndReplaceCondition
static bool checkAndReplaceCondition(CmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut, Instruction *ContextInst, Module *ReproducerModule, ArrayRef< ReproducerEntry > ReproducerCondStack, DominatorTree &DT, SmallVectorImpl< Instruction * > &ToRemove)
Definition:ConstraintElimination.cpp:1430
checkAndReplaceCmp
static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
Definition:ConstraintElimination.cpp:1487
ConstraintElimination.h
ConstraintSystem.h
DataLayout.h
DebugCounter.h
This file provides an implementation of debug counters.
DEBUG_COUNTER
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
Definition:DebugCounter.h:190
Debug.h
LLVM_DEBUG
#define LLVM_DEBUG(...)
Definition:Debug.h:106
Dominators.h
Other
std::optional< std::vector< StOtherPiece > > Other
Definition:ELFYAML.cpp:1315
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
GlobalsModRef.h
This is the interface for a simple mod/ref and alias analysis over globals.
GEP
Hexagon Common GEP
Definition:HexagonCommonGEP.cpp:170
IRBuilder.h
Function.h
Module.h
Module.h This file contains the declarations for the Module class.
InstrTypes.h
Instructions.h
LoopInfo.h
F
#define F(x, y, z)
Definition:MD5.cpp:55
I
#define I(x, y, z)
Definition:MD5.cpp:58
MathExtras.h
Signed
@ Signed
Definition:NVPTXISelLowering.cpp:4789
II
uint64_t IntrinsicInst * II
Definition:NVVMIntrRange.cpp:51
OptimizationRemarkEmitter.h
P
#define P(N)
if
if(PassOpts->AAPipeline)
Definition:PassBuilderBindings.cpp:64
Pass.h
PatternMatch.h
getName
static StringRef getName(Value *V)
Definition:ProvenanceAnalysisEvaluator.cpp:20
Cond
const SmallVectorImpl< MachineOperand > & Cond
Definition:RISCVRedundantCopyElimination.cpp:75
isValid
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Definition:RustDemangle.cpp:181
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
STLExtras.h
This file contains some templates that are useful if you are working with the STL at all.
OS
raw_pwrite_stream & OS
Definition:SampleProfWriter.cpp:51
ScalarEvolutionExpressions.h
ScalarEvolution.h
ScopeExit.h
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
SmallVector.h
This file defines the SmallVector class.
Statistic.h
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
STATISTIC
#define STATISTIC(VARNAME, DESC)
Definition:Statistic.h:166
ValueMapper.h
ValueTracking.h
Verifier.h
RHS
Value * RHS
Definition:X86PartialReduction.cpp:74
LHS
Value * LHS
Definition:X86PartialReduction.cpp:73
FunctionType
Definition:ItaniumDemangle.h:823
llvm::APInt
Class for arbitrary precision integers.
Definition:APInt.h:78
llvm::APInt::sgt
bool sgt(const APInt &RHS) const
Signed greater than comparison.
Definition:APInt.h:1201
llvm::APInt::isZero
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition:APInt.h:380
llvm::APInt::urem
APInt urem(const APInt &RHS) const
Unsigned remainder operation.
Definition:APInt.cpp:1640
llvm::APInt::isNegative
bool isNegative() const
Determine sign of this APInt.
Definition:APInt.h:329
llvm::APInt::getLimitedValue
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition:APInt.h:475
llvm::APInt::slt
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition:APInt.h:1130
llvm::APInt::isOne
bool isOne() const
Determine if this is a value of 1.
Definition:APInt.h:389
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition:PassManager.h:253
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition:PassManager.h:410
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition:ArrayRef.h:41
llvm::BasicBlockEdge
Definition:Dominators.h:94
llvm::BasicBlock
LLVM Basic Block Representation.
Definition:BasicBlock.h:61
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition:BasicBlock.h:213
llvm::BasicBlock::getTerminator
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition:BasicBlock.h:240
llvm::CFGAnalyses
Represents analyses that only rely on functions' control flow.
Definition:Analysis.h:72
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition:Instructions.h:1479
llvm::CmpInst
This class is the base class for the comparison instructions.
Definition:InstrTypes.h:661
llvm::CmpInst::makeCmpResultType
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Definition:InstrTypes.h:980
llvm::CmpInst::isEquality
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition:InstrTypes.h:913
llvm::CmpInst::Predicate
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition:InstrTypes.h:673
llvm::CmpInst::BAD_ICMP_PREDICATE
@ BAD_ICMP_PREDICATE
Definition:InstrTypes.h:706
llvm::CmpInst::ICMP_SLT
@ ICMP_SLT
signed less than
Definition:InstrTypes.h:702
llvm::CmpInst::ICMP_SLE
@ ICMP_SLE
signed less or equal
Definition:InstrTypes.h:703
llvm::CmpInst::ICMP_UGE
@ ICMP_UGE
unsigned greater or equal
Definition:InstrTypes.h:697
llvm::CmpInst::ICMP_UGT
@ ICMP_UGT
unsigned greater than
Definition:InstrTypes.h:696
llvm::CmpInst::ICMP_SGT
@ ICMP_SGT
signed greater than
Definition:InstrTypes.h:700
llvm::CmpInst::ICMP_ULT
@ ICMP_ULT
unsigned less than
Definition:InstrTypes.h:698
llvm::CmpInst::ICMP_EQ
@ ICMP_EQ
equal
Definition:InstrTypes.h:694
llvm::CmpInst::ICMP_NE
@ ICMP_NE
not equal
Definition:InstrTypes.h:695
llvm::CmpInst::ICMP_SGE
@ ICMP_SGE
signed greater or equal
Definition:InstrTypes.h:701
llvm::CmpInst::ICMP_ULE
@ ICMP_ULE
unsigned less or equal
Definition:InstrTypes.h:699
llvm::CmpInst::isSigned
bool isSigned() const
Definition:InstrTypes.h:928
llvm::CmpInst::getSwappedPredicate
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition:InstrTypes.h:825
llvm::CmpInst::getInversePredicate
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition:InstrTypes.h:787
llvm::CmpInst::getPredicate
Predicate getPredicate() const
Return the predicate for this instruction.
Definition:InstrTypes.h:763
llvm::CmpIntrinsic
This class represents a ucmp/scmp intrinsic.
Definition:IntrinsicInst.h:852
llvm::CmpPredicate
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
Definition:CmpPredicate.h:22
llvm::CmpPredicate::hasSameSign
bool hasSameSign() const
Query samesign information, for optimizations.
Definition:CmpPredicate.h:42
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition:Constants.h:83
llvm::ConstantInt::isNegative
bool isNegative() const
Definition:Constants.h:203
llvm::ConstantInt::getSigned
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
Definition:Constants.h:126
llvm::ConstantInt::getSExtValue
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition:Constants.h:163
llvm::ConstantInt::getValue
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition:Constants.h:148
llvm::ConstantInt::getBool
static ConstantInt * getBool(LLVMContext &Context, bool V)
Definition:Constants.cpp:880
llvm::Constant
This is an important base class in LLVM.
Definition:Constant.h:42
llvm::Constant::getAllOnesValue
static Constant * getAllOnesValue(Type *Ty)
Definition:Constants.cpp:420
llvm::Constant::getNullValue
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition:Constants.cpp:373
llvm::ConstraintEliminationPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
Definition:ConstraintElimination.cpp:1942
llvm::ConstraintSystem
Definition:ConstraintSystem.h:22
llvm::ConstraintSystem::getValue2Index
DenseMap< Value *, unsigned > & getValue2Index()
Definition:ConstraintSystem.h:95
llvm::ConstraintSystem::popLastConstraint
void popLastConstraint()
Definition:ConstraintSystem.h:156
llvm::ConstraintSystem::negate
static SmallVector< int64_t, 8 > negate(SmallVector< int64_t, 8 > R)
Definition:ConstraintSystem.h:113
llvm::ConstraintSystem::isConditionImplied
bool isConditionImplied(SmallVector< int64_t, 8 > R) const
Definition:ConstraintSystem.cpp:191
llvm::ConstraintSystem::toStrictLessThan
static SmallVector< int64_t, 8 > toStrictLessThan(SmallVector< int64_t, 8 > R)
Converts the given vector to form a strict less than inequality.
Definition:ConstraintSystem.h:138
llvm::ConstraintSystem::addVariableRow
bool addVariableRow(ArrayRef< int64_t > R)
Definition:ConstraintSystem.h:76
llvm::ConstraintSystem::negateOrEqual
static SmallVector< int64_t, 8 > negateOrEqual(SmallVector< int64_t, 8 > R)
Multiplies each coefficient in the given vector by -1.
Definition:ConstraintSystem.h:126
llvm::ConstraintSystem::addVariableRowFill
bool addVariableRowFill(ArrayRef< int64_t > R)
Definition:ConstraintSystem.h:100
llvm::ConstraintSystem::dump
void dump() const
Print the constraints in the system.
Definition:ConstraintSystem.cpp:156
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition:DataLayout.h:63
llvm::DebugCounter::shouldExecute
static bool shouldExecute(unsigned CounterName)
Definition:DebugCounter.h:87
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition:DenseMap.h:156
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition:DenseMap.h:321
llvm::DenseMapBase::contains
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition:DenseMap.h:147
llvm::DenseMapBase::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition:DenseMap.h:211
llvm::DenseMap
Definition:DenseMap.h:727
llvm::DomTreeNodeBase< BasicBlock >
llvm::DomTreeNodeBase::getDFSNumIn
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
Definition:GenericDomTree.h:140
llvm::DomTreeNodeBase::getDFSNumOut
unsigned getDFSNumOut() const
Definition:GenericDomTree.h:141
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition:Dominators.h:279
llvm::DominatorTreeBase::updateDFSNumbers
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
Definition:GenericDomTree.h:805
llvm::DominatorTreeBase::getNode
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Definition:GenericDomTree.h:401
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition:Dominators.h:162
llvm::DominatorTree::dominates
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Definition:Dominators.cpp:122
llvm::Function
Definition:Function.h:63
llvm::Function::Create
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition:Function.h:173
llvm::GEPNoWrapFlags
Represents flags for the getelementptr instruction/expression.
Definition:GEPNoWrapFlags.h:26
llvm::GEPNoWrapFlags::none
static GEPNoWrapFlags none()
Definition:GEPNoWrapFlags.h:46
llvm::GEPOperator
Definition:Operator.h:425
llvm::ICmpInst::getFlippedSignednessPredicate
Predicate getFlippedSignednessPredicate() const
For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->EQ.
Definition:Instructions.h:1265
llvm::ICmpInst::getSignedPredicate
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
Definition:Instructions.h:1238
llvm::ICmpInst::isRelational
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
Definition:Instructions.h:1305
llvm::ICmpInst::getUnsignedPredicate
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
Definition:Instructions.h:1249
llvm::IRBuilderBase::CreateAssumption
CallInst * CreateAssumption(Value *Cond, ArrayRef< OperandBundleDef > OpBundles={})
Create an assume intrinsic call that allows the optimizer to assume that the provided condition will ...
Definition:IRBuilder.cpp:521
llvm::IRBuilderBase::getTrue
ConstantInt * getTrue()
Get the constant value for i1 true.
Definition:IRBuilder.h:485
llvm::IRBuilderBase::GetInsertPoint
BasicBlock::iterator GetInsertPoint() const
Definition:IRBuilder.h:194
llvm::IRBuilderBase::CreateRet
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition:IRBuilder.h:1139
llvm::IRBuilderBase::CreateSub
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition:IRBuilder.h:1387
llvm::IRBuilderBase::getFalse
ConstantInt * getFalse()
Get the constant value for i1 false.
Definition:IRBuilder.h:490
llvm::IRBuilderBase::SetInsertPoint
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition:IRBuilder.h:199
llvm::IRBuilderBase::CreateICmp
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Definition:IRBuilder.h:2380
llvm::IRBuilder
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition:IRBuilder.h:2705
llvm::Instruction
Definition:Instruction.h:68
llvm::Instruction::insertBefore
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
Definition:Instruction.cpp:99
llvm::Instruction::dropUnknownNonDebugMetadata
void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
Definition:Metadata.cpp:1633
llvm::Instruction::setDebugLoc
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition:Instruction.h:508
llvm::IntrinsicInst
A wrapper class for inspecting calls to intrinsic functions.
Definition:IntrinsicInst.h:48
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition:LLVMContext.h:67
llvm::LoopAnalysis
Analysis pass that exposes the LoopInfo for a function.
Definition:LoopInfo.h:566
llvm::LoopInfoBase::getLoopFor
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Definition:GenericLoopInfo.h:606
llvm::LoopInfo
Definition:LoopInfo.h:407
llvm::MapVector::size
size_type size() const
Definition:MapVector.h:60
llvm::MinMaxIntrinsic
This class represents min/max intrinsics.
Definition:IntrinsicInst.h:761
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition:Module.h:65
llvm::OptimizationRemarkEmitterAnalysis
Definition:OptimizationRemarkEmitter.h:164
llvm::OptimizationRemarkEmitter
The optimization diagnostic interface.
Definition:OptimizationRemarkEmitter.h:32
llvm::OptimizationRemark
Diagnostic information for applied optimization remarks.
Definition:DiagnosticInfo.h:762
llvm::PHINode
Definition:Instructions.h:2600
llvm::PHINode::getIncomingValueForBlock
Value * getIncomingValueForBlock(const BasicBlock *BB) const
Definition:Instructions.h:2775
llvm::PHINode::getNumIncomingValues
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Definition:Instructions.h:2671
llvm::PoisonValue::get
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition:Constants.cpp:1878
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition:Analysis.h:111
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition:Analysis.h:117
llvm::PreservedAnalyses::preserveSet
void preserveSet()
Mark an analysis set as preserved.
Definition:Analysis.h:146
llvm::PreservedAnalyses::preserve
void preserve()
Mark an analysis as preserved.
Definition:Analysis.h:131
llvm::SCEV
This class represents an analyzed expression in the program.
Definition:ScalarEvolution.h:71
llvm::ScalarEvolutionAnalysis
Analysis pass that exposes the ScalarEvolution for a function.
Definition:ScalarEvolution.h:2320
llvm::ScalarEvolution
The main scalar evolution driver.
Definition:ScalarEvolution.h:447
llvm::ScalarEvolution::getConstantMultiple
APInt getConstantMultiple(const SCEV *S)
Returns the max constant multiple of S.
Definition:ScalarEvolution.cpp:6395
llvm::ScalarEvolution::getSCEV
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
Definition:ScalarEvolution.cpp:4547
llvm::ScalarEvolution::isSCEVable
bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
Definition:ScalarEvolution.cpp:4441
llvm::ScalarEvolution::MonotonicallyIncreasing
@ MonotonicallyIncreasing
Definition:ScalarEvolution.h:1177
llvm::ScalarEvolution::getMinusSCEV
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
Definition:ScalarEvolution.cpp:4655
llvm::ScalarEvolution::getMonotonicPredicateType
std::optional< MonotonicPredicateType > getMonotonicPredicateType(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred)
If, for all loop invariant X, the predicate "LHS `Pred` X" is monotonically increasing or decreasing,...
Definition:ScalarEvolution.cpp:11107
llvm::SmallDenseMap
Definition:DenseMap.h:883
llvm::SmallPtrSetImpl::insert
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition:SmallPtrSet.h:384
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition:SmallPtrSet.h:519
llvm::SmallVectorBase::empty
bool empty() const
Definition:SmallVector.h:81
llvm::SmallVectorBase::size
size_t size() const
Definition:SmallVector.h:78
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition:SmallVector.h:573
llvm::SmallVectorImpl::pop_back_val
T pop_back_val()
Definition:SmallVector.h:673
llvm::SmallVectorImpl::emplace_back
reference emplace_back(ArgTypes &&... Args)
Definition:SmallVector.h:937
llvm::SmallVectorTemplateBase::pop_back
void pop_back()
Definition:SmallVector.h:425
llvm::SmallVectorTemplateBase::push_back
void push_back(const T &Elt)
Definition:SmallVector.h:413
llvm::SmallVectorTemplateCommon::back
reference back()
Definition:SmallVector.h:308
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition:Type.h:45
llvm::Type::getIntegerBitWidth
unsigned getIntegerBitWidth() const
llvm::Type::isPointerTy
bool isPointerTy() const
True if this is an instance of PointerType.
Definition:Type.h:264
llvm::Type::getScalarSizeInBits
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
llvm::Type::isIntegerTy
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition:Type.h:237
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition:Use.h:43
llvm::User
Definition:User.h:44
llvm::User::setOperand
void setOperand(unsigned i, Value *Val)
Definition:User.h:233
llvm::User::getOperand
Value * getOperand(unsigned i) const
Definition:User.h:228
llvm::ValueMap< const Value *, WeakTrackingVH >
llvm::ValueMap::find
iterator find(const KeyT &Val)
Definition:ValueMap.h:155
llvm::ValueMap::end
iterator end()
Definition:ValueMap.h:135
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition:Value.h:255
llvm::Value::printAsOperand
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
Definition:AsmWriter.cpp:5144
llvm::Value::stripPointerCastsSameRepresentation
const Value * stripPointerCastsSameRepresentation() const
Strip off pointer casts, all-zero GEPs and address space casts but ensures the representation of the ...
Definition:Value.cpp:702
llvm::cl::opt
Definition:CommandLine.h:1423
llvm::ilist_detail::node_parent_access::getParent
const ParentTy * getParent() const
Definition:ilist_node.h:32
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition:raw_ostream.h:52
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition:raw_ostream.h:661
uint64_t
unsigned
llvm::AMDGPU::Hwreg::Offset
Offset
Definition:SIDefines.h:553
llvm::ARM_AM::sub
@ sub
Definition:ARMAddressingModes.h:38
llvm::ARM_AM::add
@ add
Definition:ARMAddressingModes.h:39
llvm::CallingConv::C
@ C
The default llvm calling convention, compatible with C.
Definition:CallingConv.h:34
llvm::Intrinsic::not_intrinsic
@ not_intrinsic
Definition:Intrinsics.h:44
llvm::JumpTable::Simplified
@ Simplified
Definition:TargetOptions.h:47
llvm::M68k::MemAddrModeKind::U
@ U
llvm::M68k::MemAddrModeKind::V
@ V
llvm::M68k::MemAddrModeKind::L
@ L
llvm::PatternMatch::m_Add
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1102
llvm::PatternMatch::m_NUWAdd
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWAdd(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1314
llvm::PatternMatch::m_LogicalOp
auto m_LogicalOp()
Matches either L && R or L || R where L and R are arbitrary values.
Definition:PatternMatch.h:3119
llvm::PatternMatch::m_NSWSub
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1289
llvm::PatternMatch::match
bool match(Val *V, const Pattern &P)
Definition:PatternMatch.h:49
llvm::PatternMatch::m_DisjointOr
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1395
llvm::PatternMatch::m_ConstantInt
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
Definition:PatternMatch.h:168
llvm::PatternMatch::m_NSWTrunc
NoWrapTrunc_match< OpTy, TruncInst::NoSignedWrap > m_NSWTrunc(const OpTy &Op)
Matches trunc nsw.
Definition:PatternMatch.h:2089
llvm::PatternMatch::m_NNegZExt
NNegZExt_match< OpTy > m_NNegZExt(const OpTy &Op)
Definition:PatternMatch.h:2112
llvm::PatternMatch::m_LogicalOr
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
Definition:PatternMatch.h:3099
llvm::PatternMatch::m_NSWShl
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoSignedWrap > m_NSWShl(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1305
llvm::PatternMatch::m_ZExt
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
Definition:PatternMatch.h:2107
llvm::PatternMatch::m_NUWShl
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWShl(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1348
llvm::PatternMatch::m_NUWMul
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1340
llvm::PatternMatch::m_Br
brc_match< Cond_t, bind_ty< BasicBlock >, bind_ty< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
Definition:PatternMatch.h:2220
llvm::PatternMatch::m_NUWSub
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWSub(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1332
llvm::PatternMatch::m_Value
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
Definition:PatternMatch.h:92
llvm::PatternMatch::m_NSWAdd
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1281
llvm::PatternMatch::m_ICmp
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Definition:PatternMatch.h:1627
llvm::PatternMatch::m_LogicalAnd
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
Definition:PatternMatch.h:3081
llvm::PatternMatch::m_SExt
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
Definition:PatternMatch.h:2101
llvm::PatternMatch::m_Zero
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
Definition:PatternMatch.h:612
llvm::PatternMatch::m_NSWMul
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoSignedWrap > m_NSWMul(const LHS &L, const RHS &R)
Definition:PatternMatch.h:1297
llvm::RISCVFenceField::R
@ R
Definition:RISCVBaseInfo.h:373
llvm::X86::FirstMacroFusionInstKind::Cmp
@ Cmp
llvm::cfg::UpdateKind::Insert
@ Insert
llvm::cl::Hidden
@ Hidden
Definition:CommandLine.h:137
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition:CommandLine.h:443
llvm::codeview::EncodedFramePtrReg::BasePtr
@ BasePtr
llvm::coro::ABI::Switch
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
llvm::logicalview::LVComparePass::Added
@ Added
llvm::ore::NV
DiagnosticInfoOptimizationBase::Argument NV
Definition:OptimizationRemarkEmitter.h:135
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::MulOverflow
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
Definition:MathExtras.h:754
llvm::stable_sort
void stable_sort(R &&Range)
Definition:STLExtras.h:2037
llvm::all_of
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition:STLExtras.h:1739
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition:STLExtras.h:1697
llvm::make_scope_exit
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition:ScopeExit.h:59
llvm::Successor
@ Successor
Definition:SIMachineScheduler.h:35
llvm::verifyFunction
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
Definition:Verifier.cpp:7301
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition:STLExtras.h:2115
llvm::make_early_inc_range
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...
Definition:STLExtras.h:657
llvm::getPointerOperand
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
Definition:Instructions.h:4998
llvm::MaxAnalysisRecursionDepth
constexpr unsigned MaxAnalysisRecursionDepth
Definition:ValueTracking.h:44
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition:STLExtras.h:1664
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition:Debug.cpp:163
llvm::remapInstructionsInBlocks
void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
Definition:CloneFunction.cpp:1014
llvm::BitWidth
constexpr unsigned BitWidth
Definition:BitmaskEnum.h:217
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition:STLExtras.h:1873
llvm::isGuaranteedToTransferExecutionToSuccessor
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
Definition:ValueTracking.cpp:7927
llvm::PseudoProbeReservedId::Last
@ Last
llvm::count_if
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition:STLExtras.h:1945
llvm::AddOverflow
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
Definition:MathExtras.h:702
llvm::SubOverflow
std::enable_if_t< std::is_signed_v< T >, T > SubOverflow(T X, T Y, T &Result)
Subtract two signed integers, computing the two's complement truncated result, returning true if an o...
Definition:MathExtras.h:728
llvm::isGuaranteedNotToBePoison
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.
Definition:ValueTracking.cpp:7856
llvm::isKnownNonNegative
bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
Definition:ValueTracking.cpp:292
std
Implement std::hash so that hash_code can be used in STL containers.
Definition:BitVector.h:858
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition:BitVector.h:860
N
#define N
llvm::MinMax
Definition:AssumeBundleQueries.h:70
llvm::SmallMapVector
A MapVector that performs no allocations if smaller than a certain size.
Definition:MapVector.h:254
llvm::cl::desc
Definition:CommandLine.h:409

Generated on Sun Jul 20 2025 13:53:07 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp