OSDN Git Service

[InstCombine] not(sub X, Y) --> add (not X), Y
authorSanjay Patel <spatel@rotateright.com>
Fri, 27 Jul 2018 10:54:48 +0000 (10:54 +0000)
committerSanjay Patel <spatel@rotateright.com>
Fri, 27 Jul 2018 10:54:48 +0000 (10:54 +0000)
The tests with constants show a missing optimization.
Analysis for adds is better than subs, so this can also
help with other transforms. And codegen is better with
adds for targets like x86 (destructive ops, no sub-from).

https://rise4fun.com/Alive/llK

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338118 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/Transforms/InstCombine/sub-not.ll
test/Transforms/InstCombine/vector-xor.ll

index d1922cc..372bc41 100644 (file)
@@ -2545,6 +2545,10 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
       }
     }
 
+    // ~(X - Y) --> ~X + Y
+    if (match(NotVal, m_OneUse(m_Sub(m_Value(X), m_Value(Y)))))
+      return BinaryOperator::CreateAdd(Builder.CreateNot(X), Y);
+
     // ~(~X >>s Y) --> (X >>s Y)
     if (match(NotVal, m_AShr(m_Not(m_Value(X)), m_Value(Y))))
       return BinaryOperator::CreateAShr(X, Y);
index ea7101b..5fc4236 100644 (file)
@@ -5,8 +5,8 @@ declare void @use(i8)
 
 define i8 @sub_not(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sub_not(
-; CHECK-NEXT:    [[S:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = xor i8 [[S]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = add i8 [[TMP1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %s = sub i8 %x, %y
@@ -29,8 +29,8 @@ define i8 @sub_not_extra_use(i8 %x, i8 %y) {
 
 define <2 x i8> @sub_not_vec(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @sub_not_vec(
-; CHECK-NEXT:    [[S:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = xor <2 x i8> [[S]], <i8 -1, i8 undef>
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[TMP1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %s = sub <2 x i8> %x, %y
index 80189e6..fc75a8c 100644 (file)
@@ -194,9 +194,8 @@ define <4 x i32> @test_v4i32_not_sub_splatconst(<4 x i32> %a0) {
 
 define <4 x i32> @test_v4i32_not_sub_const(<4 x i32> %a0) {
 ; CHECK-LABEL: @test_v4i32_not_sub_const(
-; CHECK-NEXT:    [[TMP1:%.*]] = sub <4 x i32> <i32 3, i32 5, i32 -1, i32 15>, [[A0:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], <i32 -1, i32 -1, i32 -1, i32 -1>
-; CHECK-NEXT:    ret <4 x i32> [[TMP2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[A0:%.*]], <i32 -4, i32 -6, i32 0, i32 -16>
+; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
 ;
   %1 = sub <4 x i32> <i32  3, i32  5, i32 -1, i32 15>, %a0
   %2 = xor <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, %1
@@ -205,9 +204,8 @@ define <4 x i32> @test_v4i32_not_sub_const(<4 x i32> %a0) {
 
 define <4 x i32> @test_v4i32_not_sub_const_undef(<4 x i32> %a0) {
 ; CHECK-LABEL: @test_v4i32_not_sub_const_undef(
-; CHECK-NEXT:    [[TMP1:%.*]] = sub <4 x i32> <i32 3, i32 undef, i32 -1, i32 15>, [[A0:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], <i32 -1, i32 -1, i32 -1, i32 undef>
-; CHECK-NEXT:    ret <4 x i32> [[TMP2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i32> [[A0:%.*]], <i32 -4, i32 undef, i32 0, i32 -16>
+; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
 ;
   %1 = sub <4 x i32> <i32  3, i32 undef, i32 -1, i32 15>, %a0
   %2 = xor <4 x i32> <i32 -1, i32 -1, i32 -1, i32 undef>, %1