Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); }
/// Returns the comparison predicate underlying the intrinsic.
- ICmpInst::Predicate getPredicate() const {
- switch (getIntrinsicID()) {
+ static ICmpInst::Predicate getPredicate(Intrinsic::ID ID) {
+ switch (ID) {
case Intrinsic::umin:
return ICmpInst::Predicate::ICMP_ULT;
case Intrinsic::umax:
}
}
+ /// Returns the comparison predicate underlying the intrinsic.
+ ICmpInst::Predicate getPredicate() const {
+ return getPredicate(getIntrinsicID());
+ }
+
/// Whether the intrinsic is signed or unsigned.
- bool isSigned() const { return ICmpInst::isSigned(getPredicate()); };
+ static bool isSigned(Intrinsic::ID ID) {
+ return ICmpInst::isSigned(getPredicate(ID));
+ };
+
+ /// Whether the intrinsic is signed or unsigned.
+ bool isSigned() const { return isSigned(getIntrinsicID()); };
+
+ /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
+ /// so there is a certain threshold value, upon reaching which,
+ /// their value can no longer change. Return said threshold.
+ static APInt getSaturationPoint(Intrinsic::ID ID, unsigned numBits) {
+ switch (ID) {
+ case Intrinsic::umin:
+ return APInt::getMinValue(numBits);
+ case Intrinsic::umax:
+ return APInt::getMaxValue(numBits);
+ case Intrinsic::smin:
+ return APInt::getSignedMinValue(numBits);
+ case Intrinsic::smax:
+ return APInt::getSignedMaxValue(numBits);
+ default:
+ llvm_unreachable("Invalid intrinsic");
+ }
+ }
+
+ /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
+ /// so there is a certain threshold value, upon reaching which,
+ /// their value can no longer change. Return said threshold.
+ APInt getSaturationPoint(unsigned numBits) const {
+ return getSaturationPoint(getIntrinsicID(), numBits);
+ }
+
+ /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
+ /// so there is a certain threshold value, upon reaching which,
+ /// their value can no longer change. Return said threshold.
+ static Constant *getSaturationPoint(Intrinsic::ID ID, Type *Ty) {
+ return Constant::getIntegerValue(
+ Ty, getSaturationPoint(ID, Ty->getScalarSizeInBits()));
+ }
+
+ /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values,
+ /// so there is a certain threshold value, upon reaching which,
+ /// their value can no longer change. Return said threshold.
+ Constant *getSaturationPoint(Type *Ty) const {
+ return getSaturationPoint(getIntrinsicID(), Ty);
+ }
};
/// This class represents an intrinsic that is based on a binary operation.
!getConstIntOrUndef(Operands[1], C1))
return nullptr;
- unsigned BitWidth = Ty->getScalarSizeInBits();
switch (IntrinsicID) {
default: break;
case Intrinsic::smax:
- if (!C0 && !C1)
- return UndefValue::get(Ty);
- if (!C0 || !C1)
- return ConstantInt::get(Ty, APInt::getSignedMaxValue(BitWidth));
- return ConstantInt::get(Ty, C0->sgt(*C1) ? *C0 : *C1);
-
case Intrinsic::smin:
- if (!C0 && !C1)
- return UndefValue::get(Ty);
- if (!C0 || !C1)
- return ConstantInt::get(Ty, APInt::getSignedMinValue(BitWidth));
- return ConstantInt::get(Ty, C0->slt(*C1) ? *C0 : *C1);
-
case Intrinsic::umax:
- if (!C0 && !C1)
- return UndefValue::get(Ty);
- if (!C0 || !C1)
- return ConstantInt::get(Ty, APInt::getMaxValue(BitWidth));
- return ConstantInt::get(Ty, C0->ugt(*C1) ? *C0 : *C1);
-
case Intrinsic::umin:
if (!C0 && !C1)
return UndefValue::get(Ty);
if (!C0 || !C1)
- return ConstantInt::get(Ty, APInt::getMinValue(BitWidth));
- return ConstantInt::get(Ty, C0->ult(*C1) ? *C0 : *C1);
+ return MinMaxIntrinsic::getSaturationPoint(IntrinsicID, Ty);
+ return ConstantInt::get(
+ Ty, ICmpInst::compare(*C0, *C1,
+ MinMaxIntrinsic::getPredicate(IntrinsicID))
+ ? *C0
+ : *C1);
case Intrinsic::usub_with_overflow:
case Intrinsic::ssub_with_overflow:
return nullptr;
}
-static APInt getMaxMinLimit(Intrinsic::ID IID, unsigned BitWidth) {
- switch (IID) {
- case Intrinsic::smax: return APInt::getSignedMaxValue(BitWidth);
- case Intrinsic::smin: return APInt::getSignedMinValue(BitWidth);
- case Intrinsic::umax: return APInt::getMaxValue(BitWidth);
- case Intrinsic::umin: return APInt::getMinValue(BitWidth);
- default: llvm_unreachable("Unexpected intrinsic");
- }
-}
-
-static ICmpInst::Predicate getMaxMinPredicate(Intrinsic::ID IID) {
- switch (IID) {
- case Intrinsic::smax: return ICmpInst::ICMP_SGE;
- case Intrinsic::smin: return ICmpInst::ICMP_SLE;
- case Intrinsic::umax: return ICmpInst::ICMP_UGE;
- case Intrinsic::umin: return ICmpInst::ICMP_ULE;
- default: llvm_unreachable("Unexpected intrinsic");
- }
-}
-
/// Given a min/max intrinsic, see if it can be removed based on having an
/// operand that is another min/max intrinsic with shared operand(s). The caller
/// is expected to swap the operand arguments to handle commutation.
// Assume undef is the limit value.
if (Q.isUndefValue(Op1))
- return ConstantInt::get(ReturnType, getMaxMinLimit(IID, BitWidth));
+ return ConstantInt::get(
+ ReturnType, MinMaxIntrinsic::getSaturationPoint(IID, BitWidth));
const APInt *C;
if (match(Op1, m_APIntAllowUndef(C))) {
// Clamp to limit value. For example:
// umax(i8 %x, i8 255) --> 255
- if (*C == getMaxMinLimit(IID, BitWidth))
+ if (*C == MinMaxIntrinsic::getSaturationPoint(IID, BitWidth))
return ConstantInt::get(ReturnType, *C);
// If the constant op is the opposite of the limit value, the other must
// be larger/smaller or equal. For example:
// umin(i8 %x, i8 255) --> %x
- if (*C == getMaxMinLimit(getInverseMinMaxIntrinsic(IID), BitWidth))
+ if (*C == MinMaxIntrinsic::getSaturationPoint(
+ getInverseMinMaxIntrinsic(IID), BitWidth))
return Op0;
// Remove nested call if constant operands allow it. Example:
Value *M00 = MinMax0->getOperand(0), *M01 = MinMax0->getOperand(1);
const APInt *InnerC;
if ((match(M00, m_APInt(InnerC)) || match(M01, m_APInt(InnerC))) &&
- ((IID == Intrinsic::smax && InnerC->sge(*C)) ||
- (IID == Intrinsic::smin && InnerC->sle(*C)) ||
- (IID == Intrinsic::umax && InnerC->uge(*C)) ||
- (IID == Intrinsic::umin && InnerC->ule(*C))))
+ ICmpInst::compare(*InnerC, *C,
+ ICmpInst::getNonStrictPredicate(
+ MinMaxIntrinsic::getPredicate(IID))))
return Op0;
}
}
if (Value *V = foldMinMaxSharedOp(IID, Op1, Op0))
return V;
- ICmpInst::Predicate Pred = getMaxMinPredicate(IID);
+ ICmpInst::Predicate Pred =
+ ICmpInst::getNonStrictPredicate(MinMaxIntrinsic::getPredicate(IID));
if (isICmpTrue(Pred, Op0, Op1, Q.getWithoutUndef(), RecursionLimit))
return Op0;
if (isICmpTrue(Pred, Op1, Op0, Q.getWithoutUndef(), RecursionLimit))