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
38 changes: 38 additions & 0 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5553,6 +5553,44 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,

// TODO: Copy inf handling from instructions
break;
case Intrinsic::amdgcn_rsq: {
KnownFPClass KnownSrc;
// The only negative value that can be returned is -inf for -0 inputs.
Known.knownNot(fcNegZero | fcNegSubnormal | fcNegNormal);

computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses,
KnownSrc, Q, Depth + 1);

// Negative -> nan
if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
Known.knownNot(fcNan);
else if (KnownSrc.isKnownNever(fcSNan))
Known.knownNot(fcSNan);

// +inf -> +0
if (KnownSrc.isKnownNeverPosInfinity())
Known.knownNot(fcPosZero);

Type *EltTy = II->getType()->getScalarType();

// f32 denormal always flushed.
if (EltTy->isFloatTy())
Known.knownNot(fcPosSubnormal);

if (const Function *F = II->getFunction()) {
DenormalMode Mode = F->getDenormalMode(EltTy->getFltSemantics());

// -0 -> -inf
if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
Known.knownNot(fcNegInf);

// +0 -> +inf
if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
Known.knownNot(fcPosInf);
}

break;
}
default:
break;
}
Expand Down
112 changes: 56 additions & 56 deletions llvm/test/Transforms/Attributor/AMDGPU/nofpclass-amdgcn-rsq.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ declare float @llvm.amdgcn.rsq.f32(float)
declare double @llvm.amdgcn.rsq.f64(double)

