Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5374,7 +5374,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
}
case Intrinsic::exp:
case Intrinsic::exp2:
case Intrinsic::exp10: {
case Intrinsic::exp10:
case Intrinsic::amdgcn_exp2: {
Known.knownNot(fcNegative);
if ((InterestedClasses & fcNan) == fcNone)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ((InterestedClasses & fcNan) == fcNone)
if ((InterestedClasses & (fcNan | fcSubnormal)) == fcNone)

break;
Expand All @@ -5387,6 +5388,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known.signBitMustBeZero();
}

Type *EltTy = II->getType()->getScalarType();
if (IID == Intrinsic::amdgcn_exp2 && EltTy->isFloatTy())
Known.knownNot(fcSubnormal);

break;
}
case Intrinsic::fptrunc_round: {
Expand Down
48 changes: 24 additions & 24 deletions llvm/test/Transforms/Attributor/AMDGPU/nofpclass-amdgcn-exp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,110 +4,110 @@
declare float @llvm.amdgcn.exp2.f32(float)

define half @ret_exp_f16(half %arg0) {
; CHECK-LABEL: define half @ret_exp_f16(
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_exp_f16(
; CHECK-SAME: half [[ARG0:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.amdgcn.exp2.f16(half [[ARG0]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.amdgcn.exp2.f16(half [[ARG0]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret half [[CALL]]
;
%call = call half @llvm.amdgcn.exp2.f16(half %arg0)
ret half %call
}

define float @ret_exp_f32(float %arg0) {
; CHECK-LABEL: define float @ret_exp_f32(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_f32(
; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_noinf(float nofpclass(inf) %arg0) {
; CHECK-LABEL: define float @ret_exp_noinf(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_noinf(
; CHECK-SAME: float nofpclass(inf) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(inf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(inf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_nopinf(float nofpclass(pinf) %arg0) {
; CHECK-LABEL: define float @ret_exp_nopinf(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_nopinf(
; CHECK-SAME: float nofpclass(pinf) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(pinf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(pinf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_noninf(float nofpclass(ninf) %arg0) {
; CHECK-LABEL: define float @ret_exp_noninf(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_noninf(
; CHECK-SAME: float nofpclass(ninf) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(ninf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(ninf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_nonan(float nofpclass(nan) %arg0) {
; CHECK-LABEL: define float @ret_exp_nonan(
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_exp_nonan(
; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(nan) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(nan) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_nonan_noinf(float nofpclass(nan inf) %arg0) {
; CHECK-LABEL: define float @ret_exp_nonan_noinf(
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_exp_nonan_noinf(
; CHECK-SAME: float nofpclass(nan inf) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(nan inf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(nan inf) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_nonan_noinf_nozero(float nofpclass(nan inf zero) %arg0) {
; CHECK-LABEL: define float @ret_exp_nonan_noinf_nozero(
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_exp_nonan_noinf_nozero(
; CHECK-SAME: float nofpclass(nan inf zero) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(nan inf zero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(nan inf zero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_noinf_nozero(float nofpclass(inf zero) %arg0) {
; CHECK-LABEL: define float @ret_exp_noinf_nozero(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_noinf_nozero(
; CHECK-SAME: float nofpclass(inf zero) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(inf zero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(inf zero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_noinf_nonegzero(float nofpclass(inf nzero) %arg0) {
; CHECK-LABEL: define float @ret_exp_noinf_nonegzero(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_exp_noinf_nonegzero(
; CHECK-SAME: float nofpclass(inf nzero) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float nofpclass(inf nzero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float nofpclass(inf nzero) [[ARG0]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.exp2.f32(float %arg0)
ret float %call
}

define float @ret_exp_positive_source(i32 %arg) {
; CHECK-LABEL: define float @ret_exp_positive_source(
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_exp_positive_source(
; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i32 [[ARG]] to float
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float [[UITOFP]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%uitofp = uitofp i32 %arg to float
Expand All @@ -117,10 +117,10 @@ define float @ret_exp_positive_source(i32 %arg) {

; Could produce a nan because we don't know if the multiply is negative.
define float @ret_exp_unknown_sign(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
; CHECK-LABEL: define float @ret_exp_unknown_sign(
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_exp_unknown_sign(
; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[UNKNOWN_SIGN_NOT_NAN:%.*]] = fmul nnan float [[ARG0]], [[ARG1]]
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.exp2.f32(float [[UNKNOWN_SIGN_NOT_NAN]]) #[[ATTR2]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.amdgcn.exp2.f32(float [[UNKNOWN_SIGN_NOT_NAN]]) #[[ATTR2]]
; CHECK-NEXT: ret float [[CALL]]
;
%unknown.sign.not.nan = fmul nnan float %arg0, %arg1
Expand Down