forked from OSchip/llvm-project
[InstCombine] Fold sub of umin to usub.sat
We were handling sub of umax, but not the conjugated umin case. https://alive2.llvm.org/ce/z/4fdZfy https://alive2.llvm.org/ce/z/BhUQBM
This commit is contained in:
parent
4b5261e10f
commit
e2f627e5e3
|
@ -2187,12 +2187,23 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
|
||||||
return replaceInstUsesWith(
|
return replaceInstUsesWith(
|
||||||
I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op1}));
|
I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op1}));
|
||||||
|
|
||||||
|
// Op0 - umin(X, Op0) --> usub.sat(Op0, X)
|
||||||
|
if (match(Op1, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op0)))))
|
||||||
|
return replaceInstUsesWith(
|
||||||
|
I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op0, X}));
|
||||||
|
|
||||||
// Op0 - umax(X, Op0) --> 0 - usub.sat(X, Op0)
|
// Op0 - umax(X, Op0) --> 0 - usub.sat(X, Op0)
|
||||||
if (match(Op1, m_OneUse(m_c_UMax(m_Value(X), m_Specific(Op0))))) {
|
if (match(Op1, m_OneUse(m_c_UMax(m_Value(X), m_Specific(Op0))))) {
|
||||||
Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op0});
|
Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op0});
|
||||||
return BinaryOperator::CreateNeg(USub);
|
return BinaryOperator::CreateNeg(USub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// umin(X, Op1) - Op1 --> 0 - usub.sat(Op1, X)
|
||||||
|
if (match(Op0, m_OneUse(m_c_UMin(m_Value(X), m_Specific(Op1))))) {
|
||||||
|
Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {Op1, X});
|
||||||
|
return BinaryOperator::CreateNeg(USub);
|
||||||
|
}
|
||||||
|
|
||||||
// C - ctpop(X) => ctpop(~X) if C is bitwidth
|
// C - ctpop(X) => ctpop(~X) if C is bitwidth
|
||||||
if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits())) &&
|
if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits())) &&
|
||||||
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(X)))))
|
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(X)))))
|
||||||
|
|
|
@ -39,9 +39,8 @@ define i32 @na_minus_max_na_b(i32 %A, i32 %B) {
|
||||||
|
|
||||||
define i5 @sub_umin(i5 %a, i5 %b) {
|
define i5 @sub_umin(i5 %a, i5 %b) {
|
||||||
; CHECK-LABEL: @sub_umin(
|
; CHECK-LABEL: @sub_umin(
|
||||||
; CHECK-NEXT: [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A:%.*]], i5 [[B:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.usub.sat.i5(i5 [[A:%.*]], i5 [[B:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i5 [[A]], [[UMIN]]
|
; CHECK-NEXT: ret i5 [[TMP1]]
|
||||||
; CHECK-NEXT: ret i5 [[R]]
|
|
||||||
;
|
;
|
||||||
%umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
|
%umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
|
||||||
%r = sub i5 %a, %umin
|
%r = sub i5 %a, %umin
|
||||||
|
@ -50,9 +49,8 @@ define i5 @sub_umin(i5 %a, i5 %b) {
|
||||||
|
|
||||||
define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) {
|
define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) {
|
||||||
; CHECK-LABEL: @sub_umin_commute_vec(
|
; CHECK-LABEL: @sub_umin_commute_vec(
|
||||||
; CHECK-NEXT: [[UMIN:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[B:%.*]], <2 x i8> [[A:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B:%.*]], <2 x i8> [[A:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub <2 x i8> [[B]], [[UMIN]]
|
; CHECK-NEXT: ret <2 x i8> [[TMP1]]
|
||||||
; CHECK-NEXT: ret <2 x i8> [[R]]
|
|
||||||
;
|
;
|
||||||
%umin = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %b, <2 x i8> %a)
|
%umin = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %b, <2 x i8> %a)
|
||||||
%r = sub <2 x i8> %b, %umin
|
%r = sub <2 x i8> %b, %umin
|
||||||
|
@ -569,9 +567,8 @@ define i8 @umax_sub_op1_use(i8 %x, i8 %y) {
|
||||||
|
|
||||||
define i8 @umin_sub_op1(i8 %x, i8 %y) {
|
define i8 @umin_sub_op1(i8 %x, i8 %y) {
|
||||||
; CHECK-LABEL: @umin_sub_op1(
|
; CHECK-LABEL: @umin_sub_op1(
|
||||||
; CHECK-NEXT: [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y]], [[U]]
|
; CHECK-NEXT: ret i8 [[TMP1]]
|
||||||
; CHECK-NEXT: ret i8 [[R]]
|
|
||||||
;
|
;
|
||||||
%u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
|
%u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
|
||||||
%r = sub i8 %y, %u
|
%r = sub i8 %y, %u
|
||||||
|
@ -580,9 +577,8 @@ define i8 @umin_sub_op1(i8 %x, i8 %y) {
|
||||||
|
|
||||||
define i8 @umin_sub_op1_commute(i8 %x, i8 %y) {
|
define i8 @umin_sub_op1_commute(i8 %x, i8 %y) {
|
||||||
; CHECK-LABEL: @umin_sub_op1_commute(
|
; CHECK-LABEL: @umin_sub_op1_commute(
|
||||||
; CHECK-NEXT: [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y]], [[U]]
|
; CHECK-NEXT: ret i8 [[TMP1]]
|
||||||
; CHECK-NEXT: ret i8 [[R]]
|
|
||||||
;
|
;
|
||||||
%u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
|
%u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
|
||||||
%r = sub i8 %y, %u
|
%r = sub i8 %y, %u
|
||||||
|
@ -591,8 +587,8 @@ define i8 @umin_sub_op1_commute(i8 %x, i8 %y) {
|
||||||
|
|
||||||
define i8 @umin_sub_op0(i8 %x, i8 %y) {
|
define i8 @umin_sub_op0(i8 %x, i8 %y) {
|
||||||
; CHECK-LABEL: @umin_sub_op0(
|
; CHECK-LABEL: @umin_sub_op0(
|
||||||
; CHECK-NEXT: [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i8 [[U]], [[Y]]
|
; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[TMP1]]
|
||||||
; CHECK-NEXT: ret i8 [[R]]
|
; CHECK-NEXT: ret i8 [[R]]
|
||||||
;
|
;
|
||||||
%u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
|
%u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
|
||||||
|
@ -602,8 +598,8 @@ define i8 @umin_sub_op0(i8 %x, i8 %y) {
|
||||||
|
|
||||||
define i8 @umin_sub_op0_commute(i8 %x, i8 %y) {
|
define i8 @umin_sub_op0_commute(i8 %x, i8 %y) {
|
||||||
; CHECK-LABEL: @umin_sub_op0_commute(
|
; CHECK-LABEL: @umin_sub_op0_commute(
|
||||||
; CHECK-NEXT: [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y:%.*]], i8 [[X:%.*]])
|
||||||
; CHECK-NEXT: [[R:%.*]] = sub i8 [[U]], [[Y]]
|
; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[TMP1]]
|
||||||
; CHECK-NEXT: ret i8 [[R]]
|
; CHECK-NEXT: ret i8 [[R]]
|
||||||
;
|
;
|
||||||
%u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
|
%u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
|
||||||
|
|
Loading…
Reference in New Issue