Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -5190,8 +5190,51 @@ break; } case Instruction::ExtractValue: { - computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses, - Known, Depth + 1, Q, TLI); + const ExtractValueInst *Extract = cast(Op); + ArrayRef Indices = Extract->getIndices(); + const Value *Src = Extract->getAggregateOperand(); + if (isa(Src->getType()) && Indices.size() == 1 && + Indices[0] == 0) { + if (const auto *II = dyn_cast(Src)) { + switch (II->getIntrinsicID()) { + case Intrinsic::frexp : { + Known.knownNot(fcSubnormal); + + KnownFPClass KnownSrc; + computeKnownFPClass(II->getArgOperand(0), DemandedElts, + InterestedClasses, KnownSrc, Depth + 1, Q, TLI); + + const Function *F = cast(Op)->getFunction(); + + if (KnownSrc.isKnownNever(fcNegative)) + Known.knownNot(fcNegative); + else { + if (F && KnownSrc.isKnownNeverLogicalNegZero(*F, Op->getType())) + Known.knownNot(fcNegZero); + if (KnownSrc.isKnownNever(fcNegInf)) + Known.knownNot(fcNegInf); + } + + if (KnownSrc.isKnownNever(fcPositive)) + Known.knownNot(fcPositive); + else { + if (F && KnownSrc.isKnownNeverLogicalPosZero(*F, Op->getType())) + Known.knownNot(fcPosZero); + if (KnownSrc.isKnownNever(fcPosInf)) + Known.knownNot(fcPosInf); + } + + Known.propagateNaN(KnownSrc); + return; + } + default: + break; + } + } + } + + computeKnownFPClass(Src, DemandedElts, InterestedClasses, Known, Depth + 1, + Q, TLI); break; } case Instruction::PHI: { Index: llvm/test/Transforms/Attributor/nofpclass-frexp.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass-frexp.ll +++ llvm/test/Transforms/Attributor/nofpclass-frexp.ll @@ -7,8 +7,8 @@ define { float, i32 } @ret_frexp_f32(float %arg0) { ; CHECK-LABEL: define { float, i32 } @ret_frexp_f32 -; CHECK-SAME: (float [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7:[0-9]+]] ; CHECK-NEXT: ret { float, i32 } [[CALL]] ; %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0) @@ -17,8 +17,8 @@ define { float, i32 } @ret_frexp_f32_nonan(float nofpclass(nan) %arg0) { ; CHECK-LABEL: define { float, i32 } @ret_frexp_f32_nonan -; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: ret { float, i32 } [[CALL]] ; %call = call { float, i32 } @llvm.frexp.f32.i32(float %arg0) @@ -26,9 +26,9 @@ } define float @ret_frexp_f32_0_nonan(float nofpclass(nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonan -; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan sub) float @ret_frexp_f32_0_nonan +; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -38,9 +38,9 @@ } define float @ret_frexp_f32_0_nosnan(float nofpclass(snan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nosnan -; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(snan sub) float @ret_frexp_f32_0_nosnan +; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -50,9 +50,9 @@ } define float @ret_frexp_f32_0_noqnan(float nofpclass(qnan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noqnan -; CHECK-SAME: (float nofpclass(qnan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_noqnan +; CHECK-SAME: (float nofpclass(qnan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -63,8 +63,8 @@ define i32 @ret_frexp_f32_1_nonan(float nofpclass(nan) %arg0) { ; CHECK-LABEL: define i32 @ret_frexp_f32_1_nonan -; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_1:%.*]] = extractvalue { float, i32 } [[CALL]], 1 ; CHECK-NEXT: ret i32 [[CALL_1]] ; @@ -74,9 +74,9 @@ } define <2 x float> @ret_frexp_v2f32_0_nonan(<2 x float> nofpclass(nan) %arg0) { -; CHECK-LABEL: define <2 x float> @ret_frexp_v2f32_0_nonan -; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan sub) <2 x float> @ret_frexp_v2f32_0_nonan +; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[CALL]], 0 ; CHECK-NEXT: ret <2 x float> [[CALL_0]] ; @@ -87,8 +87,8 @@ define <2 x i32> @ret_frexp_v2f32_1_nonan(<2 x float> nofpclass(nan) %arg0) { ; CHECK-LABEL: define <2 x i32> @ret_frexp_v2f32_1_nonan -; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[ARG0]]) +; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float> [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { <2 x float>, <2 x i32> } [[CALL]], 1 ; CHECK-NEXT: ret <2 x i32> [[CALL_0]] ; @@ -98,9 +98,9 @@ } define float @ret_frexp_v4f32_0_nonan_elt1(<4 x float> nofpclass(nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_v4f32_0_nonan_elt1 -; CHECK-SAME: (<4 x float> nofpclass(nan) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan sub) float @ret_frexp_v4f32_0_nonan_elt1 +; CHECK-SAME: (<4 x float> nofpclass(nan) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float> [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { <4 x float>, <4 x i32> } [[CALL]], 0 ; CHECK-NEXT: [[ELT_2:%.*]] = extractelement <4 x float> [[CALL_0]], i32 2 ; CHECK-NEXT: ret float [[ELT_2]] @@ -112,9 +112,9 @@ } define float @ret_frexp_f32_0_nopos_nopzero(float nofpclass(pinf psub pnorm pzero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopos_nopzero -; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pinf pzero sub pnorm) float @ret_frexp_f32_0_nopos_nopzero +; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -124,9 +124,9 @@ } define float @ret_frexp_f32_0_nopos_nopzero_nonan(float nofpclass(pinf psub pnorm pzero nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopos_nopzero_nonan -; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan pinf pzero sub pnorm) float @ret_frexp_f32_0_nopos_nopzero_nonan +; CHECK-SAME: (float nofpclass(nan pinf pzero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -136,9 +136,9 @@ } define float @ret_frexp_f32_0_nopos(float nofpclass(pinf psub pnorm) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopos -; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pinf sub) float @ret_frexp_f32_0_nopos +; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -148,9 +148,9 @@ } define float @ret_frexp_f32_0_nopos_nonan(float nofpclass(pinf psub pnorm nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopos_nonan -; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan pinf sub) float @ret_frexp_f32_0_nopos_nonan +; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -160,9 +160,9 @@ } define float @ret_frexp_f32_0_nopos_nozero(float nofpclass(pinf psub pnorm zero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopos_nozero -; CHECK-SAME: (float nofpclass(pinf zero psub pnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pinf zero sub pnorm) float @ret_frexp_f32_0_nopos_nozero +; CHECK-SAME: (float nofpclass(pinf zero psub pnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -172,9 +172,9 @@ } define float @ret_frexp_f32_0_noneg_nonzero(float nofpclass(ninf nsub nnorm nzero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noneg_nonzero -; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nonzero +; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -184,9 +184,9 @@ } define float @ret_frexp_f32_0_noneg_nonzero_nonan(float nofpclass(ninf nsub nnorm nzero nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noneg_nonzero_nonan -; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nonzero_nonan +; CHECK-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -196,9 +196,9 @@ } define float @ret_frexp_f32_0_noneg(float nofpclass(ninf nsub nnorm) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noneg -; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(ninf sub) float @ret_frexp_f32_0_noneg +; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -208,9 +208,9 @@ } define float @ret_frexp_f32_0_noneg_nonan(float nofpclass(ninf nsub nnorm nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noneg_nonan -; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan ninf sub) float @ret_frexp_f32_0_noneg_nonan +; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -220,9 +220,9 @@ } define float @ret_frexp_f32_0_noneg_nozero(float nofpclass(ninf nsub nnorm nzero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noneg_nozero -; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @ret_frexp_f32_0_noneg_nozero +; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -232,9 +232,9 @@ } define float @ret_frexp_f32_0_nopzero(float nofpclass(pzero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pzero sub) float @ret_frexp_f32_0_nopzero +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -244,9 +244,9 @@ } define float @ret_frexp_f32_0_nonzero(float nofpclass(nzero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nzero sub) float @ret_frexp_f32_0_nonzero +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -256,9 +256,9 @@ } define float @ret_frexp_f32_0_nozero(float nofpclass(zero) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nozero -; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(zero sub) float @ret_frexp_f32_0_nozero +; CHECK-SAME: (float nofpclass(zero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -268,9 +268,9 @@ } define float @ret_frexp_f32_0_nopinf(float nofpclass(pinf) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopinf -; CHECK-SAME: (float nofpclass(pinf) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pinf sub) float @ret_frexp_f32_0_nopinf +; CHECK-SAME: (float nofpclass(pinf) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -280,9 +280,9 @@ } define float @ret_frexp_f32_0_noninf(float nofpclass(ninf) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noninf -; CHECK-SAME: (float nofpclass(ninf) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(ninf sub) float @ret_frexp_f32_0_noninf +; CHECK-SAME: (float nofpclass(ninf) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -292,9 +292,9 @@ } define float @ret_frexp_f32_0_noinf(float nofpclass(inf) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_noinf -; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(inf sub) float @ret_frexp_f32_0_noinf +; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -304,9 +304,9 @@ } define float @ret_frexp_f32_0_nozero_nonan(float nofpclass(zero nan) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nozero_nonan -; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan zero sub) float @ret_frexp_f32_0_nozero_nonan +; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -316,9 +316,9 @@ } define float @ret_frexp_f32_0_nozero_noinf(float nofpclass(zero inf) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nozero_noinf -; CHECK-SAME: (float nofpclass(inf zero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(inf zero sub) float @ret_frexp_f32_0_nozero_noinf +; CHECK-SAME: (float nofpclass(inf zero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -328,9 +328,9 @@ } define float @ret_frexp_f32_0_nozero_nonan_noinf(float nofpclass(zero nan inf) %arg0) { -; CHECK-LABEL: define float @ret_frexp_f32_0_nozero_nonan_noinf -; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nan inf zero sub) float @ret_frexp_f32_0_nozero_nonan_noinf +; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -340,9 +340,9 @@ } define float @ret_frexp_f32_0_nonzero_ftz_daz(float nofpclass(nzero) %arg0) #1 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero_ftz_daz -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR0:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nonzero_ftz_daz +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR2:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -352,9 +352,9 @@ } define float @ret_frexp_f32_0_nonzero_ftpz_dapz(float nofpclass(nzero) %arg0) #2 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero_ftpz_dapz -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR1:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nzero sub) float @ret_frexp_f32_0_nonzero_ftpz_dapz +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR3:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -364,9 +364,9 @@ } define float @ret_frexp_f32_0_nonzero_dynamic_dynamic(float nofpclass(nzero) %arg0) #3 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero_dynamic_dynamic -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR2:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nonzero_dynamic_dynamic +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR4:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -376,9 +376,9 @@ } define float @ret_frexp_f32_0_nonzero_ieee_daz(float nofpclass(nzero) %arg0) #4 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero_ieee_daz -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR3:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nonzero_ieee_daz +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR5:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -388,9 +388,9 @@ } define float @ret_frexp_f32_0_nonzero_daz_ieee(float nofpclass(nzero) %arg0) #5 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nonzero_daz_ieee -; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR4:[0-9]+]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(nzero sub) float @ret_frexp_f32_0_nonzero_daz_ieee +; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR6:[0-9]+]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -400,9 +400,9 @@ } define float @ret_frexp_f32_0_nopzero_ftz_daz(float nofpclass(pzero) %arg0) #1 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero_ftz_daz -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nopzero_ftz_daz +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -412,9 +412,9 @@ } define float @ret_frexp_f32_0_nopzero_ftpz_dapz(float nofpclass(pzero) %arg0) #2 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero_ftpz_dapz -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nopzero_ftpz_dapz +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -424,9 +424,9 @@ } define float @ret_frexp_f32_0_nopzero_dynamic_dynamic(float nofpclass(pzero) %arg0) #3 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero_dynamic_dynamic -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR2]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nopzero_dynamic_dynamic +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR4]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -436,9 +436,9 @@ } define float @ret_frexp_f32_0_nopzero_ieee_daz(float nofpclass(pzero) %arg0) #4 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero_ieee_daz -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(sub) float @ret_frexp_f32_0_nopzero_ieee_daz +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR5]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; @@ -448,9 +448,9 @@ } define float @ret_frexp_f32_0_nopzero_daz_ieee(float nofpclass(pzero) %arg0) #5 { -; CHECK-LABEL: define float @ret_frexp_f32_0_nopzero_daz_ieee -; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR4]] { -; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) +; CHECK-LABEL: define nofpclass(pzero sub) float @ret_frexp_f32_0_nopzero_daz_ieee +; CHECK-SAME: (float nofpclass(pzero) [[ARG0:%.*]]) #[[ATTR6]] { +; CHECK-NEXT: [[CALL:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[ARG0]]) #[[ATTR7]] ; CHECK-NEXT: [[CALL_0:%.*]] = extractvalue { float, i32 } [[CALL]], 0 ; CHECK-NEXT: ret float [[CALL_0]] ; Index: llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll =================================================================== --- llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll +++ llvm/test/Transforms/Inline/simplify-instruction-computeKnownFPClass-context.ll @@ -187,5 +187,26 @@ declare double @llvm.ldexp.f64.i32(double, i32) +define i1 @simplify_fcmp_ord_frexp_caller(double nofpclass(zero inf) %i0) { +; CHECK-LABEL: define i1 @simplify_fcmp_ord_frexp_caller +; CHECK-SAME: (double nofpclass(inf zero) [[I0:%.*]]) { +; CHECK-NEXT: [[FREXP_I:%.*]] = call { double, i32 } @llvm.frexp.f64.i32(double [[I0]]) +; CHECK-NEXT: [[FREXP_0_I:%.*]] = extractvalue { double, i32 } [[FREXP_I]], 0 +; CHECK-NEXT: [[CMP_I:%.*]] = fcmp one double [[FREXP_0_I]], 0x7FF0000000000000 +; CHECK-NEXT: ret i1 [[CMP_I]] +; + %call = call i1 @simplify_fcmp_ord_frexp_callee(double %i0) + ret i1 %call +} + +define internal i1 @simplify_fcmp_ord_frexp_callee(double %a) { + %frexp = call { double, i32 } @llvm.frexp.f64.i32(double %a) + %frexp.0 = extractvalue { double, i32 } %frexp, 0 + %cmp = fcmp one double %frexp.0, 0x7FF0000000000000 + ret i1 %cmp +} + +declare { double, i32 } @llvm.frexp.f64.i32(double) + attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) }