From: Sanjay Patel Date: Fri, 22 Jan 2021 18:33:21 +0000 (-0500) Subject: [InstCombine] narrow abs with sign-extended input X-Git-Tag: llvmorg-13-init~446 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=411c144e4c99f4d4370ed2b9c248dc6bb9a39648;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 7d63b30..5ba51d2 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 7e5eadf..7452798 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 baeb44d..1f5f1c2 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]], +; 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]], +; 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)