[InstCombine] canonicalize fcmp+select to minnum/maxnum intrinsics

This is the opposite direction of D62158 (we have to choose 1 form or the other).
Now that we have FMF on the select, this becomes more palatable. And the benefits
of having a single IR instruction for this operation (less chances of missing folds
based on extra uses, etc) overcome my previous comments about the potential advantage
of larger pattern matching/analysis.

Differential Revision: https://reviews.llvm.org/D62414

llvm-svn: 364721
This commit is contained in:
Sanjay Patel 2019-06-30 13:40:31 +00:00
parent 78ee2fbf98
commit 706b48251f
2 changed files with 21 additions and 12 deletions

View File

@ -2030,6 +2030,19 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
}
}
// Canonicalize select of FP values where NaN and -0.0 are not valid as
// minnum/maxnum intrinsics.
if (isa<FPMathOperator>(SI) && SI.hasNoNaNs() && SI.hasNoSignedZeros()) {
Value *X, *Y;
if (match(&SI, m_OrdFMax(m_Value(X), m_Value(Y))))
return replaceInstUsesWith(
SI, Builder.CreateBinaryIntrinsic(Intrinsic::maxnum, X, Y, &SI));
if (match(&SI, m_OrdFMin(m_Value(X), m_Value(Y))))
return replaceInstUsesWith(
SI, Builder.CreateBinaryIntrinsic(Intrinsic::minnum, X, Y, &SI));
}
// See if we can fold the select into a phi node if the condition is a select.
if (auto *PN = dyn_cast<PHINode>(SI.getCondition()))
// The true/false values have to be live in the PHI predecessor's blocks.

View File

@ -313,9 +313,8 @@ define double @fneg_fmin(double %x, double %y) {
define float @maxnum_ogt_fmf_on_select(float %a, float %b) {
; CHECK-LABEL: @maxnum_ogt_fmf_on_select(
; CHECK-NEXT: [[COND:%.*]] = fcmp ogt float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[F:%.*]] = select nnan nsz i1 [[COND]], float [[A]], float [[B]]
; CHECK-NEXT: ret float [[F]]
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[A:%.*]], float [[B:%.*]])
; CHECK-NEXT: ret float [[TMP1]]
;
%cond = fcmp ogt float %a, %b
%f = select nnan nsz i1 %cond, float %a, float %b
@ -324,9 +323,8 @@ define float @maxnum_ogt_fmf_on_select(float %a, float %b) {
define <2 x float> @maxnum_oge_fmf_on_select(<2 x float> %a, <2 x float> %b) {
; CHECK-LABEL: @maxnum_oge_fmf_on_select(
; CHECK-NEXT: [[COND:%.*]] = fcmp oge <2 x float> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[F:%.*]] = select nnan ninf nsz <2 x i1> [[COND]], <2 x float> [[A]], <2 x float> [[B]]
; CHECK-NEXT: ret <2 x float> [[F]]
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x float> @llvm.maxnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
; CHECK-NEXT: ret <2 x float> [[TMP1]]
;
%cond = fcmp oge <2 x float> %a, %b
%f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b
@ -379,9 +377,8 @@ define float @maxnum_no_nnan(float %a, float %b) {
define float @minnum_olt_fmf_on_select(float %a, float %b) {
; CHECK-LABEL: @minnum_olt_fmf_on_select(
; CHECK-NEXT: [[COND:%.*]] = fcmp olt float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[F:%.*]] = select nnan nsz i1 [[COND]], float [[A]], float [[B]]
; CHECK-NEXT: ret float [[F]]
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[A:%.*]], float [[B:%.*]])
; CHECK-NEXT: ret float [[TMP1]]
;
%cond = fcmp olt float %a, %b
%f = select nnan nsz i1 %cond, float %a, float %b
@ -390,9 +387,8 @@ define float @minnum_olt_fmf_on_select(float %a, float %b) {
define <2 x float> @minnum_ole_fmf_on_select(<2 x float> %a, <2 x float> %b) {
; CHECK-LABEL: @minnum_ole_fmf_on_select(
; CHECK-NEXT: [[COND:%.*]] = fcmp ole <2 x float> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[F:%.*]] = select nnan ninf nsz <2 x i1> [[COND]], <2 x float> [[A]], <2 x float> [[B]]
; CHECK-NEXT: ret <2 x float> [[F]]
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
; CHECK-NEXT: ret <2 x float> [[TMP1]]
;
%cond = fcmp ole <2 x float> %a, %b
%f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b