[llvm] c048a02 - [InstCombine] fold FP trunc into exact itofp
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sun May 24 06:33:00 PDT 2020
Author: Sanjay Patel
Date: 2020-05-24T09:30:19-04:00
New Revision: c048a02b5b26c21a2a891131e3d52c7ddbc3cf62
URL: https://github.com/llvm/llvm-project/commit/c048a02b5b26c21a2a891131e3d52c7ddbc3cf62
DIFF: https://github.com/llvm/llvm-project/commit/c048a02b5b26c21a2a891131e3d52c7ddbc3cf62.diff
LOG: [InstCombine] fold FP trunc into exact itofp
Similar to D79116 and rGbfd512160fe0 - if the 1st cast
is exact, then we can go directly to the destination
type because there is no double-rounding.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
llvm/test/Transforms/InstCombine/fptrunc.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 44ca3613ae4d..c68f9e898007 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1558,6 +1558,48 @@ static Type *getMinimumFPType(Value *V) {
return V->getType();
}
+/// Return true if the cast from integer to FP can be proven to be exact for all
+/// possible inputs (the conversion does not lose any precision).
+static bool isKnownExactCastIntToFP(CastInst &I) {
+ CastInst::CastOps Opcode = I.getOpcode();
+ assert((Opcode == CastInst::SIToFP || Opcode == CastInst::UIToFP) &&
+ "Unexpected cast");
+ Value *Src = I.getOperand(0);
+ Type *SrcTy = Src->getType();
+ Type *FPTy = I.getType();
+ bool IsSigned = Opcode == Instruction::SIToFP;
+ int SrcSize = (int)SrcTy->getScalarSizeInBits() - IsSigned;
+
+ // Easy case - if the source integer type has less bits than the FP mantissa,
+ // then the cast must be exact.
+ int DestNumSigBits = FPTy->getFPMantissaWidth();
+ if (SrcSize <= DestNumSigBits)
+ return true;
+
+ // Cast from FP to integer and back to FP is independent of the intermediate
+ // integer width because of poison on overflow.
+ Value *F;
+ if (match(Src, m_FPToSI(m_Value(F))) || match(Src, m_FPToUI(m_Value(F)))) {
+ // If this is uitofp (fptosi F), the source needs an extra bit to avoid
+ // potential rounding of negative FP input values.
+ int SrcNumSigBits = F->getType()->getFPMantissaWidth();
+ if (!IsSigned && match(Src, m_FPToSI(m_Value())))
+ SrcNumSigBits++;
+
+ // [su]itofp (fpto[su]i F) --> exact if the source type has less or equal
+ // significant bits than the destination (and make sure neither type is
+ // weird -- ppc_fp128).
+ if (SrcNumSigBits > 0 && DestNumSigBits > 0 &&
+ SrcNumSigBits <= DestNumSigBits)
+ return true;
+ }
+
+ // TODO:
+ // Try harder to find if the source integer type has less significant bits.
+ // For example, compute number of sign bits or compute low bit mask.
+ return false;
+}
+
Instruction *InstCombiner::visitFPTrunc(FPTruncInst &FPT) {
if (Instruction *I = commonCastTransforms(FPT))
return I;
@@ -1731,48 +1773,14 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &FPT) {
if (Instruction *I = shrinkInsertElt(FPT, Builder))
return I;
- return nullptr;
-}
-
-/// Return true if the cast from integer to FP can be proven to be exact for all
-/// possible inputs (the conversion does not lose any precision).
-static bool isKnownExactCastIntToFP(CastInst &I) {
- CastInst::CastOps Opcode = I.getOpcode();
- assert((Opcode == CastInst::SIToFP || Opcode == CastInst::UIToFP) &&
- "Unexpected cast");
- Value *Src = I.getOperand(0);
- Type *SrcTy = Src->getType();
- Type *FPTy = I.getType();
- bool IsSigned = Opcode == Instruction::SIToFP;
- int SrcSize = (int)SrcTy->getScalarSizeInBits() - IsSigned;
-
- // Easy case - if the source integer type has less bits than the FP mantissa,
- // then the cast must be exact.
- int DestNumSigBits = FPTy->getFPMantissaWidth();
- if (SrcSize <= DestNumSigBits)
- return true;
-
- // Cast from FP to integer and back to FP is independent of the intermediate
- // integer width because of poison on overflow.
- Value *F;
- if (match(Src, m_FPToSI(m_Value(F))) || match(Src, m_FPToUI(m_Value(F)))) {
- // If this is uitofp (fptosi F), the source needs an extra bit to avoid
- // potential rounding of negative FP input values.
- int SrcNumSigBits = F->getType()->getFPMantissaWidth();
- if (!IsSigned && match(Src, m_FPToSI(m_Value())))
- SrcNumSigBits++;
-
- // [su]itofp (fpto[su]i F) --> exact if the source type has less or equal
- // significant bits than the destination (and make sure neither type is
- // weird -- ppc_fp128).
- if (SrcNumSigBits > 0 && DestNumSigBits > 0 &&
- SrcNumSigBits <= DestNumSigBits)
- return true;
+ Value *Src = FPT.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);
}
- // TODO:
- // Try harder to find if the source integer type has less significant bits.
- return false;
+ return nullptr;
}
Instruction *InstCombiner::visitFPExt(CastInst &FPExt) {
diff --git a/llvm/test/Transforms/InstCombine/fptrunc.ll b/llvm/test/Transforms/InstCombine/fptrunc.ll
index 9c9ee11a32c2..c04c4b5c66c4 100644
--- a/llvm/test/Transforms/InstCombine/fptrunc.ll
+++ b/llvm/test/Transforms/InstCombine/fptrunc.ll
@@ -141,8 +141,7 @@ define float @fptrunc_select_true_val_type_mismatch_fast(half %x, double %y, i1
define <2 x float> @ItoFtoF_s54_f64_f32(<2 x i54> %i) {
; CHECK-LABEL: @ItoFtoF_s54_f64_f32(
-; CHECK-NEXT: [[X:%.*]] = sitofp <2 x i54> [[I:%.*]] to <2 x double>
-; CHECK-NEXT: [[R:%.*]] = fptrunc <2 x double> [[X]] to <2 x float>
+; CHECK-NEXT: [[R:%.*]] = sitofp <2 x i54> [[I:%.*]] to <2 x float>
; CHECK-NEXT: ret <2 x float> [[R]]
;
%x = sitofp <2 x i54> %i to <2 x double>
@@ -157,7 +156,7 @@ define half @ItoFtoF_u24_f32_f16(i24 %i) {
; CHECK-LABEL: @ItoFtoF_u24_f32_f16(
; CHECK-NEXT: [[X:%.*]] = uitofp i24 [[I:%.*]] to float
; CHECK-NEXT: call void @use(float [[X]])
-; CHECK-NEXT: [[R:%.*]] = fptrunc float [[X]] to half
+; CHECK-NEXT: [[R:%.*]] = uitofp i24 [[I]] to half
; CHECK-NEXT: ret half [[R]]
;
%x = uitofp i24 %i to float
More information about the llvm-commits
mailing list