Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1435,6 +1435,36 @@ return nullptr; } +// Determine if this is a vector of ConstantFPs and if so, return the minimal +// type we can safely truncate all elements to. +// TODO: Make these support undef elements. +static Type *shrinkFPConstantVector(Value *V) { + auto *CV = dyn_cast(V); + if (!CV || !CV->getType()->isVectorTy()) + return nullptr; + + Type *MinType = nullptr; + + unsigned NumElts = CV->getType()->getVectorNumElements(); + for (unsigned i = 0; i != NumElts; ++i) { + auto *CFP = dyn_cast_or_null(CV->getAggregateElement(i)); + if (!CFP) + return nullptr; + + Type *T = shrinkFPConstant(CFP); + if (!T) + return nullptr; + + // If we haven't found a type yet or this type has a larger mantissa than + // our previous type, this is our new minimal type. + if (!MinType || T->getFPMantissaWidth() > MinType->getFPMantissaWidth()) + MinType = T; + } + + // Make a vector type from the minimal type. + return VectorType::get(MinType, NumElts); +} + /// Find the minimum FP type we can safely truncate to. static Type *getMinimumFPType(Value *V) { if (auto *FPExt = dyn_cast(V)) @@ -1447,6 +1477,10 @@ if (Type *T = shrinkFPConstant(CFP)) return T; + // Try to shrink a vector of FP constants. + if (Type *T = shrinkFPConstantVector(V)) + return T; + return V->getType(); } Index: llvm/trunk/test/Transforms/InstCombine/fpextend.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/fpextend.ll +++ llvm/trunk/test/Transforms/InstCombine/fpextend.ll @@ -59,9 +59,7 @@ define <2 x float> @test5(<2 x float> %x) nounwind { ; CHECK-LABEL: @test5( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP1:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> -; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], zeroinitializer -; CHECK-NEXT: [[TMP34:%.*]] = fptrunc <2 x double> [[TMP3]] to <2 x float> +; CHECK-NEXT: [[TMP34:%.*]] = fadd <2 x float> [[X:%.*]], zeroinitializer ; CHECK-NEXT: ret <2 x float> [[TMP34]] ; entry: @@ -75,23 +73,36 @@ define <2 x float> @test6(<2 x float> %x) nounwind { ; CHECK-LABEL: @test6( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP34:%.*]] = fadd <2 x float> [[X:%.*]], +; CHECK-NEXT: ret <2 x float> [[TMP34]] +; +entry: + %tmp1 = fpext <2 x float> %x to <2 x double> + %tmp3 = fadd <2 x double> %tmp1, + %tmp34 = fptrunc <2 x double> %tmp3 to <2 x float> + ret <2 x float> %tmp34 +} + +; Test with an undef element +; TODO: Support undef elements. +define <2 x float> @test6_undef(<2 x float> %x) nounwind { +; CHECK-LABEL: @test6_undef( +; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP1:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> -; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], +; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[TMP1]], ; CHECK-NEXT: [[TMP34:%.*]] = fptrunc <2 x double> [[TMP3]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP34]] ; entry: %tmp1 = fpext <2 x float> %x to <2 x double> - %tmp3 = fadd <2 x double> %tmp1, + %tmp3 = fadd <2 x double> %tmp1, %tmp34 = fptrunc <2 x double> %tmp3 to <2 x float> ret <2 x float> %tmp34 } define <2 x float> @not_half_shrinkable(<2 x float> %x) { ; CHECK-LABEL: @not_half_shrinkable( -; CHECK-NEXT: [[EXT:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> -; CHECK-NEXT: [[ADD:%.*]] = fadd <2 x double> [[EXT]], -; CHECK-NEXT: [[R:%.*]] = fptrunc <2 x double> [[ADD]] to <2 x float> +; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], ; CHECK-NEXT: ret <2 x float> [[R]] ; %ext = fpext <2 x float> %x to <2 x double>