[llvm] cc83927 - [CVP] Canonicalize signed minmax into unsigned (#82478)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 22 10:42:54 PST 2024
Author: Yingwei Zheng
Date: 2024-02-23T02:42:49+08:00
New Revision: cc839275164a7768451531af868fa70eb9e71cbd
URL: https://github.com/llvm/llvm-project/commit/cc839275164a7768451531af868fa70eb9e71cbd
DIFF: https://github.com/llvm/llvm-project/commit/cc839275164a7768451531af868fa70eb9e71cbd.diff
LOG: [CVP] Canonicalize signed minmax into unsigned (#82478)
This patch turns signed minmax to unsigned to match the behavior for
signed icmps.
Alive2: https://alive2.llvm.org/ce/z/UAAM42
Added:
Modified:
llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index c71870bc1b6569..6ce9eb3656c93a 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -47,11 +47,6 @@ using namespace llvm;
#define DEBUG_TYPE "correlated-value-propagation"
-static cl::opt<bool> CanonicalizeICmpPredicatesToUnsigned(
- "canonicalize-icmp-predicates-to-unsigned", cl::init(true), cl::Hidden,
- cl::desc("Enables canonicalization of signed relational predicates to "
- "unsigned (e.g. sgt => ugt)"));
-
STATISTIC(NumPhis, "Number of phis propagated");
STATISTIC(NumPhiCommon, "Number of phis deleted via common incoming value");
STATISTIC(NumSelects, "Number of selects propagated");
@@ -90,6 +85,8 @@ STATISTIC(NumSaturating,
"Number of saturating arithmetics converted to normal arithmetics");
STATISTIC(NumNonNull, "Number of function pointer arguments marked non-null");
STATISTIC(NumMinMax, "Number of llvm.[us]{min,max} intrinsics removed");
+STATISTIC(NumSMinMax,
+ "Number of llvm.s{min,max} intrinsics simplified to unsigned");
STATISTIC(NumUDivURemsNarrowedExpanded,
"Number of bound udiv's/urem's expanded");
STATISTIC(NumZExt, "Number of non-negative deductions");
@@ -289,9 +286,6 @@ static bool processPHI(PHINode *P, LazyValueInfo *LVI, DominatorTree *DT,
}
static bool processICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
- if (!CanonicalizeICmpPredicatesToUnsigned)
- return false;
-
// Only for signed relational comparisons of scalar integers.
if (Cmp->getType()->isVectorTy() ||
!Cmp->getOperand(0)->getType()->isIntegerTy())
@@ -528,6 +522,7 @@ static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
}
// See if this min/max intrinsic always picks it's one specific operand.
+// If not, check whether we can canonicalize signed minmax into unsigned version
static bool processMinMaxIntrinsic(MinMaxIntrinsic *MM, LazyValueInfo *LVI) {
CmpInst::Predicate Pred = CmpInst::getNonStrictPredicate(MM->getPredicate());
ConstantRange LHS_CR = LVI->getConstantRangeAtUse(MM->getOperandUse(0),
@@ -546,6 +541,20 @@ static bool processMinMaxIntrinsic(MinMaxIntrinsic *MM, LazyValueInfo *LVI) {
MM->eraseFromParent();
return true;
}
+
+ if (MM->isSigned() &&
+ ConstantRange::areInsensitiveToSignednessOfICmpPredicate(LHS_CR,
+ RHS_CR)) {
+ ++NumSMinMax;
+ IRBuilder<> B(MM);
+ MM->replaceAllUsesWith(B.CreateBinaryIntrinsic(
+ MM->getIntrinsicID() == Intrinsic::smin ? Intrinsic::umin
+ : Intrinsic::umax,
+ MM->getLHS(), MM->getRHS()));
+ MM->eraseFromParent();
+ return true;
+ }
+
return false;
}
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
index d21b8f2418c2ee..c9ee233b5a4612 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/min-max.ll
@@ -176,8 +176,8 @@ define i8 @test15(i8 %x) {
; CHECK-LABEL: @test15(
; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41
; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 42)
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 42)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%lim = icmp sge i8 %x, 41
call void @llvm.assume(i1 %lim)
@@ -189,8 +189,8 @@ define i8 @test16(i8 %x) {
; CHECK-LABEL: @test16(
; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 41
; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 42)
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 42)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%lim = icmp sge i8 %x, 41
call void @llvm.assume(i1 %lim)
@@ -290,3 +290,68 @@ if.end:
%phi = phi i64 [%val, %bb1], [0, %entry]
ret i64 %phi
}
+
+define i8 @test_smax_to_umax_nneg(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_smax_to_umax_nneg(
+; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
+; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %nneg_a = and i8 %a, 127
+ %nneg_b = and i8 %b, 127
+ %ret = call i8 @llvm.smax.i8(i8 %nneg_a, i8 %nneg_b)
+ ret i8 %ret
+}
+
+define i8 @test_smax_to_umax_neg(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_smax_to_umax_neg(
+; CHECK-NEXT: [[NEG_A:%.*]] = or i8 [[A:%.*]], -128
+; CHECK-NEXT: [[NEG_B:%.*]] = or i8 [[B:%.*]], -128
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[NEG_A]], i8 [[NEG_B]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %neg_a = or i8 %a, 128
+ %neg_b = or i8 %b, 128
+ %ret = call i8 @llvm.smax.i8(i8 %neg_a, i8 %neg_b)
+ ret i8 %ret
+}
+
+define i8 @test_smin_to_umin_nneg(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_smin_to_umin_nneg(
+; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
+; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %nneg_a = and i8 %a, 127
+ %nneg_b = and i8 %b, 127
+ %ret = call i8 @llvm.smin.i8(i8 %nneg_a, i8 %nneg_b)
+ ret i8 %ret
+}
+
+define i8 @test_smin_to_umin_neg(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_smin_to_umin_neg(
+; CHECK-NEXT: [[NEG_A:%.*]] = or i8 [[A:%.*]], -128
+; CHECK-NEXT: [[NEG_B:%.*]] = or i8 [[B:%.*]], -128
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[NEG_A]], i8 [[NEG_B]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %neg_a = or i8 %a, 128
+ %neg_b = or i8 %b, 128
+ %ret = call i8 @llvm.smin.i8(i8 %neg_a, i8 %neg_b)
+ ret i8 %ret
+}
+
+define i8 @test_umax_nneg(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_umax_nneg(
+; CHECK-NEXT: [[NNEG_A:%.*]] = and i8 [[A:%.*]], 127
+; CHECK-NEXT: [[NNEG_B:%.*]] = and i8 [[B:%.*]], 127
+; CHECK-NEXT: [[RET:%.*]] = call i8 @llvm.umax.i8(i8 [[NNEG_A]], i8 [[NNEG_B]])
+; CHECK-NEXT: ret i8 [[RET]]
+;
+ %nneg_a = and i8 %a, 127
+ %nneg_b = and i8 %b, 127
+ %ret = call i8 @llvm.umax.i8(i8 %nneg_a, i8 %nneg_b)
+ ret i8 %ret
+}
More information about the llvm-commits
mailing list