mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-10 13:51:37 +00:00
[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
35a05a2b7d
commit
be2a9114ad
@ -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
Block a user