[llvm] r360185 - [InstCombine] Add new combine to add folding

Robert Lougher via llvm-commits llvm-commits at lists.llvm.org
Tue May 7 12:36:41 PDT 2019


Author: rlougher
Date: Tue May  7 12:36:41 2019
New Revision: 360185

URL: http://llvm.org/viewvc/llvm-project?rev=360185&view=rev
Log:
[InstCombine] Add new combine to add folding

(X | C1) + C2 --> (X | C1) ^ C1 iff (C1 == -C2)

I verified the correctness using Alive:
https://rise4fun.com/Alive/YNV

This transform enables the following transform that already exists in
instcombine:

(X | Y) ^ Y --> X & ~Y

As a result, the full expected transform is:

(X | C1) + C2 --> X & ~C1 iff (C1 == -C2)

There already exists the transform in the sub case:

(X | Y) - Y --> X & ~Y

However this does not trigger in the case where Y is constant due to an earlier
transform:

X - (-C) --> X + C

With this new add fold, both the add and sub constant cases are handled.

Patch by Chris Dawson.

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

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
    llvm/trunk/test/Transforms/InstCombine/add.ll
    llvm/trunk/test/Transforms/InstCombine/sub.ll
    llvm/trunk/test/Transforms/InstCombine/with_overflow.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=360185&r1=360184&r2=360185&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Tue May  7 12:36:41 2019
@@ -892,6 +892,11 @@ Instruction *InstCombiner::foldAddWithCo
   if (!match(Op1, m_APInt(C)))
     return nullptr;
 
+  // (X | C2) + C --> (X | C2) ^ C2 iff (C2 == -C)
+  const APInt *C2;
+  if (match(Op0, m_Or(m_Value(), m_APInt(C2))) && *C2 == -*C)
+    return BinaryOperator::CreateXor(Op0, ConstantInt::get(Add.getType(), *C2));
+
   if (C->isSignMask()) {
     // If wrapping is not allowed, then the addition must set the sign bit:
     // X + (signmask) --> X | signmask
@@ -906,7 +911,6 @@ Instruction *InstCombiner::foldAddWithCo
   // Is this add the last step in a convoluted sext?
   // add(zext(xor i16 X, -32768), -32768) --> sext X
   Type *Ty = Add.getType();
-  const APInt *C2;
   if (match(Op0, m_ZExt(m_Xor(m_Value(X), m_APInt(C2)))) &&
       C2->isMinSignedValue() && C2->sext(Ty->getScalarSizeInBits()) == *C)
     return CastInst::Create(Instruction::SExt, X, Ty);

Modified: llvm/trunk/test/Transforms/InstCombine/add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/add.ll?rev=360185&r1=360184&r2=360185&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/add.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/add.ll Tue May  7 12:36:41 2019
@@ -982,9 +982,8 @@ define i32 @add_to_sub2(i32 %A, i32 %M)
 ; (X | C1) + C2 --> (X | C1) ^ C1 iff (C1 == -C2)
 define i32 @test44(i32 %A) {
 ; CHECK-LABEL: @test44(
-; CHECK-NEXT:    [[B:%.*]] = or i32 [[A:%.*]], 123
-; CHECK-NEXT:    [[C:%.*]] = add nsw i32 [[B]], -123
-; CHECK-NEXT:    ret i32 [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], -124
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %B = or i32 %A, 123
   %C = add i32 %B, -123
@@ -994,8 +993,8 @@ define i32 @test44(i32 %A) {
 define i32 @test44_extra_use(i32 %A) {
 ; CHECK-LABEL: @test44_extra_use(
 ; CHECK-NEXT:    [[B:%.*]] = or i32 [[A:%.*]], 123
-; CHECK-NEXT:    [[C:%.*]] = add nsw i32 [[B]], -123
-; CHECK-NEXT:    [[D:%.*]] = mul i32 [[B]], [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A]], -124
+; CHECK-NEXT:    [[D:%.*]] = mul i32 [[B]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[D]]
 ;
   %B = or i32 %A, 123
@@ -1017,9 +1016,8 @@ define i32 @test44_non_matching(i32 %A)
 
 define <2 x i32> @test44_vec(<2 x i32> %A) {
 ; CHECK-LABEL: @test44_vec(
-; CHECK-NEXT:    [[B:%.*]] = or <2 x i32> [[A:%.*]], <i32 123, i32 123>
-; CHECK-NEXT:    [[C:%.*]] = add nsw <2 x i32> [[B]], <i32 -123, i32 -123>
-; CHECK-NEXT:    ret <2 x i32> [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], <i32 -124, i32 -124>
+; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
 ;
   %B = or <2 x i32> %A, <i32 123, i32 123>
   %C = add <2 x i32> %B, <i32 -123, i32 -123>

Modified: llvm/trunk/test/Transforms/InstCombine/sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=360185&r1=360184&r2=360185&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/sub.ll Tue May  7 12:36:41 2019
@@ -1270,9 +1270,8 @@ define <2 x i32> @test69(<2 x i32> %x) {
 ; Check (X | Y) - Y --> X & ~Y when Y is a constant
 define i32 @test70(i32 %A) {
 ; CHECK-LABEL: @test70(
-; CHECK-NEXT:    [[B:%.*]] = or i32 [[A:%.*]], 123
-; CHECK-NEXT:    [[C:%.*]] = add nsw i32 [[B]], -123
-; CHECK-NEXT:    ret i32 [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], -124
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %B = or i32 %A, 123
   %C = sub i32 %B, 123

Modified: llvm/trunk/test/Transforms/InstCombine/with_overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/with_overflow.ll?rev=360185&r1=360184&r2=360185&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/with_overflow.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/with_overflow.ll Tue May  7 12:36:41 2019
@@ -531,10 +531,9 @@ define { i32, i1 } @umul_canonicalize_co
 
 define { i8, i1 } @uadd_always_overflow(i8 %x) nounwind {
 ; CHECK-LABEL: @uadd_always_overflow(
-; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], -64
-; CHECK-NEXT:    [[A:%.*]] = add nsw i8 [[Y]], 64
-; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 undef, i1 true }, i8 [[A]], 0
-; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], 63
+; CHECK-NEXT:    [[TMP2:%.*]] = insertvalue { i8, i1 } { i8 undef, i1 true }, i8 [[TMP1]], 0
+; CHECK-NEXT:    ret { i8, i1 } [[TMP2]]
 ;
   %y = or i8 %x, 192
   %a = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %y, i8 64)




More information about the llvm-commits mailing list