Index: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1757,8 +1757,18 @@ return false; } -Instruction *InstCombiner::visitFPExt(CastInst &CI) { - return commonCastTransforms(CI); +Instruction *InstCombiner::visitFPExt(CastInst &FPExt) { + // If the source operand is a cast from integer to FP and known exact, then + // cast the integer operand directly to the destination type. + Type *Ty = FPExt.getType(); + Value *Src = FPExt.getOperand(0); + if (isa(Src) || isa(Src)) { + auto *FPCast = cast(Src); + if (isKnownExactCastIntToFP(*FPCast)) + return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty); + } + + return commonCastTransforms(FPExt); } /// fpto{s/u}i({u/s}itofp(X)) --> X or zext(X) or sext(X) or trunc(X) Index: llvm/test/Transforms/InstCombine/fpextend.ll =================================================================== --- llvm/test/Transforms/InstCombine/fpextend.ll +++ llvm/test/Transforms/InstCombine/fpextend.ll @@ -259,10 +259,11 @@ ret float %t56 } +; Convert from integer is exact, so convert directly to double. + define double @ItoFtoF_s25_f32_f64(i25 %i) { ; CHECK-LABEL: @ItoFtoF_s25_f32_f64( -; CHECK-NEXT: [[X:%.*]] = sitofp i25 [[I:%.*]] to float -; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double +; CHECK-NEXT: [[R:%.*]] = sitofp i25 [[I:%.*]] to double ; CHECK-NEXT: ret double [[R]] ; %x = sitofp i25 %i to float @@ -270,10 +271,11 @@ ret double %r } +; Convert from integer is exact, so convert directly to fp128. + define fp128 @ItoFtoF_u24_f32_f128(i24 %i) { ; CHECK-LABEL: @ItoFtoF_u24_f32_f128( -; CHECK-NEXT: [[X:%.*]] = uitofp i24 [[I:%.*]] to float -; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to fp128 +; CHECK-NEXT: [[R:%.*]] = uitofp i24 [[I:%.*]] to fp128 ; CHECK-NEXT: ret fp128 [[R]] ; %x = uitofp i24 %i to float @@ -281,6 +283,8 @@ ret fp128 %r } +; Negative test - intermediate rounding in float type. + define double @ItoFtoF_s26_f32_f64(i26 %i) { ; CHECK-LABEL: @ItoFtoF_s26_f32_f64( ; CHECK-NEXT: [[X:%.*]] = sitofp i26 [[I:%.*]] to float @@ -292,6 +296,8 @@ ret double %r } +; Negative test - intermediate rounding in float type. + define double @ItoFtoF_u25_f32_f64(i25 %i) { ; CHECK-LABEL: @ItoFtoF_u25_f32_f64( ; CHECK-NEXT: [[X:%.*]] = uitofp i25 [[I:%.*]] to float