[llvm] 86b4d86 - [InstCombine] canonicalize cmp+select as umin/umax
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 8 14:26:07 PST 2023
Author: Sanjay Patel
Date: 2023-02-08T17:25:58-05:00
New Revision: 86b4d8645fc1b86693fef564cef68f24599c930f
URL: https://github.com/llvm/llvm-project/commit/86b4d8645fc1b86693fef564cef68f24599c930f
DIFF: https://github.com/llvm/llvm-project/commit/86b4d8645fc1b86693fef564cef68f24599c930f.diff
LOG: [InstCombine] canonicalize cmp+select as umin/umax
(V == 0) ? 1 : V --> umax(V, 1)
(V == UMAX) ? UMAX-1 : V --> umin(V, UMAX-1)
https://alive2.llvm.org/ce/z/pfDBAf
This is one pair of the variants discussed in issue #60374.
Enhancements for the other end of the constant range and
signed variants are potential follow-ups, but that may
require more work because we canonicalize at least one
min/max like that to icmp+zext.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/div-shift.ll
llvm/test/Transforms/InstCombine/select.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index e7d8208f94fd4..894b11c9d918c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1593,13 +1593,26 @@ static Instruction *foldSelectZeroOrOnes(ICmpInst *Cmp, Value *TVal,
return nullptr;
}
-static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI) {
+static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
+ InstCombiner::BuilderTy &Builder) {
const APInt *CmpC;
Value *V;
CmpInst::Predicate Pred;
if (!match(ICI, m_ICmp(Pred, m_Value(V), m_APInt(CmpC))))
return nullptr;
+ // Match clamp away from min/max value as a max/min operation.
+ Value *TVal = SI.getTrueValue();
+ Value *FVal = SI.getFalseValue();
+ if (Pred == ICmpInst::ICMP_EQ && V == FVal) {
+ // (V == 0) ? 1 : V --> umax(V, 1)
+ if (CmpC->isMinValue() && match(TVal, m_SpecificInt(*CmpC + 1)))
+ return Builder.CreateBinaryIntrinsic(Intrinsic::umax, V, TVal);
+ // (V == UMAX) ? UMAX-1 : V --> umin(V, UMAX-1)
+ if (CmpC->isMaxValue() && match(TVal, m_SpecificInt(*CmpC - 1)))
+ return Builder.CreateBinaryIntrinsic(Intrinsic::umin, V, TVal);
+ }
+
BinaryOperator *BO;
const APInt *C;
CmpInst::Predicate CPred;
@@ -1632,7 +1645,7 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this))
return NewSPF;
- if (Value *V = foldSelectInstWithICmpConst(SI, ICI))
+ if (Value *V = foldSelectInstWithICmpConst(SI, ICI, Builder))
return replaceInstUsesWith(SI, V);
if (Value *V = canonicalizeClampLike(SI, *ICI, Builder))
diff --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index b87ace5a630ef..efdaa0ce9d059 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -90,8 +90,7 @@ define i32 @t5(i1 %x, i1 %y, i32 %V) {
define i32 @t6(i32 %x, i32 %z) {
; CHECK-LABEL: @t6(
-; CHECK-NEXT: [[X_IS_ZERO:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK-NEXT: [[DIVISOR:%.*]] = select i1 [[X_IS_ZERO]], i32 1, i32 [[X]]
+; CHECK-NEXT: [[DIVISOR:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 1)
; CHECK-NEXT: [[Y:%.*]] = udiv i32 [[Z:%.*]], [[DIVISOR]]
; CHECK-NEXT: ret i32 [[Y]]
;
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 96303bae2f753..87a26cf6c1b5c 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3399,8 +3399,7 @@ define <vscale x 2 x i1> @scalable_non_zero(<vscale x 2 x i32> %x) {
define i32 @clamp_zero(i32 %x) {
; CHECK-LABEL: @clamp_zero(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 1, i32 [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 1)
; CHECK-NEXT: ret i32 [[SEL]]
;
%cmp = icmp eq i32 %x, 0
@@ -3412,7 +3411,7 @@ define i32 @clamp_zero_use(i32 %x) {
; CHECK-LABEL: @clamp_zero_use(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: call void @use1(i1 [[CMP]])
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 1, i32 [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1)
; CHECK-NEXT: ret i32 [[SEL]]
;
%cmp = icmp eq i32 %x, 0
@@ -3421,6 +3420,8 @@ define i32 @clamp_zero_use(i32 %x) {
ret i32 %sel
}
+; negative test - wrong cmp constant
+
define i32 @not_clamp_zero1(i32 %x) {
; CHECK-LABEL: @not_clamp_zero1(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2
@@ -3432,6 +3433,8 @@ define i32 @not_clamp_zero1(i32 %x) {
ret i32 %sel
}
+; negative test - wrong select constant
+
define i32 @not_clamp_zero2(i32 %x) {
; CHECK-LABEL: @not_clamp_zero2(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
@@ -3445,8 +3448,7 @@ define i32 @not_clamp_zero2(i32 %x) {
define <2 x i8> @clamp_umaxval(<2 x i8> %x) {
; CHECK-LABEL: @clamp_umaxval(
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 -2, i8 -2>, <2 x i8> [[X]]
+; CHECK-NEXT: [[SEL:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[X:%.*]], <2 x i8> <i8 -2, i8 -2>)
; CHECK-NEXT: ret <2 x i8> [[SEL]]
;
%cmp = icmp eq <2 x i8> %x, <i8 255, i8 255>
@@ -3454,6 +3456,8 @@ define <2 x i8> @clamp_umaxval(<2 x i8> %x) {
ret <2 x i8> %sel
}
+; negative test - wrong cmp constant
+
define i8 @not_clamp_umax1(i8 %x) {
; CHECK-LABEL: @not_clamp_umax1(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -3
@@ -3465,6 +3469,8 @@ define i8 @not_clamp_umax1(i8 %x) {
ret i8 %sel
}
+; negative test - wrong select constant
+
define i8 @not_clamp_umax2(i8 %x) {
; CHECK-LABEL: @not_clamp_umax2(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -1
More information about the llvm-commits
mailing list