[PATCH] Added instruction combine to transform few more negative values addition to subtraction (Part 3)

Dinesh Dwivedi dinesh.d at samsung.com
Thu Jun 19 05:22:26 PDT 2014


Hi rafael, bkramer, jingyue, nicholas,

First Part: http://reviews.llvm.org/D3733
2nd Part: http://reviews.llvm.org/D4209

This patch enable following transform
  (x + (~(y | c) + 1)   -->   x - (y | c) if c is odd
  (x + (~((y >> z) | c) + 1)   -->   x - ((y>>z) | c)  if c is odd

Z3 verification code:
  http://rise4fun.com/Z3/ZA06

http://reviews.llvm.org/D4210

Files:
  lib/Transforms/InstCombine/InstCombineAddSub.cpp
  test/Transforms/InstCombine/add2.ll

Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -960,7 +960,7 @@
 // This function checks for following negative patterns
 //   ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
 //   TODO: ADD(XOR(AND(Z, ~C), ~C), 1) == NEG(OR(Z, C)) if C is even
-//   TODO: XOR(AND(Z, ~C), (~C + 1)) == NEG(OR(Z, C)) if C is odd
+//   XOR(AND(Z, ~C), (~C + 1)) == NEG(OR(Z, C)) if C is odd
 Value *checkForNegativeOperand(BinaryOperator &I,
                                InstCombiner::BuilderTy *Builder) {
   Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
@@ -995,6 +995,23 @@
     }
   }
 
+  // Restore LSH and RHS
+  LHS = I.getOperand(0);
+  RHS = I.getOperand(1);
+
+  // if XOR is on other side, swap
+  if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1))))
+    std::swap(LHS, RHS);
+
+  // C2 is ODD
+  // LHS = XOR(Y, C1), Y = AND(Z, C2), C1 == (C2 + 1) => LHS == NOT(AND(Z, ~C2))
+  // ADD(LHS, RHS) == SUB(RHS, AND(Z, ~C2))
+  if (match(LHS, m_Xor(m_Value(Y), m_APInt(C1))) && !C1->countTrailingZeros())
+    if (match(Y, m_And(m_Value(Z), m_APInt(C2))) && *C1 == (*C2 + 1)) {
+      Value *NewOr = Builder->CreateOr(Z, ~(*C2));
+      return Builder->CreateSub(RHS, NewOr, "", IHasNUW, IHasNSW);
+    }
+
   return nullptr;
 }
 
Index: test/Transforms/InstCombine/add2.ll
===================================================================
--- test/Transforms/InstCombine/add2.ll
+++ test/Transforms/InstCombine/add2.ll
@@ -150,6 +150,41 @@
 ; CHECK-NEXT: ret i32 [[SUB]]
 }
 
+define i32 @test15(i32 %x) {
+ %x.not = and i32 %x, -1431655766
+ %add3 = xor i32 %x.not, -1431655765
+ %add1 = add nsw i32 %add3, %x
+ ret i32 %add1
+; CHECK-LABEL: @test15(
+; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 1431655765
+; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub nsw i32 %x, [[OR]]
+; CHECK-NEXT: ret i32 [[SUB]]
+}
+
+define i32 @test16(i32 %x, i32 %y) {
+ %x.not = and i32 %x, -1431655766
+ %add2 = xor i32 %x.not, -1431655765
+ %add1 = add nsw i32 %add2, %y
+ ret i32 %add1
+; CHECK-LABEL: @test16(
+; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 1431655765
+; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub nsw i32 %y, [[OR]]
+; CHECK-NEXT: ret i32 [[SUB]]
+}
+
+define i32 @test17(i32 %x, i32 %y) {
+ %shr = ashr i32 %x, 3
+ %shr.not = and i32 %shr, -1431655766
+ %add2 = xor i32 %shr.not, -1431655765
+ %add1 = add nsw i32 %add2, %y
+ ret i32 %add1
+; CHECK-LABEL: @test17(
+; CHECK-NEXT: [[SHR:%[a-z0-9]+]] = ashr i32 %x, 3
+; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 [[SHR]], 1431655765
+; CHECK-NEXT: [[SUB:%[a-z0-9]+]] = sub nsw i32 %y, [[OR]]
+; CHECK-NEXT: ret i32 [[SUB]]
+}
+
 define i16 @add_nsw_mul_nsw(i16 %x) {
  %add1 = add nsw i16 %x, %x
  %add2 = add nsw i16 %add1, %x
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4210.10629.patch
Type: text/x-patch
Size: 2849 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140619/630df442/attachment.bin>


More information about the llvm-commits mailing list