[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.

llvm-svn: 302659
This commit is contained in:
Sanjay Patel 2017-05-10 13:56:52 +00:00
parent b7fb267ed3
commit 2e069f250a
2 changed files with 14 additions and 6 deletions

View File

@ -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;
}

View File

@ -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, <i8 7, i8 7>
; CHECK-NEXT: [[SHR:%.*]] = ashr exact <2 x i8> [[SHL]], <i8 7, i8 7>
; CHECK-NEXT: [[INC:%.*]] = add nsw <2 x i8> [[SHR]], <i8 1, i8 1>
; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> %x, <i8 1, i8 1>
; CHECK-NEXT: [[INC:%.*]] = and <2 x i8> [[TMP1]], <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[INC]]
;
%shl = shl <2 x i8> %x, <i8 7, i8 7>