[llvm] 411c144 - [InstCombine] narrow abs with sign-extended input
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 22 10:44:36 PST 2021
Author: Sanjay Patel
Date: 2021-01-22T13:36:04-05:00
New Revision: 411c144e4c99f4d4370ed2b9c248dc6bb9a39648
URL: https://github.com/llvm/llvm-project/commit/411c144e4c99f4d4370ed2b9c248dc6bb9a39648
DIFF: https://github.com/llvm/llvm-project/commit/411c144e4c99f4d4370ed2b9c248dc6bb9a39648.diff
LOG: [InstCombine] narrow abs with sign-extended input
In the motivating cases from https://llvm.org/PR48816 ,
we have a trailing trunc. But that is not required to
reduce the abs width:
https://alive2.llvm.org/ce/z/ECaz-p
...as long as we clear the int-min-is-poison bit (nsw).
We have some existing tests that are affected, and I'm
not sure what the overall implications are, but in general
we favor narrowing operations over preserving nsw/nuw.
If that causes problems, we could restrict this transform
based on type (shouldChangeType() and/or vector vs. scalar).
Differential Revision: https://reviews.llvm.org/D95235
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/abs-1.ll
llvm/test/Transforms/InstCombine/abs-intrinsic.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7d63b30d35f8..5ba51d255109 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -820,6 +820,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
return BinaryOperator::CreateNeg(IIOperand);
}
+ // abs (sext X) --> zext (abs X*)
+ // Clear the IsIntMin (nsw) bit on the abs to allow narrowing.
+ if (match(IIOperand, m_OneUse(m_SExt(m_Value(X))))) {
+ Value *NarrowAbs =
+ Builder.CreateBinaryIntrinsic(Intrinsic::abs, X, Builder.getFalse());
+ return CastInst::Create(Instruction::ZExt, NarrowAbs, II->getType());
+ }
+
break;
}
case Intrinsic::bswap: {
diff --git a/llvm/test/Transforms/InstCombine/abs-1.ll b/llvm/test/Transforms/InstCombine/abs-1.ll
index 7e5eadf5b25e..7452798ead77 100644
--- a/llvm/test/Transforms/InstCombine/abs-1.ll
+++ b/llvm/test/Transforms/InstCombine/abs-1.ll
@@ -102,9 +102,9 @@ define i8 @abs_canonical_4(i8 %x) {
define i32 @abs_canonical_5(i8 %x) {
; CHECK-LABEL: @abs_canonical_5(
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[CONV]], i1 true)
-; CHECK-NEXT: ret i32 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[TMP2]]
;
%cmp = icmp sgt i8 %x, 0
%conv = sext i8 %x to i32
@@ -250,9 +250,9 @@ define i8 @nabs_canonical_4(i8 %x) {
define i32 @nabs_canonical_5(i8 %x) {
; CHECK-LABEL: @nabs_canonical_5(
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[CONV]], i1 false)
-; CHECK-NEXT: [[ABS:%.*]] = sub nsw i32 0, [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT: [[ABS:%.*]] = sub nsw i32 0, [[TMP2]]
; CHECK-NEXT: ret i32 [[ABS]]
;
%cmp = icmp sgt i8 %x, 0
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index baeb44d1d8dc..1f5f1c2ba562 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -64,9 +64,9 @@ define <4 x i32> @abs_trailing_zeros_negative_vec(<4 x i32> %x) {
; sign bits, the abs reduces this to 2 sign bits.
define i32 @abs_signbits(i30 %x) {
; CHECK-LABEL: @abs_signbits(
-; CHECK-NEXT: [[EXT:%.*]] = sext i30 [[X:%.*]] to i32
-; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[EXT]], i1 false)
-; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[ABS]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = call i30 @llvm.abs.i30(i30 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[NARROW:%.*]] = add nuw i30 [[TMP1]], 1
+; CHECK-NEXT: [[ADD:%.*]] = zext i30 [[NARROW]] to i32
; CHECK-NEXT: ret i32 [[ADD]]
;
%ext = sext i30 %x to i32
@@ -77,9 +77,9 @@ define i32 @abs_signbits(i30 %x) {
define <4 x i32> @abs_signbits_vec(<4 x i30> %x) {
; CHECK-LABEL: @abs_signbits_vec(
-; CHECK-NEXT: [[EXT:%.*]] = sext <4 x i30> [[X:%.*]] to <4 x i32>
-; CHECK-NEXT: [[ABS:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[EXT]], i1 false)
-; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <4 x i32> [[ABS]], <i32 1, i32 1, i32 1, i32 1>
+; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i30> @llvm.abs.v4i30(<4 x i30> [[X:%.*]], i1 false)
+; CHECK-NEXT: [[NARROW:%.*]] = add nuw <4 x i30> [[TMP1]], <i30 1, i30 1, i30 1, i30 1>
+; CHECK-NEXT: [[ADD:%.*]] = zext <4 x i30> [[NARROW]] to <4 x i32>
; CHECK-NEXT: ret <4 x i32> [[ADD]]
;
%ext = sext <4 x i30> %x to <4 x i32>
@@ -295,8 +295,8 @@ define i1 @abs_ne_int_min_nopoison(i8 %x) {
define i32 @abs_sext(i8 %x) {
; CHECK-LABEL: @abs_sext(
-; CHECK-NEXT: [[S:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[S]], i1 false)
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[A:%.*]] = zext i8 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[A]]
;
%s = sext i8 %x to i32
@@ -306,8 +306,8 @@ define i32 @abs_sext(i8 %x) {
define <3 x i82> @abs_nsw_sext(<3 x i7> %x) {
; CHECK-LABEL: @abs_nsw_sext(
-; CHECK-NEXT: [[S:%.*]] = sext <3 x i7> [[X:%.*]] to <3 x i82>
-; CHECK-NEXT: [[A:%.*]] = call <3 x i82> @llvm.abs.v3i82(<3 x i82> [[S]], i1 true)
+; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i7> @llvm.abs.v3i7(<3 x i7> [[X:%.*]], i1 false)
+; CHECK-NEXT: [[A:%.*]] = zext <3 x i7> [[TMP1]] to <3 x i82>
; CHECK-NEXT: ret <3 x i82> [[A]]
;
%s = sext <3 x i7> %x to <3 x i82>
@@ -332,10 +332,8 @@ define i32 @abs_sext_extra_use(i8 %x, i32* %p) {
define i8 @trunc_abs_sext(i8 %x) {
; CHECK-LABEL: @trunc_abs_sext(
-; CHECK-NEXT: [[S:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[A:%.*]] = tail call i32 @llvm.abs.i32(i32 [[S]], i1 true)
-; CHECK-NEXT: [[T:%.*]] = trunc i32 [[A]] to i8
-; CHECK-NEXT: ret i8 [[T]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false)
+; CHECK-NEXT: ret i8 [[TMP1]]
;
%s = sext i8 %x to i32
%a = tail call i32 @llvm.abs.i32(i32 %s, i1 true)
@@ -345,10 +343,8 @@ define i8 @trunc_abs_sext(i8 %x) {
define <4 x i8> @trunc_abs_sext_vec(<4 x i8> %x) {
; CHECK-LABEL: @trunc_abs_sext_vec(
-; CHECK-NEXT: [[S:%.*]] = sext <4 x i8> [[X:%.*]] to <4 x i32>
-; CHECK-NEXT: [[A:%.*]] = tail call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[S]], i1 true)
-; CHECK-NEXT: [[T:%.*]] = trunc <4 x i32> [[A]] to <4 x i8>
-; CHECK-NEXT: ret <4 x i8> [[T]]
+; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.abs.v4i8(<4 x i8> [[X:%.*]], i1 false)
+; CHECK-NEXT: ret <4 x i8> [[TMP1]]
;
%s = sext <4 x i8> %x to <4 x i32>
%a = tail call <4 x i32> @llvm.abs.v4i32(<4 x i32> %s, i1 true)
More information about the llvm-commits
mailing list