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