Make APFloat->int conversions deterministic even in
authorDale Johannesen <dalej@apple.com>
Tue, 25 Sep 2007 23:07:07 +0000 (23:07 +0000)
committerDale Johannesen <dalej@apple.com>
Tue, 25 Sep 2007 23:07:07 +0000 (23:07 +0000)
cases with undefined behavior.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42328 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/APFloat.cpp
lib/VMCore/ConstantFold.cpp

index b3705f5058f19a9b81584d56d3dc426726c57ce7..348b8ab1cd90290f918914722c9bfb2e675e6e7f 100644 (file)
@@ -1399,13 +1399,28 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width,
   unsigned int msb, partsCount;
   int bits;
 
-  /* Handle the three special cases first.  */
-  if(category == fcInfinity || category == fcNaN)
-    return opInvalidOp;
-
   partsCount = partCountForBits(width);
 
-  if(category == fcZero) {
+  /* Handle the three special cases first.  We produce
+     a deterministic result even for the Invalid cases. */
+  if (category == fcNaN) {
+    // Neither sign nor isSigned affects this.
+    APInt::tcSet(parts, 0, partsCount);
+    return opInvalidOp;
+  }
+  if (category == fcInfinity) {
+    if (!sign && isSigned)
+      APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
+    else if (!sign && !isSigned)
+      APInt::tcSetLeastSignificantBits(parts, partsCount, width);
+    else if (sign && isSigned) {
+      APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
+      APInt::tcShiftLeft(parts, partsCount, width-1);
+    } else // sign && !isSigned
+      APInt::tcSet(parts, 0, partsCount);
+    return opInvalidOp;
+  }
+  if (category == fcZero) {
     APInt::tcSet(parts, 0, partsCount);
     return opOK;
   }
@@ -1418,6 +1433,19 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width,
   if(bits > 0) {
     lost_fraction = tmp.shiftSignificandRight(bits);
   } else {
+    if (-bits >= semantics->precision) {
+      // Unrepresentably large.
+      if (!sign && isSigned)
+        APInt::tcSetLeastSignificantBits(parts, partsCount, width-1);
+      else if (!sign && !isSigned)
+        APInt::tcSetLeastSignificantBits(parts, partsCount, width);
+      else if (sign && isSigned) {
+        APInt::tcSetLeastSignificantBits(parts, partsCount, 1);
+        APInt::tcShiftLeft(parts, partsCount, width-1);
+      } else // sign && !isSigned
+        APInt::tcSet(parts, 0, partsCount);
+      return (opStatus)(opOverflow | opInexact);
+    }
     tmp.shiftSignificandLeft(-bits);
     lost_fraction = lfExactlyZero;
   }
index d8b8566193aedd95f6fe1d89844c8e443e1246fc..7154afb1833a74c43842850b36b8454ebc06af6f 100644 (file)
@@ -197,8 +197,6 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V,
       APFloat::opStatus status = V.convertToInteger(x, DestBitWidth, 
                              opc==Instruction::FPToSI,
                              APFloat::rmTowardZero);
-      if (status!=APFloat::opOK && status!=APFloat::opInexact)
-        return 0; // give up
       APInt Val(DestBitWidth, 2, x);
       return ConstantInt::get(Val);
     }