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