From d07ba468a4335ac072085519831e896049c5e52c Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Wed, 3 Jul 2019 09:41:50 +0000 Subject: [PATCH] [InstCombine] Y - ~X --> X + Y + 1 fold (PR42457) Summary: I *think* we'd want this new variant, because we obviously have better handling for `add` as compared to `sub`/`not`. https://rise4fun.com/Alive/WMn Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=42457 | PR42457 ]] Reviewers: spatel, nikic, huihuiz, efriedma Reviewed By: spatel Subscribers: RKSimon, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63992 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365011 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 6 ++++++ .../InstCombine/fold-sub-of-not-to-inc-of-add.ll | 15 ++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 0b0cc4bc6e7..ba15b023f2a 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1580,6 +1580,12 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { if (match(Op1, m_OneUse(m_Add(m_Value(X), m_One())))) return BinaryOperator::CreateAdd(Builder.CreateNot(X), Op0); + // Y - ~X --> (X + 1) + Y + if (match(Op1, m_OneUse(m_Not(m_Value(X))))) { + return BinaryOperator::CreateAdd( + Builder.CreateAdd(Op0, ConstantInt::get(I.getType(), 1)), X); + } + if (Constant *C = dyn_cast(Op0)) { bool IsNegate = match(C, m_ZeroInt()); Value *X; diff --git a/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll b/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll index 1febe4bafab..cf9d051d125 100644 --- a/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll +++ b/test/Transforms/InstCombine/fold-sub-of-not-to-inc-of-add.ll @@ -4,7 +4,8 @@ ; Given: ; sub %y, (xor %x, -1) ; Transform it to: -; add (add %x, %y), 1 +; add (add %x, 1), %y +; We prefer this form because that is what -reassociate would produce. ;------------------------------------------------------------------------------; ; Scalar tests @@ -12,8 +13,8 @@ define i32 @p0_scalar(i32 %x, i32 %y) { ; CHECK-LABEL: @p0_scalar( -; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], -1 -; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], 1 +; CHECK-NEXT: [[T1:%.*]] = add i32 [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = xor i32 %x, -1 @@ -27,8 +28,8 @@ define i32 @p0_scalar(i32 %x, i32 %y) { define <4 x i32> @p1_vector_splat(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @p1_vector_splat( -; CHECK-NEXT: [[T0:%.*]] = xor <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[Y:%.*]], +; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = xor <4 x i32> %x, @@ -38,8 +39,8 @@ define <4 x i32> @p1_vector_splat(<4 x i32> %x, <4 x i32> %y) { define <4 x i32> @p2_vector_undef(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @p2_vector_undef( -; CHECK-NEXT: [[T0:%.*]] = xor <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> [[Y:%.*]], [[T0]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[Y:%.*]], +; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = xor <4 x i32> %x, -- 2.11.0