Skip to content

Commit

Permalink
ValueTracking: Handle minimum/maximum in computeKnownFPClass
Browse files Browse the repository at this point in the history
  • Loading branch information
arsenm committed May 2, 2023
1 parent 20831c3 commit 9feb7cb
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 44 deletions.
6 changes: 4 additions & 2 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4728,7 +4728,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
break;
}
case Intrinsic::minnum:
case Intrinsic::maxnum: {
case Intrinsic::maxnum:
case Intrinsic::minimum:
case Intrinsic::maximum: {
KnownFPClass Known2;
computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses,
Known, Depth + 1, Q, TLI);
Expand All @@ -4739,7 +4741,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known |= Known2;

// If either operand is not NaN, the result is not NaN.
if (NeverNaN)
if (NeverNaN && (IID == Intrinsic::minnum || IID == Intrinsic::maxnum))
Known.knownNot(fcNan);

// Fixup zero handling if denormals could be returned as a zero.
Expand Down
84 changes: 42 additions & 42 deletions llvm/test/Transforms/Attributor/nofpclass-minimum-maximum.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ define float @ret_minimum(float %arg0, float %arg1) #0 {
}

define float @ret_minimum_noinf__noinf(float nofpclass(inf) %arg0, float nofpclass(inf) %arg1) #0 {
; CHECK-LABEL: define float @ret_minimum_noinf__noinf
; CHECK-LABEL: define nofpclass(inf) float @ret_minimum_noinf__noinf
; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]], float nofpclass(inf) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand Down Expand Up @@ -46,29 +46,29 @@ define float @ret_minimum_nonan__noinf(float nofpclass(nan) %arg0, float nofpcla
}

define float @ret_minimum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
; CHECK-LABEL: define float @ret_minimum_noinf_nonan__nonan
; CHECK-LABEL: define nofpclass(nan) float @ret_minimum_noinf_nonan__nonan
; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
; CHECK-LABEL: define float @ret_minimum_nonan__noinf_nonan
; CHECK-LABEL: define nofpclass(nan) float @ret_minimum_nonan__noinf_nonan
; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_norm_zero__norm_sub(float nofpclass(norm zero) %arg0, float nofpclass(norm sub) %arg1) #0 {
; CHECK-LABEL: define float @ret_minimum_norm_zero__norm_sub
; CHECK-LABEL: define nofpclass(norm) float @ret_minimum_norm_zero__norm_sub
; CHECK-SAME: (float nofpclass(zero norm) [[ARG0:%.*]], float nofpclass(sub norm) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(norm) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand All @@ -86,9 +86,9 @@ define float @ret_maximum(float %arg0, float %arg1) #0 {
}

define float @ret_maximum_noinf__noinf(float nofpclass(inf) %arg0, float nofpclass(inf) %arg1) #0 {
; CHECK-LABEL: define float @ret_maximum_noinf__noinf
; CHECK-LABEL: define nofpclass(inf) float @ret_maximum_noinf__noinf
; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]], float nofpclass(inf) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.maximum.f32(float %arg0, float %arg1)
Expand Down Expand Up @@ -116,29 +116,29 @@ define float @ret_maximum_nonan__noinf(float nofpclass(nan) %arg0, float nofpcla
}

define float @ret_maximum_noinf_nonan__nonan(float nofpclass(inf nan) %arg0, float nofpclass(nan) %arg1) #0 {
; CHECK-LABEL: define float @ret_maximum_noinf_nonan__nonan
; CHECK-LABEL: define nofpclass(nan) float @ret_maximum_noinf_nonan__nonan
; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.maximum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_maximum_nonan__noinf_nonan(float nofpclass(nan) %arg0, float nofpclass(inf nan) %arg1) #0 {
; CHECK-LABEL: define float @ret_maximum_nonan__noinf_nonan
; CHECK-LABEL: define nofpclass(nan) float @ret_maximum_nonan__noinf_nonan
; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.maximum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_maximum_norm_zero__norm_sub(float nofpclass(norm zero) %arg0, float nofpclass(norm sub) %arg1) #0 {
; CHECK-LABEL: define float @ret_maximum_norm_zero__norm_sub
; CHECK-LABEL: define nofpclass(norm) float @ret_maximum_norm_zero__norm_sub
; CHECK-SAME: (float nofpclass(zero norm) [[ARG0:%.*]], float nofpclass(sub norm) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(norm) float @llvm.maximum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.maximum.f32(float %arg0, float %arg1)
Expand Down Expand Up @@ -175,69 +175,69 @@ define float @ret_minimum_dynamic_dynamic(float %arg0, float %arg1) #3 {
}

