mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[InstSimplify] fold min/max with limit constant
This is already done within InstCombine: https://alive2.llvm.org/ce/z/MiGE22 ...but leaving it out of analysis makes it harder to avoid infinite loops there. (cherry picked from commit e260e10c4a21784c146c94a2a14b7e78b09a9cf7)
This commit is contained in:
parent
de802b8e6e
commit
5a14ea148e
@ -744,6 +744,10 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
|
|||||||
/// minimum/maximum flavor.
|
/// minimum/maximum flavor.
|
||||||
CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF);
|
CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF);
|
||||||
|
|
||||||
|
/// Return the minimum or maximum constant value for the specified integer
|
||||||
|
/// min/max flavor and type.
|
||||||
|
APInt getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth);
|
||||||
|
|
||||||
/// Check if the values in \p VL are select instructions that can be converted
|
/// Check if the values in \p VL are select instructions that can be converted
|
||||||
/// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a
|
/// to a min or max (vector) intrinsic. Returns the intrinsic ID, if such a
|
||||||
/// conversion is possible, together with a bool indicating whether all select
|
/// conversion is possible, together with a bool indicating whether all select
|
||||||
|
@ -4080,6 +4080,22 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
|
|||||||
std::swap(TrueVal, FalseVal);
|
std::swap(TrueVal, FalseVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for integer min/max with a limit constant:
|
||||||
|
// X > MIN_INT ? X : MIN_INT --> X
|
||||||
|
// X < MAX_INT ? X : MAX_INT --> X
|
||||||
|
if (TrueVal->getType()->isIntOrIntVectorTy()) {
|
||||||
|
Value *X, *Y;
|
||||||
|
SelectPatternFlavor SPF =
|
||||||
|
matchDecomposedSelectPattern(cast<ICmpInst>(CondVal), TrueVal, FalseVal,
|
||||||
|
X, Y).Flavor;
|
||||||
|
if (SelectPatternResult::isMinOrMax(SPF) && Pred == getMinMaxPred(SPF)) {
|
||||||
|
APInt LimitC = getMinMaxLimit(getInverseMinMaxFlavor(SPF),
|
||||||
|
X->getType()->getScalarSizeInBits());
|
||||||
|
if (match(Y, m_SpecificInt(LimitC)))
|
||||||
|
return X;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Pred == ICmpInst::ICMP_EQ && match(CmpRHS, m_Zero())) {
|
if (Pred == ICmpInst::ICMP_EQ && match(CmpRHS, m_Zero())) {
|
||||||
Value *X;
|
Value *X;
|
||||||
const APInt *Y;
|
const APInt *Y;
|
||||||
|
@ -6253,6 +6253,16 @@ CmpInst::Predicate llvm::getInverseMinMaxPred(SelectPatternFlavor SPF) {
|
|||||||
return getMinMaxPred(getInverseMinMaxFlavor(SPF));
|
return getMinMaxPred(getInverseMinMaxFlavor(SPF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APInt llvm::getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth) {
|
||||||
|
switch (SPF) {
|
||||||
|
case SPF_SMAX: return APInt::getSignedMaxValue(BitWidth);
|
||||||
|
case SPF_SMIN: return APInt::getSignedMinValue(BitWidth);
|
||||||
|
case SPF_UMAX: return APInt::getMaxValue(BitWidth);
|
||||||
|
case SPF_UMIN: return APInt::getMinValue(BitWidth);
|
||||||
|
default: llvm_unreachable("Unexpected flavor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<Intrinsic::ID, bool>
|
std::pair<Intrinsic::ID, bool>
|
||||||
llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
|
llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
|
||||||
// Check if VL contains select instructions that can be folded into a min/max
|
// Check if VL contains select instructions that can be folded into a min/max
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
define i8 @smax_min_limit(i8 %x) {
|
define i8 @smax_min_limit(i8 %x) {
|
||||||
; CHECK-LABEL: @smax_min_limit(
|
; CHECK-LABEL: @smax_min_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -128
|
; CHECK-NEXT: ret i8 [[X:%.*]]
|
||||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 -128
|
|
||||||
; CHECK-NEXT: ret i8 [[SEL]]
|
|
||||||
;
|
;
|
||||||
%cmp = icmp sgt i8 %x, -128
|
%cmp = icmp sgt i8 %x, -128
|
||||||
%sel = select i1 %cmp, i8 %x, i8 -128
|
%sel = select i1 %cmp, i8 %x, i8 -128
|
||||||
@ -14,9 +12,7 @@ define i8 @smax_min_limit(i8 %x) {
|
|||||||
|
|
||||||
define i8 @smin_max_limit(i8 %x) {
|
define i8 @smin_max_limit(i8 %x) {
|
||||||
; CHECK-LABEL: @smin_max_limit(
|
; CHECK-LABEL: @smin_max_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 127
|
; CHECK-NEXT: ret i8 [[X:%.*]]
|
||||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 127
|
|
||||||
; CHECK-NEXT: ret i8 [[SEL]]
|
|
||||||
;
|
;
|
||||||
%cmp = icmp slt i8 %x, 127
|
%cmp = icmp slt i8 %x, 127
|
||||||
%sel = select i1 %cmp, i8 %x, i8 127
|
%sel = select i1 %cmp, i8 %x, i8 127
|
||||||
@ -25,9 +21,7 @@ define i8 @smin_max_limit(i8 %x) {
|
|||||||
|
|
||||||
define <2 x i8> @umax_min_limit(<2 x i8> %x) {
|
define <2 x i8> @umax_min_limit(<2 x i8> %x) {
|
||||||
; CHECK-LABEL: @umax_min_limit(
|
; CHECK-LABEL: @umax_min_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[X:%.*]], zeroinitializer
|
; CHECK-NEXT: ret <2 x i8> [[X:%.*]]
|
||||||
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> zeroinitializer
|
|
||||||
; CHECK-NEXT: ret <2 x i8> [[SEL]]
|
|
||||||
;
|
;
|
||||||
%cmp = icmp ugt <2 x i8> %x, zeroinitializer
|
%cmp = icmp ugt <2 x i8> %x, zeroinitializer
|
||||||
%sel = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> zeroinitializer
|
%sel = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> zeroinitializer
|
||||||
@ -36,15 +30,15 @@ define <2 x i8> @umax_min_limit(<2 x i8> %x) {
|
|||||||
|
|
||||||
define i8 @umin_max_limit(i8 %x) {
|
define i8 @umin_max_limit(i8 %x) {
|
||||||
; CHECK-LABEL: @umin_max_limit(
|
; CHECK-LABEL: @umin_max_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -1
|
; CHECK-NEXT: ret i8 [[X:%.*]]
|
||||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 -1
|
|
||||||
; CHECK-NEXT: ret i8 [[SEL]]
|
|
||||||
;
|
;
|
||||||
%cmp = icmp ult i8 %x, 255
|
%cmp = icmp ult i8 %x, 255
|
||||||
%sel = select i1 %cmp, i8 %x, i8 255
|
%sel = select i1 %cmp, i8 %x, i8 255
|
||||||
ret i8 %sel
|
ret i8 %sel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; negative test - wrong limit
|
||||||
|
|
||||||
define i8 @smax_not_min_limit(i8 %x) {
|
define i8 @smax_not_min_limit(i8 %x) {
|
||||||
; CHECK-LABEL: @smax_not_min_limit(
|
; CHECK-LABEL: @smax_not_min_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -127
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -127
|
||||||
@ -56,6 +50,8 @@ define i8 @smax_not_min_limit(i8 %x) {
|
|||||||
ret i8 %sel
|
ret i8 %sel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; negative test - wrong limit
|
||||||
|
|
||||||
define i8 @smin_not_min_limit(i8 %x) {
|
define i8 @smin_not_min_limit(i8 %x) {
|
||||||
; CHECK-LABEL: @smin_not_min_limit(
|
; CHECK-LABEL: @smin_not_min_limit(
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
|
||||||
|
Loading…
Reference in New Issue
Block a user