define half @ret_rsq_f16(half %arg) {
; CHECK-LABEL: define half @ret_rsq_f16(
; CHECK-LABEL: define nofpclass(nzero nsub nnorm) half @ret_rsq_f16(
; CHECK-SAME: half [[ARG:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.amdgcn.rsq.f16(half [[ARG]]) #[[ATTR4:[0-9]+]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub nnorm) half @llvm.amdgcn.rsq.f16(half [[ARG]]) #[[ATTR4:[0-9]+]]
; CHECK-NEXT: ret half [[CALL]]
;
%call = call half @llvm.amdgcn.rsq.f16(half %arg)
ret half %call
}

define float @ret_rsq_f32(float %arg) {
; CHECK-LABEL: define float @ret_rsq_f32(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define double @ret_rsq_f64(double %arg) {
; CHECK-LABEL: define double @ret_rsq_f64(
; CHECK-LABEL: define nofpclass(nzero nsub nnorm) double @ret_rsq_f64(
; CHECK-SAME: double [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
Expand All @@ -37,249 +37,249 @@ define double @ret_rsq_f64(double %arg) {

; Result could still be -0 if negative argument is flushed.
define float @ret_rsq_f32_dynamic_denormal_input(float %arg) #0 {
; CHECK-LABEL: define float @ret_rsq_f32_dynamic_denormal_input(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_dynamic_denormal_input(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_dynamic_denormal_input_known_nzero(float nofpclass(nzero) %arg) #0 {
; CHECK-LABEL: define float @ret_rsq_f32_dynamic_denormal_input_known_nzero(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_dynamic_denormal_input_known_nzero(
; CHECK-SAME: float nofpclass(nzero) [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_dynamic_denormal_input_known_nzero_nsub(float nofpclass(nzero nsub) %arg) #0 {
; CHECK-LABEL: define float @ret_rsq_f32_dynamic_denormal_input_known_nzero_nsub(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_rsq_f32_dynamic_denormal_input_known_nzero_nsub(
; CHECK-SAME: float nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nzero nsub) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nzero nsub) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define double @ret_rsq_f64_dynamic_denormal_input(double %arg) #1 {
; CHECK-LABEL: define double @ret_rsq_f64_dynamic_denormal_input(
; CHECK-LABEL: define nofpclass(nzero nsub nnorm) double @ret_rsq_f64_dynamic_denormal_input(
; CHECK-SAME: double [[ARG:%.*]]) #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define double @ret_rsq_f64_dynamic_denormal_input_known_nzero(double nofpclass(nzero) %arg) #0 {
; CHECK-LABEL: define double @ret_rsq_f64_dynamic_denormal_input_known_nzero(
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) double @ret_rsq_f64_dynamic_denormal_input_known_nzero(
; CHECK-SAME: double nofpclass(nzero) [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define double @ret_rsq_f64_dynamic_denormal_input_known_nzero_nsub(double nofpclass(nzero nsub) %arg) #0 {
; CHECK-LABEL: define double @ret_rsq_f64_dynamic_denormal_input_known_nzero_nsub(
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) double @ret_rsq_f64_dynamic_denormal_input_known_nzero_nsub(
; CHECK-SAME: double nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(nzero nsub) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(nzero nsub) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define float @ret_rsq_f32__no_snan_input(float nofpclass(snan) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32__no_snan_input(
; CHECK-LABEL: define nofpclass(snan nzero sub nnorm) float @ret_rsq_f32__no_snan_input(
; CHECK-SAME: float nofpclass(snan) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(snan) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(snan) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_nsz(float %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_nsz(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_nsz(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call nsz float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nsz nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call nsz float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_neg_zero(float nofpclass(nzero) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_neg_zero(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_rsq_f32_known_no_neg_zero(
; CHECK-SAME: float nofpclass(nzero) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_pos_zero(float nofpclass(pzero) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_pos_zero(
; CHECK-LABEL: define nofpclass(pinf nzero sub nnorm) float @ret_rsq_f32_known_no_pos_zero(
; CHECK-SAME: float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(pinf nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define double @ret_rsq_f64_known_zero(double nofpclass(zero) %arg) {
; CHECK-LABEL: define double @ret_rsq_f64_known_zero(
; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) double @ret_rsq_f64_known_zero(
; CHECK-SAME: double nofpclass(zero) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(zero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(zero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define float @ret_rsq_f32_known_no_nan(float nofpclass(nan) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_nan(
; CHECK-LABEL: define nofpclass(snan nzero sub nnorm) float @ret_rsq_f32_known_no_nan(
; CHECK-SAME: float nofpclass(nan) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call nsz float @llvm.amdgcn.rsq.f32(float nofpclass(nan) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nsz nofpclass(snan nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nan) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call nsz float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_inf(float nofpclass(inf) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_inf(
; CHECK-LABEL: define nofpclass(zero sub nnorm) float @ret_rsq_f32_known_no_inf(
; CHECK-SAME: float nofpclass(inf) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_nan_no_inf(float nofpclass(nan inf) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_nan_no_inf(
; CHECK-LABEL: define nofpclass(snan zero sub nnorm) float @ret_rsq_f32_known_no_nan_no_inf(
; CHECK-SAME: float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nan inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(snan zero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nan inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_poison() {
; CHECK-LABEL: define float @ret_rsq_f32_poison(
; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @ret_rsq_f32_poison(
; CHECK-SAME: ) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float poison) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan inf zero sub nnorm) float @llvm.amdgcn.rsq.f32(float poison) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float poison)
ret float %call
}

define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal(float nofpclass(nsub nnorm) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal(
; CHECK-SAME: float nofpclass(nsub nnorm) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf(float nofpclass(ninf nsub nnorm) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf(
; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_neg_zero(float nofpclass(ninf nzero nsub nnorm) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_neg_zero(
; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_neg_zero(
; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nzero nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nzero nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_nan(float nofpclass(nan ninf nsub nnorm) %arg) {
; CHECK-LABEL: define float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_nan(
; CHECK-LABEL: define nofpclass(nan nzero sub nnorm) float @ret_rsq_f32_known_no_neg_normal_no_neg_subnormal_no_neg_inf_no_nan(
; CHECK-SAME: float nofpclass(nan ninf nsub nnorm) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(nan ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(nan ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_nnan_known_no_neg_normal_no_neg_subnormal_no_neg_inf(float nofpclass(ninf nsub nnorm) %arg) {
; CHECK-LABEL: define nofpclass(nan) float @ret_rsq_f32_nnan_known_no_neg_normal_no_neg_subnormal_no_neg_inf(
; CHECK-LABEL: define nofpclass(nan nzero sub nnorm) float @ret_rsq_f32_nnan_known_no_neg_normal_no_neg_subnormal_no_neg_inf(
; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call nnan nofpclass(nan) float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nnan nofpclass(nan nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(ninf nsub nnorm) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call nnan float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_dynamic_denormal_input_known_pzero(float nofpclass(pzero) %arg) #0 {
; CHECK-LABEL: define float @ret_rsq_f32_dynamic_denormal_input_known_pzero(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_dynamic_denormal_input_known_pzero(
; CHECK-SAME: float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define float @ret_rsq_f32_dynamic_denormal_input_known_pzero_psub(float nofpclass(pzero) %arg) #1 {
; CHECK-LABEL: define float @ret_rsq_f32_dynamic_denormal_input_known_pzero_psub(
; CHECK-LABEL: define nofpclass(nzero sub nnorm) float @ret_rsq_f32_dynamic_denormal_input_known_pzero_psub(
; CHECK-SAME: float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero sub nnorm) float @llvm.amdgcn.rsq.f32(float nofpclass(pzero) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret float [[CALL]]
;
%call = call float @llvm.amdgcn.rsq.f32(float %arg)
ret float %call
}

define double @ret_rsq_f64_known_not_pinf(double nofpclass(pinf) %arg) {
; CHECK-LABEL: define double @ret_rsq_f64_known_not_pinf(
; CHECK-LABEL: define nofpclass(zero nsub nnorm) double @ret_rsq_f64_known_not_pinf(
; CHECK-SAME: double nofpclass(pinf) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(pinf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(pinf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define double @ret_rsq_f64_known_not_ninf(double nofpclass(ninf) %arg) {
; CHECK-LABEL: define double @ret_rsq_f64_known_not_ninf(
; CHECK-LABEL: define nofpclass(nzero nsub nnorm) double @ret_rsq_f64_known_not_ninf(
; CHECK-SAME: double nofpclass(ninf) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(ninf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(ninf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
ret double %call
}

define double @ret_rsq_f64_known_not_inf(double nofpclass(inf) %arg) {
; CHECK-LABEL: define double @ret_rsq_f64_known_not_inf(
; CHECK-LABEL: define nofpclass(zero nsub nnorm) double @ret_rsq_f64_known_not_inf(
; CHECK-SAME: double nofpclass(inf) [[ARG:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.amdgcn.rsq.f64(double nofpclass(inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(zero nsub nnorm) double @llvm.amdgcn.rsq.f64(double nofpclass(inf) [[ARG]]) #[[ATTR4]]
; CHECK-NEXT: ret double [[CALL]]
;
%call = call double @llvm.amdgcn.rsq.f64(double %arg)
Expand Down