forked from OSchip/llvm-project
[InstCombine] fold fpext into exact integer-to-FP cast
We can combine a floating-point extension cast with a conversion from integer if we know the earlier cast is exact. This is an optimization suggested in PR36617: https://bugs.llvm.org/show_bug.cgi?id=36617#c19 However, this patch does not change the example suggested there. This patch only uses the existing analysis to handle cases where the integer source value magnitude is narrower than the intermediate FP mantissa (guarantees that the conversion to FP is exact). Follow-up patches to the analysis function can enable more cases. Differential Revision: https://reviews.llvm.org/D79116
This commit is contained in:
parent
1d2c1fcf41
commit
a62533c29f
|
@ -1757,8 +1757,18 @@ static bool isKnownExactCastIntToFP(CastInst &I) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::visitFPExt(CastInst &CI) {
|
Instruction *InstCombiner::visitFPExt(CastInst &FPExt) {
|
||||||
return commonCastTransforms(CI);
|
// 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<SIToFPInst>(Src) || isa<UIToFPInst>(Src)) {
|
||||||
|
auto *FPCast = cast<CastInst>(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)
|
/// fpto{s/u}i({u/s}itofp(X)) --> X or zext(X) or sext(X) or trunc(X)
|
||||||
|
|
|
@ -259,10 +259,11 @@ define float @test18(half %x, half %y) nounwind {
|
||||||
ret float %t56
|
ret float %t56
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Convert from integer is exact, so convert directly to double.
|
||||||
|
|
||||||
define double @ItoFtoF_s25_f32_f64(i25 %i) {
|
define double @ItoFtoF_s25_f32_f64(i25 %i) {
|
||||||
; CHECK-LABEL: @ItoFtoF_s25_f32_f64(
|
; CHECK-LABEL: @ItoFtoF_s25_f32_f64(
|
||||||
; CHECK-NEXT: [[X:%.*]] = sitofp i25 [[I:%.*]] to float
|
; CHECK-NEXT: [[R:%.*]] = sitofp i25 [[I:%.*]] to double
|
||||||
; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double
|
|
||||||
; CHECK-NEXT: ret double [[R]]
|
; CHECK-NEXT: ret double [[R]]
|
||||||
;
|
;
|
||||||
%x = sitofp i25 %i to float
|
%x = sitofp i25 %i to float
|
||||||
|
@ -270,10 +271,11 @@ define double @ItoFtoF_s25_f32_f64(i25 %i) {
|
||||||
ret double %r
|
ret double %r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Convert from integer is exact, so convert directly to fp128.
|
||||||
|
|
||||||
define fp128 @ItoFtoF_u24_f32_f128(i24 %i) {
|
define fp128 @ItoFtoF_u24_f32_f128(i24 %i) {
|
||||||
; CHECK-LABEL: @ItoFtoF_u24_f32_f128(
|
; CHECK-LABEL: @ItoFtoF_u24_f32_f128(
|
||||||
; CHECK-NEXT: [[X:%.*]] = uitofp i24 [[I:%.*]] to float
|
; CHECK-NEXT: [[R:%.*]] = uitofp i24 [[I:%.*]] to fp128
|
||||||
; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to fp128
|
|
||||||
; CHECK-NEXT: ret fp128 [[R]]
|
; CHECK-NEXT: ret fp128 [[R]]
|
||||||
;
|
;
|
||||||
%x = uitofp i24 %i to float
|
%x = uitofp i24 %i to float
|
||||||
|
@ -281,6 +283,8 @@ define fp128 @ItoFtoF_u24_f32_f128(i24 %i) {
|
||||||
ret fp128 %r
|
ret fp128 %r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Negative test - intermediate rounding in float type.
|
||||||
|
|
||||||
define double @ItoFtoF_s26_f32_f64(i26 %i) {
|
define double @ItoFtoF_s26_f32_f64(i26 %i) {
|
||||||
; CHECK-LABEL: @ItoFtoF_s26_f32_f64(
|
; CHECK-LABEL: @ItoFtoF_s26_f32_f64(
|
||||||
; CHECK-NEXT: [[X:%.*]] = sitofp i26 [[I:%.*]] to float
|
; CHECK-NEXT: [[X:%.*]] = sitofp i26 [[I:%.*]] to float
|
||||||
|
@ -292,6 +296,8 @@ define double @ItoFtoF_s26_f32_f64(i26 %i) {
|
||||||
ret double %r
|
ret double %r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Negative test - intermediate rounding in float type.
|
||||||
|
|
||||||
define double @ItoFtoF_u25_f32_f64(i25 %i) {
|
define double @ItoFtoF_u25_f32_f64(i25 %i) {
|
||||||
; CHECK-LABEL: @ItoFtoF_u25_f32_f64(
|
; CHECK-LABEL: @ItoFtoF_u25_f32_f64(
|
||||||
; CHECK-NEXT: [[X:%.*]] = uitofp i25 [[I:%.*]] to float
|
; CHECK-NEXT: [[X:%.*]] = uitofp i25 [[I:%.*]] to float
|
||||||
|
|
Loading…
Reference in New Issue