Index: llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -247,6 +247,11 @@ Res = NPN; break; } + case Instruction::FPToUI: + case Instruction::FPToSI: + Res = CastInst::Create( + static_cast(Opc), I->getOperand(0), Ty); + break; default: // TODO: Can handle more cases here. llvm_unreachable("Unreachable!"); @@ -491,6 +496,16 @@ return false; return true; } + case Instruction::FPToUI: + case Instruction::FPToSI: { + int32_t BitWidth = Ty->getScalarSizeInBits(); + Type *InputTy = I->getOperand(0)->getType()->getScalarType(); + const fltSemantics &semantics = InputTy->getFltSemantics(); + int32_t MinBitWidth = I->getOpcode() == Instruction::FPToSI + ? APFloatBase::semanticsMaxExponent(semantics) + 1 + : APFloatBase::semanticsMaxExponent(semantics); + return BitWidth > MinBitWidth; + } default: // TODO: Can handle more cases here. break; Index: llvm/test/Transforms/InstCombine/trunc-fp-to-int.ll =================================================================== --- llvm/test/Transforms/InstCombine/trunc-fp-to-int.ll +++ llvm/test/Transforms/InstCombine/trunc-fp-to-int.ll @@ -7,9 +7,8 @@ define i16 @half_fptoui_i17_i16(half %x) { ; CHECK-LABEL: @half_fptoui_i17_i16( -; CHECK-NEXT: [[I:%.*]] = fptoui half [[X:%.*]] to i17 -; CHECK-NEXT: [[R:%.*]] = trunc i17 [[I]] to i16 -; CHECK-NEXT: ret i16 [[R]] +; CHECK-NEXT: [[I:%.*]] = fptoui half [[X:%.*]] to i16 +; CHECK-NEXT: ret i16 [[I]] ; %i = fptoui half %x to i17 %r = trunc i17 %i to i16 @@ -33,9 +32,8 @@ define i16 @half_fptoui_i32_i16(half %x) { ; CHECK-LABEL: @half_fptoui_i32_i16( -; CHECK-NEXT: [[I:%.*]] = fptoui half [[X:%.*]] to i32 -; CHECK-NEXT: [[R:%.*]] = trunc i32 [[I]] to i16 -; CHECK-NEXT: ret i16 [[R]] +; CHECK-NEXT: [[I:%.*]] = fptoui half [[X:%.*]] to i16 +; CHECK-NEXT: ret i16 [[I]] ; %i = fptoui half %x to i32 %r = trunc i32 %i to i16 @@ -59,9 +57,8 @@ define <4 x i16> @half_fptoui_4xi32_4xi16(<4 x half> %x) { ; CHECK-LABEL: @half_fptoui_4xi32_4xi16( -; CHECK-NEXT: [[I:%.*]] = fptoui <4 x half> [[X:%.*]] to <4 x i32> -; CHECK-NEXT: [[R:%.*]] = trunc <4 x i32> [[I]] to <4 x i16> -; CHECK-NEXT: ret <4 x i16> [[R]] +; CHECK-NEXT: [[I:%.*]] = fptoui <4 x half> [[X:%.*]] to <4 x i16> +; CHECK-NEXT: ret <4 x i16> [[I]] ; %i = fptoui <4 x half> %x to <4 x i32> %r = trunc <4 x i32> %i to <4 x i16> @@ -70,9 +67,8 @@ define i128 @bfloat_fptoui_i129_i128(bfloat %x) { ; CHECK-LABEL: @bfloat_fptoui_i129_i128( -; CHECK-NEXT: [[I:%.*]] = fptoui bfloat [[X:%.*]] to i129 -; CHECK-NEXT: [[R:%.*]] = trunc i129 [[I]] to i128 -; CHECK-NEXT: ret i128 [[R]] +; CHECK-NEXT: [[I:%.*]] = fptoui bfloat [[X:%.*]] to i128 +; CHECK-NEXT: ret i128 [[I]] ; %i = fptoui bfloat %x to i129 %r = trunc i129 %i to i128 @@ -94,9 +90,8 @@ define i128 @float_fptoui_i129_i128(float %x) { ; CHECK-LABEL: @float_fptoui_i129_i128( -; CHECK-NEXT: [[I:%.*]] = fptoui float [[X:%.*]] to i129 -; CHECK-NEXT: [[R:%.*]] = trunc i129 [[I]] to i128 -; CHECK-NEXT: ret i128 [[R]] +; CHECK-NEXT: [[I:%.*]] = fptoui float [[X:%.*]] to i128 +; CHECK-NEXT: ret i128 [[I]] ; %i = fptoui float %x to i129 %r = trunc i129 %i to i128 @@ -116,11 +111,10 @@ ret i127 %r } -define i1024 @float_fptoui_i1025_i1024(double %x) { -; CHECK-LABEL: @float_fptoui_i1025_i1024( -; CHECK-NEXT: [[I:%.*]] = fptoui double [[X:%.*]] to i1025 -; CHECK-NEXT: [[R:%.*]] = trunc i1025 [[I]] to i1024 -; CHECK-NEXT: ret i1024 [[R]] +define i1024 @double_fptoui_i1025_i1024(double %x) { +; CHECK-LABEL: @double_fptoui_i1025_i1024( +; CHECK-NEXT: [[I:%.*]] = fptoui double [[X:%.*]] to i1024 +; CHECK-NEXT: ret i1024 [[I]] ; %i = fptoui double %x to i1025 %r = trunc i1025 %i to i1024 @@ -129,13 +123,142 @@ ; Negative test - not enough bits to hold max double value (2**1023 * (2 − 2**−52)) -define i1023 @float_fptoui_i1024_i1023(float %x) { -; CHECK-LABEL: @float_fptoui_i1024_i1023( -; CHECK-NEXT: [[I:%.*]] = fptoui float [[X:%.*]] to i1024 +define i1023 @double_fptoui_i1024_i1023(double %x) { +; CHECK-LABEL: @double_fptoui_i1024_i1023( +; CHECK-NEXT: [[I:%.*]] = fptoui double [[X:%.*]] to i1024 ; CHECK-NEXT: [[R:%.*]] = trunc i1024 [[I]] to i1023 ; CHECK-NEXT: ret i1023 [[R]] ; - %i = fptoui float %x to i1024 + %i = fptoui double %x to i1024 %r = trunc i1024 %i to i1023 ret i1023 %r } + +; Negative test - not enough bits to hold min half value (-65504). + +define i16 @half_fptosi_i17_i16(half %x) { +; CHECK-LABEL: @half_fptosi_i17_i16( +; CHECK-NEXT: [[I:%.*]] = fptosi half [[X:%.*]] to i17 +; CHECK-NEXT: [[R:%.*]] = trunc i17 [[I]] to i16 +; CHECK-NEXT: ret i16 [[R]] +; + %i = fptosi half %x to i17 + %r = trunc i17 %i to i16 + ret i16 %r +} + +define i17 @half_fptosi_i18_i17(half %x) { +; CHECK-LABEL: @half_fptosi_i18_i17( +; CHECK-NEXT: [[I:%.*]] = fptosi half [[X:%.*]] to i17 +; CHECK-NEXT: ret i17 [[I]] +; + %i = fptosi half %x to i18 + %r = trunc i18 %i to i17 + ret i17 %r +} + +; Wider intermediate type is ok. + +define i17 @half_fptosi_i32_i17(half %x) { +; CHECK-LABEL: @half_fptosi_i32_i17( +; CHECK-NEXT: [[I:%.*]] = fptoui half [[X:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = trunc i32 [[I]] to i17 +; CHECK-NEXT: ret i17 [[R]] +; + %i = fptoui half %x to i32 + %r = trunc i32 %i to i17 + ret i17 %r +} + +; Wider final type is ok. + +define i18 @half_fptoui_i32_i18(half %x) { +; CHECK-LABEL: @half_fptoui_i32_i18( +; CHECK-NEXT: [[I:%.*]] = fptosi half [[X:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = trunc i32 [[I]] to i18 +; CHECK-NEXT: ret i18 [[R]] +; + %i = fptosi half %x to i32 + %r = trunc i32 %i to i18 + ret i18 %r +} + +; Vectors work too. + +define <4 x i17> @half_fptosi_4xi32_4xi17(<4 x half> %x) { +; CHECK-LABEL: @half_fptosi_4xi32_4xi17( +; CHECK-NEXT: [[I:%.*]] = fptosi <4 x half> [[X:%.*]] to <4 x i17> +; CHECK-NEXT: ret <4 x i17> [[I]] +; + %i = fptosi <4 x half> %x to <4 x i32> + %r = trunc <4 x i32> %i to <4 x i17> + ret <4 x i17> %r +} + +; Negative test - not enough bits to hold min float value. + +define i128 @bfloat_fptosi_i129_i128(bfloat %x) { +; CHECK-LABEL: @bfloat_fptosi_i129_i128( +; CHECK-NEXT: [[I:%.*]] = fptosi bfloat [[X:%.*]] to i129 +; CHECK-NEXT: [[R:%.*]] = trunc i129 [[I]] to i128 +; CHECK-NEXT: ret i128 [[R]] +; + %i = fptosi bfloat %x to i129 + %r = trunc i129 %i to i128 + ret i128 %r +} + +define i129 @bfloat_fptosi_i130_i129(bfloat %x) { +; CHECK-LABEL: @bfloat_fptosi_i130_i129( +; CHECK-NEXT: [[I:%.*]] = fptosi bfloat [[X:%.*]] to i129 +; CHECK-NEXT: ret i129 [[I]] +; + %i = fptosi bfloat %x to i130 + %r = trunc i130 %i to i129 + ret i129 %r +} + +define i129 @float_fptosi_i130_i129(float %x) { +; CHECK-LABEL: @float_fptosi_i130_i129( +; CHECK-NEXT: [[I:%.*]] = fptosi float [[X:%.*]] to i129 +; CHECK-NEXT: ret i129 [[I]] +; + %i = fptosi float %x to i130 + %r = trunc i130 %i to i129 + ret i129 %r +} + +; Negative test - not enough bits to hold min float value. + +define i128 @float_fptosi_i129_i128(float %x) { +; CHECK-LABEL: @float_fptosi_i129_i128( +; CHECK-NEXT: [[I:%.*]] = fptoui float [[X:%.*]] to i128 +; CHECK-NEXT: ret i128 [[I]] +; + %i = fptoui float %x to i129 + %r = trunc i129 %i to i128 + ret i128 %r +} + +define i1025 @double_fptosi_i1026_i1025(double %x) { +; CHECK-LABEL: @double_fptosi_i1026_i1025( +; CHECK-NEXT: [[I:%.*]] = fptosi double [[X:%.*]] to i1025 +; CHECK-NEXT: ret i1025 [[I]] +; + %i = fptosi double %x to i1026 + %r = trunc i1026 %i to i1025 + ret i1025 %r +} + +; Negative test - not enough bits to hold min double value. + +define i1024 @double_fptosi_i1025_i1024(double %x) { +; CHECK-LABEL: @double_fptosi_i1025_i1024( +; CHECK-NEXT: [[I:%.*]] = fptosi double [[X:%.*]] to i1025 +; CHECK-NEXT: [[R:%.*]] = trunc i1025 [[I]] to i1024 +; CHECK-NEXT: ret i1024 [[R]] +; + %i = fptosi double %x to i1025 + %r = trunc i1025 %i to i1024 + ret i1024 %r +}