[llvm] 5094e12 - [InstCombine] fold min/max intrinsic with negated operand to abs
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 8 11:47:28 PDT 2021
Author: Sanjay Patel
Date: 2021-04-08T14:37:39-04:00
New Revision: 5094e1279eb2e168bf6818b368bf6ff4835de2bc
URL: https://github.com/llvm/llvm-project/commit/5094e1279eb2e168bf6818b368bf6ff4835de2bc
DIFF: https://github.com/llvm/llvm-project/commit/5094e1279eb2e168bf6818b368bf6ff4835de2bc.diff
LOG: [InstCombine] fold min/max intrinsic with negated operand to abs
The smax case shows up in https://llvm.org/PR49885 .
The others seem unlikely, but we might as well try
for uniformity (although that could mean an extra
instruction to create "nabs").
smax -- https://alive2.llvm.org/ce/z/8yYaGy
smin -- https://alive2.llvm.org/ce/z/0_7zc_
umax -- https://alive2.llvm.org/ce/z/EcsZWs
umin -- https://alive2.llvm.org/ce/z/Xw6WvB
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 4d9005840b4b6..b139960b478e6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -911,6 +911,22 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
}
+ // smax(X, -X) --> abs(X)
+ // smin(X, -X) --> -abs(X)
+ // umax(X, -X) --> -abs(X)
+ // umin(X, -X) --> abs(X)
+ if (isKnownNegation(I0, I1)) {
+ // This is some variant of abs(). See if we can propagate 'nsw' to the abs
+ // operation and potentially its negation.
+ bool IntMinIsPoison = isKnownNegation(I0, I1, /* NeedNSW */ true);
+ Value *Abs = Builder.CreateBinaryIntrinsic(
+ Intrinsic::abs, I0,
+ ConstantInt::getBool(II->getContext(), IntMinIsPoison));
+ if (IID == Intrinsic::smin || IID == Intrinsic::umax)
+ Abs = Builder.CreateNeg(Abs, "nabs", /* NUW */ false, IntMinIsPoison);
+ return replaceInstUsesWith(CI, Abs);
+ }
+
break;
}
case Intrinsic::bswap: {
diff --git a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
index 5d3064fb94e0c..3d6d3e333b2bf 100644
--- a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
@@ -611,9 +611,8 @@ define i8 @not_umin_of_not_constant_op(i8 %x) {
define i8 @smax_negation(i8 %x, i8 %y) {
; CHECK-LABEL: @smax_negation(
; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = sub i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%s1 = sub i8 %x, %y
%s2 = sub i8 %y, %x
@@ -624,9 +623,8 @@ define i8 @smax_negation(i8 %x, i8 %y) {
define i8 @smax_negation_nsw(i8 %x, i8 %y) {
; CHECK-LABEL: @smax_negation_nsw(
; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%s1 = sub nsw i8 %x, %y
%s2 = sub nsw i8 %y, %x
@@ -637,9 +635,8 @@ define i8 @smax_negation_nsw(i8 %x, i8 %y) {
define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
; CHECK-LABEL: @smax_negation_not_nsw(
; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = sub nuw i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[S1]], i8 [[S2]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%s1 = sub nsw i8 %x, %y
%s2 = sub nuw i8 %y, %x
@@ -649,9 +646,8 @@ define i8 @smax_negation_not_nsw(i8 %x, i8 %y) {
define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
; CHECK-LABEL: @smax_negation_vec(
-; CHECK-NEXT: [[S:%.*]] = sub <3 x i8> <i8 0, i8 undef, i8 0>, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call <3 x i8> @llvm.smax.v3i8(<3 x i8> [[X]], <3 x i8> [[S]])
-; CHECK-NEXT: ret <3 x i8> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.abs.v3i8(<3 x i8> [[X:%.*]], i1 false)
+; CHECK-NEXT: ret <3 x i8> [[TMP1]]
;
%s = sub <3 x i8> <i8 0, i8 undef, i8 0>, %x
%r = call <3 x i8> @llvm.smax.v3i8(<3 x i8> %x, <3 x i8> %s)
@@ -661,9 +657,9 @@ define <3 x i8> @smax_negation_vec(<3 x i8> %x) {
define i8 @smin_negation(i8 %x, i8 %y) {
; CHECK-LABEL: @smin_negation(
; CHECK-NEXT: [[S1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = sub i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[S1]], i8 [[S2]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 false)
+; CHECK-NEXT: [[NABS:%.*]] = sub i8 0, [[TMP1]]
+; CHECK-NEXT: ret i8 [[NABS]]
;
%s1 = sub i8 %x, %y
%s2 = sub i8 %y, %x
@@ -674,9 +670,9 @@ define i8 @smin_negation(i8 %x, i8 %y) {
define i8 @umax_negation(i8 %x, i8 %y) {
; CHECK-LABEL: @umax_negation(
; CHECK-NEXT: [[S1:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[S2:%.*]] = sub nsw i8 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[S1]], i8 [[S2]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[S1]], i1 true)
+; CHECK-NEXT: [[NABS:%.*]] = sub nsw i8 0, [[TMP1]]
+; CHECK-NEXT: ret i8 [[NABS]]
;
%s1 = sub nsw i8 %x, %y
%s2 = sub nsw i8 %y, %x
@@ -686,9 +682,8 @@ define i8 @umax_negation(i8 %x, i8 %y) {
define i8 @umin_negation(i8 %x) {
; CHECK-LABEL: @umin_negation(
-; CHECK-NEXT: [[S:%.*]] = sub nsw i8 0, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[S]], i8 [[X]])
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%s = sub nsw i8 0, %x
%r = call i8 @llvm.umin.i8(i8 %s, i8 %x)
More information about the llvm-commits
mailing list