/// contains - Return true if the specified value is in the set. /// bool ConstantRange::contains(const APInt &V) const { if (Lower == Upper) return isFullSet(); if (!isWrappedSet()) return Lower.ule(V) && V.ult(Upper); return Lower.ule(V) || V.ult(Upper); }
/// intersectWith - Return the range that results from the intersection of this /// range with another range. /// ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); // Handle common special cases if (isEmptySet() || CR.isFullSet()) return *this; if (isFullSet() || CR.isEmptySet()) return CR; if (!isWrappedSet()) { if (!CR.isWrappedSet()) { using namespace APIntOps; APInt L = umax(Lower, CR.Lower); APInt U = umin(Upper, CR.Upper); if (L.ult(U)) // If range isn't empty... return ConstantRange(L, U); else return ConstantRange(getBitWidth(), false);// Otherwise, empty set } else return intersect1Wrapped(CR, *this); } else { // We know "this" is wrapped... if (!CR.isWrappedSet()) return intersect1Wrapped(*this, CR); else { // Both ranges are wrapped... using namespace APIntOps; APInt L = umax(Lower, CR.Lower); APInt U = umin(Upper, CR.Upper); return ConstantRange(L, U); } } return *this; }
/// truncate - Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values as if the source range had been /// truncated to the specified type. ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { assert(getBitWidth() > DstTySize && "Not a value truncation"); if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false); if (isFullSet()) return ConstantRange(DstTySize, /*isFullSet=*/true); APInt MaxValue = APInt::getMaxValue(DstTySize).zext(getBitWidth()); APInt MaxBitValue(getBitWidth(), 0); MaxBitValue.setBit(DstTySize); APInt LowerDiv(Lower), UpperDiv(Upper); ConstantRange Union(DstTySize, /*isFullSet=*/false); // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue] // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and // then we do the union with [MaxValue, Upper) if (isWrappedSet()) { // if Upper is greater than Max Value, it covers the whole truncated range. if (Upper.uge(MaxValue)) return ConstantRange(DstTySize, /*isFullSet=*/true); Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize)); UpperDiv = APInt::getMaxValue(getBitWidth()); // Union covers the MaxValue case, so return if the remaining range is just // MaxValue. if (LowerDiv == UpperDiv) return Union; } // Chop off the most significant bits that are past the destination bitwidth. if (LowerDiv.uge(MaxValue)) { APInt Div(getBitWidth(), 0); APInt::udivrem(LowerDiv, MaxBitValue, Div, LowerDiv); UpperDiv = UpperDiv - MaxBitValue * Div; } if (UpperDiv.ule(MaxValue)) return ConstantRange(LowerDiv.trunc(DstTySize), UpperDiv.trunc(DstTySize)).unionWith(Union); // The truncated value wrapps around. Check if we can do better than fullset. APInt UpperModulo = UpperDiv - MaxBitValue; if (UpperModulo.ult(LowerDiv)) return ConstantRange(LowerDiv.trunc(DstTySize), UpperModulo.trunc(DstTySize)).unionWith(Union); return ConstantRange(DstTySize, /*isFullSet=*/true); }
/// \brief Compute the size of the object pointed by Ptr. Returns true and the /// object size in Size if successful, and false otherwise. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign) { ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), RoundToAlign); SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr)); if (!Visitor.bothKnown(Data)) return false; APInt ObjSize = Data.first, Offset = Data.second; // check for overflow if (Offset.slt(0) || ObjSize.ult(Offset)) Size = 0; else Size = (ObjSize - Offset).getZExtValue(); return true; }
/// FoldSPFofSPF - We have an SPF (e.g. a min or max) of an SPF of the form: /// SPF2(SPF1(A, B), C) Instruction *InstCombiner::FoldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1, Value *A, Value *B, Instruction &Outer, SelectPatternFlavor SPF2, Value *C) { if (C == A || C == B) { // MAX(MAX(A, B), B) -> MAX(A, B) // MIN(MIN(a, b), a) -> MIN(a, b) if (SPF1 == SPF2) return ReplaceInstUsesWith(Outer, Inner); // MAX(MIN(a, b), a) -> a // MIN(MAX(a, b), a) -> a if ((SPF1 == SPF_SMIN && SPF2 == SPF_SMAX) || (SPF1 == SPF_SMAX && SPF2 == SPF_SMIN) || (SPF1 == SPF_UMIN && SPF2 == SPF_UMAX) || (SPF1 == SPF_UMAX && SPF2 == SPF_UMIN)) return ReplaceInstUsesWith(Outer, C); } if (SPF1 == SPF2) { if (ConstantInt *CB = dyn_cast<ConstantInt>(B)) { if (ConstantInt *CC = dyn_cast<ConstantInt>(C)) { APInt ACB = CB->getValue(); APInt ACC = CC->getValue(); // MIN(MIN(A, 23), 97) -> MIN(A, 23) // MAX(MAX(A, 97), 23) -> MAX(A, 97) if ((SPF1 == SPF_UMIN && ACB.ule(ACC)) || (SPF1 == SPF_SMIN && ACB.sle(ACC)) || (SPF1 == SPF_UMAX && ACB.uge(ACC)) || (SPF1 == SPF_SMAX && ACB.sge(ACC))) return ReplaceInstUsesWith(Outer, Inner); // MIN(MIN(A, 97), 23) -> MIN(A, 23) // MAX(MAX(A, 23), 97) -> MAX(A, 97) if ((SPF1 == SPF_UMIN && ACB.ugt(ACC)) || (SPF1 == SPF_SMIN && ACB.sgt(ACC)) || (SPF1 == SPF_UMAX && ACB.ult(ACC)) || (SPF1 == SPF_SMAX && ACB.slt(ACC))) { Outer.replaceUsesOfWith(Inner, A); return &Outer; } } } } return nullptr; }
APInt swift::constantFoldComparison(APInt lhs, APInt rhs, BuiltinValueKind ID) { bool result; switch (ID) { default: llvm_unreachable("Invalid integer compare kind"); case BuiltinValueKind::ICMP_EQ: result = lhs == rhs; break; case BuiltinValueKind::ICMP_NE: result = lhs != rhs; break; case BuiltinValueKind::ICMP_SLT: result = lhs.slt(rhs); break; case BuiltinValueKind::ICMP_SGT: result = lhs.sgt(rhs); break; case BuiltinValueKind::ICMP_SLE: result = lhs.sle(rhs); break; case BuiltinValueKind::ICMP_SGE: result = lhs.sge(rhs); break; case BuiltinValueKind::ICMP_ULT: result = lhs.ult(rhs); break; case BuiltinValueKind::ICMP_UGT: result = lhs.ugt(rhs); break; case BuiltinValueKind::ICMP_ULE: result = lhs.ule(rhs); break; case BuiltinValueKind::ICMP_UGE: result = lhs.uge(rhs); break; } return APInt(1, result); }
/// FoldSPFofSPF - We have an SPF (e.g. a min or max) of an SPF of the form: /// SPF2(SPF1(A, B), C) Instruction *InstCombiner::FoldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1, Value *A, Value *B, Instruction &Outer, SelectPatternFlavor SPF2, Value *C) { if (C == A || C == B) { // MAX(MAX(A, B), B) -> MAX(A, B) // MIN(MIN(a, b), a) -> MIN(a, b) if (SPF1 == SPF2) return ReplaceInstUsesWith(Outer, Inner); // MAX(MIN(a, b), a) -> a // MIN(MAX(a, b), a) -> a if ((SPF1 == SPF_SMIN && SPF2 == SPF_SMAX) || (SPF1 == SPF_SMAX && SPF2 == SPF_SMIN) || (SPF1 == SPF_UMIN && SPF2 == SPF_UMAX) || (SPF1 == SPF_UMAX && SPF2 == SPF_UMIN)) return ReplaceInstUsesWith(Outer, C); } if (SPF1 == SPF2) { if (ConstantInt *CB = dyn_cast<ConstantInt>(B)) { if (ConstantInt *CC = dyn_cast<ConstantInt>(C)) { APInt ACB = CB->getValue(); APInt ACC = CC->getValue(); // MIN(MIN(A, 23), 97) -> MIN(A, 23) // MAX(MAX(A, 97), 23) -> MAX(A, 97) if ((SPF1 == SPF_UMIN && ACB.ule(ACC)) || (SPF1 == SPF_SMIN && ACB.sle(ACC)) || (SPF1 == SPF_UMAX && ACB.uge(ACC)) || (SPF1 == SPF_SMAX && ACB.sge(ACC))) return ReplaceInstUsesWith(Outer, Inner); // MIN(MIN(A, 97), 23) -> MIN(A, 23) // MAX(MAX(A, 23), 97) -> MAX(A, 97) if ((SPF1 == SPF_UMIN && ACB.ugt(ACC)) || (SPF1 == SPF_SMIN && ACB.sgt(ACC)) || (SPF1 == SPF_UMAX && ACB.ult(ACC)) || (SPF1 == SPF_SMAX && ACB.slt(ACC))) { Outer.replaceUsesOfWith(Inner, A); return &Outer; } } } } // ABS(ABS(X)) -> ABS(X) // NABS(NABS(X)) -> NABS(X) if (SPF1 == SPF2 && (SPF1 == SPF_ABS || SPF1 == SPF_NABS)) { return ReplaceInstUsesWith(Outer, Inner); } // ABS(NABS(X)) -> ABS(X) // NABS(ABS(X)) -> NABS(X) if ((SPF1 == SPF_ABS && SPF2 == SPF_NABS) || (SPF1 == SPF_NABS && SPF2 == SPF_ABS)) { SelectInst *SI = cast<SelectInst>(Inner); Value *NewSI = Builder->CreateSelect( SI->getCondition(), SI->getFalseValue(), SI->getTrueValue()); return ReplaceInstUsesWith(Outer, NewSI); } return nullptr; }