Index: llvm/include/llvm/IR/ConstantRange.h =================================================================== --- llvm/include/llvm/IR/ConstantRange.h +++ llvm/include/llvm/IR/ConstantRange.h @@ -150,6 +150,13 @@ const APInt &Other, unsigned NoWrapKind); + /// Whether ConstantRange calculations for this intrinsic are supported. + static bool isIntrinsicSupported(Intrinsic::ID IntrinsicID); + + /// Compute range of intrinsic result for the given operand ranges. + static ConstantRange intrinsic(Intrinsic::ID IntrinsicID, + ArrayRef Ops); + /// Set up \p Pred and \p RHS such that /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if /// successful. Index: llvm/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/lib/Analysis/LazyValueInfo.cpp +++ llvm/lib/Analysis/LazyValueInfo.cpp @@ -400,8 +400,6 @@ BasicBlock *BB); Optional solveBlockValueOverflowIntrinsic( WithOverflowInst *WO, BasicBlock *BB); - Optional solveBlockValueSaturatingIntrinsic( - SaturatingInst *SI, BasicBlock *BB); Optional solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB); Optional solveBlockValueExtractValue( @@ -1035,43 +1033,24 @@ }); } -Optional -LazyValueInfoImpl::solveBlockValueSaturatingIntrinsic(SaturatingInst *SI, - BasicBlock *BB) { - switch (SI->getIntrinsicID()) { - case Intrinsic::uadd_sat: - return solveBlockValueBinaryOpImpl( - SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) { - return CR1.uadd_sat(CR2); - }); - case Intrinsic::usub_sat: - return solveBlockValueBinaryOpImpl( - SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) { - return CR1.usub_sat(CR2); - }); - case Intrinsic::sadd_sat: - return solveBlockValueBinaryOpImpl( - SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) { - return CR1.sadd_sat(CR2); - }); - case Intrinsic::ssub_sat: - return solveBlockValueBinaryOpImpl( - SI, BB, [](const ConstantRange &CR1, const ConstantRange &CR2) { - return CR1.ssub_sat(CR2); - }); - default: - llvm_unreachable("All llvm.sat intrinsic are handled."); - } -} - Optional LazyValueInfoImpl::solveBlockValueIntrinsic( IntrinsicInst *II, BasicBlock *BB) { - if (auto *SI = dyn_cast(II)) - return solveBlockValueSaturatingIntrinsic(SI, BB); + if (!ConstantRange::isIntrinsicSupported(II->getIntrinsicID())) { + LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined (unknown intrinsic).\n"); + return ValueLatticeElement::getOverdefined(); + } - LLVM_DEBUG(dbgs() << " compute BB '" << BB->getName() - << "' - overdefined (unknown intrinsic).\n"); - return ValueLatticeElement::getOverdefined(); + SmallVector OpRanges; + for (Value *Op : II->args()) { + Optional Range = getRangeFor(Op, II, BB); + if (!Range) + return None; + OpRanges.push_back(*Range); + } + + return ValueLatticeElement::getRange( + ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges)); } Optional LazyValueInfoImpl::solveBlockValueExtractValue( Index: llvm/lib/IR/ConstantRange.cpp =================================================================== --- llvm/lib/IR/ConstantRange.cpp +++ llvm/lib/IR/ConstantRange.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" #include "llvm/Support/Compiler.h" @@ -835,6 +836,34 @@ } } +bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) { + switch (IntrinsicID) { + case Intrinsic::uadd_sat: + case Intrinsic::usub_sat: + case Intrinsic::sadd_sat: + case Intrinsic::ssub_sat: + return true; + default: + return false; + } +} + +ConstantRange ConstantRange::intrinsic(Intrinsic::ID IntrinsicID, + ArrayRef Ops) { + switch (IntrinsicID) { + case Intrinsic::uadd_sat: + return Ops[0].uadd_sat(Ops[1]); + case Intrinsic::usub_sat: + return Ops[0].usub_sat(Ops[1]); + case Intrinsic::sadd_sat: + return Ops[0].sadd_sat(Ops[1]); + case Intrinsic::ssub_sat: + return Ops[0].ssub_sat(Ops[1]); + default: + llvm_unreachable("Unsupported intrinsic"); + } +} + ConstantRange ConstantRange::add(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet())