[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