Skip to content

Commit

Permalink
[ConstantRange] Add API for intrinsics (NFC)
Browse files Browse the repository at this point in the history
This adds a common API for compute constant ranges of intrinsics.
The intention here is that
a) we can reuse the same code across different passes that handle
   constant ranges, i.e. this can be reused in SCCP
b) we only have to add knowledge about supported intrinsics to
   ConstantRange, not any consumers.

Differential Revision: https://reviews.llvm.org/D84587
  • Loading branch information
nikic committed Jul 29, 2020
1 parent 77c3b01 commit 897bdca
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 36 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/ConstantRange.h
Expand Up @@ -150,6 +150,14 @@ class LLVM_NODISCARD ConstantRange {
const APInt &Other,
unsigned NoWrapKind);

/// Returns true if ConstantRange calculations are supported for intrinsic
/// with \p IntrinsicID.
static bool isIntrinsicSupported(Intrinsic::ID IntrinsicID);

/// Compute range of intrinsic result for the given operand ranges.
static ConstantRange intrinsic(Intrinsic::ID IntrinsicID,
ArrayRef<ConstantRange> Ops);

/// Set up \p Pred and \p RHS such that
/// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if
/// successful.
Expand Down
51 changes: 15 additions & 36 deletions llvm/lib/Analysis/LazyValueInfo.cpp
Expand Up @@ -400,8 +400,6 @@ class LazyValueInfoImpl {
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueOverflowIntrinsic(
WithOverflowInst *WO, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueSaturatingIntrinsic(
SaturatingInst *SI, BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueIntrinsic(IntrinsicInst *II,
BasicBlock *BB);
Optional<ValueLatticeElement> solveBlockValueExtractValue(
Expand Down Expand Up @@ -1035,43 +1033,24 @@ LazyValueInfoImpl::solveBlockValueOverflowIntrinsic(WithOverflowInst *WO,
});
}

Optional<ValueLatticeElement>
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<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueIntrinsic(
IntrinsicInst *II, BasicBlock *BB) {
if (auto *SI = dyn_cast<SaturatingInst>(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<ConstantRange, 2> OpRanges;
for (Value *Op : II->args()) {
Optional<ConstantRange> Range = getRangeFor(Op, II, BB);
if (!Range)
return None;
OpRanges.push_back(*Range);
}

return ValueLatticeElement::getRange(
ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges));
}

Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueExtractValue(
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/IR/ConstantRange.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -835,6 +836,35 @@ ConstantRange ConstantRange::overflowingBinaryOp(Instruction::BinaryOps BinOp,
}
}

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<ConstantRange> 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:
assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
llvm_unreachable("Unsupported intrinsic");
}
}

ConstantRange
ConstantRange::add(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
Expand Down

0 comments on commit 897bdca

Please sign in to comment.