forked from OSchip/llvm-project
[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:
parent
eee52b5090
commit
78e4b4d3c4
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue