Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4357,12 +4357,38 @@ assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth"); - const APFloat *C; - if (match(V, m_APFloat(C))) { - // We know all of the classes for a scalar constant or a splat vector - // constant! - Known.KnownFPClasses = C->classify(); - Known.SignBit = C->isNegative(); + if (auto *CFP = dyn_cast_or_null(V)) { + Known.KnownFPClasses = CFP->getValueAPF().classify(); + Known.SignBit = CFP->isNegative(); + return; + } + + // Try to handle fixed width vector constants + auto *VFVTy = dyn_cast(V->getType()); + const Constant *CV = dyn_cast(V); + if (VFVTy && CV) { + Known.KnownFPClasses = fcNone; + + // For vectors, verify that each element is not NaN. + unsigned NumElts = VFVTy->getNumElements(); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = CV->getAggregateElement(i); + if (!Elt) { + Known = KnownFPClass(); + return; + } + if (isa(Elt)) + continue; + auto *CElt = dyn_cast(Elt); + if (!CElt) { + Known = KnownFPClass(); + return; + } + + KnownFPClass KnownElt{CElt->getValueAPF().classify(), CElt->isNegative()}; + Known |= KnownElt; + } + return; } Index: llvm/test/Transforms/Attributor/nofpclass.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass.ll +++ llvm/test/Transforms/Attributor/nofpclass.ll @@ -85,8 +85,28 @@ ret <2 x double> } +; Test a vector element that's a constant but not ConstantFP. +define <2 x double> @returned_strange_constant_vector_elt() { +; CHECK-LABEL: define <2 x double> @returned_strange_constant_vector_elt() { +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret <2 x double> +; + call void @unknown() + ret <2 x double> +} + +; Test a vector element that's an undef/poison +define <3 x double> @returned_undef_constant_vector_elt() { +; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) <3 x double> @returned_undef_constant_vector_elt() { +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret <3 x double> +; + call void @unknown() + ret <3 x double> +} + define <2 x double> @returned_qnan_zero_vector() { -; CHECK-LABEL: define noundef <2 x double> @returned_qnan_zero_vector() { +; CHECK-LABEL: define noundef nofpclass(snan inf nzero sub norm) <2 x double> @returned_qnan_zero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> ;