[llvm] 61a89e1 - [LegalizeDAG][Mips] Add an assert to protect a uint_to_fp implementation from double rounding. Add a i32->f32 uint_to_fp implementation that avoids this code.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 16 11:08:44 PST 2020


Author: Craig Topper
Date: 2020-01-16T11:08:16-08:00
New Revision: 61a89e17df4c3baf9cdf317d8ae3a73788f2aa92

URL: https://github.com/llvm/llvm-project/commit/61a89e17df4c3baf9cdf317d8ae3a73788f2aa92
DIFF: https://github.com/llvm/llvm-project/commit/61a89e17df4c3baf9cdf317d8ae3a73788f2aa92.diff

LOG: [LegalizeDAG][Mips] Add an assert to protect a uint_to_fp implementation from double rounding. Add a i32->f32 uint_to_fp implementation that avoids this code.

The algorithm here only works if the sint_to_fp doesn't do any
rounding. Otherwise it can round before the offset fixup is
applied. Add an assert to protect this.

To avoid breaking the one test in tree that tested this code
with a set of types that fail the assert, I've enabled i32->f32
to use the i64->f32 algorithm. This only occurs when f64 isn't
a legal type. If f64 is legal then we do i32->f64->f32 instead.

Differential Revision: https://reviews.llvm.org/D72794

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/test/CodeGen/Mips/uitofp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index ffa2f4542b92..d416aad91953 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2421,10 +2421,11 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(SDNode *Node,
   assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
 
   // TODO: Generalize this for use with other types.
-  if (SrcVT == MVT::i64 && DestVT == MVT::f32) {
-    LLVM_DEBUG(dbgs() << "Converting unsigned i64 to f32\n");
+  if ((SrcVT == MVT::i32 || SrcVT == MVT::i64) && DestVT == MVT::f32) {
+    LLVM_DEBUG(dbgs() << "Converting unsigned i32/i64 to f32\n");
     // For unsigned conversions, convert them to signed conversions using the
-    // algorithm from the x86_64 __floatundidf in compiler_rt.
+    // algorithm from the x86_64 __floatundisf in compiler_rt. That method
+    // should be valid for i32->f32 as well.
 
     // TODO: This really should be implemented using a branch rather than a
     // select.  We happen to get lucky and machinesink does the right
@@ -2469,8 +2470,13 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(SDNode *Node,
     return DAG.getSelect(dl, DestVT, SignBitTest, Slow, Fast);
   }
 
-  // FIXME: This can produce slightly incorrect results. See details in
-  // FIXME: https://reviews.llvm.org/D69275
+  // The following optimization is valid only if every value in SrcVT (when
+  // treated as signed) is representable in DestVT.  Check that the mantissa
+  // size of DestVT is >= than the number of bits in SrcVT -1.
+  assert(APFloat::semanticsPrecision(DAG.EVTToAPFloatSemantics(DestVT)) >=
+             SrcVT.getSizeInBits() - 1 &&
+         "Cannot perform lossless SINT_TO_FP!");
+
   SDValue Tmp1;
   if (Node->isStrictFPOpcode()) {
     Tmp1 = DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, { DestVT, MVT::Other },

diff  --git a/llvm/test/CodeGen/Mips/uitofp.ll b/llvm/test/CodeGen/Mips/uitofp.ll
index 9b1f7478fb72..63b0c7bdb29c 100644
--- a/llvm/test/CodeGen/Mips/uitofp.ll
+++ b/llvm/test/CodeGen/Mips/uitofp.ll
@@ -7,17 +7,18 @@ define void @f0() nounwind {
 ; CHECK-NEXT:    addiu $sp, $sp, -8
 ; CHECK-NEXT:    addiu $1, $zero, 1
 ; CHECK-NEXT:    sw $1, 4($sp)
-; CHECK-NEXT:    lui $1, %hi($CPI0_0)
-; CHECK-NEXT:    addiu $1, $1, %lo($CPI0_0)
-; CHECK-NEXT:    lw $2, 4($sp)
-; CHECK-NEXT:    srl $3, $2, 29
-; CHECK-NEXT:    andi $3, $3, 4
-; CHECK-NEXT:    addu $1, $1, $3
-; CHECK-NEXT:    lwc1 $f0, 0($1)
-; CHECK-NEXT:    mtc1 $2, $f1
+; CHECK-NEXT:    lw $1, 4($sp)
+; CHECK-NEXT:    srl $2, $1, 1
+; CHECK-NEXT:    andi $3, $1, 1
+; CHECK-NEXT:    or $2, $3, $2
+; CHECK-NEXT:    mtc1 $2, $f0
+; CHECK-NEXT:    cvt.s.w $f0, $f0
+; CHECK-NEXT:    add.s $f0, $f0, $f0
+; CHECK-NEXT:    mtc1 $1, $f1
 ; CHECK-NEXT:    cvt.s.w $f1, $f1
-; CHECK-NEXT:    add.s $f0, $f1, $f0
-; CHECK-NEXT:    swc1 $f0, 0($sp)
+; CHECK-NEXT:    slti $1, $1, 0
+; CHECK-NEXT:    movn.s $f1, $f0, $1
+; CHECK-NEXT:    swc1 $f1, 0($sp)
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    addiu $sp, $sp, 8
 entry:


        


More information about the llvm-commits mailing list