xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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"
22e8d8bef9SDimitry Andric #include "llvm/IR/Dominators.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/Function.h"
24*81ad6265SDimitry Andric #include "llvm/IR/IRBuilder.h"
25e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h"
26e8d8bef9SDimitry Andric #include "llvm/IR/PatternMatch.h"
27e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h"
28e8d8bef9SDimitry Andric #include "llvm/Pass.h"
29e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
30e8d8bef9SDimitry Andric #include "llvm/Support/DebugCounter.h"
31*81ad6265SDimitry Andric #include "llvm/Support/MathExtras.h"
32e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar.h"
33e8d8bef9SDimitry Andric 
34fe6060f1SDimitry Andric #include <string>
35fe6060f1SDimitry Andric 
36e8d8bef9SDimitry Andric using namespace llvm;
37e8d8bef9SDimitry Andric using namespace PatternMatch;
38e8d8bef9SDimitry Andric 
39e8d8bef9SDimitry Andric #define DEBUG_TYPE "constraint-elimination"
40e8d8bef9SDimitry Andric 
41e8d8bef9SDimitry Andric STATISTIC(NumCondsRemoved, "Number of instructions removed");
42e8d8bef9SDimitry Andric DEBUG_COUNTER(EliminatedCounter, "conds-eliminated",
43e8d8bef9SDimitry Andric               "Controls which conditions are eliminated");
44e8d8bef9SDimitry Andric 
45e8d8bef9SDimitry Andric static int64_t MaxConstraintValue = std::numeric_limits<int64_t>::max();
46*81ad6265SDimitry Andric static int64_t MinSignedConstraintValue = std::numeric_limits<int64_t>::min();
47e8d8bef9SDimitry Andric 
4804eeddc0SDimitry Andric namespace {
4904eeddc0SDimitry Andric 
50*81ad6265SDimitry Andric class ConstraintInfo;
5104eeddc0SDimitry Andric 
52*81ad6265SDimitry Andric struct StackEntry {
53*81ad6265SDimitry Andric   unsigned NumIn;
54*81ad6265SDimitry Andric   unsigned NumOut;
55*81ad6265SDimitry Andric   bool IsNot;
56*81ad6265SDimitry Andric   bool IsSigned = false;
57*81ad6265SDimitry Andric   /// Variables that can be removed from the system once the stack entry gets
58*81ad6265SDimitry Andric   /// removed.
59*81ad6265SDimitry Andric   SmallVector<Value *, 2> ValuesToRelease;
60*81ad6265SDimitry Andric 
61*81ad6265SDimitry Andric   StackEntry(unsigned NumIn, unsigned NumOut, bool IsNot, bool IsSigned,
62*81ad6265SDimitry Andric              SmallVector<Value *, 2> ValuesToRelease)
63*81ad6265SDimitry Andric       : NumIn(NumIn), NumOut(NumOut), IsNot(IsNot), IsSigned(IsSigned),
64*81ad6265SDimitry Andric         ValuesToRelease(ValuesToRelease) {}
6504eeddc0SDimitry Andric };
6604eeddc0SDimitry Andric 
67*81ad6265SDimitry Andric /// Struct to express a pre-condition of the form %Op0 Pred %Op1.
68*81ad6265SDimitry Andric struct PreconditionTy {
69*81ad6265SDimitry Andric   CmpInst::Predicate Pred;
70*81ad6265SDimitry Andric   Value *Op0;
71*81ad6265SDimitry Andric   Value *Op1;
7204eeddc0SDimitry Andric 
73*81ad6265SDimitry Andric   PreconditionTy(CmpInst::Predicate Pred, Value *Op0, Value *Op1)
74*81ad6265SDimitry Andric       : Pred(Pred), Op0(Op0), Op1(Op1) {}
75*81ad6265SDimitry Andric };
7604eeddc0SDimitry Andric 
77*81ad6265SDimitry Andric struct ConstraintTy {
78*81ad6265SDimitry Andric   SmallVector<int64_t, 8> Coefficients;
79*81ad6265SDimitry Andric   SmallVector<PreconditionTy, 2> Preconditions;
8004eeddc0SDimitry Andric 
81*81ad6265SDimitry Andric   bool IsSigned = false;
82*81ad6265SDimitry Andric   bool IsEq = false;
8304eeddc0SDimitry Andric 
84*81ad6265SDimitry Andric   ConstraintTy() = default;
8504eeddc0SDimitry Andric 
86*81ad6265SDimitry Andric   ConstraintTy(SmallVector<int64_t, 8> Coefficients, bool IsSigned)
87*81ad6265SDimitry Andric       : Coefficients(Coefficients), IsSigned(IsSigned) {}
88*81ad6265SDimitry Andric 
89*81ad6265SDimitry Andric   unsigned size() const { return Coefficients.size(); }
90*81ad6265SDimitry Andric 
91*81ad6265SDimitry Andric   unsigned empty() const { return Coefficients.empty(); }
9204eeddc0SDimitry Andric 
9304eeddc0SDimitry Andric   /// Returns true if any constraint has a non-zero coefficient for any of the
9404eeddc0SDimitry Andric   /// newly added indices. Zero coefficients for new indices are removed. If it
9504eeddc0SDimitry Andric   /// returns true, no new variable need to be added to the system.
9604eeddc0SDimitry Andric   bool needsNewIndices(const DenseMap<Value *, unsigned> &NewIndices) {
9704eeddc0SDimitry Andric     for (unsigned I = 0; I < NewIndices.size(); ++I) {
98*81ad6265SDimitry Andric       int64_t Last = Coefficients.pop_back_val();
9904eeddc0SDimitry Andric       if (Last != 0)
10004eeddc0SDimitry Andric         return true;
10104eeddc0SDimitry Andric     }
10204eeddc0SDimitry Andric     return false;
10304eeddc0SDimitry Andric   }
10404eeddc0SDimitry Andric 
105*81ad6265SDimitry Andric   /// Returns true if all preconditions for this list of constraints are
106*81ad6265SDimitry Andric   /// satisfied given \p CS and the corresponding \p Value2Index mapping.
107*81ad6265SDimitry Andric   bool isValid(const ConstraintInfo &Info) const;
108*81ad6265SDimitry Andric };
109*81ad6265SDimitry Andric 
110*81ad6265SDimitry Andric /// Wrapper encapsulating separate constraint systems and corresponding value
111*81ad6265SDimitry Andric /// mappings for both unsigned and signed information. Facts are added to and
112*81ad6265SDimitry Andric /// conditions are checked against the corresponding system depending on the
113*81ad6265SDimitry Andric /// signed-ness of their predicates. While the information is kept separate
114*81ad6265SDimitry Andric /// based on signed-ness, certain conditions can be transferred between the two
115*81ad6265SDimitry Andric /// systems.
116*81ad6265SDimitry Andric class ConstraintInfo {
117*81ad6265SDimitry Andric   DenseMap<Value *, unsigned> UnsignedValue2Index;
118*81ad6265SDimitry Andric   DenseMap<Value *, unsigned> SignedValue2Index;
119*81ad6265SDimitry Andric 
120*81ad6265SDimitry Andric   ConstraintSystem UnsignedCS;
121*81ad6265SDimitry Andric   ConstraintSystem SignedCS;
122*81ad6265SDimitry Andric 
123*81ad6265SDimitry Andric public:
124*81ad6265SDimitry Andric   DenseMap<Value *, unsigned> &getValue2Index(bool Signed) {
125*81ad6265SDimitry Andric     return Signed ? SignedValue2Index : UnsignedValue2Index;
126*81ad6265SDimitry Andric   }
127*81ad6265SDimitry Andric   const DenseMap<Value *, unsigned> &getValue2Index(bool Signed) const {
128*81ad6265SDimitry Andric     return Signed ? SignedValue2Index : UnsignedValue2Index;
129*81ad6265SDimitry Andric   }
130*81ad6265SDimitry Andric 
131*81ad6265SDimitry Andric   ConstraintSystem &getCS(bool Signed) {
132*81ad6265SDimitry Andric     return Signed ? SignedCS : UnsignedCS;
133*81ad6265SDimitry Andric   }
134*81ad6265SDimitry Andric   const ConstraintSystem &getCS(bool Signed) const {
135*81ad6265SDimitry Andric     return Signed ? SignedCS : UnsignedCS;
136*81ad6265SDimitry Andric   }
137*81ad6265SDimitry Andric 
138*81ad6265SDimitry Andric   void popLastConstraint(bool Signed) { getCS(Signed).popLastConstraint(); }
139*81ad6265SDimitry Andric   void popLastNVariables(bool Signed, unsigned N) {
140*81ad6265SDimitry Andric     getCS(Signed).popLastNVariables(N);
141*81ad6265SDimitry Andric   }
142*81ad6265SDimitry Andric 
143*81ad6265SDimitry Andric   bool doesHold(CmpInst::Predicate Pred, Value *A, Value *B) const;
144*81ad6265SDimitry Andric 
145*81ad6265SDimitry Andric   void addFact(CmpInst::Predicate Pred, Value *A, Value *B, bool IsNegated,
146*81ad6265SDimitry Andric                unsigned NumIn, unsigned NumOut,
147*81ad6265SDimitry Andric                SmallVectorImpl<StackEntry> &DFSInStack);
148*81ad6265SDimitry Andric 
149*81ad6265SDimitry Andric   /// Turn a comparison of the form \p Op0 \p Pred \p Op1 into a vector of
150*81ad6265SDimitry Andric   /// constraints, using indices from the corresponding constraint system.
151*81ad6265SDimitry Andric   /// Additional indices for newly discovered values are added to \p NewIndices.
152*81ad6265SDimitry Andric   ConstraintTy getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
153*81ad6265SDimitry Andric                              DenseMap<Value *, unsigned> &NewIndices) const;
154*81ad6265SDimitry Andric 
155*81ad6265SDimitry Andric   /// Turn a condition \p CmpI into a vector of constraints, using indices from
156*81ad6265SDimitry Andric   /// the corresponding constraint system. Additional indices for newly
157*81ad6265SDimitry Andric   /// discovered values are added to \p NewIndices.
158*81ad6265SDimitry Andric   ConstraintTy getConstraint(CmpInst *Cmp,
159*81ad6265SDimitry Andric                              DenseMap<Value *, unsigned> &NewIndices) const {
160*81ad6265SDimitry Andric     return getConstraint(Cmp->getPredicate(), Cmp->getOperand(0),
161*81ad6265SDimitry Andric                          Cmp->getOperand(1), NewIndices);
162*81ad6265SDimitry Andric   }
163*81ad6265SDimitry Andric 
164*81ad6265SDimitry Andric   /// Try to add information from \p A \p Pred \p B to the unsigned/signed
165*81ad6265SDimitry Andric   /// system if \p Pred is signed/unsigned.
166*81ad6265SDimitry Andric   void transferToOtherSystem(CmpInst::Predicate Pred, Value *A, Value *B,
167*81ad6265SDimitry Andric                              bool IsNegated, unsigned NumIn, unsigned NumOut,
168*81ad6265SDimitry Andric                              SmallVectorImpl<StackEntry> &DFSInStack);
16904eeddc0SDimitry Andric };
17004eeddc0SDimitry Andric 
17104eeddc0SDimitry Andric } // namespace
17204eeddc0SDimitry Andric 
173e8d8bef9SDimitry Andric // Decomposes \p V into a vector of pairs of the form { c, X } where c * X. The
174e8d8bef9SDimitry Andric // sum of the pairs equals \p V.  The first pair is the constant-factor and X
175e8d8bef9SDimitry Andric // must be nullptr. If the expression cannot be decomposed, returns an empty
176e8d8bef9SDimitry Andric // vector.
177*81ad6265SDimitry Andric static SmallVector<std::pair<int64_t, Value *>, 4>
178*81ad6265SDimitry Andric decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
179*81ad6265SDimitry Andric           bool IsSigned) {
180*81ad6265SDimitry Andric 
181*81ad6265SDimitry Andric   auto CanUseSExt = [](ConstantInt *CI) {
182*81ad6265SDimitry Andric     const APInt &Val = CI->getValue();
183*81ad6265SDimitry Andric     return Val.sgt(MinSignedConstraintValue) && Val.slt(MaxConstraintValue);
184*81ad6265SDimitry Andric   };
185*81ad6265SDimitry Andric   // Decompose \p V used with a signed predicate.
186*81ad6265SDimitry Andric   if (IsSigned) {
187e8d8bef9SDimitry Andric     if (auto *CI = dyn_cast<ConstantInt>(V)) {
188*81ad6265SDimitry Andric       if (CanUseSExt(CI))
189e8d8bef9SDimitry Andric         return {{CI->getSExtValue(), nullptr}};
190e8d8bef9SDimitry Andric     }
191*81ad6265SDimitry Andric 
192*81ad6265SDimitry Andric     return {{0, nullptr}, {1, V}};
193*81ad6265SDimitry Andric   }
194*81ad6265SDimitry Andric 
195*81ad6265SDimitry Andric   if (auto *CI = dyn_cast<ConstantInt>(V)) {
196*81ad6265SDimitry Andric     if (CI->uge(MaxConstraintValue))
197*81ad6265SDimitry Andric       return {};
198*81ad6265SDimitry Andric     return {{CI->getZExtValue(), nullptr}};
199*81ad6265SDimitry Andric   }
200e8d8bef9SDimitry Andric   auto *GEP = dyn_cast<GetElementPtrInst>(V);
201fe6060f1SDimitry Andric   if (GEP && GEP->getNumOperands() == 2 && GEP->isInBounds()) {
202fe6060f1SDimitry Andric     Value *Op0, *Op1;
203e8d8bef9SDimitry Andric     ConstantInt *CI;
204fe6060f1SDimitry Andric 
205fe6060f1SDimitry Andric     // If the index is zero-extended, it is guaranteed to be positive.
206fe6060f1SDimitry Andric     if (match(GEP->getOperand(GEP->getNumOperands() - 1),
207fe6060f1SDimitry Andric               m_ZExt(m_Value(Op0)))) {
208*81ad6265SDimitry Andric       if (match(Op0, m_NUWShl(m_Value(Op1), m_ConstantInt(CI))) &&
209*81ad6265SDimitry Andric           CanUseSExt(CI))
210fe6060f1SDimitry Andric         return {{0, nullptr},
211fe6060f1SDimitry Andric                 {1, GEP->getPointerOperand()},
212fe6060f1SDimitry Andric                 {std::pow(int64_t(2), CI->getSExtValue()), Op1}};
213*81ad6265SDimitry Andric       if (match(Op0, m_NSWAdd(m_Value(Op1), m_ConstantInt(CI))) &&
214*81ad6265SDimitry Andric           CanUseSExt(CI))
215fe6060f1SDimitry Andric         return {{CI->getSExtValue(), nullptr},
216fe6060f1SDimitry Andric                 {1, GEP->getPointerOperand()},
217fe6060f1SDimitry Andric                 {1, Op1}};
218fe6060f1SDimitry Andric       return {{0, nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}};
219fe6060f1SDimitry Andric     }
220fe6060f1SDimitry Andric 
221fe6060f1SDimitry Andric     if (match(GEP->getOperand(GEP->getNumOperands() - 1), m_ConstantInt(CI)) &&
222*81ad6265SDimitry Andric         !CI->isNegative() && CanUseSExt(CI))
223fe6060f1SDimitry Andric       return {{CI->getSExtValue(), nullptr}, {1, GEP->getPointerOperand()}};
224fe6060f1SDimitry Andric 
225fe6060f1SDimitry Andric     SmallVector<std::pair<int64_t, Value *>, 4> Result;
226e8d8bef9SDimitry Andric     if (match(GEP->getOperand(GEP->getNumOperands() - 1),
227*81ad6265SDimitry Andric               m_NUWShl(m_Value(Op0), m_ConstantInt(CI))) &&
228*81ad6265SDimitry Andric         CanUseSExt(CI))
229fe6060f1SDimitry Andric       Result = {{0, nullptr},
230e8d8bef9SDimitry Andric                 {1, GEP->getPointerOperand()},
231e8d8bef9SDimitry Andric                 {std::pow(int64_t(2), CI->getSExtValue()), Op0}};
232fe6060f1SDimitry Andric     else if (match(GEP->getOperand(GEP->getNumOperands() - 1),
233*81ad6265SDimitry Andric                    m_NSWAdd(m_Value(Op0), m_ConstantInt(CI))) &&
234*81ad6265SDimitry Andric              CanUseSExt(CI))
235fe6060f1SDimitry Andric       Result = {{CI->getSExtValue(), nullptr},
236e8d8bef9SDimitry Andric                 {1, GEP->getPointerOperand()},
237fe6060f1SDimitry Andric                 {1, Op0}};
238fe6060f1SDimitry Andric     else {
239fe6060f1SDimitry Andric       Op0 = GEP->getOperand(GEP->getNumOperands() - 1);
240fe6060f1SDimitry Andric       Result = {{0, nullptr}, {1, GEP->getPointerOperand()}, {1, Op0}};
241fe6060f1SDimitry Andric     }
242*81ad6265SDimitry Andric     // If Op0 is signed non-negative, the GEP is increasing monotonically and
243*81ad6265SDimitry Andric     // can be de-composed.
244*81ad6265SDimitry Andric     Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0,
245*81ad6265SDimitry Andric                                ConstantInt::get(Op0->getType(), 0));
246fe6060f1SDimitry Andric     return Result;
247e8d8bef9SDimitry Andric   }
248e8d8bef9SDimitry Andric 
249e8d8bef9SDimitry Andric   Value *Op0;
250fe6060f1SDimitry Andric   if (match(V, m_ZExt(m_Value(Op0))))
251fe6060f1SDimitry Andric     V = Op0;
252fe6060f1SDimitry Andric 
253e8d8bef9SDimitry Andric   Value *Op1;
254e8d8bef9SDimitry Andric   ConstantInt *CI;
255*81ad6265SDimitry Andric   if (match(V, m_NUWAdd(m_Value(Op0), m_ConstantInt(CI))) &&
256*81ad6265SDimitry Andric       !CI->uge(MaxConstraintValue))
257*81ad6265SDimitry Andric     return {{CI->getZExtValue(), nullptr}, {1, Op0}};
258*81ad6265SDimitry Andric   if (match(V, m_Add(m_Value(Op0), m_ConstantInt(CI))) && CI->isNegative() &&
259*81ad6265SDimitry Andric       CanUseSExt(CI)) {
260*81ad6265SDimitry Andric     Preconditions.emplace_back(
261*81ad6265SDimitry Andric         CmpInst::ICMP_UGE, Op0,
262*81ad6265SDimitry Andric         ConstantInt::get(Op0->getType(), CI->getSExtValue() * -1));
263e8d8bef9SDimitry Andric     return {{CI->getSExtValue(), nullptr}, {1, Op0}};
264*81ad6265SDimitry Andric   }
265e8d8bef9SDimitry Andric   if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1))))
266e8d8bef9SDimitry Andric     return {{0, nullptr}, {1, Op0}, {1, Op1}};
267e8d8bef9SDimitry Andric 
268*81ad6265SDimitry Andric   if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && CanUseSExt(CI))
269e8d8bef9SDimitry Andric     return {{-1 * CI->getSExtValue(), nullptr}, {1, Op0}};
270e8d8bef9SDimitry Andric   if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
27104eeddc0SDimitry Andric     return {{0, nullptr}, {1, Op0}, {-1, Op1}};
272e8d8bef9SDimitry Andric 
273e8d8bef9SDimitry Andric   return {{0, nullptr}, {1, V}};
274e8d8bef9SDimitry Andric }
275e8d8bef9SDimitry Andric 
276*81ad6265SDimitry Andric ConstraintTy
277*81ad6265SDimitry Andric ConstraintInfo::getConstraint(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
278*81ad6265SDimitry Andric                               DenseMap<Value *, unsigned> &NewIndices) const {
279*81ad6265SDimitry Andric   bool IsEq = false;
280*81ad6265SDimitry Andric   // Try to convert Pred to one of ULE/SLT/SLE/SLT.
281*81ad6265SDimitry Andric   switch (Pred) {
282*81ad6265SDimitry Andric   case CmpInst::ICMP_UGT:
283*81ad6265SDimitry Andric   case CmpInst::ICMP_UGE:
284*81ad6265SDimitry Andric   case CmpInst::ICMP_SGT:
285*81ad6265SDimitry Andric   case CmpInst::ICMP_SGE: {
286*81ad6265SDimitry Andric     Pred = CmpInst::getSwappedPredicate(Pred);
287*81ad6265SDimitry Andric     std::swap(Op0, Op1);
288*81ad6265SDimitry Andric     break;
289*81ad6265SDimitry Andric   }
290*81ad6265SDimitry Andric   case CmpInst::ICMP_EQ:
291*81ad6265SDimitry Andric     if (match(Op1, m_Zero())) {
292*81ad6265SDimitry Andric       Pred = CmpInst::ICMP_ULE;
293*81ad6265SDimitry Andric     } else {
294*81ad6265SDimitry Andric       IsEq = true;
295*81ad6265SDimitry Andric       Pred = CmpInst::ICMP_ULE;
296*81ad6265SDimitry Andric     }
297*81ad6265SDimitry Andric     break;
298*81ad6265SDimitry Andric   case CmpInst::ICMP_NE:
299*81ad6265SDimitry Andric     if (!match(Op1, m_Zero()))
300*81ad6265SDimitry Andric       return {};
301*81ad6265SDimitry Andric     Pred = CmpInst::getSwappedPredicate(CmpInst::ICMP_UGT);
302*81ad6265SDimitry Andric     std::swap(Op0, Op1);
303*81ad6265SDimitry Andric     break;
304*81ad6265SDimitry Andric   default:
305*81ad6265SDimitry Andric     break;
306*81ad6265SDimitry Andric   }
307*81ad6265SDimitry Andric 
308*81ad6265SDimitry Andric   // Only ULE and ULT predicates are supported at the moment.
309*81ad6265SDimitry Andric   if (Pred != CmpInst::ICMP_ULE && Pred != CmpInst::ICMP_ULT &&
310*81ad6265SDimitry Andric       Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SLT)
311*81ad6265SDimitry Andric     return {};
312*81ad6265SDimitry Andric 
313*81ad6265SDimitry Andric   SmallVector<PreconditionTy, 4> Preconditions;
314*81ad6265SDimitry Andric   bool IsSigned = CmpInst::isSigned(Pred);
315*81ad6265SDimitry Andric   auto &Value2Index = getValue2Index(IsSigned);
316*81ad6265SDimitry Andric   auto ADec = decompose(Op0->stripPointerCastsSameRepresentation(),
317*81ad6265SDimitry Andric                         Preconditions, IsSigned);
318*81ad6265SDimitry Andric   auto BDec = decompose(Op1->stripPointerCastsSameRepresentation(),
319*81ad6265SDimitry Andric                         Preconditions, IsSigned);
320*81ad6265SDimitry Andric   // Skip if decomposing either of the values failed.
321*81ad6265SDimitry Andric   if (ADec.empty() || BDec.empty())
322*81ad6265SDimitry Andric     return {};
323*81ad6265SDimitry Andric 
324*81ad6265SDimitry Andric   int64_t Offset1 = ADec[0].first;
325*81ad6265SDimitry Andric   int64_t Offset2 = BDec[0].first;
326*81ad6265SDimitry Andric   Offset1 *= -1;
327*81ad6265SDimitry Andric 
328*81ad6265SDimitry Andric   // Create iterator ranges that skip the constant-factor.
329*81ad6265SDimitry Andric   auto VariablesA = llvm::drop_begin(ADec);
330*81ad6265SDimitry Andric   auto VariablesB = llvm::drop_begin(BDec);
331e8d8bef9SDimitry Andric 
332fe6060f1SDimitry Andric   // First try to look up \p V in Value2Index and NewIndices. Otherwise add a
333fe6060f1SDimitry Andric   // new entry to NewIndices.
334fe6060f1SDimitry Andric   auto GetOrAddIndex = [&Value2Index, &NewIndices](Value *V) -> unsigned {
335fe6060f1SDimitry Andric     auto V2I = Value2Index.find(V);
336fe6060f1SDimitry Andric     if (V2I != Value2Index.end())
337fe6060f1SDimitry Andric       return V2I->second;
338fe6060f1SDimitry Andric     auto Insert =
339fe6060f1SDimitry Andric         NewIndices.insert({V, Value2Index.size() + NewIndices.size() + 1});
340fe6060f1SDimitry Andric     return Insert.first->second;
341e8d8bef9SDimitry Andric   };
342e8d8bef9SDimitry Andric 
343fe6060f1SDimitry Andric   // Make sure all variables have entries in Value2Index or NewIndices.
344e8d8bef9SDimitry Andric   for (const auto &KV :
345e8d8bef9SDimitry Andric        concat<std::pair<int64_t, Value *>>(VariablesA, VariablesB))
346fe6060f1SDimitry Andric     GetOrAddIndex(KV.second);
347e8d8bef9SDimitry Andric 
348e8d8bef9SDimitry Andric   // Build result constraint, by first adding all coefficients from A and then
349e8d8bef9SDimitry Andric   // subtracting all coefficients from B.
350*81ad6265SDimitry Andric   ConstraintTy Res(
351*81ad6265SDimitry Andric       SmallVector<int64_t, 8>(Value2Index.size() + NewIndices.size() + 1, 0),
352*81ad6265SDimitry Andric       IsSigned);
353*81ad6265SDimitry Andric   Res.IsEq = IsEq;
354*81ad6265SDimitry Andric   auto &R = Res.Coefficients;
355e8d8bef9SDimitry Andric   for (const auto &KV : VariablesA)
356fe6060f1SDimitry Andric     R[GetOrAddIndex(KV.second)] += KV.first;
357e8d8bef9SDimitry Andric 
358e8d8bef9SDimitry Andric   for (const auto &KV : VariablesB)
359fe6060f1SDimitry Andric     R[GetOrAddIndex(KV.second)] -= KV.first;
360e8d8bef9SDimitry Andric 
361*81ad6265SDimitry Andric   int64_t OffsetSum;
362*81ad6265SDimitry Andric   if (AddOverflow(Offset1, Offset2, OffsetSum))
363*81ad6265SDimitry Andric     return {};
364*81ad6265SDimitry Andric   if (Pred == (IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT))
365*81ad6265SDimitry Andric     if (AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
366*81ad6265SDimitry Andric       return {};
367*81ad6265SDimitry Andric   R[0] = OffsetSum;
368*81ad6265SDimitry Andric   Res.Preconditions = std::move(Preconditions);
369*81ad6265SDimitry Andric   return Res;
370e8d8bef9SDimitry Andric }
371e8d8bef9SDimitry Andric 
372*81ad6265SDimitry Andric bool ConstraintTy::isValid(const ConstraintInfo &Info) const {
373*81ad6265SDimitry Andric   return Coefficients.size() > 0 &&
374*81ad6265SDimitry Andric          all_of(Preconditions, [&Info](const PreconditionTy &C) {
375*81ad6265SDimitry Andric            return Info.doesHold(C.Pred, C.Op0, C.Op1);
376*81ad6265SDimitry Andric          });
377*81ad6265SDimitry Andric }
378*81ad6265SDimitry Andric 
379*81ad6265SDimitry Andric bool ConstraintInfo::doesHold(CmpInst::Predicate Pred, Value *A,
380*81ad6265SDimitry Andric                               Value *B) const {
381*81ad6265SDimitry Andric   DenseMap<Value *, unsigned> NewIndices;
382*81ad6265SDimitry Andric   auto R = getConstraint(Pred, A, B, NewIndices);
383*81ad6265SDimitry Andric 
384*81ad6265SDimitry Andric   if (!NewIndices.empty())
385*81ad6265SDimitry Andric     return false;
386*81ad6265SDimitry Andric 
387*81ad6265SDimitry Andric   // TODO: properly check NewIndices.
388*81ad6265SDimitry Andric   return NewIndices.empty() && R.Preconditions.empty() && !R.IsEq &&
389*81ad6265SDimitry Andric          !R.empty() &&
390*81ad6265SDimitry Andric          getCS(CmpInst::isSigned(Pred)).isConditionImplied(R.Coefficients);
391*81ad6265SDimitry Andric }
392*81ad6265SDimitry Andric 
393*81ad6265SDimitry Andric void ConstraintInfo::transferToOtherSystem(
394*81ad6265SDimitry Andric     CmpInst::Predicate Pred, Value *A, Value *B, bool IsNegated, unsigned NumIn,
395*81ad6265SDimitry Andric     unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
396*81ad6265SDimitry Andric   // Check if we can combine facts from the signed and unsigned systems to
397*81ad6265SDimitry Andric   // derive additional facts.
398*81ad6265SDimitry Andric   if (!A->getType()->isIntegerTy())
399*81ad6265SDimitry Andric     return;
400*81ad6265SDimitry Andric   // FIXME: This currently depends on the order we add facts. Ideally we
401*81ad6265SDimitry Andric   // would first add all known facts and only then try to add additional
402*81ad6265SDimitry Andric   // facts.
403*81ad6265SDimitry Andric   switch (Pred) {
404*81ad6265SDimitry Andric   default:
405*81ad6265SDimitry Andric     break;
406*81ad6265SDimitry Andric   case CmpInst::ICMP_ULT:
407*81ad6265SDimitry Andric     //  If B is a signed positive constant, A >=s 0 and A <s B.
408*81ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0))) {
409*81ad6265SDimitry Andric       addFact(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0),
410*81ad6265SDimitry Andric               IsNegated, NumIn, NumOut, DFSInStack);
411*81ad6265SDimitry Andric       addFact(CmpInst::ICMP_SLT, A, B, IsNegated, NumIn, NumOut, DFSInStack);
412*81ad6265SDimitry Andric     }
413*81ad6265SDimitry Andric     break;
414*81ad6265SDimitry Andric   case CmpInst::ICMP_SLT:
415*81ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0)))
416*81ad6265SDimitry Andric       addFact(CmpInst::ICMP_ULT, A, B, IsNegated, NumIn, NumOut, DFSInStack);
417*81ad6265SDimitry Andric     break;
418*81ad6265SDimitry Andric   case CmpInst::ICMP_SGT:
419*81ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), -1)))
420*81ad6265SDimitry Andric       addFact(CmpInst::ICMP_UGE, A, ConstantInt::get(B->getType(), 0),
421*81ad6265SDimitry Andric               IsNegated, NumIn, NumOut, DFSInStack);
422*81ad6265SDimitry Andric     break;
423*81ad6265SDimitry Andric   case CmpInst::ICMP_SGE:
424*81ad6265SDimitry Andric     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0))) {
425*81ad6265SDimitry Andric       addFact(CmpInst::ICMP_UGE, A, B, IsNegated, NumIn, NumOut, DFSInStack);
426*81ad6265SDimitry Andric     }
427*81ad6265SDimitry Andric     break;
428*81ad6265SDimitry Andric   }
429e8d8bef9SDimitry Andric }
430e8d8bef9SDimitry Andric 
431e8d8bef9SDimitry Andric namespace {
432e8d8bef9SDimitry Andric /// Represents either a condition that holds on entry to a block or a basic
433e8d8bef9SDimitry Andric /// block, with their respective Dominator DFS in and out numbers.
434e8d8bef9SDimitry Andric struct ConstraintOrBlock {
435e8d8bef9SDimitry Andric   unsigned NumIn;
436e8d8bef9SDimitry Andric   unsigned NumOut;
437e8d8bef9SDimitry Andric   bool IsBlock;
438e8d8bef9SDimitry Andric   bool Not;
439e8d8bef9SDimitry Andric   union {
440e8d8bef9SDimitry Andric     BasicBlock *BB;
441e8d8bef9SDimitry Andric     CmpInst *Condition;
442e8d8bef9SDimitry Andric   };
443e8d8bef9SDimitry Andric 
444e8d8bef9SDimitry Andric   ConstraintOrBlock(DomTreeNode *DTN)
445e8d8bef9SDimitry Andric       : NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), IsBlock(true),
446e8d8bef9SDimitry Andric         BB(DTN->getBlock()) {}
447e8d8bef9SDimitry Andric   ConstraintOrBlock(DomTreeNode *DTN, CmpInst *Condition, bool Not)
448e8d8bef9SDimitry Andric       : NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), IsBlock(false),
449e8d8bef9SDimitry Andric         Not(Not), Condition(Condition) {}
450e8d8bef9SDimitry Andric };
451e8d8bef9SDimitry Andric 
452*81ad6265SDimitry Andric /// Keep state required to build worklist.
453*81ad6265SDimitry Andric struct State {
454*81ad6265SDimitry Andric   DominatorTree &DT;
455*81ad6265SDimitry Andric   SmallVector<ConstraintOrBlock, 64> WorkList;
456e8d8bef9SDimitry Andric 
457*81ad6265SDimitry Andric   State(DominatorTree &DT) : DT(DT) {}
458*81ad6265SDimitry Andric 
459*81ad6265SDimitry Andric   /// Process block \p BB and add known facts to work-list.
460*81ad6265SDimitry Andric   void addInfoFor(BasicBlock &BB);
461*81ad6265SDimitry Andric 
462*81ad6265SDimitry Andric   /// Returns true if we can add a known condition from BB to its successor
463*81ad6265SDimitry Andric   /// block Succ. Each predecessor of Succ can either be BB or be dominated
464*81ad6265SDimitry Andric   /// by Succ (e.g. the case when adding a condition from a pre-header to a
465*81ad6265SDimitry Andric   /// loop header).
466*81ad6265SDimitry Andric   bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ) const {
467*81ad6265SDimitry Andric     if (BB.getSingleSuccessor()) {
468*81ad6265SDimitry Andric       assert(BB.getSingleSuccessor() == Succ);
469*81ad6265SDimitry Andric       return DT.properlyDominates(&BB, Succ);
470*81ad6265SDimitry Andric     }
471*81ad6265SDimitry Andric     return any_of(successors(&BB),
472*81ad6265SDimitry Andric                   [Succ](const BasicBlock *S) { return S != Succ; }) &&
473*81ad6265SDimitry Andric            all_of(predecessors(Succ), [&BB, Succ, this](BasicBlock *Pred) {
474*81ad6265SDimitry Andric              return Pred == &BB || DT.dominates(Succ, Pred);
475*81ad6265SDimitry Andric            });
476*81ad6265SDimitry Andric   }
477e8d8bef9SDimitry Andric };
478*81ad6265SDimitry Andric 
479e8d8bef9SDimitry Andric } // namespace
480e8d8bef9SDimitry Andric 
481fe6060f1SDimitry Andric #ifndef NDEBUG
482*81ad6265SDimitry Andric static void dumpWithNames(const ConstraintSystem &CS,
483fe6060f1SDimitry Andric                           DenseMap<Value *, unsigned> &Value2Index) {
484fe6060f1SDimitry Andric   SmallVector<std::string> Names(Value2Index.size(), "");
485fe6060f1SDimitry Andric   for (auto &KV : Value2Index) {
486fe6060f1SDimitry Andric     Names[KV.second - 1] = std::string("%") + KV.first->getName().str();
487fe6060f1SDimitry Andric   }
488fe6060f1SDimitry Andric   CS.dump(Names);
489fe6060f1SDimitry Andric }
490*81ad6265SDimitry Andric 
491*81ad6265SDimitry Andric static void dumpWithNames(ArrayRef<int64_t> C,
492*81ad6265SDimitry Andric                           DenseMap<Value *, unsigned> &Value2Index) {
493*81ad6265SDimitry Andric   ConstraintSystem CS;
494*81ad6265SDimitry Andric   CS.addVariableRowFill(C);
495*81ad6265SDimitry Andric   dumpWithNames(CS, Value2Index);
496*81ad6265SDimitry Andric }
497fe6060f1SDimitry Andric #endif
498fe6060f1SDimitry Andric 
499*81ad6265SDimitry Andric void State::addInfoFor(BasicBlock &BB) {
500e8d8bef9SDimitry Andric   WorkList.emplace_back(DT.getNode(&BB));
501e8d8bef9SDimitry Andric 
502349cc55cSDimitry Andric   // True as long as long as the current instruction is guaranteed to execute.
503349cc55cSDimitry Andric   bool GuaranteedToExecute = true;
504349cc55cSDimitry Andric   // Scan BB for assume calls.
505349cc55cSDimitry Andric   // TODO: also use this scan to queue conditions to simplify, so we can
506349cc55cSDimitry Andric   // interleave facts from assumes and conditions to simplify in a single
507349cc55cSDimitry Andric   // basic block. And to skip another traversal of each basic block when
508349cc55cSDimitry Andric   // simplifying.
509349cc55cSDimitry Andric   for (Instruction &I : BB) {
510349cc55cSDimitry Andric     Value *Cond;
511349cc55cSDimitry Andric     // For now, just handle assumes with a single compare as condition.
512349cc55cSDimitry Andric     if (match(&I, m_Intrinsic<Intrinsic::assume>(m_Value(Cond))) &&
513*81ad6265SDimitry Andric         isa<ICmpInst>(Cond)) {
514349cc55cSDimitry Andric       if (GuaranteedToExecute) {
515349cc55cSDimitry Andric         // The assume is guaranteed to execute when BB is entered, hence Cond
516349cc55cSDimitry Andric         // holds on entry to BB.
517*81ad6265SDimitry Andric         WorkList.emplace_back(DT.getNode(&BB), cast<ICmpInst>(Cond), false);
518349cc55cSDimitry Andric       } else {
519349cc55cSDimitry Andric         // Otherwise the condition only holds in the successors.
520*81ad6265SDimitry Andric         for (BasicBlock *Succ : successors(&BB)) {
521*81ad6265SDimitry Andric           if (!canAddSuccessor(BB, Succ))
522*81ad6265SDimitry Andric             continue;
523*81ad6265SDimitry Andric           WorkList.emplace_back(DT.getNode(Succ), cast<ICmpInst>(Cond), false);
524*81ad6265SDimitry Andric         }
525349cc55cSDimitry Andric       }
526349cc55cSDimitry Andric     }
527349cc55cSDimitry Andric     GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
528349cc55cSDimitry Andric   }
529349cc55cSDimitry Andric 
530e8d8bef9SDimitry Andric   auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
531e8d8bef9SDimitry Andric   if (!Br || !Br->isConditional())
532*81ad6265SDimitry Andric     return;
533e8d8bef9SDimitry Andric 
534e8d8bef9SDimitry Andric   // If the condition is an OR of 2 compares and the false successor only has
535e8d8bef9SDimitry Andric   // the current block as predecessor, queue both negated conditions for the
536e8d8bef9SDimitry Andric   // false successor.
537e8d8bef9SDimitry Andric   Value *Op0, *Op1;
538e8d8bef9SDimitry Andric   if (match(Br->getCondition(), m_LogicalOr(m_Value(Op0), m_Value(Op1))) &&
539*81ad6265SDimitry Andric       isa<ICmpInst>(Op0) && isa<ICmpInst>(Op1)) {
540e8d8bef9SDimitry Andric     BasicBlock *FalseSuccessor = Br->getSuccessor(1);
541*81ad6265SDimitry Andric     if (canAddSuccessor(BB, FalseSuccessor)) {
542*81ad6265SDimitry Andric       WorkList.emplace_back(DT.getNode(FalseSuccessor), cast<ICmpInst>(Op0),
543e8d8bef9SDimitry Andric                             true);
544*81ad6265SDimitry Andric       WorkList.emplace_back(DT.getNode(FalseSuccessor), cast<ICmpInst>(Op1),
545e8d8bef9SDimitry Andric                             true);
546e8d8bef9SDimitry Andric     }
547*81ad6265SDimitry Andric     return;
548e8d8bef9SDimitry Andric   }
549e8d8bef9SDimitry Andric 
550e8d8bef9SDimitry Andric   // If the condition is an AND of 2 compares and the true successor only has
551e8d8bef9SDimitry Andric   // the current block as predecessor, queue both conditions for the true
552e8d8bef9SDimitry Andric   // successor.
553e8d8bef9SDimitry Andric   if (match(Br->getCondition(), m_LogicalAnd(m_Value(Op0), m_Value(Op1))) &&
554*81ad6265SDimitry Andric       isa<ICmpInst>(Op0) && isa<ICmpInst>(Op1)) {
555e8d8bef9SDimitry Andric     BasicBlock *TrueSuccessor = Br->getSuccessor(0);
556*81ad6265SDimitry Andric     if (canAddSuccessor(BB, TrueSuccessor)) {
557*81ad6265SDimitry Andric       WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<ICmpInst>(Op0),
558e8d8bef9SDimitry Andric                             false);
559*81ad6265SDimitry Andric       WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<ICmpInst>(Op1),
560e8d8bef9SDimitry Andric                             false);
561e8d8bef9SDimitry Andric     }
562*81ad6265SDimitry Andric     return;
563e8d8bef9SDimitry Andric   }
564e8d8bef9SDimitry Andric 
565*81ad6265SDimitry Andric   auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
566e8d8bef9SDimitry Andric   if (!CmpI)
567*81ad6265SDimitry Andric     return;
568*81ad6265SDimitry Andric   if (canAddSuccessor(BB, Br->getSuccessor(0)))
569e8d8bef9SDimitry Andric     WorkList.emplace_back(DT.getNode(Br->getSuccessor(0)), CmpI, false);
570*81ad6265SDimitry Andric   if (canAddSuccessor(BB, Br->getSuccessor(1)))
571e8d8bef9SDimitry Andric     WorkList.emplace_back(DT.getNode(Br->getSuccessor(1)), CmpI, true);
572e8d8bef9SDimitry Andric }
573e8d8bef9SDimitry Andric 
574*81ad6265SDimitry Andric void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
575*81ad6265SDimitry Andric                              bool IsNegated, unsigned NumIn, unsigned NumOut,
576*81ad6265SDimitry Andric                              SmallVectorImpl<StackEntry> &DFSInStack) {
577*81ad6265SDimitry Andric   // If the constraint has a pre-condition, skip the constraint if it does not
578*81ad6265SDimitry Andric   // hold.
579*81ad6265SDimitry Andric   DenseMap<Value *, unsigned> NewIndices;
580*81ad6265SDimitry Andric   auto R = getConstraint(Pred, A, B, NewIndices);
581*81ad6265SDimitry Andric   if (!R.isValid(*this))
582*81ad6265SDimitry Andric     return;
583*81ad6265SDimitry Andric 
584*81ad6265SDimitry Andric   //LLVM_DEBUG(dbgs() << "Adding " << *Condition << " " << IsNegated << "\n");
585*81ad6265SDimitry Andric   bool Added = false;
586*81ad6265SDimitry Andric   assert(CmpInst::isSigned(Pred) == R.IsSigned &&
587*81ad6265SDimitry Andric          "condition and constraint signs must match");
588*81ad6265SDimitry Andric   auto &CSToUse = getCS(R.IsSigned);
589*81ad6265SDimitry Andric   if (R.Coefficients.empty())
590*81ad6265SDimitry Andric     return;
591*81ad6265SDimitry Andric 
592*81ad6265SDimitry Andric   Added |= CSToUse.addVariableRowFill(R.Coefficients);
593*81ad6265SDimitry Andric 
594*81ad6265SDimitry Andric   // If R has been added to the system, queue it for removal once it goes
595*81ad6265SDimitry Andric   // out-of-scope.
596*81ad6265SDimitry Andric   if (Added) {
597*81ad6265SDimitry Andric     SmallVector<Value *, 2> ValuesToRelease;
598*81ad6265SDimitry Andric     for (auto &KV : NewIndices) {
599*81ad6265SDimitry Andric       getValue2Index(R.IsSigned).insert(KV);
600*81ad6265SDimitry Andric       ValuesToRelease.push_back(KV.first);
601*81ad6265SDimitry Andric     }
602*81ad6265SDimitry Andric 
603*81ad6265SDimitry Andric     LLVM_DEBUG({
604*81ad6265SDimitry Andric       dbgs() << "  constraint: ";
605*81ad6265SDimitry Andric       dumpWithNames(R.Coefficients, getValue2Index(R.IsSigned));
606*81ad6265SDimitry Andric     });
607*81ad6265SDimitry Andric 
608*81ad6265SDimitry Andric     DFSInStack.emplace_back(NumIn, NumOut, IsNegated, R.IsSigned,
609*81ad6265SDimitry Andric                             ValuesToRelease);
610*81ad6265SDimitry Andric 
611*81ad6265SDimitry Andric     if (R.IsEq) {
612*81ad6265SDimitry Andric       // Also add the inverted constraint for equality constraints.
613*81ad6265SDimitry Andric       for (auto &Coeff : R.Coefficients)
614*81ad6265SDimitry Andric         Coeff *= -1;
615*81ad6265SDimitry Andric       CSToUse.addVariableRowFill(R.Coefficients);
616*81ad6265SDimitry Andric 
617*81ad6265SDimitry Andric       DFSInStack.emplace_back(NumIn, NumOut, IsNegated, R.IsSigned,
618*81ad6265SDimitry Andric                               SmallVector<Value *, 2>());
619*81ad6265SDimitry Andric     }
620*81ad6265SDimitry Andric   }
621*81ad6265SDimitry Andric }
622*81ad6265SDimitry Andric 
623*81ad6265SDimitry Andric static void
624*81ad6265SDimitry Andric tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info,
625*81ad6265SDimitry Andric                           SmallVectorImpl<Instruction *> &ToRemove) {
626*81ad6265SDimitry Andric   auto DoesConditionHold = [](CmpInst::Predicate Pred, Value *A, Value *B,
627*81ad6265SDimitry Andric                               ConstraintInfo &Info) {
628*81ad6265SDimitry Andric     DenseMap<Value *, unsigned> NewIndices;
629*81ad6265SDimitry Andric     auto R = Info.getConstraint(Pred, A, B, NewIndices);
630*81ad6265SDimitry Andric     if (R.size() < 2 || R.needsNewIndices(NewIndices) || !R.isValid(Info))
631*81ad6265SDimitry Andric       return false;
632*81ad6265SDimitry Andric 
633*81ad6265SDimitry Andric     auto &CSToUse = Info.getCS(CmpInst::isSigned(Pred));
634*81ad6265SDimitry Andric     return CSToUse.isConditionImplied(R.Coefficients);
635*81ad6265SDimitry Andric   };
636*81ad6265SDimitry Andric 
637*81ad6265SDimitry Andric   if (II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
638*81ad6265SDimitry Andric     // If A s>= B && B s>= 0, ssub.with.overflow(a, b) should not overflow and
639*81ad6265SDimitry Andric     // can be simplified to a regular sub.
640*81ad6265SDimitry Andric     Value *A = II->getArgOperand(0);
641*81ad6265SDimitry Andric     Value *B = II->getArgOperand(1);
642*81ad6265SDimitry Andric     if (!DoesConditionHold(CmpInst::ICMP_SGE, A, B, Info) ||
643*81ad6265SDimitry Andric         !DoesConditionHold(CmpInst::ICMP_SGE, B,
644*81ad6265SDimitry Andric                            ConstantInt::get(A->getType(), 0), Info))
645*81ad6265SDimitry Andric       return;
646*81ad6265SDimitry Andric 
647*81ad6265SDimitry Andric     IRBuilder<> Builder(II->getParent(), II->getIterator());
648*81ad6265SDimitry Andric     Value *Sub = nullptr;
649*81ad6265SDimitry Andric     for (User *U : make_early_inc_range(II->users())) {
650*81ad6265SDimitry Andric       if (match(U, m_ExtractValue<0>(m_Value()))) {
651*81ad6265SDimitry Andric         if (!Sub)
652*81ad6265SDimitry Andric           Sub = Builder.CreateSub(A, B);
653*81ad6265SDimitry Andric         U->replaceAllUsesWith(Sub);
654*81ad6265SDimitry Andric       } else if (match(U, m_ExtractValue<1>(m_Value())))
655*81ad6265SDimitry Andric         U->replaceAllUsesWith(Builder.getFalse());
656*81ad6265SDimitry Andric       else
657*81ad6265SDimitry Andric         continue;
658*81ad6265SDimitry Andric 
659*81ad6265SDimitry Andric       if (U->use_empty()) {
660*81ad6265SDimitry Andric         auto *I = cast<Instruction>(U);
661*81ad6265SDimitry Andric         ToRemove.push_back(I);
662*81ad6265SDimitry Andric         I->setOperand(0, PoisonValue::get(II->getType()));
663*81ad6265SDimitry Andric       }
664*81ad6265SDimitry Andric     }
665*81ad6265SDimitry Andric 
666*81ad6265SDimitry Andric     if (II->use_empty())
667*81ad6265SDimitry Andric       II->eraseFromParent();
668*81ad6265SDimitry Andric   }
669*81ad6265SDimitry Andric }
670*81ad6265SDimitry Andric 
671*81ad6265SDimitry Andric static bool eliminateConstraints(Function &F, DominatorTree &DT) {
672*81ad6265SDimitry Andric   bool Changed = false;
673*81ad6265SDimitry Andric   DT.updateDFSNumbers();
674*81ad6265SDimitry Andric 
675*81ad6265SDimitry Andric   ConstraintInfo Info;
676*81ad6265SDimitry Andric   State S(DT);
677*81ad6265SDimitry Andric 
678*81ad6265SDimitry Andric   // First, collect conditions implied by branches and blocks with their
679*81ad6265SDimitry Andric   // Dominator DFS in and out numbers.
680*81ad6265SDimitry Andric   for (BasicBlock &BB : F) {
681*81ad6265SDimitry Andric     if (!DT.getNode(&BB))
682*81ad6265SDimitry Andric       continue;
683*81ad6265SDimitry Andric     S.addInfoFor(BB);
684*81ad6265SDimitry Andric   }
685*81ad6265SDimitry Andric 
686e8d8bef9SDimitry Andric   // Next, sort worklist by dominance, so that dominating blocks and conditions
687e8d8bef9SDimitry Andric   // come before blocks and conditions dominated by them. If a block and a
688e8d8bef9SDimitry Andric   // condition have the same numbers, the condition comes before the block, as
689e8d8bef9SDimitry Andric   // it holds on entry to the block.
690*81ad6265SDimitry Andric   stable_sort(S.WorkList, [](const ConstraintOrBlock &A, const ConstraintOrBlock &B) {
691e8d8bef9SDimitry Andric     return std::tie(A.NumIn, A.IsBlock) < std::tie(B.NumIn, B.IsBlock);
692e8d8bef9SDimitry Andric   });
693e8d8bef9SDimitry Andric 
694*81ad6265SDimitry Andric   SmallVector<Instruction *> ToRemove;
695*81ad6265SDimitry Andric 
696e8d8bef9SDimitry Andric   // Finally, process ordered worklist and eliminate implied conditions.
697e8d8bef9SDimitry Andric   SmallVector<StackEntry, 16> DFSInStack;
698*81ad6265SDimitry Andric   for (ConstraintOrBlock &CB : S.WorkList) {
699e8d8bef9SDimitry Andric     // First, pop entries from the stack that are out-of-scope for CB. Remove
700e8d8bef9SDimitry Andric     // the corresponding entry from the constraint system.
701e8d8bef9SDimitry Andric     while (!DFSInStack.empty()) {
702e8d8bef9SDimitry Andric       auto &E = DFSInStack.back();
703e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Top of stack : " << E.NumIn << " " << E.NumOut
704e8d8bef9SDimitry Andric                         << "\n");
705e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "CB: " << CB.NumIn << " " << CB.NumOut << "\n");
706e8d8bef9SDimitry Andric       assert(E.NumIn <= CB.NumIn);
707e8d8bef9SDimitry Andric       if (CB.NumOut <= E.NumOut)
708e8d8bef9SDimitry Andric         break;
709*81ad6265SDimitry Andric       LLVM_DEBUG({
710*81ad6265SDimitry Andric         dbgs() << "Removing ";
711*81ad6265SDimitry Andric         dumpWithNames(Info.getCS(E.IsSigned).getLastConstraint(),
712*81ad6265SDimitry Andric                       Info.getValue2Index(E.IsSigned));
713*81ad6265SDimitry Andric         dbgs() << "\n";
714*81ad6265SDimitry Andric       });
715*81ad6265SDimitry Andric 
716*81ad6265SDimitry Andric       Info.popLastConstraint(E.IsSigned);
717*81ad6265SDimitry Andric       // Remove variables in the system that went out of scope.
718*81ad6265SDimitry Andric       auto &Mapping = Info.getValue2Index(E.IsSigned);
719*81ad6265SDimitry Andric       for (Value *V : E.ValuesToRelease)
720*81ad6265SDimitry Andric         Mapping.erase(V);
721*81ad6265SDimitry Andric       Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
722e8d8bef9SDimitry Andric       DFSInStack.pop_back();
723e8d8bef9SDimitry Andric     }
724e8d8bef9SDimitry Andric 
725e8d8bef9SDimitry Andric     LLVM_DEBUG({
726e8d8bef9SDimitry Andric       dbgs() << "Processing ";
727e8d8bef9SDimitry Andric       if (CB.IsBlock)
728e8d8bef9SDimitry Andric         dbgs() << *CB.BB;
729e8d8bef9SDimitry Andric       else
730e8d8bef9SDimitry Andric         dbgs() << *CB.Condition;
731e8d8bef9SDimitry Andric       dbgs() << "\n";
732e8d8bef9SDimitry Andric     });
733e8d8bef9SDimitry Andric 
734e8d8bef9SDimitry Andric     // For a block, check if any CmpInsts become known based on the current set
735e8d8bef9SDimitry Andric     // of constraints.
736e8d8bef9SDimitry Andric     if (CB.IsBlock) {
737*81ad6265SDimitry Andric       for (Instruction &I : make_early_inc_range(*CB.BB)) {
738*81ad6265SDimitry Andric         if (auto *II = dyn_cast<WithOverflowInst>(&I)) {
739*81ad6265SDimitry Andric           tryToSimplifyOverflowMath(II, Info, ToRemove);
740*81ad6265SDimitry Andric           continue;
741*81ad6265SDimitry Andric         }
742*81ad6265SDimitry Andric         auto *Cmp = dyn_cast<ICmpInst>(&I);
743e8d8bef9SDimitry Andric         if (!Cmp)
744e8d8bef9SDimitry Andric           continue;
745fe6060f1SDimitry Andric 
746fe6060f1SDimitry Andric         DenseMap<Value *, unsigned> NewIndices;
747*81ad6265SDimitry Andric         auto R = Info.getConstraint(Cmp, NewIndices);
748*81ad6265SDimitry Andric         if (R.IsEq || R.empty() || R.needsNewIndices(NewIndices) ||
749*81ad6265SDimitry Andric             !R.isValid(Info))
750e8d8bef9SDimitry Andric           continue;
751fe6060f1SDimitry Andric 
752*81ad6265SDimitry Andric         auto &CSToUse = Info.getCS(R.IsSigned);
753*81ad6265SDimitry Andric         if (CSToUse.isConditionImplied(R.Coefficients)) {
754e8d8bef9SDimitry Andric           if (!DebugCounter::shouldExecute(EliminatedCounter))
755e8d8bef9SDimitry Andric             continue;
756e8d8bef9SDimitry Andric 
757e8d8bef9SDimitry Andric           LLVM_DEBUG({
758*81ad6265SDimitry Andric             dbgs() << "Condition " << *Cmp
759*81ad6265SDimitry Andric                    << " implied by dominating constraints\n";
760*81ad6265SDimitry Andric             dumpWithNames(CSToUse, Info.getValue2Index(R.IsSigned));
761e8d8bef9SDimitry Andric           });
762349cc55cSDimitry Andric           Cmp->replaceUsesWithIf(
763349cc55cSDimitry Andric               ConstantInt::getTrue(F.getParent()->getContext()), [](Use &U) {
764349cc55cSDimitry Andric                 // Conditions in an assume trivially simplify to true. Skip uses
765349cc55cSDimitry Andric                 // in assume calls to not destroy the available information.
766349cc55cSDimitry Andric                 auto *II = dyn_cast<IntrinsicInst>(U.getUser());
767349cc55cSDimitry Andric                 return !II || II->getIntrinsicID() != Intrinsic::assume;
768349cc55cSDimitry Andric               });
769e8d8bef9SDimitry Andric           NumCondsRemoved++;
770e8d8bef9SDimitry Andric           Changed = true;
771e8d8bef9SDimitry Andric         }
772*81ad6265SDimitry Andric         if (CSToUse.isConditionImplied(
773*81ad6265SDimitry Andric                 ConstraintSystem::negate(R.Coefficients))) {
774e8d8bef9SDimitry Andric           if (!DebugCounter::shouldExecute(EliminatedCounter))
775e8d8bef9SDimitry Andric             continue;
776e8d8bef9SDimitry Andric 
777e8d8bef9SDimitry Andric           LLVM_DEBUG({
778*81ad6265SDimitry Andric             dbgs() << "Condition !" << *Cmp
779*81ad6265SDimitry Andric                    << " implied by dominating constraints\n";
780*81ad6265SDimitry Andric             dumpWithNames(CSToUse, Info.getValue2Index(R.IsSigned));
781e8d8bef9SDimitry Andric           });
782e8d8bef9SDimitry Andric           Cmp->replaceAllUsesWith(
783e8d8bef9SDimitry Andric               ConstantInt::getFalse(F.getParent()->getContext()));
784e8d8bef9SDimitry Andric           NumCondsRemoved++;
785e8d8bef9SDimitry Andric           Changed = true;
786e8d8bef9SDimitry Andric         }
787e8d8bef9SDimitry Andric       }
788e8d8bef9SDimitry Andric       continue;
789e8d8bef9SDimitry Andric     }
790e8d8bef9SDimitry Andric 
791fe6060f1SDimitry Andric     // Set up a function to restore the predicate at the end of the scope if it
792fe6060f1SDimitry Andric     // has been negated. Negate the predicate in-place, if required.
793*81ad6265SDimitry Andric     auto *CI = dyn_cast<ICmpInst>(CB.Condition);
794fe6060f1SDimitry Andric     auto PredicateRestorer = make_scope_exit([CI, &CB]() {
795fe6060f1SDimitry Andric       if (CB.Not && CI)
796fe6060f1SDimitry Andric         CI->setPredicate(CI->getInversePredicate());
797fe6060f1SDimitry Andric     });
798fe6060f1SDimitry Andric     if (CB.Not) {
799fe6060f1SDimitry Andric       if (CI) {
800fe6060f1SDimitry Andric         CI->setPredicate(CI->getInversePredicate());
801fe6060f1SDimitry Andric       } else {
802fe6060f1SDimitry Andric         LLVM_DEBUG(dbgs() << "Can only negate compares so far.\n");
803fe6060f1SDimitry Andric         continue;
804fe6060f1SDimitry Andric       }
805fe6060f1SDimitry Andric     }
806fe6060f1SDimitry Andric 
807*81ad6265SDimitry Andric     ICmpInst::Predicate Pred;
808*81ad6265SDimitry Andric     Value *A, *B;
809*81ad6265SDimitry Andric     if (match(CB.Condition, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
810*81ad6265SDimitry Andric       // Otherwise, add the condition to the system and stack, if we can
811*81ad6265SDimitry Andric       // transform it into a constraint.
812*81ad6265SDimitry Andric       Info.addFact(Pred, A, B, CB.Not, CB.NumIn, CB.NumOut, DFSInStack);
813*81ad6265SDimitry Andric       Info.transferToOtherSystem(Pred, A, B, CB.Not, CB.NumIn, CB.NumOut,
814*81ad6265SDimitry Andric                                  DFSInStack);
815e8d8bef9SDimitry Andric     }
816fe6060f1SDimitry Andric   }
817e8d8bef9SDimitry Andric 
818*81ad6265SDimitry Andric #ifndef NDEBUG
819*81ad6265SDimitry Andric   unsigned SignedEntries =
820*81ad6265SDimitry Andric       count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; });
821*81ad6265SDimitry Andric   assert(Info.getCS(false).size() == DFSInStack.size() - SignedEntries &&
822fe6060f1SDimitry Andric          "updates to CS and DFSInStack are out of sync");
823*81ad6265SDimitry Andric   assert(Info.getCS(true).size() == SignedEntries &&
824*81ad6265SDimitry Andric          "updates to CS and DFSInStack are out of sync");
825*81ad6265SDimitry Andric #endif
826*81ad6265SDimitry Andric 
827*81ad6265SDimitry Andric   for (Instruction *I : ToRemove)
828*81ad6265SDimitry Andric     I->eraseFromParent();
829e8d8bef9SDimitry Andric   return Changed;
830e8d8bef9SDimitry Andric }
831e8d8bef9SDimitry Andric 
832e8d8bef9SDimitry Andric PreservedAnalyses ConstraintEliminationPass::run(Function &F,
833e8d8bef9SDimitry Andric                                                  FunctionAnalysisManager &AM) {
834e8d8bef9SDimitry Andric   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
835e8d8bef9SDimitry Andric   if (!eliminateConstraints(F, DT))
836e8d8bef9SDimitry Andric     return PreservedAnalyses::all();
837e8d8bef9SDimitry Andric 
838e8d8bef9SDimitry Andric   PreservedAnalyses PA;
839e8d8bef9SDimitry Andric   PA.preserve<DominatorTreeAnalysis>();
840e8d8bef9SDimitry Andric   PA.preserveSet<CFGAnalyses>();
841e8d8bef9SDimitry Andric   return PA;
842e8d8bef9SDimitry Andric }
843e8d8bef9SDimitry Andric 
844e8d8bef9SDimitry Andric namespace {
845e8d8bef9SDimitry Andric 
846e8d8bef9SDimitry Andric class ConstraintElimination : public FunctionPass {
847e8d8bef9SDimitry Andric public:
848e8d8bef9SDimitry Andric   static char ID;
849e8d8bef9SDimitry Andric 
850e8d8bef9SDimitry Andric   ConstraintElimination() : FunctionPass(ID) {
851e8d8bef9SDimitry Andric     initializeConstraintEliminationPass(*PassRegistry::getPassRegistry());
852e8d8bef9SDimitry Andric   }
853e8d8bef9SDimitry Andric 
854e8d8bef9SDimitry Andric   bool runOnFunction(Function &F) override {
855e8d8bef9SDimitry Andric     auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
856e8d8bef9SDimitry Andric     return eliminateConstraints(F, DT);
857e8d8bef9SDimitry Andric   }
858e8d8bef9SDimitry Andric 
859e8d8bef9SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
860e8d8bef9SDimitry Andric     AU.setPreservesCFG();
861e8d8bef9SDimitry Andric     AU.addRequired<DominatorTreeWrapperPass>();
862e8d8bef9SDimitry Andric     AU.addPreserved<GlobalsAAWrapperPass>();
863e8d8bef9SDimitry Andric     AU.addPreserved<DominatorTreeWrapperPass>();
864e8d8bef9SDimitry Andric   }
865e8d8bef9SDimitry Andric };
866e8d8bef9SDimitry Andric 
867e8d8bef9SDimitry Andric } // end anonymous namespace
868e8d8bef9SDimitry Andric 
869e8d8bef9SDimitry Andric char ConstraintElimination::ID = 0;
870e8d8bef9SDimitry Andric 
871e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(ConstraintElimination, "constraint-elimination",
872e8d8bef9SDimitry Andric                       "Constraint Elimination", false, false)
873e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
874e8d8bef9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
875e8d8bef9SDimitry Andric INITIALIZE_PASS_END(ConstraintElimination, "constraint-elimination",
876e8d8bef9SDimitry Andric                     "Constraint Elimination", false, false)
877e8d8bef9SDimitry Andric 
878e8d8bef9SDimitry Andric FunctionPass *llvm::createConstraintEliminationPass() {
879e8d8bef9SDimitry Andric   return new ConstraintElimination();
880e8d8bef9SDimitry Andric }
881