define float @ret_minimum_noinf_nozero__noinf_nozero(float nofpclass(inf zero) %arg0, float nofpclass(inf zero) %arg1) #1 {
; CHECK-LABEL: define float @ret_minimum_noinf_nozero__noinf_nozero
; CHECK-LABEL: define nofpclass(inf zero) float @ret_minimum_noinf_nozero__noinf_nozero
; CHECK-SAME: (float nofpclass(inf zero) [[ARG0:%.*]], float nofpclass(inf zero) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define <2 x float> @ret_minimum_noinf_nozero__noinf_nozero_v2f32(<2 x float> nofpclass(inf zero) %arg0, <2 x float> nofpclass(inf zero) %arg1) #1 {
; CHECK-LABEL: define <2 x float> @ret_minimum_noinf_nozero__noinf_nozero_v2f32
; CHECK-LABEL: define nofpclass(inf zero) <2 x float> @ret_minimum_noinf_nozero__noinf_nozero_v2f32
; CHECK-SAME: (<2 x float> nofpclass(inf zero) [[ARG0:%.*]], <2 x float> nofpclass(inf zero) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[ARG0]], <2 x float> [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf zero) <2 x float> @llvm.minimum.v2f32(<2 x float> [[ARG0]], <2 x float> [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
%call = call <2 x float> @llvm.minimum.v2f32(<2 x float> %arg0, <2 x float> %arg1)
ret <2 x float> %call
}

define float @ret_minimum_daz_daz_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #1 {
; CHECK-LABEL: define float @ret_minimum_daz_daz_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_daz_daz_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_dapz_dapz_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #2 {
; CHECK-LABEL: define float @ret_minimum_dapz_dapz_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_dapz_dapz_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_dynamic_dynamic_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #3 {
; CHECK-LABEL: define float @ret_minimum_dynamic_dynamic_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_dynamic_dynamic_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_daz_daz_nozero_nosub__nozero_nosub(float nofpclass(zero sub) %arg0, float nofpclass(zero sub) %arg1) #1 {
; CHECK-LABEL: define float @ret_minimum_daz_daz_nozero_nosub__nozero_nosub
; CHECK-LABEL: define nofpclass(zero sub) float @ret_minimum_daz_daz_nozero_nosub__nozero_nosub
; CHECK-SAME: (float nofpclass(zero sub) [[ARG0:%.*]], float nofpclass(zero sub) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_dynamic_dynamic_nozero_nosub__nozero_nosub(float nofpclass(zero sub) %arg0, float nofpclass(zero sub) %arg1) #3 {
; CHECK-LABEL: define float @ret_minimum_dynamic_dynamic_nozero_nosub__nozero_nosub
; CHECK-LABEL: define nofpclass(zero sub) float @ret_minimum_dynamic_dynamic_nozero_nosub__nozero_nosub
; CHECK-SAME: (float nofpclass(zero sub) [[ARG0:%.*]], float nofpclass(zero sub) [[ARG1:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand Down Expand Up @@ -265,9 +265,9 @@ define float @ret_minimum_daz_daz_nonzero__nonzero(float nofpclass(nzero) %arg0,
}

define float @ret_minimum_daz_daz_nonzero_nonsub__nonzero_nonsub(float nofpclass(nzero nsub) %arg0, float nofpclass(nzero nsub) %arg1) #1 {
; CHECK-LABEL: define float @ret_minimum_daz_daz_nonzero_nonsub__nonzero_nonsub
; CHECK-LABEL: define nofpclass(nsub) float @ret_minimum_daz_daz_nonzero_nonsub__nonzero_nonsub
; CHECK-SAME: (float nofpclass(nzero nsub) [[ARG0:%.*]], float nofpclass(nzero nsub) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nsub) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand All @@ -285,9 +285,9 @@ define float @ret_minimum_dapz_dapz_nopzero__nopzero(float nofpclass(pzero) %arg
}

define float @ret_minimum_dapz_dapz_nopzero_nopsub__nopzero_nopsub(float nofpclass(pzero psub) %arg0, float nofpclass(pzero psub) %arg1) #2 {
; CHECK-LABEL: define float @ret_minimum_dapz_dapz_nopzero_nopsub__nopzero_nopsub
; CHECK-LABEL: define nofpclass(psub) float @ret_minimum_dapz_dapz_nopzero_nopsub__nopzero_nopsub
; CHECK-SAME: (float nofpclass(pzero psub) [[ARG0:%.*]], float nofpclass(pzero psub) [[ARG1:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(psub) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand All @@ -305,39 +305,39 @@ define float @ret_minimum_dapz_dapz_nonzero__nonzero(float nofpclass(nzero) %arg
}

define float @ret_minimum_ieee_daz_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #4 {
; CHECK-LABEL: define float @ret_minimum_ieee_daz_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_ieee_daz_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_daz_ieee_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #5 {
; CHECK-LABEL: define float @ret_minimum_daz_ieee_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_daz_ieee_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR6:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_ieee_dapz_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #6 {
; CHECK-LABEL: define float @ret_minimum_ieee_dapz_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_ieee_dapz_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR7:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
ret float %call
}

define float @ret_minimum_dapz_ieee_nozero__nozero(float nofpclass(zero) %arg0, float nofpclass(zero) %arg1) #7 {
; CHECK-LABEL: define float @ret_minimum_dapz_ieee_nozero__nozero
; CHECK-LABEL: define nofpclass(zero) float @ret_minimum_dapz_ieee_nozero__nozero
; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]], float nofpclass(zero) [[ARG1:%.*]]) #[[ATTR8:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero) float @llvm.minimum.f32(float [[ARG0]], float [[ARG1]]) #[[ATTR9]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.minimum.f32(float %arg0, float %arg1)
Expand Down

0 comments on commit 9feb7cb

Please sign in to comment.