xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1e8d8bef9SDimitry Andric //===-- ConstraintElimination.cpp - Eliminate conds using constraints. ----===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // Eliminate conditions based on constraints collected from dominating
10e8d8bef9SDimitry Andric // conditions.
11e8d8bef9SDimitry Andric //
12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
13e8d8bef9SDimitry Andric 
14e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/ConstraintElimination.h"
15e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h"
16fe6060f1SDimitry Andric #include "llvm/ADT/ScopeExit.h"
17e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h"
18e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h"
19e8d8bef9SDimitry Andric #include "llvm/Analysis/ConstraintSystem.h"
20e8d8bef9SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
21349cc55cSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
22*bdd1243dSDimitry Andric #include "llvm/IR/DataLayout.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/Dominators.h"
24e8d8bef9SDimitry Andric #include "llvm/IR/Function.h"
25*bdd1243dSDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
2681ad6265SDimitry Andric #include "llvm/IR/IRBuilder.h"
27e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h"
28e8d8bef9SDimitry Andric #include "llvm/IR/PatternMatch.h"
29e8d8bef9SDimitry Andric #include "llvm/Pass.h"
30*bdd1243dSDimitry Andric #include "llvm/Support/CommandLine.h"
31e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
32e8d8bef9SDimitry Andric #include "llvm/Support/DebugCounter.h"
3381ad6265SDimitry Andric #include "llvm/Support/MathExtras.h"
34e8d8bef9SDimitry Andric 
35*bdd1243dSDimitry Andric #include <cmath>
36fe6060f1SDimitry Andric #include <string>
37fe6060f1SDimitry Andric 
38e8d8bef9SDimitry Andric using namespace llvm;
39e8d8bef9SDimitry Andric using namespace PatternMatch;
40e8d8bef9SDimitry Andric 
41e8d8bef9SDimitry Andric #define DEBUG_TYPE "constraint-elimination"
42e8d8bef9SDimitry Andric 
43e8d8bef9SDimitry Andric STATISTIC(NumCondsRemoved, "Number of instructions removed");
44e8d8bef9SDimitry Andric DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
45e8d8bef9SDimitry Andric               "Controls which conditions are eliminated");
46e8d8bef9SDimitry Andric 
47*bdd1243dSDimitry Andric static cl::opt<unsigned>
48*bdd1243dSDimitry Andric     MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden,
49*bdd1243dSDimitry Andric             cl::desc("Maximum number of rows to keep in constraint system"));
50*bdd1243dSDimitry Andric 
51e8d8bef9SDimitry Andric static int64_t MaxConstraintValue = std::numeric_limits<int64_t>::max();
5281ad6265SDimitry Andric static int64_t MinSignedConstraintValue = std::numeric_limits<int64_t>::min();
53e8d8bef9SDimitry Andric 
54*bdd1243dSDimitry Andric // A helper to multiply 2 signed integers where overflowing is allowed.
55*bdd1243dSDimitry Andric static int64_t multiplyWithOverflow(int64_t A, int64_t B) {
56*bdd1243dSDimitry Andric   int64_t Result;
57*bdd1243dSDimitry Andric   MulOverflow(A, B, Result);
58*bdd1243dSDimitry Andric   return Result;
59*bdd1243dSDimitry Andric }
60*bdd1243dSDimitry Andric 
61*bdd1243dSDimitry Andric // A helper to add 2 signed integers where overflowing is allowed.
62*bdd1243dSDimitry Andric static int64_t addWithOverflow(int64_t A, int64_t B) {
63*bdd1243dSDimitry Andric   int64_t Result;
64*bdd1243dSDimitry Andric   AddOverflow(A, B, Result);
65*bdd1243dSDimitry Andric   return Result;
66*bdd1243dSDimitry Andric }
67*bdd1243dSDimitry Andric 
6804eeddc0SDimitry Andric namespace {
6904eeddc0SDimitry Andric 
7081ad6265SDimitry Andric class ConstraintInfo;
7104eeddc0SDimitry Andric 
7281ad6265SDimitry Andric struct StackEntry {
7381ad6265SDimitry Andric   unsigned NumIn;
7481ad6265SDimitry Andric   unsigned NumOut;
7581ad6265SDimitry Andric   bool IsSigned = false;
7681ad6265SDimitry Andric   /// Variables that can be removed from the system once the stack entry gets
7781ad6265SDimitry Andric   /// removed.
7881ad6265SDimitry Andric   SmallVector<Value *, 2> ValuesToRelease;
7981ad6265SDimitry Andric 
80*bdd1243dSDimitry Andric   StackEntry(unsigned NumIn, unsigned NumOut, bool IsSigned,
8181ad6265SDimitry Andric              SmallVector<Value *, 2> ValuesToRelease)
82*bdd1243dSDimitry Andric       : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
8381ad6265SDimitry Andric         ValuesToRelease(ValuesToRelease) {}
8404eeddc0SDimitry Andric };
8504eeddc0SDimitry Andric 
8681ad6265SDimitry Andric /// Struct to express a pre-condition of the form %Op0 Pred %Op1.
8781ad6265SDimitry Andric struct PreconditionTy {
8881ad6265SDimitry Andric   CmpInst::Predicate Pred;
8981ad6265SDimitry Andric   Value *Op0;
9081ad6265SDimitry Andric   Value *Op1;
9104eeddc0SDimitry Andric 
9281ad6265SDimitry Andric   PreconditionTy(CmpInst::Predicate Pred, Value *Op0, Value *Op1)
9381ad6265SDimitry Andric       : Pred(Pred), Op0(Op0), Op1(Op1) {}
9481ad6265SDimitry Andric };
9504eeddc0SDimitry Andric 
9681ad6265SDimitry Andric struct ConstraintTy {
9781ad6265SDimitry Andric   SmallVector<int64_t, 8> Coefficients;
9881ad6265SDimitry Andric   SmallVector<PreconditionTy, 2> Preconditions;
9904eeddc0SDimitry Andric 
100*bdd1243dSDimitry Andric   SmallVector<SmallVector<int64_t, 8>> ExtraInfo;
101*bdd1243dSDimitry Andric 
10281ad6265SDimitry Andric   bool IsSigned = false;
10381ad6265SDimitry Andric   bool IsEq = false;
10404eeddc0SDimitry Andric 
10581ad6265SDimitry Andric   ConstraintTy() = default;
10604eeddc0SDimitry Andric 
10781ad6265SDimitry Andric   ConstraintTy(SmallVector<int64_t, 8> Coefficients, bool IsSigned)
10881ad6265SDimitry Andric       : Coefficients(Coefficients), IsSigned(IsSigned) {}
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric   unsigned size() const { return Coefficients.size(); }
11181ad6265SDimitry Andric 
11281ad6265SDimitry Andric   unsigned empty() const { return Coefficients.empty(); }
11304eeddc0SDimitry Andric 
11481ad6265SDimitry Andric   /// Returns true if all preconditions for this list of constraints are
11581ad6265SDimitry Andric   /// satisfied given \p CS and the corresponding \p Value2Index mapping.
11681ad6265SDimitry Andric   bool isValid(const ConstraintInfo &Info) const;
11781ad6265SDimitry Andric };
11881ad6265SDimitry Andric 
11981ad6265SDimitry Andric /// Wrapper encapsulating separate constraint systems and corresponding value
12081ad6265SDimitry Andric /// mappings for both unsigned and signed information. Facts are added to and
12181ad6265SDimitry Andric /// conditions are checked against the corresponding system depending on the
12281ad6265SDimitry Andric /// signed-ness of their predicates. While the information is kept separate
12381ad6265SDimitry Andric /// based on signed-ness, certain conditions can be transferred between the two
12481ad6265SDimitry Andric /// systems.
12581ad6265SDimitry Andric class ConstraintInfo {
12681ad6265SDimitry Andric   DenseMap<Value *, unsigned> UnsignedValue2Index;
12781ad6265SDimitry Andric   DenseMap<Value *, unsigned> SignedValue2Index;
12881ad6265SDimitry Andric 
12981ad6265SDimitry Andric   ConstraintSystem UnsignedCS;
13081ad6265SDimitry Andric   ConstraintSystem SignedCS;
13181ad6265SDimitry Andric 
132*bdd1243dSDimitry Andric   const DataLayout &DL;
133*bdd1243dSDimitry Andric 
13481ad6265SDimitry Andric public:
135*bdd1243dSDimitry Andric   ConstraintInfo(const DataLayout &DL) : DL(DL) {}
136*bdd1243dSDimitry Andric 
13781ad6265SDimitry Andric   DenseMap<Value *, unsigned> &getValue2Index(bool Signed) {
13881ad6265SDimitry Andric     return Signed ? SignedValue2Index : UnsignedValue2Index;
13981ad6265SDimitry Andric   }
14081ad6265SDimitry Andric   const DenseMap<Value *, unsigned> &getValue2Index(bool Signed) const {
14181ad6265SDimitry Andric     return Signed ? SignedValue2Index : UnsignedValue2Index;
14281ad6265SDimitry Andric   }
14381ad6265SDimitry Andric 
14481ad6265SDimitry Andric   ConstraintSystem &getCS(bool Signed) {
14581ad6265SDimitry Andric     return Signed ? SignedCS : UnsignedCS;
14681ad6265SDimitry Andric   }
14781ad6265SDimitry Andric   const ConstraintSystem &getCS(bool Signed) const {
14881ad6265SDimitry Andric     return Signed ? SignedCS : UnsignedCS;
14981ad6265SDimitry Andric   }
15081ad6265SDimitry Andric 
15181ad6265SDimitry Andric   void popLastConstraint(bool Signed) { getCS(Signed).popLastConstraint(); }
15281ad6265SDimitry Andric   void popLastNVariables(bool Signed, unsigned N) {
15381ad6265SDimitry Andric     getCS(Signed).popLastNVariables(N);
15481ad6265SDimitry Andric   }
15581ad6265SDimitry Andric 
15681ad6265SDimitry Andric   bool doesHold(CmpInst::Predicate Pred, Value *A, Value *B) const;
15781ad6265SDimitry Andric 
158*bdd1243dSDimitry Andric   void addFact(CmpInst::Predicate Pred, Value *A, Value *B, unsigned NumIn,
159*bdd1243dSDimitry Andric                unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
16081ad6265SDimitry Andric 
16181ad6265SDimitry Andric   /// Turn a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
16281ad6265SDimitry Andric   /// constraints, using indices from the corresponding constraint system.
163*bdd1243dSDimitry Andric   /// New variables that need to be added to the system are collected in
164*bdd1243dSDimitry Andric   /// \p NewVariables.
16581ad6265SDimitry Andric   ConstraintTy getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
166*bdd1243dSDimitry Andric                              SmallVectorImpl<Value *> &NewVariables) const;
16781ad6265SDimitry Andric 
168*bdd1243dSDimitry Andric   /// Turns a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
169*bdd1243dSDimitry Andric   /// constraints using getConstraint. Returns an empty constraint if the result
170*bdd1243dSDimitry Andric   /// cannot be used to query the existing constraint system, e.g. because it
171*bdd1243dSDimitry Andric   /// would require adding new variables. Also tries to convert signed
172*bdd1243dSDimitry Andric   /// predicates to unsigned ones if possible to allow using the unsigned system
173*bdd1243dSDimitry Andric   /// which increases the effectiveness of the signed <-> unsigned transfer
174*bdd1243dSDimitry Andric   /// logic.
175*bdd1243dSDimitry Andric   ConstraintTy getConstraintForSolving(CmpInst::Predicate Pred, Value *Op0,
176*bdd1243dSDimitry Andric                                        Value *Op1) const;
17781ad6265SDimitry Andric 
17881ad6265SDimitry Andric   /// Try to add information from \p A \p Pred \p B to the unsigned/signed
17981ad6265SDimitry Andric   /// system if \p Pred is signed/unsigned.
18081ad6265SDimitry Andric   void transferToOtherSystem(CmpInst::Predicate Pred, Value *A, Value *B,
181*bdd1243dSDimitry Andric                              unsigned NumIn, unsigned NumOut,
18281ad6265SDimitry Andric                              SmallVectorImpl<StackEntry> &DFSInStack);
18304eeddc0SDimitry Andric };
18404eeddc0SDimitry Andric 
185*bdd1243dSDimitry Andric /// Represents a (Coefficient * Variable) entry after IR decomposition.
186*bdd1243dSDimitry Andric struct DecompEntry {
187*bdd1243dSDimitry Andric   int64_t Coefficient;
188*bdd1243dSDimitry Andric   Value *Variable;
189*bdd1243dSDimitry Andric   /// True if the variable is known positive in the current constraint.
190*bdd1243dSDimitry Andric   bool IsKnownNonNegative;
191*bdd1243dSDimitry Andric 
192*bdd1243dSDimitry Andric   DecompEntry(int64_t Coefficient, Value *Variable,
193*bdd1243dSDimitry Andric               bool IsKnownNonNegative = false)
194*bdd1243dSDimitry Andric       : Coefficient(Coefficient), Variable(Variable),
195*bdd1243dSDimitry Andric         IsKnownNonNegative(IsKnownNonNegative) {}
196*bdd1243dSDimitry Andric };
197*bdd1243dSDimitry Andric 
198*bdd1243dSDimitry Andric /// Represents an Offset + Coefficient1 * Variable1 + ... decomposition.
199*bdd1243dSDimitry Andric struct Decomposition {
200*bdd1243dSDimitry Andric   int64_t Offset = 0;
201*bdd1243dSDimitry Andric   SmallVector<DecompEntry, 3> Vars;
202*bdd1243dSDimitry Andric 
203*bdd1243dSDimitry Andric   Decomposition(int64_t Offset) : Offset(Offset) {}
204*bdd1243dSDimitry Andric   Decomposition(Value *V, bool IsKnownNonNegative = false) {
205*bdd1243dSDimitry Andric     Vars.emplace_back(1, V, IsKnownNonNegative);
206*bdd1243dSDimitry Andric   }
207*bdd1243dSDimitry Andric   Decomposition(int64_t Offset, ArrayRef<DecompEntry> Vars)
208*bdd1243dSDimitry Andric       : Offset(Offset), Vars(Vars) {}
209*bdd1243dSDimitry Andric 
210*bdd1243dSDimitry Andric   void add(int64_t OtherOffset) {
211*bdd1243dSDimitry Andric     Offset = addWithOverflow(Offset, OtherOffset);
212*bdd1243dSDimitry Andric   }
213*bdd1243dSDimitry Andric 
214*bdd1243dSDimitry Andric   void add(const Decomposition &Other) {
215*bdd1243dSDimitry Andric     add(Other.Offset);
216*bdd1243dSDimitry Andric     append_range(Vars, Other.Vars);
217*bdd1243dSDimitry Andric   }
218*bdd1243dSDimitry Andric 
219*bdd1243dSDimitry Andric   void mul(int64_t Factor) {
220*bdd1243dSDimitry Andric     Offset = multiplyWithOverflow(Offset, Factor);
221*bdd1243dSDimitry Andric     for (auto &Var : Vars)
222*bdd1243dSDimitry Andric       Var.Coefficient = multiplyWithOverflow(Var.Coefficient, Factor);
223*bdd1243dSDimitry Andric   }
224*bdd1243dSDimitry Andric };
225*bdd1243dSDimitry Andric 
22604eeddc0SDimitry Andric } // namespace
22704eeddc0SDimitry Andric 
228*bdd1243dSDimitry Andric static Decomposition decompose(Value *V,
229*bdd1243dSDimitry Andric                                SmallVectorImpl<PreconditionTy> &Preconditions,
230*bdd1243dSDimitry Andric                                bool IsSigned, const DataLayout &DL);
23181ad6265SDimitry Andric 
232*bdd1243dSDimitry Andric static bool canUseSExt(ConstantInt *CI) {
23381ad6265SDimitry Andric   const APInt &Val = CI->getValue();
23481ad6265SDimitry Andric   return Val.sgt(MinSignedConstraintValue) && Val.slt(MaxConstraintValue);
235*bdd1243dSDimitry Andric }
236*bdd1243dSDimitry Andric 
237*bdd1243dSDimitry Andric static Decomposition
238*bdd1243dSDimitry Andric decomposeGEP(GetElementPtrInst &GEP,
239*bdd1243dSDimitry Andric              SmallVectorImpl<PreconditionTy> &Preconditions, bool IsSigned,
240*bdd1243dSDimitry Andric              const DataLayout &DL) {
241*bdd1243dSDimitry Andric   // Do not reason about pointers where the index size is larger than 64 bits,
242*bdd1243dSDimitry Andric   // as the coefficients used to encode constraints are 64 bit integers.
243*bdd1243dSDimitry Andric   if (DL.getIndexTypeSizeInBits(GEP.getPointerOperand()->getType()) > 64)
244*bdd1243dSDimitry Andric     return &GEP;
245*bdd1243dSDimitry Andric 
246*bdd1243dSDimitry Andric   if (!GEP.isInBounds())
247*bdd1243dSDimitry Andric     return &GEP;
248*bdd1243dSDimitry Andric 
249*bdd1243dSDimitry Andric   assert(!IsSigned && "The logic below only supports decomposition for "
250*bdd1243dSDimitry Andric                       "unsinged predicates at the moment.");
251*bdd1243dSDimitry Andric   Type *PtrTy = GEP.getType()->getScalarType();
252*bdd1243dSDimitry Andric   unsigned BitWidth = DL.getIndexTypeSizeInBits(PtrTy);
253*bdd1243dSDimitry Andric   MapVector<Value *, APInt> VariableOffsets;
254*bdd1243dSDimitry Andric   APInt ConstantOffset(BitWidth, 0);
255*bdd1243dSDimitry Andric   if (!GEP.collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))
256*bdd1243dSDimitry Andric     return &GEP;
257*bdd1243dSDimitry Andric 
258*bdd1243dSDimitry Andric   // Handle the (gep (gep ....), C) case by incrementing the constant
259*bdd1243dSDimitry Andric   // coefficient of the inner GEP, if C is a constant.
260*bdd1243dSDimitry Andric   auto *InnerGEP = dyn_cast<GetElementPtrInst>(GEP.getPointerOperand());
261*bdd1243dSDimitry Andric   if (VariableOffsets.empty() && InnerGEP && InnerGEP->getNumOperands() == 2) {
262*bdd1243dSDimitry Andric     auto Result = decompose(InnerGEP, Preconditions, IsSigned, DL);
263*bdd1243dSDimitry Andric     Result.add(ConstantOffset.getSExtValue());
264*bdd1243dSDimitry Andric 
265*bdd1243dSDimitry Andric     if (ConstantOffset.isNegative()) {
266*bdd1243dSDimitry Andric       unsigned Scale = DL.getTypeAllocSize(InnerGEP->getResultElementType());
267*bdd1243dSDimitry Andric       int64_t ConstantOffsetI = ConstantOffset.getSExtValue();
268*bdd1243dSDimitry Andric       if (ConstantOffsetI % Scale != 0)
269*bdd1243dSDimitry Andric         return &GEP;
270*bdd1243dSDimitry Andric       // Add pre-condition ensuring the GEP is increasing monotonically and
271*bdd1243dSDimitry Andric       // can be de-composed.
272*bdd1243dSDimitry Andric       // Both sides are normalized by being divided by Scale.
273*bdd1243dSDimitry Andric       Preconditions.emplace_back(
274*bdd1243dSDimitry Andric           CmpInst::ICMP_SGE, InnerGEP->getOperand(1),
275*bdd1243dSDimitry Andric           ConstantInt::get(InnerGEP->getOperand(1)->getType(),
276*bdd1243dSDimitry Andric                            -1 * (ConstantOffsetI / Scale)));
277*bdd1243dSDimitry Andric     }
278*bdd1243dSDimitry Andric     return Result;
279*bdd1243dSDimitry Andric   }
280*bdd1243dSDimitry Andric 
281*bdd1243dSDimitry Andric   Decomposition Result(ConstantOffset.getSExtValue(),
282*bdd1243dSDimitry Andric                        DecompEntry(1, GEP.getPointerOperand()));
283*bdd1243dSDimitry Andric   for (auto [Index, Scale] : VariableOffsets) {
284*bdd1243dSDimitry Andric     auto IdxResult = decompose(Index, Preconditions, IsSigned, DL);
285*bdd1243dSDimitry Andric     IdxResult.mul(Scale.getSExtValue());
286*bdd1243dSDimitry Andric     Result.add(IdxResult);
287*bdd1243dSDimitry Andric 
288*bdd1243dSDimitry Andric     // If Op0 is signed non-negative, the GEP is increasing monotonically and
289*bdd1243dSDimitry Andric     // can be de-composed.
290*bdd1243dSDimitry Andric     if (!isKnownNonNegative(Index, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
291*bdd1243dSDimitry Andric       Preconditions.emplace_back(CmpInst::ICMP_SGE, Index,
292*bdd1243dSDimitry Andric                                  ConstantInt::get(Index->getType(), 0));
293*bdd1243dSDimitry Andric   }
294*bdd1243dSDimitry Andric   return Result;
295*bdd1243dSDimitry Andric }
296*bdd1243dSDimitry Andric 
297*bdd1243dSDimitry Andric // Decomposes \p V into a constant offset + list of pairs { Coefficient,
298*bdd1243dSDimitry Andric // Variable } where Coefficient * Variable. The sum of the constant offset and
299*bdd1243dSDimitry Andric // pairs equals \p V.
300*bdd1243dSDimitry Andric static Decomposition decompose(Value *V,
301*bdd1243dSDimitry Andric                                SmallVectorImpl<PreconditionTy> &Preconditions,
302*bdd1243dSDimitry Andric                                bool IsSigned, const DataLayout &DL) {
303*bdd1243dSDimitry Andric 
304*bdd1243dSDimitry Andric   auto MergeResults = [&Preconditions, IsSigned, &DL](Value *A, Value *B,
305*bdd1243dSDimitry Andric                                                       bool IsSignedB) {
306*bdd1243dSDimitry Andric     auto ResA = decompose(A, Preconditions, IsSigned, DL);
307*bdd1243dSDimitry Andric     auto ResB = decompose(B, Preconditions, IsSignedB, DL);
308*bdd1243dSDimitry Andric     ResA.add(ResB);
309*bdd1243dSDimitry Andric     return ResA;
31081ad6265SDimitry Andric   };
311*bdd1243dSDimitry Andric 
31281ad6265SDimitry Andric   // Decompose \p V used with a signed predicate.
31381ad6265SDimitry Andric   if (IsSigned) {
314e8d8bef9SDimitry Andric     if (auto *CI = dyn_cast<ConstantInt>(V)) {
315*bdd1243dSDimitry Andric       if (canUseSExt(CI))
316*bdd1243dSDimitry Andric         return CI->getSExtValue();
317e8d8bef9SDimitry Andric     }
318*bdd1243dSDimitry Andric     Value *Op0;
319*bdd1243dSDimitry Andric     Value *Op1;
320*bdd1243dSDimitry Andric     if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1))))
321*bdd1243dSDimitry Andric       return MergeResults(Op0, Op1, IsSigned);
32281ad6265SDimitry Andric 
323*bdd1243dSDimitry Andric     return V;
32481ad6265SDimitry Andric   }
32581ad6265SDimitry Andric 
32681ad6265SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(V)) {
32781ad6265SDimitry Andric     if (CI->uge(MaxConstraintValue))
328*bdd1243dSDimitry Andric       return V;
329*bdd1243dSDimitry Andric     return int64_t(CI->getZExtValue());
330fe6060f1SDimitry Andric   }
331fe6060f1SDimitry Andric 
332*bdd1243dSDimitry Andric   if (auto *GEP = dyn_cast<GetElementPtrInst>(V))
333*bdd1243dSDimitry Andric     return decomposeGEP(*GEP, Preconditions, IsSigned, DL);
334e8d8bef9SDimitry Andric 
335e8d8bef9SDimitry Andric   Value *Op0;
336*bdd1243dSDimitry Andric   bool IsKnownNonNegative = false;
337*bdd1243dSDimitry Andric   if (match(V, m_ZExt(m_Value(Op0)))) {
338*bdd1243dSDimitry Andric     IsKnownNonNegative = true;
339fe6060f1SDimitry Andric     V = Op0;
340*bdd1243dSDimitry Andric   }
341fe6060f1SDimitry Andric 
342e8d8bef9SDimitry Andric   Value *Op1;
343e8d8bef9SDimitry Andric   ConstantInt *CI;
344*bdd1243dSDimitry Andric   if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1)))) {
345*bdd1243dSDimitry Andric     return MergeResults(Op0, Op1, IsSigned);
346*bdd1243dSDimitry Andric   }
347*bdd1243dSDimitry Andric   if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1)))) {
348*bdd1243dSDimitry Andric     if (!isKnownNonNegative(Op0, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
349*bdd1243dSDimitry Andric       Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0,
350*bdd1243dSDimitry Andric                                  ConstantInt::get(Op0->getType(), 0));
351*bdd1243dSDimitry Andric     if (!isKnownNonNegative(Op1, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
352*bdd1243dSDimitry Andric       Preconditions.emplace_back(CmpInst::ICMP_SGE, Op1,
353*bdd1243dSDimitry Andric                                  ConstantInt::get(Op1->getType(), 0));
354*bdd1243dSDimitry Andric 
355*bdd1243dSDimitry Andric     return MergeResults(Op0, Op1, IsSigned);
356*bdd1243dSDimitry Andric   }
357*bdd1243dSDimitry Andric 
35881ad6265SDimitry Andric   if (match(V, m_Add(m_Value(Op0), m_ConstantInt(CI))) && CI->isNegative() &&
359*bdd1243dSDimitry Andric       canUseSExt(CI)) {
36081ad6265SDimitry Andric     Preconditions.emplace_back(
36181ad6265SDimitry Andric         CmpInst::ICMP_UGE, Op0,
36281ad6265SDimitry Andric         ConstantInt::get(Op0->getType(), CI->getSExtValue() * -1));
363*bdd1243dSDimitry Andric     return MergeResults(Op0, CI, true);
36481ad6265SDimitry Andric   }
365e8d8bef9SDimitry Andric 
366*bdd1243dSDimitry Andric   if (match(V, m_NUWShl(m_Value(Op1), m_ConstantInt(CI))) && canUseSExt(CI)) {
367*bdd1243dSDimitry Andric     int64_t Mult = int64_t(std::pow(int64_t(2), CI->getSExtValue()));
368*bdd1243dSDimitry Andric     auto Result = decompose(Op1, Preconditions, IsSigned, DL);
369*bdd1243dSDimitry Andric     Result.mul(Mult);
370*bdd1243dSDimitry Andric     return Result;
371*bdd1243dSDimitry Andric   }
372*bdd1243dSDimitry Andric 
373*bdd1243dSDimitry Andric   if (match(V, m_NUWMul(m_Value(Op1), m_ConstantInt(CI))) && canUseSExt(CI) &&
374*bdd1243dSDimitry Andric       (!CI->isNegative())) {
375*bdd1243dSDimitry Andric     auto Result = decompose(Op1, Preconditions, IsSigned, DL);
376*bdd1243dSDimitry Andric     Result.mul(CI->getSExtValue());
377*bdd1243dSDimitry Andric     return Result;
378*bdd1243dSDimitry Andric   }
379*bdd1243dSDimitry Andric 
380*bdd1243dSDimitry Andric   if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI))
381*bdd1243dSDimitry Andric     return {-1 * CI->getSExtValue(), {{1, Op0}}};
382e8d8bef9SDimitry Andric   if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
383*bdd1243dSDimitry Andric     return {0, {{1, Op0}, {-1, Op1}}};
384e8d8bef9SDimitry Andric 
385*bdd1243dSDimitry Andric   return {V, IsKnownNonNegative};
386e8d8bef9SDimitry Andric }
387e8d8bef9SDimitry Andric 
38881ad6265SDimitry Andric ConstraintTy
38981ad6265SDimitry Andric ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
390*bdd1243dSDimitry Andric                               SmallVectorImpl<Value *> &NewVariables) const {
391*bdd1243dSDimitry Andric   assert(NewVariables.empty() && "NewVariables must be empty when passed in");
39281ad6265SDimitry Andric   bool IsEq = false;
39381ad6265SDimitry Andric   // Try to convert Pred to one of ULE/SLT/SLE/SLT.
39481ad6265SDimitry Andric   switch (Pred) {
39581ad6265SDimitry Andric   case CmpInst::ICMP_UGT:
39681ad6265SDimitry Andric   case CmpInst::ICMP_UGE:
39781ad6265SDimitry Andric   case CmpInst::ICMP_SGT:
39881ad6265SDimitry Andric   case CmpInst::ICMP_SGE: {
39981ad6265SDimitry Andric     Pred = CmpInst::getSwappedPredicate(Pred);
40081ad6265SDimitry Andric     std::swap(Op0, Op1);
40181ad6265SDimitry Andric     break;
40281ad6265SDimitry Andric   }
40381ad6265SDimitry Andric   case CmpInst::ICMP_EQ:
40481ad6265SDimitry Andric     if (match(Op1, m_Zero())) {
40581ad6265SDimitry Andric       Pred = CmpInst::ICMP_ULE;
40681ad6265SDimitry Andric     } else {
40781ad6265SDimitry Andric       IsEq = true;
40881ad6265SDimitry Andric       Pred = CmpInst::ICMP_ULE;
40981ad6265SDimitry Andric     }
41081ad6265SDimitry Andric     break;
41181ad6265SDimitry Andric   case CmpInst::ICMP_NE:
41281ad6265SDimitry Andric     if (!match(Op1, m_Zero()))
41381ad6265SDimitry Andric       return {};
41481ad6265SDimitry Andric     Pred = CmpInst::getSwappedPredicate(CmpInst::ICMP_UGT);
41581ad6265SDimitry Andric     std::swap(Op0, Op1);
41681ad6265SDimitry Andric     break;
41781ad6265SDimitry Andric   default:
41881ad6265SDimitry Andric     break;
41981ad6265SDimitry Andric   }
42081ad6265SDimitry Andric 
42181ad6265SDimitry Andric   if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT &&
42281ad6265SDimitry Andric       Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SLT)
42381ad6265SDimitry Andric     return {};
42481ad6265SDimitry Andric 
42581ad6265SDimitry Andric   SmallVector<PreconditionTy, 4> Preconditions;
42681ad6265SDimitry Andric   bool IsSigned = CmpInst::isSigned(Pred);
42781ad6265SDimitry Andric   auto &Value2Index = getValue2Index(IsSigned);
42881ad6265SDimitry Andric   auto ADec = decompose(Op0->stripPointerCastsSameRepresentation(),
429*bdd1243dSDimitry Andric                         Preconditions, IsSigned, DL);
43081ad6265SDimitry Andric   auto BDec = decompose(Op1->stripPointerCastsSameRepresentation(),
431*bdd1243dSDimitry Andric                         Preconditions, IsSigned, DL);
432*bdd1243dSDimitry Andric   int64_t Offset1 = ADec.Offset;
433*bdd1243dSDimitry Andric   int64_t Offset2 = BDec.Offset;
43481ad6265SDimitry Andric   Offset1 *= -1;
43581ad6265SDimitry Andric 
436*bdd1243dSDimitry Andric   auto &VariablesA = ADec.Vars;
437*bdd1243dSDimitry Andric   auto &VariablesB = BDec.Vars;
438e8d8bef9SDimitry Andric 
439*bdd1243dSDimitry Andric   // First try to look up \p V in Value2Index and NewVariables. Otherwise add a
440*bdd1243dSDimitry Andric   // new entry to NewVariables.
441*bdd1243dSDimitry Andric   DenseMap<Value *, unsigned> NewIndexMap;
442*bdd1243dSDimitry Andric   auto GetOrAddIndex = [&Value2Index, &NewVariables,
443*bdd1243dSDimitry Andric                         &NewIndexMap](Value *V) -> unsigned {
444fe6060f1SDimitry Andric     auto V2I = Value2Index.find(V);
445fe6060f1SDimitry Andric     if (V2I != Value2Index.end())
446fe6060f1SDimitry Andric       return V2I->second;
447fe6060f1SDimitry Andric     auto Insert =
448*bdd1243dSDimitry Andric         NewIndexMap.insert({V, Value2Index.size() + NewVariables.size() + 1});
449*bdd1243dSDimitry Andric     if (Insert.second)
450*bdd1243dSDimitry Andric       NewVariables.push_back(V);
451fe6060f1SDimitry Andric     return Insert.first->second;
452e8d8bef9SDimitry Andric   };
453e8d8bef9SDimitry Andric 
454*bdd1243dSDimitry Andric   // Make sure all variables have entries in Value2Index or NewVariables.
455*bdd1243dSDimitry Andric   for (const auto &KV : concat<DecompEntry>(VariablesA, VariablesB))
456*bdd1243dSDimitry Andric     GetOrAddIndex(KV.Variable);
457e8d8bef9SDimitry Andric 
458e8d8bef9SDimitry Andric   // Build result constraint, by first adding all coefficients from A and then
459e8d8bef9SDimitry Andric   // subtracting all coefficients from B.
46081ad6265SDimitry Andric   ConstraintTy Res(
461*bdd1243dSDimitry Andric       SmallVector<int64_t, 8>(Value2Index.size() + NewVariables.size() + 1, 0),
46281ad6265SDimitry Andric       IsSigned);
463*bdd1243dSDimitry Andric   // Collect variables that are known to be positive in all uses in the
464*bdd1243dSDimitry Andric   // constraint.
465*bdd1243dSDimitry Andric   DenseMap<Value *, bool> KnownNonNegativeVariables;
46681ad6265SDimitry Andric   Res.IsEq = IsEq;
46781ad6265SDimitry Andric   auto &R = Res.Coefficients;
468*bdd1243dSDimitry Andric   for (const auto &KV : VariablesA) {
469*bdd1243dSDimitry Andric     R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
470*bdd1243dSDimitry Andric     auto I =
471*bdd1243dSDimitry Andric         KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative});
472*bdd1243dSDimitry Andric     I.first->second &= KV.IsKnownNonNegative;
473*bdd1243dSDimitry Andric   }
474e8d8bef9SDimitry Andric 
475*bdd1243dSDimitry Andric   for (const auto &KV : VariablesB) {
476*bdd1243dSDimitry Andric     R[GetOrAddIndex(KV.Variable)] -= KV.Coefficient;
477*bdd1243dSDimitry Andric     auto I =
478*bdd1243dSDimitry Andric         KnownNonNegativeVariables.insert({KV.Variable, KV.IsKnownNonNegative});
479*bdd1243dSDimitry Andric     I.first->second &= KV.IsKnownNonNegative;
480*bdd1243dSDimitry Andric   }
481e8d8bef9SDimitry Andric 
48281ad6265SDimitry Andric   int64_t OffsetSum;
48381ad6265SDimitry Andric   if (AddOverflow(Offset1, Offset2, OffsetSum))
48481ad6265SDimitry Andric     return {};
48581ad6265SDimitry Andric   if (Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT))
48681ad6265SDimitry Andric     if (AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
48781ad6265SDimitry Andric       return {};
48881ad6265SDimitry Andric   R[0] = OffsetSum;
48981ad6265SDimitry Andric   Res.Preconditions = std::move(Preconditions);
490*bdd1243dSDimitry Andric 
491*bdd1243dSDimitry Andric   // Remove any (Coefficient, Variable) entry where the Coefficient is 0 for new
492*bdd1243dSDimitry Andric   // variables.
493*bdd1243dSDimitry Andric   while (!NewVariables.empty()) {
494*bdd1243dSDimitry Andric     int64_t Last = R.back();
495*bdd1243dSDimitry Andric     if (Last != 0)
496*bdd1243dSDimitry Andric       break;
497*bdd1243dSDimitry Andric     R.pop_back();
498*bdd1243dSDimitry Andric     Value *RemovedV = NewVariables.pop_back_val();
499*bdd1243dSDimitry Andric     NewIndexMap.erase(RemovedV);
500*bdd1243dSDimitry Andric   }
501*bdd1243dSDimitry Andric 
502*bdd1243dSDimitry Andric   // Add extra constraints for variables that are known positive.
503*bdd1243dSDimitry Andric   for (auto &KV : KnownNonNegativeVariables) {
504*bdd1243dSDimitry Andric     if (!KV.second || (Value2Index.find(KV.first) == Value2Index.end() &&
505*bdd1243dSDimitry Andric                        NewIndexMap.find(KV.first) == NewIndexMap.end()))
506*bdd1243dSDimitry Andric       continue;
507*bdd1243dSDimitry Andric     SmallVector<int64_t, 8> C(Value2Index.size() + NewVariables.size() + 1, 0);
508*bdd1243dSDimitry Andric     C[GetOrAddIndex(KV.first)] = -1;
509*bdd1243dSDimitry Andric     Res.ExtraInfo.push_back(C);
510*bdd1243dSDimitry Andric   }
51181ad6265SDimitry Andric   return Res;
512e8d8bef9SDimitry Andric }
513e8d8bef9SDimitry Andric 
514*bdd1243dSDimitry Andric ConstraintTy ConstraintInfo::getConstraintForSolving(CmpInst::Predicate Pred,
515*bdd1243dSDimitry Andric                                                      Value *Op0,
516*bdd1243dSDimitry Andric                                                      Value *Op1) const {
517*bdd1243dSDimitry Andric   // If both operands are known to be non-negative, change signed predicates to
518*bdd1243dSDimitry Andric   // unsigned ones. This increases the reasoning effectiveness in combination
519*bdd1243dSDimitry Andric   // with the signed <-> unsigned transfer logic.
520*bdd1243dSDimitry Andric   if (CmpInst::isSigned(Pred) &&
521*bdd1243dSDimitry Andric       isKnownNonNegative(Op0, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1) &&
522*bdd1243dSDimitry Andric       isKnownNonNegative(Op1, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
523*bdd1243dSDimitry Andric     Pred = CmpInst::getUnsignedPredicate(Pred);
524*bdd1243dSDimitry Andric 
525*bdd1243dSDimitry Andric   SmallVector<Value *> NewVariables;
526*bdd1243dSDimitry Andric   ConstraintTy R = getConstraint(Pred, Op0, Op1, NewVariables);
527*bdd1243dSDimitry Andric   if (R.IsEq || !NewVariables.empty())
528*bdd1243dSDimitry Andric     return {};
529*bdd1243dSDimitry Andric   return R;
530*bdd1243dSDimitry Andric }
531*bdd1243dSDimitry Andric 
53281ad6265SDimitry Andric bool ConstraintTy::isValid(const ConstraintInfo &Info) const {
53381ad6265SDimitry Andric   return Coefficients.size() > 0 &&
53481ad6265SDimitry Andric          all_of(Preconditions, [&Info](const PreconditionTy &C) {
53581ad6265SDimitry Andric            return Info.doesHold(C.Pred, C.Op0, C.Op1);
53681ad6265SDimitry Andric          });
53781ad6265SDimitry Andric }
53881ad6265SDimitry Andric 
53981ad6265SDimitry Andric bool ConstraintInfo::doesHold(CmpInst::Predicate Pred, Value *A,
54081ad6265SDimitry Andric                               Value *B) const {
541*bdd1243dSDimitry Andric   auto R = getConstraintForSolving(Pred, A, B);
542*bdd1243dSDimitry Andric   return R.Preconditions.empty() && !R.empty() &&
543*bdd1243dSDimitry Andric          getCS(R.IsSigned).isConditionImplied(R.Coefficients);
54481ad6265SDimitry Andric }
54581ad6265SDimitry Andric 
54681ad6265SDimitry Andric void ConstraintInfo::transferToOtherSystem(
547*bdd1243dSDimitry Andric     CmpInst::Predicate Pred, Value *A, Value *B, unsigned NumIn,
54881ad6265SDimitry Andric     unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
54981ad6265SDimitry Andric   // Check if we can combine facts from the signed and unsigned systems to
55081ad6265SDimitry Andric   // derive additional facts.
55181ad6265SDimitry Andric   if (!A->getType()->isIntegerTy())
55281ad6265SDimitry Andric     return;
55381ad6265SDimitry Andric   // FIXME: This currently depends on the order we add facts. Ideally we
55481ad6265SDimitry Andric   // would first add all known facts and only then try to add additional
55581ad6265SDimitry Andric   // facts.
55681ad6265SDimitry Andric   switch (Pred) {
55781ad6265SDimitry Andric   default:
55881ad6265SDimitry Andric     break;
55981ad6265SDimitry Andric   case CmpInst::ICMP_ULT:
56081ad6265SDimitry Andric     //  If B is a signed positive constant, A >=s 0 and A <s B.
56181ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0))) {
562*bdd1243dSDimitry Andric       addFact(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0), NumIn,
563*bdd1243dSDimitry Andric               NumOut, DFSInStack);
564*bdd1243dSDimitry Andric       addFact(CmpInst::ICMP_SLT, A, B, NumIn, NumOut, DFSInStack);
56581ad6265SDimitry Andric     }
56681ad6265SDimitry Andric     break;
56781ad6265SDimitry Andric   case CmpInst::ICMP_SLT:
56881ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0)))
569*bdd1243dSDimitry Andric       addFact(CmpInst::ICMP_ULT, A, B, NumIn, NumOut, DFSInStack);
57081ad6265SDimitry Andric     break;
57181ad6265SDimitry Andric   case CmpInst::ICMP_SGT:
57281ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), -1)))
573*bdd1243dSDimitry Andric       addFact(CmpInst::ICMP_UGE, A, ConstantInt::get(B->getType(), 0), NumIn,
574*bdd1243dSDimitry Andric               NumOut, DFSInStack);
57581ad6265SDimitry Andric     break;
57681ad6265SDimitry Andric   case CmpInst::ICMP_SGE:
57781ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0))) {
578*bdd1243dSDimitry Andric       addFact(CmpInst::ICMP_UGE, A, B, NumIn, NumOut, DFSInStack);
57981ad6265SDimitry Andric     }
58081ad6265SDimitry Andric     break;
58181ad6265SDimitry Andric   }
582e8d8bef9SDimitry Andric }
583e8d8bef9SDimitry Andric 
584e8d8bef9SDimitry Andric namespace {
585*bdd1243dSDimitry Andric /// Represents either
586*bdd1243dSDimitry Andric ///  * a condition that holds on entry to a block (=conditional fact)
587*bdd1243dSDimitry Andric ///  * an assume (=assume fact)
588*bdd1243dSDimitry Andric ///  * an instruction to simplify.
589*bdd1243dSDimitry Andric /// It also tracks the Dominator DFS in and out numbers for each entry.
590*bdd1243dSDimitry Andric struct FactOrCheck {
591*bdd1243dSDimitry Andric   Instruction *Inst;
592e8d8bef9SDimitry Andric   unsigned NumIn;
593e8d8bef9SDimitry Andric   unsigned NumOut;
594*bdd1243dSDimitry Andric   bool IsCheck;
595e8d8bef9SDimitry Andric   bool Not;
596e8d8bef9SDimitry Andric 
597*bdd1243dSDimitry Andric   FactOrCheck(DomTreeNode *DTN, Instruction *Inst, bool IsCheck, bool Not)
598*bdd1243dSDimitry Andric       : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
599*bdd1243dSDimitry Andric         IsCheck(IsCheck), Not(Not) {}
600*bdd1243dSDimitry Andric 
601*bdd1243dSDimitry Andric   static FactOrCheck getFact(DomTreeNode *DTN, Instruction *Inst,
602*bdd1243dSDimitry Andric                              bool Not = false) {
603*bdd1243dSDimitry Andric     return FactOrCheck(DTN, Inst, false, Not);
604*bdd1243dSDimitry Andric   }
605*bdd1243dSDimitry Andric 
606*bdd1243dSDimitry Andric   static FactOrCheck getCheck(DomTreeNode *DTN, Instruction *Inst) {
607*bdd1243dSDimitry Andric     return FactOrCheck(DTN, Inst, true, false);
608*bdd1243dSDimitry Andric   }
609*bdd1243dSDimitry Andric 
610*bdd1243dSDimitry Andric   bool isAssumeFact() const {
611*bdd1243dSDimitry Andric     if (!IsCheck && isa<IntrinsicInst>(Inst)) {
612*bdd1243dSDimitry Andric       assert(match(Inst, m_Intrinsic<Intrinsic::assume>()));
613*bdd1243dSDimitry Andric       return true;
614*bdd1243dSDimitry Andric     }
615*bdd1243dSDimitry Andric     return false;
616*bdd1243dSDimitry Andric   }
617*bdd1243dSDimitry Andric 
618*bdd1243dSDimitry Andric   bool isConditionFact() const { return !IsCheck && isa<CmpInst>(Inst); }
619e8d8bef9SDimitry Andric };
620e8d8bef9SDimitry Andric 
62181ad6265SDimitry Andric /// Keep state required to build worklist.
62281ad6265SDimitry Andric struct State {
62381ad6265SDimitry Andric   DominatorTree &DT;
624*bdd1243dSDimitry Andric   SmallVector<FactOrCheck, 64> WorkList;
625e8d8bef9SDimitry Andric 
62681ad6265SDimitry Andric   State(DominatorTree &DT) : DT(DT) {}
62781ad6265SDimitry Andric 
62881ad6265SDimitry Andric   /// Process block \p BB and add known facts to work-list.
62981ad6265SDimitry Andric   void addInfoFor(BasicBlock &BB);
63081ad6265SDimitry Andric 
63181ad6265SDimitry Andric   /// Returns true if we can add a known condition from BB to its successor
632*bdd1243dSDimitry Andric   /// block Succ.
63381ad6265SDimitry Andric   bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ) const {
634*bdd1243dSDimitry Andric     return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
63581ad6265SDimitry Andric   }
636e8d8bef9SDimitry Andric };
63781ad6265SDimitry Andric 
638e8d8bef9SDimitry Andric } // namespace
639e8d8bef9SDimitry Andric 
640fe6060f1SDimitry Andric #ifndef NDEBUG
64181ad6265SDimitry Andric static void dumpWithNames(const ConstraintSystem &CS,
642fe6060f1SDimitry Andric                           DenseMap<Value *, unsigned> &Value2Index) {
643fe6060f1SDimitry Andric   SmallVector<std::string> Names(Value2Index.size(), "");
644fe6060f1SDimitry Andric   for (auto &KV : Value2Index) {
645fe6060f1SDimitry Andric     Names[KV.second - 1] = std::string("%") + KV.first->getName().str();
646fe6060f1SDimitry Andric   }
647fe6060f1SDimitry Andric   CS.dump(Names);
648fe6060f1SDimitry Andric }
64981ad6265SDimitry Andric 
65081ad6265SDimitry Andric static void dumpWithNames(ArrayRef<int64_t> C,
65181ad6265SDimitry Andric                           DenseMap<Value *, unsigned> &Value2Index) {
65281ad6265SDimitry Andric   ConstraintSystem CS;
65381ad6265SDimitry Andric   CS.addVariableRowFill(C);
65481ad6265SDimitry Andric   dumpWithNames(CS, Value2Index);
65581ad6265SDimitry Andric }
656fe6060f1SDimitry Andric #endif
657fe6060f1SDimitry Andric 
65881ad6265SDimitry Andric void State::addInfoFor(BasicBlock &BB) {
659349cc55cSDimitry Andric   // True as long as long as the current instruction is guaranteed to execute.
660349cc55cSDimitry Andric   bool GuaranteedToExecute = true;
661*bdd1243dSDimitry Andric   // Queue conditions and assumes.
662349cc55cSDimitry Andric   for (Instruction &I : BB) {
663*bdd1243dSDimitry Andric     if (auto Cmp = dyn_cast<ICmpInst>(&I)) {
664*bdd1243dSDimitry Andric       WorkList.push_back(FactOrCheck::getCheck(DT.getNode(&BB), Cmp));
665*bdd1243dSDimitry Andric       continue;
666*bdd1243dSDimitry Andric     }
667*bdd1243dSDimitry Andric 
668*bdd1243dSDimitry Andric     if (match(&I, m_Intrinsic<Intrinsic::ssub_with_overflow>())) {
669*bdd1243dSDimitry Andric       WorkList.push_back(FactOrCheck::getCheck(DT.getNode(&BB), &I));
670*bdd1243dSDimitry Andric       continue;
671*bdd1243dSDimitry Andric     }
672*bdd1243dSDimitry Andric 
673349cc55cSDimitry Andric     Value *Cond;
674349cc55cSDimitry Andric     // For now, just handle assumes with a single compare as condition.
675349cc55cSDimitry Andric     if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
67681ad6265SDimitry Andric         isa<ICmpInst>(Cond)) {
677349cc55cSDimitry Andric       if (GuaranteedToExecute) {
678349cc55cSDimitry Andric         // The assume is guaranteed to execute when BB is entered, hence Cond
679349cc55cSDimitry Andric         // holds on entry to BB.
680*bdd1243dSDimitry Andric         WorkList.emplace_back(FactOrCheck::getFact(DT.getNode(I.getParent()),
681*bdd1243dSDimitry Andric                                                    cast<Instruction>(Cond)));
682349cc55cSDimitry Andric       } else {
683*bdd1243dSDimitry Andric         WorkList.emplace_back(
684*bdd1243dSDimitry Andric             FactOrCheck::getFact(DT.getNode(I.getParent()), &I));
685349cc55cSDimitry Andric       }
686349cc55cSDimitry Andric     }
687349cc55cSDimitry Andric     GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
688349cc55cSDimitry Andric   }
689349cc55cSDimitry Andric 
690e8d8bef9SDimitry Andric   auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
691e8d8bef9SDimitry Andric   if (!Br || !Br->isConditional())
69281ad6265SDimitry Andric     return;
693e8d8bef9SDimitry Andric 
694*bdd1243dSDimitry Andric   Value *Cond = Br->getCondition();
695e8d8bef9SDimitry Andric 
696*bdd1243dSDimitry Andric   // If the condition is a chain of ORs/AND and the successor only has the
697*bdd1243dSDimitry Andric   // current block as predecessor, queue conditions for the successor.
698*bdd1243dSDimitry Andric   Value *Op0, *Op1;
699*bdd1243dSDimitry Andric   if (match(Cond, m_LogicalOr(m_Value(Op0), m_Value(Op1))) ||
700*bdd1243dSDimitry Andric       match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
701*bdd1243dSDimitry Andric     bool IsOr = match(Cond, m_LogicalOr());
702*bdd1243dSDimitry Andric     bool IsAnd = match(Cond, m_LogicalAnd());
703*bdd1243dSDimitry Andric     // If there's a select that matches both AND and OR, we need to commit to
704*bdd1243dSDimitry Andric     // one of the options. Arbitrarily pick OR.
705*bdd1243dSDimitry Andric     if (IsOr && IsAnd)
706*bdd1243dSDimitry Andric       IsAnd = false;
707*bdd1243dSDimitry Andric 
708*bdd1243dSDimitry Andric     BasicBlock *Successor = Br->getSuccessor(IsOr ? 1 : 0);
709*bdd1243dSDimitry Andric     if (canAddSuccessor(BB, Successor)) {
710*bdd1243dSDimitry Andric       SmallVector<Value *> CondWorkList;
711*bdd1243dSDimitry Andric       SmallPtrSet<Value *, 8> SeenCond;
712*bdd1243dSDimitry Andric       auto QueueValue = [&CondWorkList, &SeenCond](Value *V) {
713*bdd1243dSDimitry Andric         if (SeenCond.insert(V).second)
714*bdd1243dSDimitry Andric           CondWorkList.push_back(V);
715*bdd1243dSDimitry Andric       };
716*bdd1243dSDimitry Andric       QueueValue(Op1);
717*bdd1243dSDimitry Andric       QueueValue(Op0);
718*bdd1243dSDimitry Andric       while (!CondWorkList.empty()) {
719*bdd1243dSDimitry Andric         Value *Cur = CondWorkList.pop_back_val();
720*bdd1243dSDimitry Andric         if (auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
721*bdd1243dSDimitry Andric           WorkList.emplace_back(
722*bdd1243dSDimitry Andric               FactOrCheck::getFact(DT.getNode(Successor), Cmp, IsOr));
723*bdd1243dSDimitry Andric           continue;
724*bdd1243dSDimitry Andric         }
725*bdd1243dSDimitry Andric         if (IsOr && match(Cur, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
726*bdd1243dSDimitry Andric           QueueValue(Op1);
727*bdd1243dSDimitry Andric           QueueValue(Op0);
728*bdd1243dSDimitry Andric           continue;
729*bdd1243dSDimitry Andric         }
730*bdd1243dSDimitry Andric         if (IsAnd && match(Cur, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
731*bdd1243dSDimitry Andric           QueueValue(Op1);
732*bdd1243dSDimitry Andric           QueueValue(Op0);
733*bdd1243dSDimitry Andric           continue;
734*bdd1243dSDimitry Andric         }
735*bdd1243dSDimitry Andric       }
736e8d8bef9SDimitry Andric     }
73781ad6265SDimitry Andric     return;
738e8d8bef9SDimitry Andric   }
739e8d8bef9SDimitry Andric 
74081ad6265SDimitry Andric   auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
741e8d8bef9SDimitry Andric   if (!CmpI)
74281ad6265SDimitry Andric     return;
74381ad6265SDimitry Andric   if (canAddSuccessor(BB, Br->getSuccessor(0)))
744*bdd1243dSDimitry Andric     WorkList.emplace_back(
745*bdd1243dSDimitry Andric         FactOrCheck::getFact(DT.getNode(Br->getSuccessor(0)), CmpI));
74681ad6265SDimitry Andric   if (canAddSuccessor(BB, Br->getSuccessor(1)))
747*bdd1243dSDimitry Andric     WorkList.emplace_back(
748*bdd1243dSDimitry Andric         FactOrCheck::getFact(DT.getNode(Br->getSuccessor(1)), CmpI, true));
749*bdd1243dSDimitry Andric }
750*bdd1243dSDimitry Andric 
751*bdd1243dSDimitry Andric static bool checkAndReplaceCondition(CmpInst *Cmp, ConstraintInfo &Info) {
752*bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "Checking " << *Cmp << "\n");
753*bdd1243dSDimitry Andric 
754*bdd1243dSDimitry Andric   CmpInst::Predicate Pred = Cmp->getPredicate();
755*bdd1243dSDimitry Andric   Value *A = Cmp->getOperand(0);
756*bdd1243dSDimitry Andric   Value *B = Cmp->getOperand(1);
757*bdd1243dSDimitry Andric 
758*bdd1243dSDimitry Andric   auto R = Info.getConstraintForSolving(Pred, A, B);
759*bdd1243dSDimitry Andric   if (R.empty() || !R.isValid(Info)){
760*bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "   failed to decompose condition\n");
761*bdd1243dSDimitry Andric     return false;
762*bdd1243dSDimitry Andric   }
763*bdd1243dSDimitry Andric 
764*bdd1243dSDimitry Andric   auto &CSToUse = Info.getCS(R.IsSigned);
765*bdd1243dSDimitry Andric 
766*bdd1243dSDimitry Andric   // If there was extra information collected during decomposition, apply
767*bdd1243dSDimitry Andric   // it now and remove it immediately once we are done with reasoning
768*bdd1243dSDimitry Andric   // about the constraint.
769*bdd1243dSDimitry Andric   for (auto &Row : R.ExtraInfo)
770*bdd1243dSDimitry Andric     CSToUse.addVariableRow(Row);
771*bdd1243dSDimitry Andric   auto InfoRestorer = make_scope_exit([&]() {
772*bdd1243dSDimitry Andric     for (unsigned I = 0; I < R.ExtraInfo.size(); ++I)
773*bdd1243dSDimitry Andric       CSToUse.popLastConstraint();
774*bdd1243dSDimitry Andric   });
775*bdd1243dSDimitry Andric 
776*bdd1243dSDimitry Andric   bool Changed = false;
777*bdd1243dSDimitry Andric   if (CSToUse.isConditionImplied(R.Coefficients)) {
778*bdd1243dSDimitry Andric     if (!DebugCounter::shouldExecute(EliminatedCounter))
779*bdd1243dSDimitry Andric       return false;
780*bdd1243dSDimitry Andric 
781*bdd1243dSDimitry Andric     LLVM_DEBUG({
782*bdd1243dSDimitry Andric       dbgs() << "Condition " << *Cmp << " implied by dominating constraints\n";
783*bdd1243dSDimitry Andric       dumpWithNames(CSToUse, Info.getValue2Index(R.IsSigned));
784*bdd1243dSDimitry Andric     });
785*bdd1243dSDimitry Andric     Constant *TrueC =
786*bdd1243dSDimitry Andric         ConstantInt::getTrue(CmpInst::makeCmpResultType(Cmp->getType()));
787*bdd1243dSDimitry Andric     Cmp->replaceUsesWithIf(TrueC, [](Use &U) {
788*bdd1243dSDimitry Andric       // Conditions in an assume trivially simplify to true. Skip uses
789*bdd1243dSDimitry Andric       // in assume calls to not destroy the available information.
790*bdd1243dSDimitry Andric       auto *II = dyn_cast<IntrinsicInst>(U.getUser());
791*bdd1243dSDimitry Andric       return !II || II->getIntrinsicID() != Intrinsic::assume;
792*bdd1243dSDimitry Andric     });
793*bdd1243dSDimitry Andric     NumCondsRemoved++;
794*bdd1243dSDimitry Andric     Changed = true;
795*bdd1243dSDimitry Andric   }
796*bdd1243dSDimitry Andric   if (CSToUse.isConditionImplied(ConstraintSystem::negate(R.Coefficients))) {
797*bdd1243dSDimitry Andric     if (!DebugCounter::shouldExecute(EliminatedCounter))
798*bdd1243dSDimitry Andric       return false;
799*bdd1243dSDimitry Andric 
800*bdd1243dSDimitry Andric     LLVM_DEBUG({
801*bdd1243dSDimitry Andric       dbgs() << "Condition !" << *Cmp << " implied by dominating constraints\n";
802*bdd1243dSDimitry Andric       dumpWithNames(CSToUse, Info.getValue2Index(R.IsSigned));
803*bdd1243dSDimitry Andric     });
804*bdd1243dSDimitry Andric     Constant *FalseC =
805*bdd1243dSDimitry Andric         ConstantInt::getFalse(CmpInst::makeCmpResultType(Cmp->getType()));
806*bdd1243dSDimitry Andric     Cmp->replaceAllUsesWith(FalseC);
807*bdd1243dSDimitry Andric     NumCondsRemoved++;
808*bdd1243dSDimitry Andric     Changed = true;
809*bdd1243dSDimitry Andric   }
810*bdd1243dSDimitry Andric   return Changed;
811e8d8bef9SDimitry Andric }
812e8d8bef9SDimitry Andric 
81381ad6265SDimitry Andric void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
814*bdd1243dSDimitry Andric                              unsigned NumIn, unsigned NumOut,
81581ad6265SDimitry Andric                              SmallVectorImpl<StackEntry> &DFSInStack) {
81681ad6265SDimitry Andric   // If the constraint has a pre-condition, skip the constraint if it does not
81781ad6265SDimitry Andric   // hold.
818*bdd1243dSDimitry Andric   SmallVector<Value *> NewVariables;
819*bdd1243dSDimitry Andric   auto R = getConstraint(Pred, A, B, NewVariables);
82081ad6265SDimitry Andric   if (!R.isValid(*this))
82181ad6265SDimitry Andric     return;
82281ad6265SDimitry Andric 
823*bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "Adding '" << CmpInst::getPredicateName(Pred) << " ";
824*bdd1243dSDimitry Andric              A->printAsOperand(dbgs(), false); dbgs() << ", ";
825*bdd1243dSDimitry Andric              B->printAsOperand(dbgs(), false); dbgs() << "'\n");
82681ad6265SDimitry Andric   bool Added = false;
82781ad6265SDimitry Andric   auto &CSToUse = getCS(R.IsSigned);
82881ad6265SDimitry Andric   if (R.Coefficients.empty())
82981ad6265SDimitry Andric     return;
83081ad6265SDimitry Andric 
83181ad6265SDimitry Andric   Added |= CSToUse.addVariableRowFill(R.Coefficients);
83281ad6265SDimitry Andric 
833*bdd1243dSDimitry Andric   // If R has been added to the system, add the new variables and queue it for
834*bdd1243dSDimitry Andric   // removal once it goes out-of-scope.
83581ad6265SDimitry Andric   if (Added) {
83681ad6265SDimitry Andric     SmallVector<Value *, 2> ValuesToRelease;
837*bdd1243dSDimitry Andric     auto &Value2Index = getValue2Index(R.IsSigned);
838*bdd1243dSDimitry Andric     for (Value *V : NewVariables) {
839*bdd1243dSDimitry Andric       Value2Index.insert({V, Value2Index.size() + 1});
840*bdd1243dSDimitry Andric       ValuesToRelease.push_back(V);
84181ad6265SDimitry Andric     }
84281ad6265SDimitry Andric 
84381ad6265SDimitry Andric     LLVM_DEBUG({
84481ad6265SDimitry Andric       dbgs() << "  constraint: ";
84581ad6265SDimitry Andric       dumpWithNames(R.Coefficients, getValue2Index(R.IsSigned));
846*bdd1243dSDimitry Andric       dbgs() << "\n";
84781ad6265SDimitry Andric     });
84881ad6265SDimitry Andric 
849*bdd1243dSDimitry Andric     DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned,
850*bdd1243dSDimitry Andric                             std::move(ValuesToRelease));
85181ad6265SDimitry Andric 
85281ad6265SDimitry Andric     if (R.IsEq) {
85381ad6265SDimitry Andric       // Also add the inverted constraint for equality constraints.
85481ad6265SDimitry Andric       for (auto &Coeff : R.Coefficients)
85581ad6265SDimitry Andric         Coeff *= -1;
85681ad6265SDimitry Andric       CSToUse.addVariableRowFill(R.Coefficients);
85781ad6265SDimitry Andric 
858*bdd1243dSDimitry Andric       DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned,
85981ad6265SDimitry Andric                               SmallVector<Value *, 2>());
86081ad6265SDimitry Andric     }
86181ad6265SDimitry Andric   }
86281ad6265SDimitry Andric }
86381ad6265SDimitry Andric 
864*bdd1243dSDimitry Andric static bool replaceSubOverflowUses(IntrinsicInst *II, Value *A, Value *B,
865*bdd1243dSDimitry Andric                                    SmallVectorImpl<Instruction *> &ToRemove) {
866*bdd1243dSDimitry Andric   bool Changed = false;
867*bdd1243dSDimitry Andric   IRBuilder<> Builder(II->getParent(), II->getIterator());
868*bdd1243dSDimitry Andric   Value *Sub = nullptr;
869*bdd1243dSDimitry Andric   for (User *U : make_early_inc_range(II->users())) {
870*bdd1243dSDimitry Andric     if (match(U, m_ExtractValue<0>(m_Value()))) {
871*bdd1243dSDimitry Andric       if (!Sub)
872*bdd1243dSDimitry Andric         Sub = Builder.CreateSub(A, B);
873*bdd1243dSDimitry Andric       U->replaceAllUsesWith(Sub);
874*bdd1243dSDimitry Andric       Changed = true;
875*bdd1243dSDimitry Andric     } else if (match(U, m_ExtractValue<1>(m_Value()))) {
876*bdd1243dSDimitry Andric       U->replaceAllUsesWith(Builder.getFalse());
877*bdd1243dSDimitry Andric       Changed = true;
878*bdd1243dSDimitry Andric     } else
879*bdd1243dSDimitry Andric       continue;
880*bdd1243dSDimitry Andric 
881*bdd1243dSDimitry Andric     if (U->use_empty()) {
882*bdd1243dSDimitry Andric       auto *I = cast<Instruction>(U);
883*bdd1243dSDimitry Andric       ToRemove.push_back(I);
884*bdd1243dSDimitry Andric       I->setOperand(0, PoisonValue::get(II->getType()));
885*bdd1243dSDimitry Andric       Changed = true;
886*bdd1243dSDimitry Andric     }
887*bdd1243dSDimitry Andric   }
888*bdd1243dSDimitry Andric 
889*bdd1243dSDimitry Andric   if (II->use_empty()) {
890*bdd1243dSDimitry Andric     II->eraseFromParent();
891*bdd1243dSDimitry Andric     Changed = true;
892*bdd1243dSDimitry Andric   }
893*bdd1243dSDimitry Andric   return Changed;
894*bdd1243dSDimitry Andric }
895*bdd1243dSDimitry Andric 
896*bdd1243dSDimitry Andric static bool
89781ad6265SDimitry Andric tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
89881ad6265SDimitry Andric                           SmallVectorImpl<Instruction *> &ToRemove) {
89981ad6265SDimitry Andric   auto DoesConditionHold = [](CmpInst::Predicate Pred, Value *A, Value *B,
90081ad6265SDimitry Andric                               ConstraintInfo &Info) {
901*bdd1243dSDimitry Andric     auto R = Info.getConstraintForSolving(Pred, A, B);
902*bdd1243dSDimitry Andric     if (R.size() < 2 || !R.isValid(Info))
90381ad6265SDimitry Andric       return false;
90481ad6265SDimitry Andric 
905*bdd1243dSDimitry Andric     auto &CSToUse = Info.getCS(R.IsSigned);
90681ad6265SDimitry Andric     return CSToUse.isConditionImplied(R.Coefficients);
90781ad6265SDimitry Andric   };
90881ad6265SDimitry Andric 
909*bdd1243dSDimitry Andric   bool Changed = false;
91081ad6265SDimitry Andric   if (II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
91181ad6265SDimitry Andric     // If A s>= B && B s>= 0, ssub.with.overflow(a, b) should not overflow and
91281ad6265SDimitry Andric     // can be simplified to a regular sub.
91381ad6265SDimitry Andric     Value *A = II->getArgOperand(0);
91481ad6265SDimitry Andric     Value *B = II->getArgOperand(1);
91581ad6265SDimitry Andric     if (!DoesConditionHold(CmpInst::ICMP_SGE, A, B, Info) ||
91681ad6265SDimitry Andric         !DoesConditionHold(CmpInst::ICMP_SGE, B,
91781ad6265SDimitry Andric                            ConstantInt::get(A->getType(), 0), Info))
918*bdd1243dSDimitry Andric       return false;
919*bdd1243dSDimitry Andric     Changed = replaceSubOverflowUses(II, A, B, ToRemove);
92081ad6265SDimitry Andric   }
921*bdd1243dSDimitry Andric   return Changed;
92281ad6265SDimitry Andric }
92381ad6265SDimitry Andric 
92481ad6265SDimitry Andric static bool eliminateConstraints(Function &F, DominatorTree &DT) {
92581ad6265SDimitry Andric   bool Changed = false;
92681ad6265SDimitry Andric   DT.updateDFSNumbers();
92781ad6265SDimitry Andric 
928*bdd1243dSDimitry Andric   ConstraintInfo Info(F.getParent()->getDataLayout());
92981ad6265SDimitry Andric   State S(DT);
93081ad6265SDimitry Andric 
93181ad6265SDimitry Andric   // First, collect conditions implied by branches and blocks with their
93281ad6265SDimitry Andric   // Dominator DFS in and out numbers.
93381ad6265SDimitry Andric   for (BasicBlock &BB : F) {
93481ad6265SDimitry Andric     if (!DT.getNode(&BB))
93581ad6265SDimitry Andric       continue;
93681ad6265SDimitry Andric     S.addInfoFor(BB);
93781ad6265SDimitry Andric   }
93881ad6265SDimitry Andric 
939*bdd1243dSDimitry Andric   // Next, sort worklist by dominance, so that dominating conditions to check
940*bdd1243dSDimitry Andric   // and facts come before conditions and facts dominated by them. If a
941*bdd1243dSDimitry Andric   // condition to check and a fact have the same numbers, conditional facts come
942*bdd1243dSDimitry Andric   // first. Assume facts and checks are ordered according to their relative
943*bdd1243dSDimitry Andric   // order in the containing basic block. Also make sure conditions with
944*bdd1243dSDimitry Andric   // constant operands come before conditions without constant operands. This
945*bdd1243dSDimitry Andric   // increases the effectiveness of the current signed <-> unsigned fact
946*bdd1243dSDimitry Andric   // transfer logic.
947*bdd1243dSDimitry Andric   stable_sort(S.WorkList, [](const FactOrCheck &A, const FactOrCheck &B) {
948*bdd1243dSDimitry Andric     auto HasNoConstOp = [](const FactOrCheck &B) {
949*bdd1243dSDimitry Andric       return !isa<ConstantInt>(B.Inst->getOperand(0)) &&
950*bdd1243dSDimitry Andric              !isa<ConstantInt>(B.Inst->getOperand(1));
951*bdd1243dSDimitry Andric     };
952*bdd1243dSDimitry Andric     // If both entries have the same In numbers, conditional facts come first.
953*bdd1243dSDimitry Andric     // Otherwise use the relative order in the basic block.
954*bdd1243dSDimitry Andric     if (A.NumIn == B.NumIn) {
955*bdd1243dSDimitry Andric       if (A.isConditionFact() && B.isConditionFact()) {
956*bdd1243dSDimitry Andric         bool NoConstOpA = HasNoConstOp(A);
957*bdd1243dSDimitry Andric         bool NoConstOpB = HasNoConstOp(B);
958*bdd1243dSDimitry Andric         return NoConstOpA < NoConstOpB;
959*bdd1243dSDimitry Andric       }
960*bdd1243dSDimitry Andric       if (A.isConditionFact())
961*bdd1243dSDimitry Andric         return true;
962*bdd1243dSDimitry Andric       if (B.isConditionFact())
963*bdd1243dSDimitry Andric         return false;
964*bdd1243dSDimitry Andric       return A.Inst->comesBefore(B.Inst);
965*bdd1243dSDimitry Andric     }
966*bdd1243dSDimitry Andric     return A.NumIn < B.NumIn;
967e8d8bef9SDimitry Andric   });
968e8d8bef9SDimitry Andric 
96981ad6265SDimitry Andric   SmallVector<Instruction *> ToRemove;
97081ad6265SDimitry Andric 
971e8d8bef9SDimitry Andric   // Finally, process ordered worklist and eliminate implied conditions.
972e8d8bef9SDimitry Andric   SmallVector<StackEntry, 16> DFSInStack;
973*bdd1243dSDimitry Andric   for (FactOrCheck &CB : S.WorkList) {
974e8d8bef9SDimitry Andric     // First, pop entries from the stack that are out-of-scope for CB. Remove
975e8d8bef9SDimitry Andric     // the corresponding entry from the constraint system.
976e8d8bef9SDimitry Andric     while (!DFSInStack.empty()) {
977e8d8bef9SDimitry Andric       auto &E = DFSInStack.back();
978e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Top of stack : " << E.NumIn << " " << E.NumOut
979e8d8bef9SDimitry Andric                         << "\n");
980e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "CB: " << CB.NumIn << " " << CB.NumOut << "\n");
981e8d8bef9SDimitry Andric       assert(E.NumIn <= CB.NumIn);
982e8d8bef9SDimitry Andric       if (CB.NumOut <= E.NumOut)
983e8d8bef9SDimitry Andric         break;
98481ad6265SDimitry Andric       LLVM_DEBUG({
98581ad6265SDimitry Andric         dbgs() << "Removing ";
98681ad6265SDimitry Andric         dumpWithNames(Info.getCS(E.IsSigned).getLastConstraint(),
98781ad6265SDimitry Andric                       Info.getValue2Index(E.IsSigned));
98881ad6265SDimitry Andric         dbgs() << "\n";
98981ad6265SDimitry Andric       });
99081ad6265SDimitry Andric 
99181ad6265SDimitry Andric       Info.popLastConstraint(E.IsSigned);
99281ad6265SDimitry Andric       // Remove variables in the system that went out of scope.
99381ad6265SDimitry Andric       auto &Mapping = Info.getValue2Index(E.IsSigned);
99481ad6265SDimitry Andric       for (Value *V : E.ValuesToRelease)
99581ad6265SDimitry Andric         Mapping.erase(V);
99681ad6265SDimitry Andric       Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
997e8d8bef9SDimitry Andric       DFSInStack.pop_back();
998e8d8bef9SDimitry Andric     }
999e8d8bef9SDimitry Andric 
1000e8d8bef9SDimitry Andric     LLVM_DEBUG({
1001e8d8bef9SDimitry Andric       dbgs() << "Processing ";
1002*bdd1243dSDimitry Andric       if (CB.IsCheck)
1003*bdd1243dSDimitry Andric         dbgs() << "condition to simplify: " << *CB.Inst;
1004e8d8bef9SDimitry Andric       else
1005*bdd1243dSDimitry Andric         dbgs() << "fact to add to the system: " << *CB.Inst;
1006e8d8bef9SDimitry Andric       dbgs() << "\n";
1007e8d8bef9SDimitry Andric     });
1008e8d8bef9SDimitry Andric 
1009e8d8bef9SDimitry Andric     // For a block, check if any CmpInsts become known based on the current set
1010e8d8bef9SDimitry Andric     // of constraints.
1011*bdd1243dSDimitry Andric     if (CB.IsCheck) {
1012*bdd1243dSDimitry Andric       if (auto *II = dyn_cast<WithOverflowInst>(CB.Inst)) {
1013*bdd1243dSDimitry Andric         Changed |= tryToSimplifyOverflowMath(II, Info, ToRemove);
1014*bdd1243dSDimitry Andric       } else if (auto *Cmp = dyn_cast<ICmpInst>(CB.Inst)) {
1015*bdd1243dSDimitry Andric         Changed |= checkAndReplaceCondition(Cmp, Info);
1016e8d8bef9SDimitry Andric       }
1017e8d8bef9SDimitry Andric       continue;
1018e8d8bef9SDimitry Andric     }
1019e8d8bef9SDimitry Andric 
102081ad6265SDimitry Andric     ICmpInst::Predicate Pred;
102181ad6265SDimitry Andric     Value *A, *B;
1022*bdd1243dSDimitry Andric     Value *Cmp = CB.Inst;
1023*bdd1243dSDimitry Andric     match(Cmp, m_Intrinsic<Intrinsic::assume>(m_Value(Cmp)));
1024*bdd1243dSDimitry Andric     if (match(Cmp, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
1025*bdd1243dSDimitry Andric       if (Info.getCS(CmpInst::isSigned(Pred)).size() > MaxRows) {
1026*bdd1243dSDimitry Andric         LLVM_DEBUG(
1027*bdd1243dSDimitry Andric             dbgs()
1028*bdd1243dSDimitry Andric             << "Skip adding constraint because system has too many rows.\n");
1029*bdd1243dSDimitry Andric         continue;
1030*bdd1243dSDimitry Andric       }
1031*bdd1243dSDimitry Andric 
1032*bdd1243dSDimitry Andric       // Use the inverse predicate if required.
1033*bdd1243dSDimitry Andric       if (CB.Not)
1034*bdd1243dSDimitry Andric         Pred = CmpInst::getInversePredicate(Pred);
1035*bdd1243dSDimitry Andric 
1036*bdd1243dSDimitry Andric       Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
1037*bdd1243dSDimitry Andric       Info.transferToOtherSystem(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
1038e8d8bef9SDimitry Andric     }
1039fe6060f1SDimitry Andric   }
1040e8d8bef9SDimitry Andric 
104181ad6265SDimitry Andric #ifndef NDEBUG
104281ad6265SDimitry Andric   unsigned SignedEntries =
104381ad6265SDimitry Andric       count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; });
104481ad6265SDimitry Andric   assert(Info.getCS(false).size() == DFSInStack.size() - SignedEntries &&
1045fe6060f1SDimitry Andric          "updates to CS and DFSInStack are out of sync");
104681ad6265SDimitry Andric   assert(Info.getCS(true).size() == SignedEntries &&
104781ad6265SDimitry Andric          "updates to CS and DFSInStack are out of sync");
104881ad6265SDimitry Andric #endif
104981ad6265SDimitry Andric 
105081ad6265SDimitry Andric   for (Instruction *I : ToRemove)
105181ad6265SDimitry Andric     I->eraseFromParent();
1052e8d8bef9SDimitry Andric   return Changed;
1053e8d8bef9SDimitry Andric }
1054e8d8bef9SDimitry Andric 
1055e8d8bef9SDimitry Andric PreservedAnalyses ConstraintEliminationPass::run(Function &F,
1056e8d8bef9SDimitry Andric                                                  FunctionAnalysisManager &AM) {
1057e8d8bef9SDimitry Andric   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
1058e8d8bef9SDimitry Andric   if (!eliminateConstraints(F, DT))
1059e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
1060e8d8bef9SDimitry Andric 
1061e8d8bef9SDimitry Andric   PreservedAnalyses PA;
1062e8d8bef9SDimitry Andric   PA.preserve<DominatorTreeAnalysis>();
1063e8d8bef9SDimitry Andric   PA.preserveSet<CFGAnalyses>();
1064e8d8bef9SDimitry Andric   return PA;
1065e8d8bef9SDimitry Andric }
1066