[llvm] 0ce2920 - [InstCombine] try to narrow min/max intrinsics with constant operand
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 1 10:55:20 PST 2021
Author: Sanjay Patel
Date: 2021-02-01T13:44:13-05:00
New Revision: 0ce2920f1707266c0d94dacc8719251b7b6a2c01
URL: https://github.com/llvm/llvm-project/commit/0ce2920f1707266c0d94dacc8719251b7b6a2c01
DIFF: https://github.com/llvm/llvm-project/commit/0ce2920f1707266c0d94dacc8719251b7b6a2c01.diff
LOG: [InstCombine] try to narrow min/max intrinsics with constant operand
The constant trunc/ext may not be the optimal pre-condition,
but I think that handles the common cases.
Example of Alive2 proof:
https://alive2.llvm.org/ce/z/sREeLC
This is another step towards canonicalizing to the intrinsics.
Narrowing was identified as source of potential regression for
abs(), so we need to handle this for min/max - see:
https://llvm.org/PR48816
If this is not enough, we could process intrinsics in
the trunc-driven matching in canEvaluateTruncated().
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 5482b944e347..6c87dcaa2985 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -839,6 +839,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
}
+ Constant *C;
+ if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_Constant(C)) &&
+ I0->hasOneUse()) {
+ Constant *NarrowC = ConstantExpr::getTrunc(C, X->getType());
+ if (ConstantExpr::getZExt(NarrowC, II->getType()) == C) {
+ Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC);
+ return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
+ }
+ }
// If both operands of unsigned min/max are sign-extended, it is still ok
// to narrow the operation.
LLVM_FALLTHROUGH;
@@ -852,6 +861,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType());
}
+ Constant *C;
+ if (match(I0, m_SExt(m_Value(X))) && match(I1, m_Constant(C)) &&
+ I0->hasOneUse()) {
+ Constant *NarrowC = ConstantExpr::getTrunc(C, X->getType());
+ if (ConstantExpr::getSExt(NarrowC, II->getType()) == C) {
+ Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC);
+ return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType());
+ }
+ }
break;
}
case Intrinsic::bswap: {
diff --git a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
index ecfcd0f267c1..4e3987f4640c 100644
--- a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
@@ -213,8 +213,8 @@ define i8 @umin_zext_uses(i5 %x, i5 %y) {
define i8 @smax_sext_constant(i5 %x) {
; CHECK-LABEL: @smax_sext_constant(
-; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
+; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[M]]
;
%e = sext i5 %x to i8
@@ -222,6 +222,8 @@ define i8 @smax_sext_constant(i5 %x) {
ret i8 %m
}
+; simplifies
+
define i8 @smax_sext_constant_big(i5 %x) {
; CHECK-LABEL: @smax_sext_constant_big(
; CHECK-NEXT: ret i8 16
@@ -231,6 +233,8 @@ define i8 @smax_sext_constant_big(i5 %x) {
ret i8 %m
}
+; negative test
+
define i8 @smax_zext_constant(i5 %x) {
; CHECK-LABEL: @smax_zext_constant(
; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -244,8 +248,8 @@ define i8 @smax_zext_constant(i5 %x) {
define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
; CHECK-LABEL: @smin_sext_constant(
-; CHECK-NEXT: [[E:%.*]] = sext <3 x i5> [[X:%.*]] to <3 x i8>
-; CHECK-NEXT: [[M:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[E]], <3 x i8> <i8 7, i8 15, i8 -16>)
+; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
+; CHECK-NEXT: [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
; CHECK-NEXT: ret <3 x i8> [[M]]
;
%e = sext <3 x i5> %x to <3 x i8>
@@ -253,6 +257,8 @@ define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
ret <3 x i8> %m
}
+; negative test
+
define i8 @smin_zext_constant(i5 %x) {
; CHECK-LABEL: @smin_zext_constant(
; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -266,8 +272,8 @@ define i8 @smin_zext_constant(i5 %x) {
define i8 @umax_sext_constant(i5 %x) {
; CHECK-LABEL: @umax_sext_constant(
-; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 7)
+; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT: [[M:%.*]] = sext i5 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[M]]
;
%e = sext i5 %x to i8
@@ -275,6 +281,8 @@ define i8 @umax_sext_constant(i5 %x) {
ret i8 %m
}
+; negative test
+
define i8 @umax_sext_constant_big(i5 %x) {
; CHECK-LABEL: @umax_sext_constant_big(
; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
@@ -288,8 +296,8 @@ define i8 @umax_sext_constant_big(i5 %x) {
define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
; CHECK-LABEL: @umax_zext_constant(
-; CHECK-NEXT: [[E:%.*]] = zext <3 x i5> [[X:%.*]] to <3 x i8>
-; CHECK-NEXT: [[M:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[E]], <3 x i8> <i8 7, i8 15, i8 31>)
+; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
+; CHECK-NEXT: [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
; CHECK-NEXT: ret <3 x i8> [[M]]
;
%e = zext <3 x i5> %x to <3 x i8>
@@ -297,6 +305,8 @@ define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
ret <3 x i8> %m
}
+; simplifies
+
define i8 @umax_zext_constant_big(i5 %x) {
; CHECK-LABEL: @umax_zext_constant_big(
; CHECK-NEXT: ret i8 126
@@ -308,8 +318,8 @@ define i8 @umax_zext_constant_big(i5 %x) {
define i8 @umin_sext_constant(i5 %x) {
; CHECK-LABEL: @umin_sext_constant(
-; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
+; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[M]]
;
%e = sext i5 %x to i8
@@ -317,6 +327,8 @@ define i8 @umin_sext_constant(i5 %x) {
ret i8 %m
}
+; negative test
+
define i8 @umin_sext_constant_big(i5 %x) {
; CHECK-LABEL: @umin_sext_constant_big(
; CHECK-NEXT: [[E:%.*]] = sext i5 [[X:%.*]] to i8
@@ -330,8 +342,8 @@ define i8 @umin_sext_constant_big(i5 %x) {
define i8 @umin_zext_constant(i5 %x) {
; CHECK-LABEL: @umin_zext_constant(
-; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
-; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
+; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT: [[M:%.*]] = zext i5 [[TMP1]] to i8
; CHECK-NEXT: ret i8 [[M]]
;
%e = zext i5 %x to i8
@@ -339,6 +351,8 @@ define i8 @umin_zext_constant(i5 %x) {
ret i8 %m
}
+; simplifies
+
define i8 @umin_zext_constant_big(i5 %x) {
; CHECK-LABEL: @umin_zext_constant_big(
; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -349,6 +363,8 @@ define i8 @umin_zext_constant_big(i5 %x) {
ret i8 %m
}
+; negative test
+
define i8 @umin_zext_constanti_uses(i5 %x) {
; CHECK-LABEL: @umin_zext_constanti_uses(
; CHECK-NEXT: [[E:%.*]] = zext i5 [[X:%.*]] to i8
More information about the llvm-commits
mailing list