From 0cf1e1c3185d21b217529037b90d8a008e1c3b63 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 10 May 2017 13:56:52 +0000 Subject: [PATCH] [InstCombine] add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1 This is another step towards favoring 'not' ops over random 'xor' in IR: https://bugs.llvm.org/show_bug.cgi?id=32706 This transformation may have occurred in longer IR sequences using computeKnownBits, but that could be much more expensive to calculate. As the scalar result shows, we do not currently favor 'not' in all cases. The 'not' created by the transform is transformed again (unnecessarily). Vectors don't have this problem because vectors are (wrongly) excluded from several other combines. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302659 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 10 ++++++++++ test/Transforms/InstCombine/add.ll | 10 ++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 659b6c326c5..3709360226f 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1079,6 +1079,16 @@ static Instruction *foldAddWithConstant(BinaryOperator &Add, return new ZExtInst(Builder.CreateNUWAdd(X, NewC), Ty); } + // Shifts and add used to flip and mask off the low bit: + // add (ashr (shl i32 X, 31), 31), 1 --> and (not X), 1 + const APInt *C3; + if (*C == 1 && match(Op0, m_OneUse(m_AShr(m_Shl(m_Value(X), m_APInt(C2)), + m_APInt(C3)))) && + C2 == C3 && *C2 == Ty->getScalarSizeInBits() - 1) { + Value *NotX = Builder.CreateNot(X); + return BinaryOperator::CreateAnd(NotX, ConstantInt::get(Ty, 1)); + } + return nullptr; } diff --git a/test/Transforms/InstCombine/add.ll b/test/Transforms/InstCombine/add.ll index 955ffaaeecd..5f7101e8fec 100644 --- a/test/Transforms/InstCombine/add.ll +++ b/test/Transforms/InstCombine/add.ll @@ -31,9 +31,8 @@ define <2 x i32> @select_0_or_1_from_bool_vec(<2 x i1> %x) { define i32 @flip_and_mask(i32 %x) { ; CHECK-LABEL: @flip_and_mask( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 %x, 31 -; CHECK-NEXT: [[SHR:%.*]] = ashr exact i32 [[SHL]], 31 -; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[SHR]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 %x, 1 +; CHECK-NEXT: [[INC:%.*]] = xor i32 [[TMP1]], 1 ; CHECK-NEXT: ret i32 [[INC]] ; %shl = shl i32 %x, 31 @@ -44,9 +43,8 @@ define i32 @flip_and_mask(i32 %x) { define <2 x i8> @flip_and_mask_splat(<2 x i8> %x) { ; CHECK-LABEL: @flip_and_mask_splat( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> %x, -; CHECK-NEXT: [[SHR:%.*]] = ashr exact <2 x i8> [[SHL]], -; CHECK-NEXT: [[INC:%.*]] = add nsw <2 x i8> [[SHR]], +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> %x, +; CHECK-NEXT: [[INC:%.*]] = and <2 x i8> [[TMP1]], ; CHECK-NEXT: ret <2 x i8> [[INC]] ; %shl = shl <2 x i8> %x, -- 2.11.0