1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[InstCombine] fold add(zext(xor X, C), C) --> sext X when C is INT_MIN in the source type

The pattern may look more obviously like a sext if written as:

  define i32 @g(i16 %x) {
    %zext = zext i16 %x to i32
    %xor = xor i32 %zext, 32768
    %add = add i32 %xor, -32768
    ret i32 %add
  }

We already have that fold in visitAdd().

Differential Revision: https://reviews.llvm.org/D22477

llvm-svn: 276035
This commit is contained in:
Sanjay Patel 2016-07-19 22:09:34 +00:00
parent 9f13bab8bf
commit 563fa4255c
2 changed files with 33 additions and 6 deletions

View File

@ -1047,6 +1047,16 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
// X + (signbit) --> X ^ signbit // X + (signbit) --> X ^ signbit
if (Val->isSignBit()) if (Val->isSignBit())
return BinaryOperator::CreateXor(LHS, RHS); return BinaryOperator::CreateXor(LHS, RHS);
// Is this add the last step in a convoluted sext?
Value *X;
const APInt *C;
if (match(LHS, m_ZExt(m_Xor(m_Value(X), m_APInt(C)))) &&
C->isMinSignedValue() &&
C->sext(LHS->getType()->getScalarSizeInBits()) == *Val) {
// add(zext(xor i16 X, -32768), -32768) --> sext X
return CastInst::Create(Instruction::SExt, X, LHS->getType());
}
} }
// FIXME: Use the match above instead of dyn_cast to allow these transforms // FIXME: Use the match above instead of dyn_cast to allow these transforms

View File

@ -56,9 +56,7 @@ define i49 @test4(i49 %x) {
define i7 @sext(i4 %x) { define i7 @sext(i4 %x) {
; CHECK-LABEL: @sext( ; CHECK-LABEL: @sext(
; CHECK-NEXT: [[XOR:%.*]] = xor i4 %x, -8 ; CHECK-NEXT: [[ADD:%.*]] = sext i4 %x to i7
; CHECK-NEXT: [[ZEXT:%.*]] = zext i4 [[XOR]] to i7
; CHECK-NEXT: [[ADD:%.*]] = add nsw i7 [[ZEXT]], -8
; CHECK-NEXT: ret i7 [[ADD]] ; CHECK-NEXT: ret i7 [[ADD]]
; ;
%xor = xor i4 %x, -8 %xor = xor i4 %x, -8
@ -69,9 +67,7 @@ define i7 @sext(i4 %x) {
define <2 x i10> @sext_vec(<2 x i3> %x) { define <2 x i10> @sext_vec(<2 x i3> %x) {
; CHECK-LABEL: @sext_vec( ; CHECK-LABEL: @sext_vec(
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i3> %x, <i3 -4, i3 -4> ; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i3> %x to <2 x i10>
; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i3> [[XOR]] to <2 x i10>
; CHECK-NEXT: [[ADD:%.*]] = add nsw <2 x i10> [[ZEXT]], <i10 -4, i10 -4>
; CHECK-NEXT: ret <2 x i10> [[ADD]] ; CHECK-NEXT: ret <2 x i10> [[ADD]]
; ;
%xor = xor <2 x i3> %x, <i3 -4, i3 -4> %xor = xor <2 x i3> %x, <i3 -4, i3 -4>
@ -80,6 +76,27 @@ define <2 x i10> @sext_vec(<2 x i3> %x) {
ret <2 x i10> %add ret <2 x i10> %add
} }
; Multiple uses of the operands don't prevent the fold.
define i4 @sext_multiuse(i4 %x) {
; CHECK-LABEL: @sext_multiuse(
; CHECK-NEXT: [[XOR:%.*]] = xor i4 %x, -8
; CHECK-NEXT: [[ZEXT:%.*]] = zext i4 [[XOR]] to i7
; CHECK-NEXT: [[ADD:%.*]] = sext i4 %x to i7
; CHECK-NEXT: [[MUL:%.*]] = sdiv i7 [[ZEXT]], [[ADD]]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i7 [[MUL]] to i4
; CHECK-NEXT: [[DIV:%.*]] = sdiv i4 [[TRUNC]], [[XOR]]
; CHECK-NEXT: ret i4 [[DIV]]
;
%xor = xor i4 %x, -8
%zext = zext i4 %xor to i7
%add = add nsw i7 %zext, -8
%mul = sdiv i7 %zext, %add
%trunc = trunc i7 %mul to i4
%div = sdiv i4 %trunc, %xor
ret i4 %div
}
; Tests for Integer BitWidth > 64 && BitWidth <= 1024. ; Tests for Integer BitWidth > 64 && BitWidth <= 1024.
;; Flip sign bit then add INT_MIN -> nop. ;; Flip sign bit then add INT_MIN -> nop.