mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[IR] Add SaturatingInst and BinaryOpIntrinsic classes
Based on the suggestion in D62447, this adds a SaturatingInst class that represents the saturating add/sub family of intrinsics. It exposes the same interface as WithOverflowInst, for this reason I have also added a common base class BinaryOpIntrinsic that holds the actual implementation code and will be useful in some places handling both overflowing and saturating math. Differential Revision: https://reviews.llvm.org/D62466 llvm-svn: 361857
This commit is contained in:
parent
1cdac3fa17
commit
3a98741a79
@ -267,8 +267,9 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class represents a op.with.overflow intrinsic.
|
/// This class represents an intrinsic that is based on a binary operation.
|
||||||
class WithOverflowInst : public IntrinsicInst {
|
/// This includes op.with.overflow and saturating add/sub intrinsics.
|
||||||
|
class BinaryOpIntrinsic : public IntrinsicInst {
|
||||||
public:
|
public:
|
||||||
static bool classof(const IntrinsicInst *I) {
|
static bool classof(const IntrinsicInst *I) {
|
||||||
switch (I->getIntrinsicID()) {
|
switch (I->getIntrinsicID()) {
|
||||||
@ -278,6 +279,10 @@ namespace llvm {
|
|||||||
case Intrinsic::ssub_with_overflow:
|
case Intrinsic::ssub_with_overflow:
|
||||||
case Intrinsic::umul_with_overflow:
|
case Intrinsic::umul_with_overflow:
|
||||||
case Intrinsic::smul_with_overflow:
|
case Intrinsic::smul_with_overflow:
|
||||||
|
case Intrinsic::uadd_sat:
|
||||||
|
case Intrinsic::sadd_sat:
|
||||||
|
case Intrinsic::usub_sat:
|
||||||
|
case Intrinsic::ssub_sat:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -300,6 +305,46 @@ namespace llvm {
|
|||||||
unsigned getNoWrapKind() const;
|
unsigned getNoWrapKind() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Represents an op.with.overflow intrinsic.
|
||||||
|
class WithOverflowInst : public BinaryOpIntrinsic {
|
||||||
|
public:
|
||||||
|
static bool classof(const IntrinsicInst *I) {
|
||||||
|
switch (I->getIntrinsicID()) {
|
||||||
|
case Intrinsic::uadd_with_overflow:
|
||||||
|
case Intrinsic::sadd_with_overflow:
|
||||||
|
case Intrinsic::usub_with_overflow:
|
||||||
|
case Intrinsic::ssub_with_overflow:
|
||||||
|
case Intrinsic::umul_with_overflow:
|
||||||
|
case Intrinsic::smul_with_overflow:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static bool classof(const Value *V) {
|
||||||
|
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents a saturating add/sub intrinsic.
|
||||||
|
class SaturatingInst : public BinaryOpIntrinsic {
|
||||||
|
public:
|
||||||
|
static bool classof(const IntrinsicInst *I) {
|
||||||
|
switch (I->getIntrinsicID()) {
|
||||||
|
case Intrinsic::uadd_sat:
|
||||||
|
case Intrinsic::sadd_sat:
|
||||||
|
case Intrinsic::usub_sat:
|
||||||
|
case Intrinsic::ssub_sat:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static bool classof(const Value *V) {
|
||||||
|
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Common base class for all memory intrinsics. Simply provides
|
/// Common base class for all memory intrinsics. Simply provides
|
||||||
/// common methods.
|
/// common methods.
|
||||||
/// Written as CRTP to avoid a common base class amongst the
|
/// Written as CRTP to avoid a common base class amongst the
|
||||||
|
@ -171,13 +171,17 @@ bool ConstrainedFPIntrinsic::isTernaryOp() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction::BinaryOps WithOverflowInst::getBinaryOp() const {
|
Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
|
||||||
switch (getIntrinsicID()) {
|
switch (getIntrinsicID()) {
|
||||||
case Intrinsic::uadd_with_overflow:
|
case Intrinsic::uadd_with_overflow:
|
||||||
case Intrinsic::sadd_with_overflow:
|
case Intrinsic::sadd_with_overflow:
|
||||||
|
case Intrinsic::uadd_sat:
|
||||||
|
case Intrinsic::sadd_sat:
|
||||||
return Instruction::Add;
|
return Instruction::Add;
|
||||||
case Intrinsic::usub_with_overflow:
|
case Intrinsic::usub_with_overflow:
|
||||||
case Intrinsic::ssub_with_overflow:
|
case Intrinsic::ssub_with_overflow:
|
||||||
|
case Intrinsic::usub_sat:
|
||||||
|
case Intrinsic::ssub_sat:
|
||||||
return Instruction::Sub;
|
return Instruction::Sub;
|
||||||
case Intrinsic::umul_with_overflow:
|
case Intrinsic::umul_with_overflow:
|
||||||
case Intrinsic::smul_with_overflow:
|
case Intrinsic::smul_with_overflow:
|
||||||
@ -187,18 +191,20 @@ Instruction::BinaryOps WithOverflowInst::getBinaryOp() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WithOverflowInst::isSigned() const {
|
bool BinaryOpIntrinsic::isSigned() const {
|
||||||
switch (getIntrinsicID()) {
|
switch (getIntrinsicID()) {
|
||||||
case Intrinsic::sadd_with_overflow:
|
case Intrinsic::sadd_with_overflow:
|
||||||
case Intrinsic::ssub_with_overflow:
|
case Intrinsic::ssub_with_overflow:
|
||||||
case Intrinsic::smul_with_overflow:
|
case Intrinsic::smul_with_overflow:
|
||||||
|
case Intrinsic::sadd_sat:
|
||||||
|
case Intrinsic::ssub_sat:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned WithOverflowInst::getNoWrapKind() const {
|
unsigned BinaryOpIntrinsic::getNoWrapKind() const {
|
||||||
if (isSigned())
|
if (isSigned())
|
||||||
return OverflowingBinaryOperator::NoSignedWrap;
|
return OverflowingBinaryOperator::NoSignedWrap;
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user