Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -255,6 +255,57 @@ return Instruction::CastOps(Res); } +/// If a cast widens the result, only widen the select when we are sure that it +/// will remove a preceding truncate or remove the widening cast. +static Instruction * +foldWideningCastIntoSelect(CastInst &Cast, SelectInst &Sel, + InstCombiner::BuilderTy &Builder) { + Type *SrcTy = Sel.getType(); + Type *DstTy = Cast.getType(); + unsigned SrcWidth = SrcTy->getScalarSizeInBits(); + unsigned DstWidth = DstTy->getScalarSizeInBits(); + if (SrcWidth >= DstWidth) + return nullptr; + + Value *Cond = Sel.getCondition(); + Value *TVal = Sel.getTrueValue(); + Value *FVal = Sel.getFalseValue(); + Instruction::CastOps CastOpc = Cast.getOpcode(); + + // If both arms of the select are constants, widen the select and eliminate + // the cast. + Constant *TC, *FC; + if (match(TVal, m_Constant(TC)) && match(FVal, m_Constant(FC))) { + Constant *WideTC = ConstantExpr::getCast(CastOpc, TC, DstTy); + Constant *WideFC = ConstantExpr::getCast(CastOpc, FC, DstTy); + return SelectInst::Create(Cond, WideTC, WideFC, "", nullptr, &Sel); + } + + if (!Sel.hasOneUse() || CastOpc != Instruction::ZExt) + return nullptr; + + // Look through the select to find a truncate. The trunc+zext is replaced by + // an 'and', and the select is widened. + Constant *C; + Value *X; + if (((match(TVal, m_Constant(C)) && + match(FVal, m_OneUse(m_Trunc(m_Value(X))))) || + (match(FVal, m_Constant(C)) && + match(TVal, m_OneUse(m_Trunc(m_Value(X)))))) && + X->getType() == DstTy) { + // zext (select Cond, C, (trunc X)) --> select Cond, C', (and X, Mask) + // zext (select Cond, (trunc X), C) --> select Cond, (and X, Mask), C' + Constant *Mask = + ConstantInt::get(DstTy, APInt::getLowBitsSet(DstWidth, SrcWidth)); + Value *And = Builder.CreateAnd(X, Mask); + Constant *ExtC = ConstantExpr::getCast(CastOpc, C, DstTy); + return TVal == C ? SelectInst::Create(Cond, ExtC, And, "", nullptr, &Sel) : + SelectInst::Create(Cond, And, ExtC, "", nullptr, &Sel); + } + + return nullptr; +} + /// @brief Implement the transforms common to all CastInst visitors. Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { Value *Src = CI.getOperand(0); @@ -269,10 +320,14 @@ } // If we are casting a select, then fold the cast into the select. - if (auto *SI = dyn_cast(Src)) + if (auto *SI = dyn_cast(Src)) { if (Instruction *NV = FoldOpIntoSelect(CI, SI)) return NV; + if (Instruction *NV = foldWideningCastIntoSelect(CI, *SI, *Builder)) + return NV; + } + // If we are casting a PHI, then fold the cast into the PHI. if (isa(Src)) { // Don't do this if it would create a PHI node with an illegal type from a @@ -836,6 +891,7 @@ // type. Only do this if the dest type is a simple type, don't convert the // expression tree to something weird like i93 unless the source is also // strange. + // TODO: Should all vectors be transformed? unsigned BitsToClear; if ((DestTy->isVectorTy() || ShouldChangeType(SrcTy, DestTy)) && canEvaluateZExtd(Src, DestTy, BitsToClear, *this, &CI)) { @@ -1131,6 +1187,7 @@ // type. Only do this if the dest type is a simple type, don't convert the // expression tree to something weird like i93 unless the source is also // strange. + // TODO: Should all vectors be transformed? if ((DestTy->isVectorTy() || ShouldChangeType(SrcTy, DestTy)) && canEvaluateSExtd(Src, DestTy)) { // Okay, we can transform this! Insert the new expression now. Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -772,8 +772,8 @@ /// Given an instruction with a select as one operand and a constant as the /// other operand, try to fold the binary operator into the select arguments. -/// This also works for Cast instructions, which obviously do not have a second -/// operand. +/// This also works for some Cast instructions, which obviously do not have a +/// second operand. Instruction *InstCombiner::FoldOpIntoSelect(Instruction &Op, SelectInst *SI) { // Don't modify shared select instructions. if (!SI->hasOneUse()) @@ -788,6 +788,15 @@ if (SI->getType()->getScalarType()->isIntegerTy(1)) return nullptr; + // If Op is an extend, do not grow the select operand sizes by pulling the + // extend into or ahead of the select. This is particularly important for + // vectors because we want to use the narrowest operations possible for a + // given number of vector lanes. + unsigned SrcWidth = SI->getType()->getScalarSizeInBits(); + unsigned DstWidth = Op.getType()->getScalarSizeInBits(); + if (SrcWidth < DstWidth) + return nullptr; + // If it's a bitcast involving vectors, make sure it has the same number of // elements on both sides. if (auto *BC = dyn_cast(&Op)) { Index: test/Transforms/InstCombine/select-bitext.ll =================================================================== --- test/Transforms/InstCombine/select-bitext.ll +++ test/Transforms/InstCombine/select-bitext.ll @@ -33,12 +33,10 @@ ret double %ext } -; FIXME: We should not grow the size of the select in the next 4 cases. - define i64 @sel_sext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @sel_sext( -; CHECK-NEXT: [[TMP1:%.*]] = sext i32 %a to i64 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i64 [[TMP1]], i64 42 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i32 %a, i32 42 +; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[SEL]] to i64 ; CHECK-NEXT: ret i64 [[EXT]] ; %sel = select i1 %cmp, i32 %a, i32 42 @@ -48,8 +46,8 @@ define <4 x i64> @sel_sext_vec(<4 x i32> %a, <4 x i1> %cmp) { ; CHECK-LABEL: @sel_sext_vec( -; CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i32> %a to <4 x i64> -; CHECK-NEXT: [[EXT:%.*]] = select <4 x i1> %cmp, <4 x i64> [[TMP1]], <4 x i64> +; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> +; CHECK-NEXT: [[EXT:%.*]] = sext <4 x i32> [[SEL]] to <4 x i64> ; CHECK-NEXT: ret <4 x i64> [[EXT]] ; %sel = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> @@ -59,8 +57,8 @@ define i64 @sel_zext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @sel_zext( -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 %a to i64 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i64 [[TMP1]], i64 42 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i32 %a, i32 42 +; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SEL]] to i64 ; CHECK-NEXT: ret i64 [[EXT]] ; %sel = select i1 %cmp, i32 %a, i32 42 @@ -70,8 +68,8 @@ define <4 x i64> @sel_zext_vec(<4 x i32> %a, <4 x i1> %cmp) { ; CHECK-LABEL: @sel_zext_vec( -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i32> %a to <4 x i64> -; CHECK-NEXT: [[EXT:%.*]] = select <4 x i1> %cmp, <4 x i64> [[TMP1]], <4 x i64> +; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> +; CHECK-NEXT: [[EXT:%.*]] = zext <4 x i32> [[SEL]] to <4 x i64> ; CHECK-NEXT: ret <4 x i64> [[EXT]] ; %sel = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> @@ -79,15 +77,16 @@ ret <4 x i64> %ext } -; FIXME: The next 18 tests cycle through trunc+select and {larger,smaller,equal} {sext,zext,fpext} {scalar,vector}. -; The only cases where we eliminate an instruction are equal zext with scalar/vector, so that's probably the only -; way to justify widening the select. +; The next 18 tests cycle through trunc+select and {larger,smaller,equal} {sext,zext,fpext} {scalar,vector}. +; The only cases where we eliminate an instruction are equal zext with scalar/vector, so that's the only +; way to justify widening the select? Except all sext/zext with vectors are transformed to use a wider select +; even if it means adding IR instructions? define i64 @trunc_sel_larger_sext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_larger_sext( ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %a to i16 -; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[TRUNC]] to i64 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i64 [[TMP1]], i64 42 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i16 [[TRUNC]], i16 42 +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[SEL]] to i64 ; CHECK-NEXT: ret i64 [[EXT]] ; %trunc = trunc i32 %a to i16 @@ -99,9 +98,9 @@ define <2 x i64> @trunc_sel_larger_sext_vec(<2 x i32> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_larger_sext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = zext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[SEXT:%.*]] = shl <2 x i64> [[TRUNC]], -; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i64> [[SEXT]], -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i64> [[TMP1]], <2 x i64> +; CHECK-NEXT: [[TRUNC_OP:%.*]] = shl <2 x i64> [[TRUNC]], +; CHECK-NEXT: [[TRUNC_OP_OP:%.*]] = ashr <2 x i64> [[TRUNC_OP]], +; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i64> [[TRUNC_OP_OP]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[EXT]] ; %trunc = trunc <2 x i32> %a to <2 x i16> @@ -113,8 +112,8 @@ define i32 @trunc_sel_smaller_sext(i64 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_sext( ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 %a to i16 -; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[TRUNC]] to i32 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP1]], i32 42 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i16 [[TRUNC]], i16 42 +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[SEL]] to i32 ; CHECK-NEXT: ret i32 [[EXT]] ; %trunc = trunc i64 %a to i16 @@ -126,9 +125,9 @@ define <2 x i32> @trunc_sel_smaller_sext_vec(<2 x i64> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_sext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> %a to <2 x i32> -; CHECK-NEXT: [[SEXT:%.*]] = shl <2 x i32> [[TRUNC]], -; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[SEXT]], -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TMP1]], <2 x i32> +; CHECK-NEXT: [[TRUNC_OP:%.*]] = shl <2 x i32> [[TRUNC]], +; CHECK-NEXT: [[TRUNC_OP_OP:%.*]] = ashr <2 x i32> [[TRUNC_OP]], +; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TRUNC_OP_OP]], <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[EXT]] ; %trunc = trunc <2 x i64> %a to <2 x i16> @@ -139,9 +138,9 @@ define i32 @trunc_sel_equal_sext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_equal_sext( -; CHECK-NEXT: [[SEXT:%.*]] = shl i32 %a, 16 -; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i32 [[SEXT]], 16 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP1]], i32 42 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %a to i16 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i16 [[TRUNC]], i16 42 +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[SEL]] to i32 ; CHECK-NEXT: ret i32 [[EXT]] ; %trunc = trunc i32 %a to i16 @@ -152,9 +151,9 @@ define <2 x i32> @trunc_sel_equal_sext_vec(<2 x i32> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_equal_sext_vec( -; CHECK-NEXT: [[SEXT:%.*]] = shl <2 x i32> %a, -; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[SEXT]], -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TMP1]], <2 x i32> +; CHECK-NEXT: [[A_OP:%.*]] = shl <2 x i32> %a, +; CHECK-NEXT: [[A_OP_OP:%.*]] = ashr <2 x i32> [[A_OP]], +; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[A_OP_OP]], <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[EXT]] ; %trunc = trunc <2 x i32> %a to <2 x i16> @@ -165,9 +164,9 @@ define i64 @trunc_sel_larger_zext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_larger_zext( -; CHECK-NEXT: [[TRUNC_MASK:%.*]] = and i32 %a, 65535 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TRUNC_MASK]] to i64 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i64 [[TMP1]], i64 42 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %a to i16 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i16 [[TRUNC]], i16 42 +; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[SEL]] to i64 ; CHECK-NEXT: ret i64 [[EXT]] ; %trunc = trunc i32 %a to i16 @@ -178,9 +177,9 @@ define <2 x i64> @trunc_sel_larger_zext_vec(<2 x i32> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_larger_zext_vec( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> %a, -; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i64> [[TMP2]], <2 x i64> +; CHECK-NEXT: [[TRUNC:%.*]] = zext <2 x i32> %a to <2 x i64> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> %cmp, <2 x i64> [[TRUNC]], <2 x i64> +; CHECK-NEXT: [[EXT:%.*]] = and <2 x i64> [[SEL]], ; CHECK-NEXT: ret <2 x i64> [[EXT]] ; %trunc = trunc <2 x i32> %a to <2 x i16> @@ -191,9 +190,9 @@ define i32 @trunc_sel_smaller_zext(i64 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_zext( -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 %a to i32 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 65535 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP2]], i32 42 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 %a to i16 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, i16 [[TRUNC]], i16 42 +; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[SEL]] to i32 ; CHECK-NEXT: ret i32 [[EXT]] ; %trunc = trunc i64 %a to i16 @@ -205,8 +204,8 @@ define <2 x i32> @trunc_sel_smaller_zext_vec(<2 x i64> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_zext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> %a to <2 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[TRUNC]], -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TMP1]], <2 x i32> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TRUNC]], <2 x i32> +; CHECK-NEXT: [[EXT:%.*]] = and <2 x i32> [[SEL]], ; CHECK-NEXT: ret <2 x i32> [[EXT]] ; %trunc = trunc <2 x i64> %a to <2 x i16> @@ -218,11 +217,11 @@ define i32 @trunc_sel_equal_zext(i32 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_equal_zext( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 %a, 65535 -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP1]], i32 42 +; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP1]], i32 42, !prof !0 ; CHECK-NEXT: ret i32 [[EXT]] ; %trunc = trunc i32 %a to i16 - %sel = select i1 %cmp, i16 %trunc, i16 42 + %sel = select i1 %cmp, i16 %trunc, i16 42, !prof !0 %ext = zext i16 %sel to i32 ret i32 %ext } @@ -230,11 +229,11 @@ define <2 x i32> @trunc_sel_equal_zext_vec(<2 x i32> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_equal_zext_vec( ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> %a, -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TMP1]], <2 x i32> +; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x i32> [[TMP1]], <2 x i32> , !prof !0 ; CHECK-NEXT: ret <2 x i32> [[EXT]] ; %trunc = trunc <2 x i32> %a to <2 x i16> - %sel = select <2 x i1> %cmp, <2 x i16> %trunc, <2 x i16> + %sel = select <2 x i1> %cmp, <2 x i16> %trunc, <2 x i16> , !prof !0 %ext = zext <2 x i16> %sel to <2 x i32> ret <2 x i32> %ext } @@ -242,8 +241,8 @@ define double @trunc_sel_larger_fpext(float %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_larger_fpext( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc float %a to half -; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[TRUNC]] to double -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, double [[TMP1]], double 4.200000e+01 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, half [[TRUNC]], half 0xH5140 +; CHECK-NEXT: [[EXT:%.*]] = fpext half [[SEL]] to double ; CHECK-NEXT: ret double [[EXT]] ; %trunc = fptrunc float %a to half @@ -255,8 +254,8 @@ define <2 x double> @trunc_sel_larger_fpext_vec(<2 x float> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_larger_fpext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <2 x float> %a to <2 x half> -; CHECK-NEXT: [[TMP1:%.*]] = fpext <2 x half> [[TRUNC]] to <2 x double> -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x double> [[TMP1]], <2 x double> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> %cmp, <2 x half> [[TRUNC]], <2 x half> +; CHECK-NEXT: [[EXT:%.*]] = fpext <2 x half> [[SEL]] to <2 x double> ; CHECK-NEXT: ret <2 x double> [[EXT]] ; %trunc = fptrunc <2 x float> %a to <2 x half> @@ -268,8 +267,8 @@ define float @trunc_sel_smaller_fpext(double %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_fpext( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double %a to half -; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[TRUNC]] to float -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, float [[TMP1]], float 4.200000e+01 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, half [[TRUNC]], half 0xH5140 +; CHECK-NEXT: [[EXT:%.*]] = fpext half [[SEL]] to float ; CHECK-NEXT: ret float [[EXT]] ; %trunc = fptrunc double %a to half @@ -281,8 +280,8 @@ define <2 x float> @trunc_sel_smaller_fpext_vec(<2 x double> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_fpext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <2 x double> %a to <2 x half> -; CHECK-NEXT: [[TMP1:%.*]] = fpext <2 x half> [[TRUNC]] to <2 x float> -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x float> [[TMP1]], <2 x float> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> %cmp, <2 x half> [[TRUNC]], <2 x half> +; CHECK-NEXT: [[EXT:%.*]] = fpext <2 x half> [[SEL]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[EXT]] ; %trunc = fptrunc <2 x double> %a to <2 x half> @@ -294,8 +293,8 @@ define float @trunc_sel_equal_fpext(float %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_equal_fpext( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc float %a to half -; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[TRUNC]] to float -; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, float [[TMP1]], float 4.200000e+01 +; CHECK-NEXT: [[SEL:%.*]] = select i1 %cmp, half [[TRUNC]], half 0xH5140 +; CHECK-NEXT: [[EXT:%.*]] = fpext half [[SEL]] to float ; CHECK-NEXT: ret float [[EXT]] ; %trunc = fptrunc float %a to half @@ -307,8 +306,8 @@ define <2 x float> @trunc_sel_equal_fpext_vec(<2 x float> %a, <2 x i1> %cmp) { ; CHECK-LABEL: @trunc_sel_equal_fpext_vec( ; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <2 x float> %a to <2 x half> -; CHECK-NEXT: [[TMP1:%.*]] = fpext <2 x half> [[TRUNC]] to <2 x float> -; CHECK-NEXT: [[EXT:%.*]] = select <2 x i1> %cmp, <2 x float> [[TMP1]], <2 x float> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> %cmp, <2 x half> [[TRUNC]], <2 x half> +; CHECK-NEXT: [[EXT:%.*]] = fpext <2 x half> [[SEL]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[EXT]] ; %trunc = fptrunc <2 x float> %a to <2 x half>