[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
This commit is contained in:
Sanjay Patel 2018-07-27 10:54:48 +00:00
parent eee52b5090
commit 78e4b4d3c4
3 changed files with 12 additions and 10 deletions

View 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);

View 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

View 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