[llvm] 5cf1703 - [InstCombine] add helper for known exact cast to FP; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 12:22:45 PDT 2020


Author: Sanjay Patel
Date: 2020-05-08T15:22:36-04:00
New Revision: 5cf17034e53777ec1b1874fbbaf0b579634734fc

URL: https://github.com/llvm/llvm-project/commit/5cf17034e53777ec1b1874fbbaf0b579634734fc
DIFF: https://github.com/llvm/llvm-project/commit/5cf17034e53777ec1b1874fbbaf0b579634734fc.diff

LOG: [InstCombine] add helper for known exact cast to FP; NFC

As suggested in D79116 - there's shared logic between the
existing code and potential new folds. This could go in
ValueTracking if it seems generally useful.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 9a3e8aeb0c23..4e08043d718f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1735,6 +1735,28 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &FPT) {
   return nullptr;
 }
 
+/// Return true if the cast from integer to FP can be proven to be exact for all
+/// possible inputs (the conversion does 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.
+  if (SrcSize <= FPTy->getFPMantissaWidth())
+    return true;
+
+  // TODO:
+  // Try harder to find if the source integer type has less significant bits.
+  return false;
+}
+
 Instruction *InstCombiner::visitFPExt(CastInst &CI) {
   return commonCastTransforms(CI);
 }
@@ -1746,32 +1768,32 @@ Instruction *InstCombiner::visitFPExt(CastInst &CI) {
 Instruction *InstCombiner::foldItoFPtoI(CastInst &FI) {
   if (!isa<UIToFPInst>(FI.getOperand(0)) && !isa<SIToFPInst>(FI.getOperand(0)))
     return nullptr;
-  Instruction *OpI = cast<Instruction>(FI.getOperand(0));
 
+  auto *OpI = cast<CastInst>(FI.getOperand(0));
   Value *X = OpI->getOperand(0);
-  Type *DestType = FI.getType();
-  Type *FPType = OpI->getType();
   Type *XType = X->getType();
-  bool IsInputSigned = isa<SIToFPInst>(OpI);
+  Type *DestType = FI.getType();
   bool IsOutputSigned = isa<FPToSIInst>(FI);
 
-  // We can safely assume the conversion won't overflow the output range,
-  // because (for example) (uint8_t)18293.f is undefined behavior.
-
   // Since we can assume the conversion won't overflow, our decision as to
   // whether the input will fit in the float should depend on the minimum
   // of the input range and output range.
 
   // This means this is also safe for a signed input and unsigned output, since
   // a negative input would lead to undefined behavior.
-  int InputSize = (int)XType->getScalarSizeInBits() - IsInputSigned;
-  int OutputSize = (int)DestType->getScalarSizeInBits() - IsOutputSigned;
-  int MinIntWidth = std::min(InputSize, OutputSize);
-
-  if (MinIntWidth > FPType->getFPMantissaWidth())
-    return nullptr;
+  if (!isKnownExactCastIntToFP(*OpI)) {
+    // The first cast may not round exactly based on the source integer width
+    // and FP width, but the overflow UB rules can still allow this to fold.
+    // If the destination type is narrow, that means the intermediate FP value
+    // must be large enough to hold the source value exactly.
+    // For example, (uint8_t)((float)(uint32_t 16777217) is undefined behavior.
+    int OutputSize = (int)DestType->getScalarSizeInBits() - IsOutputSigned;
+    if (OutputSize > OpI->getType()->getFPMantissaWidth())
+      return nullptr;
+  }
 
   if (DestType->getScalarSizeInBits() > XType->getScalarSizeInBits()) {
+    bool IsInputSigned = isa<SIToFPInst>(OpI);
     if (IsInputSigned && IsOutputSigned)
       return new SExtInst(X, DestType);
     return new ZExtInst(X, DestType);


        


More information about the llvm-commits mailing list