From 78e4b4d3c442a8ee97f2488a7ec690146a42c6ac Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 27 Jul 2018 10:54:48 +0000 Subject: [PATCH] [InstCombine] not(sub X, Y) --> add (not X), Y 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 llvm-svn: 338118 --- .../lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 4 ++++ llvm/test/Transforms/InstCombine/sub-not.ll | 8 ++++---- llvm/test/Transforms/InstCombine/vector-xor.ll | 10 ++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index d1922ccd81da..372bc41f780e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -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); diff --git a/llvm/test/Transforms/InstCombine/sub-not.ll b/llvm/test/Transforms/InstCombine/sub-not.ll index ea7101bfe9da..5fc42367dad4 100644 --- a/llvm/test/Transforms/InstCombine/sub-not.ll +++ b/llvm/test/Transforms/InstCombine/sub-not.ll @@ -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]], +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %s = sub <2 x i8> %x, %y diff --git a/llvm/test/Transforms/InstCombine/vector-xor.ll b/llvm/test/Transforms/InstCombine/vector-xor.ll index 80189e693b0f..fc75a8cf439e 100644 --- a/llvm/test/Transforms/InstCombine/vector-xor.ll +++ b/llvm/test/Transforms/InstCombine/vector-xor.ll @@ -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> , [[A0:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], -; CHECK-NEXT: ret <4 x i32> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[A0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = sub <4 x i32> , %a0 %2 = xor <4 x i32> , %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> , [[A0:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], -; CHECK-NEXT: ret <4 x i32> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[A0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = sub <4 x i32> , %a0 %2 = xor <4 x i32> , %1 -- 2.34.1