Generalize tcFullMultiply so that the operands can be of differing
part widths.  Also, return the number of parts actually required to
hold the result's value.
Remove an over-cautious condition from rounding of float->hex conversion.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42669 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 01b49d08..61e8f52 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -1114,10 +1114,12 @@
   static int tcMultiply(integerPart *, const integerPart *,
 			const integerPart *, unsigned);
 
-  /// DST = LHS * RHS, where DST has twice the width as the operands.
-  /// No overflow occurs.  DST must be disjoint from both operands.
-  static void tcFullMultiply(integerPart *, const integerPart *,
-			     const integerPart *, unsigned);
+  /// DST = LHS * RHS, where DST has width the sum of the widths of
+  /// the operands.  No overflow occurs.  DST must be disjoint from
+  /// both operands. Returns the number of parts required to hold the
+  /// result.
+  static unsigned int tcFullMultiply(integerPart *, const integerPart *,
+				     const integerPart *, unsigned, unsigned);
 
   /// If RHS is zero LHS and REMAINDER are left unchanged, return one.
   /// Otherwise set LHS to LHS / RHS with the fractional part
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 3746ae8..34784a0 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -519,7 +519,7 @@
   partsCount = partCount();
 
   APInt::tcFullMultiply(fullSignificand, lhsSignificand,
-                        rhs.significandParts(), partsCount);
+                        rhs.significandParts(), partsCount, partsCount);
 
   lost_fraction = lfExactlyZero;
   omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
@@ -1795,7 +1795,7 @@
 
   /* hexDigits of zero means use the required number for the
      precision.  Otherwise, see if we are truncating.  If we are,
-     found out if we need to round away from zero.  */
+     find out if we need to round away from zero.  */
   if (hexDigits) {
     if (hexDigits < outputDigits) {
       /* We are dropping non-zero bits, so need to check how to round.
@@ -1845,7 +1845,8 @@
     do {
       q--;
       *q = hexDigitChars[hexDigitValue (*q) + 1];
-    } while (*q == '0' && q > p);
+    } while (*q == '0');
+    assert (q >= p);
   } else {
     /* Add trailing zeroes.  */
     memset (dst, '0', outputDigits);
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 63bde6c..e7b7c1f 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -2363,25 +2363,32 @@
   return overflow;
 }
 
-/* DST = LHS * RHS, where DST has twice the width as the operands.  No
-   overflow occurs.  DST must be disjoint from both operands.  */
-void
+/* DST = LHS * RHS, where DST has width the sum of the widths of the
+   operands.  No overflow occurs.  DST must be disjoint from both
+   operands.  Returns the number of parts required to hold the
+   result.  */
+unsigned int
 APInt::tcFullMultiply(integerPart *dst, const integerPart *lhs,
-                      const integerPart *rhs, unsigned int parts)
+                      const integerPart *rhs, unsigned int lhsParts,
+                      unsigned int rhsParts)
 {
-  unsigned int i;
-  int overflow;
+  /* Put the narrower number on the LHS for less loops below.  */
+  if (lhsParts > rhsParts) {
+    return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts);
+  } else {
+    unsigned int n;
 
-  assert(dst != lhs && dst != rhs);
+    assert(dst != lhs && dst != rhs);
 
-  overflow = 0;
-  tcSet(dst, 0, parts);
+    tcSet(dst, 0, rhsParts);
 
-  for(i = 0; i < parts; i++)
-    overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts,
-                               parts + 1, true);
+    for(n = 0; n < lhsParts; n++)
+      tcMultiplyPart(&dst[n], rhs, lhs[n], 0, rhsParts, rhsParts + 1, true);
 
-  assert(!overflow);
+    n = lhsParts + rhsParts;
+
+    return n - (dst[n - 1] == 0);
+  }
 }
 
 /* If RHS is zero LHS and REMAINDER are left unchanged, return one.