Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -9931,7 +9931,7 @@ :: - = select selty , , ; yields ty + = select [fast-math flags] selty , , ; yields ty selty is either i1 or {} @@ -9948,6 +9948,11 @@ values indicating the condition, and two values of the same :ref:`first class ` type. +#. The optional ``fast-math flags`` marker indicates that the select has one or more + :ref:`fast-math flags `. These are optimization hints to enable + otherwise unsafe floating-point optimizations. Fast-math flags are only valid + for selects that return a floating-point scalar or vector type. + Semantics: """""""""" Index: llvm/trunk/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/trunk/include/llvm/IR/IRBuilder.h +++ llvm/trunk/include/llvm/IR/IRBuilder.h @@ -2067,6 +2067,8 @@ MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable); Sel = addBranchMetadata(Sel, Prof, Unpred); } + if (isa(Sel)) + Sel = cast(setFPAttrs(Sel, nullptr /* MDNode* */, FMF)); return Insert(Sel, Name); } Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -5701,7 +5701,19 @@ case lltok::kw_inttoptr: case lltok::kw_ptrtoint: return ParseCast(Inst, PFS, KeywordVal); // Other. - case lltok::kw_select: return ParseSelect(Inst, PFS); + case lltok::kw_select: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); + int Res = ParseSelect(Inst, PFS); + if (Res != 0) + return Res; + if (FMF.any()) { + if (!Inst->getType()->isFPOrFPVectorTy()) + return Error(Loc, "fast-math-flags specified for select without " + "floating-point scalar or vector return type"); + Inst->setFastMathFlags(FMF); + } + return 0; + } case lltok::kw_va_arg: return ParseVA_Arg(Inst, PFS); case lltok::kw_extractelement: return ParseExtractElement(Inst, PFS); case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3835,6 +3835,11 @@ I = SelectInst::Create(Cond, TrueVal, FalseVal); InstructionList.push_back(I); + if (OpNum < Record.size() && isa(I)) { + FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]); + if (FMF.any()) + I->setFastMathFlags(FMF); + } break; } Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2636,12 +2636,16 @@ Vals.append(IVI->idx_begin(), IVI->idx_end()); break; } - case Instruction::Select: + case Instruction::Select: { Code = bitc::FUNC_CODE_INST_VSELECT; pushValueAndType(I.getOperand(1), InstID, Vals); pushValue(I.getOperand(2), InstID, Vals); pushValueAndType(I.getOperand(0), InstID, Vals); + uint64_t Flags = getOptimizationFlags(&I); + if (Flags != 0) + Vals.push_back(Flags); break; + } case Instruction::ExtractElement: Code = bitc::FUNC_CODE_INST_EXTRACTELT; pushValueAndType(I.getOperand(0), InstID, Vals); Index: llvm/trunk/test/Bitcode/compatibility.ll =================================================================== --- llvm/trunk/test/Bitcode/compatibility.ll +++ llvm/trunk/test/Bitcode/compatibility.ll @@ -815,6 +815,34 @@ ret void } +define void @fastmathflags_select(i1 %cond, float %op1, float %op2) { + %f.nnan = select nnan i1 %cond, float %op1, float %op2 + ; CHECK: %f.nnan = select nnan i1 %cond, float %op1, float %op2 + %f.ninf = select ninf i1 %cond, float %op1, float %op2 + ; CHECK: %f.ninf = select ninf i1 %cond, float %op1, float %op2 + %f.nsz = select nsz i1 %cond, float %op1, float %op2 + ; CHECK: %f.nsz = select nsz i1 %cond, float %op1, float %op2 + %f.arcp = select arcp i1 %cond, float %op1, float %op2 + ; CHECK: %f.arcp = select arcp i1 %cond, float %op1, float %op2 + %f.contract = select contract i1 %cond, float %op1, float %op2 + ; CHECK: %f.contract = select contract i1 %cond, float %op1, float %op2 + %f.afn = select afn i1 %cond, float %op1, float %op2 + ; CHECK: %f.afn = select afn i1 %cond, float %op1, float %op2 + %f.reassoc = select reassoc i1 %cond, float %op1, float %op2 + ; CHECK: %f.reassoc = select reassoc i1 %cond, float %op1, float %op2 + %f.fast = select fast i1 %cond, float %op1, float %op2 + ; CHECK: %f.fast = select fast i1 %cond, float %op1, float %op2 + ret void +} + +define void @fastmathflags_vector_select(<2 x i1> %cond, <2 x double> %op1, <2 x double> %op2) { + %f.nnan.nsz = select nnan nsz <2 x i1> %cond, <2 x double> %op1, <2 x double> %op2 + ; CHECK: %f.nnan.nsz = select nnan nsz <2 x i1> %cond, <2 x double> %op1, <2 x double> %op2 + %f.fast = select fast <2 x i1> %cond, <2 x double> %op1, <2 x double> %op2 + ; CHECK: %f.fast = select fast <2 x i1> %cond, <2 x double> %op1, <2 x double> %op2 + ret void +} + ; Check various fast math flags and floating-point types on calls. declare float @fmf1() Index: llvm/trunk/test/CodeGen/Generic/expand-experimental-reductions.ll =================================================================== --- llvm/trunk/test/CodeGen/Generic/expand-experimental-reductions.ll +++ llvm/trunk/test/CodeGen/Generic/expand-experimental-reductions.ll @@ -277,7 +277,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <2 x double> [[VEC:%.*]], <2 x double> undef, <2 x i32> ; CHECK-NEXT: [[RDX_MINMAX_CMP:%.*]] = fcmp fast ogt <2 x double> [[VEC]], [[RDX_SHUF]] -; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select <2 x i1> [[RDX_MINMAX_CMP]], <2 x double> [[VEC]], <2 x double> [[RDX_SHUF]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select fast <2 x i1> [[RDX_MINMAX_CMP]], <2 x double> [[VEC]], <2 x double> [[RDX_SHUF]] ; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x double> [[RDX_MINMAX_SELECT]], i32 0 ; CHECK-NEXT: ret double [[TMP0]] ; @@ -291,7 +291,7 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <2 x double> [[VEC:%.*]], <2 x double> undef, <2 x i32> ; CHECK-NEXT: [[RDX_MINMAX_CMP:%.*]] = fcmp fast olt <2 x double> [[VEC]], [[RDX_SHUF]] -; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select <2 x i1> [[RDX_MINMAX_CMP]], <2 x double> [[VEC]], <2 x double> [[RDX_SHUF]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select fast <2 x i1> [[RDX_MINMAX_CMP]], <2 x double> [[VEC]], <2 x double> [[RDX_SHUF]] ; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x double> [[RDX_MINMAX_SELECT]], i32 0 ; CHECK-NEXT: ret double [[TMP0]] ; Index: llvm/trunk/test/Transforms/InstCombine/fast-math.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/fast-math.ll +++ llvm/trunk/test/Transforms/InstCombine/fast-math.ll @@ -820,7 +820,7 @@ define float @max1(float %a, float %b) { ; CHECK-LABEL: @max1( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast ogt float [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[A]], float [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select fast i1 [[TMP1]], float [[A]], float [[B]] ; CHECK-NEXT: ret float [[TMP2]] ; %c = fpext float %a to double @@ -833,7 +833,7 @@ define float @max2(float %a, float %b) { ; CHECK-LABEL: @max2( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan nsz ogt float [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[A]], float [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select nnan nsz i1 [[TMP1]], float [[A]], float [[B]] ; CHECK-NEXT: ret float [[TMP2]] ; %c = call nnan float @fmaxf(float %a, float %b) @@ -844,7 +844,7 @@ define double @max3(double %a, double %b) { ; CHECK-LABEL: @max3( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast ogt double [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], double [[A]], double [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select fast i1 [[TMP1]], double [[A]], double [[B]] ; CHECK-NEXT: ret double [[TMP2]] ; %c = call fast double @fmax(double %a, double %b) @@ -854,7 +854,7 @@ define fp128 @max4(fp128 %a, fp128 %b) { ; CHECK-LABEL: @max4( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan nsz ogt fp128 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], fp128 [[A]], fp128 [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select nnan nsz i1 [[TMP1]], fp128 [[A]], fp128 [[B]] ; CHECK-NEXT: ret fp128 [[TMP2]] ; %c = call nnan fp128 @fmaxl(fp128 %a, fp128 %b) @@ -865,7 +865,7 @@ define float @min1(float %a, float %b) { ; CHECK-LABEL: @min1( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan nsz olt float [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[A]], float [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select nnan nsz i1 [[TMP1]], float [[A]], float [[B]] ; CHECK-NEXT: ret float [[TMP2]] ; %c = fpext float %a to double @@ -878,7 +878,7 @@ define float @min2(float %a, float %b) { ; CHECK-LABEL: @min2( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast olt float [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[A]], float [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select fast i1 [[TMP1]], float [[A]], float [[B]] ; CHECK-NEXT: ret float [[TMP2]] ; %c = call fast float @fminf(float %a, float %b) @@ -888,7 +888,7 @@ define double @min3(double %a, double %b) { ; CHECK-LABEL: @min3( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan nsz olt double [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], double [[A]], double [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select nnan nsz i1 [[TMP1]], double [[A]], double [[B]] ; CHECK-NEXT: ret double [[TMP2]] ; %c = call nnan double @fmin(double %a, double %b) @@ -898,7 +898,7 @@ define fp128 @min4(fp128 %a, fp128 %b) { ; CHECK-LABEL: @min4( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp fast olt fp128 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], fp128 [[A]], fp128 [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = select fast i1 [[TMP1]], fp128 [[A]], fp128 [[B]] ; CHECK-NEXT: ret fp128 [[TMP2]] ; %c = call fast fp128 @fminl(fp128 %a, fp128 %b) Index: llvm/trunk/test/Transforms/InstCombine/pow-sqrt.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/pow-sqrt.ll +++ llvm/trunk/test/Transforms/InstCombine/pow-sqrt.ll @@ -36,7 +36,7 @@ ; CHECK-NEXT: [[SQRT:%.*]] = call afn double @sqrt(double [[X:%.*]]) ; CHECK-NEXT: [[ABS:%.*]] = call afn double @llvm.fabs.f64(double [[SQRT]]) ; CHECK-NEXT: [[ISINF:%.*]] = fcmp afn oeq double [[X]], 0xFFF0000000000000 -; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: [[TMP1:%.*]] = select afn i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] ; CHECK-NEXT: ret double [[TMP1]] ; %pow = call afn double @pow(double %x, double 5.0e-01) @@ -48,7 +48,7 @@ ; CHECK-NEXT: [[SQRT:%.*]] = call afn <2 x double> @llvm.sqrt.v2f64(<2 x double> [[X:%.*]]) ; CHECK-NEXT: [[ABS:%.*]] = call afn <2 x double> @llvm.fabs.v2f64(<2 x double> [[SQRT]]) ; CHECK-NEXT: [[ISINF:%.*]] = fcmp afn oeq <2 x double> [[X]], -; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[ISINF]], <2 x double> , <2 x double> [[ABS]] +; CHECK-NEXT: [[TMP1:%.*]] = select afn <2 x i1> [[ISINF]], <2 x double> , <2 x double> [[ABS]] ; CHECK-NEXT: ret <2 x double> [[TMP1]] ; %pow = call afn <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) @@ -92,7 +92,7 @@ ; CHECK-LABEL: @pow_libcall_half_nsz( ; CHECK-NEXT: [[SQRT:%.*]] = call nsz double @sqrt(double [[X:%.*]]) ; CHECK-NEXT: [[ISINF:%.*]] = fcmp nsz oeq double [[X]], 0xFFF0000000000000 -; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[SQRT]] +; CHECK-NEXT: [[TMP1:%.*]] = select nsz i1 [[ISINF]], double 0x7FF0000000000000, double [[SQRT]] ; CHECK-NEXT: ret double [[TMP1]] ; %pow = call nsz double @pow(double %x, double 5.0e-01) @@ -103,7 +103,7 @@ ; CHECK-LABEL: @pow_intrinsic_half_nsz( ; CHECK-NEXT: [[SQRT:%.*]] = call nsz double @llvm.sqrt.f64(double [[X:%.*]]) ; CHECK-NEXT: [[ISINF:%.*]] = fcmp nsz oeq double [[X]], 0xFFF0000000000000 -; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[SQRT]] +; CHECK-NEXT: [[TMP1:%.*]] = select nsz i1 [[ISINF]], double 0x7FF0000000000000, double [[SQRT]] ; CHECK-NEXT: ret double [[TMP1]] ; %pow = call nsz double @llvm.pow.f64(double %x, double 5.0e-01) Index: llvm/trunk/test/Transforms/LoopVectorize/float-minmax-instruction-flag.ll =================================================================== --- llvm/trunk/test/Transforms/LoopVectorize/float-minmax-instruction-flag.ll +++ llvm/trunk/test/Transforms/LoopVectorize/float-minmax-instruction-flag.ll @@ -74,10 +74,10 @@ ; CHECK: middle.block: ; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <4 x float> [[TMP6]], <4 x float> undef, <4 x i32> ; CHECK-NEXT: [[RDX_MINMAX_CMP:%.*]] = fcmp fast olt <4 x float> [[TMP6]], [[RDX_SHUF]] -; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select <4 x i1> [[RDX_MINMAX_CMP]], <4 x float> [[TMP6]], <4 x float> [[RDX_SHUF]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = select fast <4 x i1> [[RDX_MINMAX_CMP]], <4 x float> [[TMP6]], <4 x float> [[RDX_SHUF]] ; CHECK-NEXT: [[RDX_SHUF1:%.*]] = shufflevector <4 x float> [[RDX_MINMAX_SELECT]], <4 x float> undef, <4 x i32> ; CHECK-NEXT: [[RDX_MINMAX_CMP2:%.*]] = fcmp fast olt <4 x float> [[RDX_MINMAX_SELECT]], [[RDX_SHUF1]] -; CHECK-NEXT: [[RDX_MINMAX_SELECT3:%.*]] = select <4 x i1> [[RDX_MINMAX_CMP2]], <4 x float> [[RDX_MINMAX_SELECT]], <4 x float> [[RDX_SHUF1]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT3:%.*]] = select fast <4 x i1> [[RDX_MINMAX_CMP2]], <4 x float> [[RDX_MINMAX_SELECT]], <4 x float> [[RDX_SHUF1]] ; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x float> [[RDX_MINMAX_SELECT3]], i32 0 ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 65536, 65536 ; CHECK-NEXT: br i1 [[CMP_N]], label [[OUT:%.*]], label [[SCALAR_PH]] Index: llvm/trunk/test/Transforms/LoopVectorize/minmax_reduction.ll =================================================================== --- llvm/trunk/test/Transforms/LoopVectorize/minmax_reduction.ll +++ llvm/trunk/test/Transforms/LoopVectorize/minmax_reduction.ll @@ -416,7 +416,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @max_red_float(float %max) #0 { entry: @@ -442,7 +442,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @max_red_float_ge(float %max) #0 { entry: @@ -468,7 +468,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_max_red_float(float %max) #0 { entry: @@ -494,7 +494,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_max_red_float_le(float %max) #0 { entry: @@ -520,7 +520,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @unordered_max_red_float(float %max) #0 { entry: @@ -546,7 +546,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @unordered_max_red_float_ge(float %max) #0 { entry: @@ -572,7 +572,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_unordered_max_red_float(float %max) #0 { entry: @@ -598,7 +598,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast ogt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_unordered_max_red_float_le(float %max) #0 { entry: @@ -627,7 +627,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @min_red_float(float %min) #0 { entry: @@ -653,7 +653,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @min_red_float_le(float %min) #0 { entry: @@ -679,7 +679,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_min_red_float(float %min) #0 { entry: @@ -705,7 +705,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_min_red_float_ge(float %min) #0 { entry: @@ -731,7 +731,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @unordered_min_red_float(float %min) #0 { entry: @@ -757,7 +757,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @unordered_min_red_float_le(float %min) #0 { entry: @@ -783,7 +783,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_unordered_min_red_float(float %min) #0 { entry: @@ -809,7 +809,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x float> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define float @inverted_unordered_min_red_float_ge(float %min) #0 { entry: @@ -836,7 +836,7 @@ ; CHECK: select <2 x i1> ; CHECK: middle.block ; CHECK: fcmp fast olt <2 x double> -; CHECK: select <2 x i1> +; CHECK: select fast <2 x i1> define double @min_red_double(double %min) #0 { entry: