================
@@ -5865,257 +5933,2301 @@ DoubleAPFloat frexp(const DoubleAPFloat &Arg, int 
&Exp,
                        std::move(Second));
 }
 
-} // namespace detail
-
-APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
-  if (usesLayout<IEEEFloat>(Semantics)) {
-    new (&IEEE) IEEEFloat(std::move(F));
-    return;
-  }
-  if (usesLayout<DoubleAPFloat>(Semantics)) {
-    const fltSemantics& S = F.getSemantics();
-    new (&Double) DoubleAPFloat(Semantics, APFloat(std::move(F), S),
-                                APFloat(APFloatBase::IEEEdouble()));
-    return;
-  }
-  llvm_unreachable("Unexpected semantics");
-}
+// class HexFloatArith implements HFP arithmetic using the conventions
+// and approaches of the arith library used by the IBM XL compiler,
+// and matches the behaviour of the hardware.
+class HexFloatArith {
+public:
+  struct value_t {
+    int sign; // -1 for negative, +1 for positive
+    int exponent;
+    APInt fraction;
+  };
+  static void fetch(const HexFloat &in, value_t &out);
+  static void align(value_t &, value_t &, bool sticky = false);
+  static void add(value_t &, const value_t &);
+  static void sub(value_t &, const value_t &);
+  static void mult(value_t &, const value_t &);
+  static void divide(value_t &, const value_t &);
+  static void norm(value_t &);
+  static int putres(const value_t &, HexFloat &);
+};
 
-Expected<APFloat::opStatus> APFloat::convertFromString(StringRef Str,
-                                                       roundingMode RM) {
-  APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM));
+unsigned int HexFloat::getNumPrecisionBits(const fltSemantics *semantics) {
+  assert(APFloat::usesLayout<HexFloat>(*semantics) && "not a HexFloat");
+  return 4 * semantics->precision;
 }
 
-hash_code hash_value(const APFloat &Arg) {
-  if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics()))
-    return hash_value(Arg.U.IEEE);
-  if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics()))
-    return hash_value(Arg.U.Double);
-  llvm_unreachable("Unexpected semantics");
+void HexFloat::initialize(const fltSemantics *ourSemantics) {
+  semantics = ourSemantics;
+  significand = APInt(getNumPrecisionBits(semantics), 0);
+  makeZero(/* IsNegative */ false);
 }
 
-APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
-    : APFloat(Semantics) {
-  auto StatusOrErr = convertFromString(S, rmNearestTiesToEven);
-  assert(StatusOrErr && "Invalid floating point representation");
-  consumeError(StatusOrErr.takeError());
+void HexFloat::assign(const HexFloat &rhs) {
+  assert(semantics == rhs.semantics);
+  sign = rhs.sign;
+  exponent = rhs.exponent;
+  significand = rhs.significand;
+  low_sign = rhs.low_sign;
+  low_exponent = rhs.low_exponent;
 }
 
-FPClassTest APFloat::classify() const {
-  if (isZero())
-    return isNegative() ? fcNegZero : fcPosZero;
-  if (isNormal())
-    return isNegative() ? fcNegNormal : fcPosNormal;
-  if (isDenormal())
-    return isNegative() ? fcNegSubnormal : fcPosSubnormal;
-  if (isInfinity())
-    return isNegative() ? fcNegInf : fcPosInf;
-  assert(isNaN() && "Other class of FP constant");
-  return isSignaling() ? fcSNan : fcQNan;
+HexFloat::HexFloat(const fltSemantics &ourSemantics)
+    : semantics(&ourSemantics) {
+  initialize(&ourSemantics);
 }
 
-bool APFloat::getExactInverse(APFloat *Inv) const {
-  // Only finite, non-zero numbers can have a useful, representable inverse.
-  // This check filters out +/- zero, +/- infinity, and NaN.
-  if (!isFiniteNonZero())
-    return false;
-
-  // Historically, this function rejects subnormal inputs.  One reason why this
-  // might be important is that subnormals may behave differently under FTZ/DAZ
-  // runtime behavior.
-  if (isDenormal())
-    return false;
-
-  // A number has an exact, representable inverse if and only if it is a power
-  // of two.
-  //
-  // Mathematical Rationale:
-  // 1. A binary floating-point number x is a dyadic rational, meaning it can
-  //    be written as x = M / 2^k for integers M (the significand) and k.
-  // 2. The inverse is 1/x = 2^k / M.
-  // 3. For 1/x to also be a dyadic rational (and thus exactly representable
-  //    in binary), its denominator M must also be a power of two.
-  //    Let's say M = 2^m.
-  // 4. Substituting this back into the formula for x, we get
-  //    x = (2^m) / (2^k) = 2^(m-k).
-  //
-  // This proves that x must be a power of two.
-
-  // getExactLog2Abs() returns the integer exponent if the number is a power of
-  // two or INT_MIN if it is not.
-  const int Exp = getExactLog2Abs();
-  if (Exp == INT_MIN)
-    return false;
-
-  // The inverse of +/- 2^Exp is +/- 2^(-Exp). We can compute this by
-  // scaling 1.0 by the negated exponent.
-  APFloat Reciprocal =
-      scalbn(APFloat::getOne(getSemantics(), /*Negative=*/isNegative()), -Exp,
-             rmTowardZero);
+HexFloat::HexFloat(const fltSemantics &ourSemantics, integerPart intValue)
+    : semantics(&ourSemantics) {
+  initialize(&ourSemantics);
+  static_assert(sizeof(intValue) <= sizeof(uint64_t));
+  if (!intValue) {
+    // initialize will have set us to zero
+    return;
+  }
 
-  // scalbn might round if the resulting exponent -Exp is outside the
-  // representable range, causing overflow (to infinity) or underflow. We
-  // must verify that the result is still the exact power of two we expect.
-  if (Reciprocal.getExactLog2Abs() != -Exp)
-    return false;
+  // intValue is regarded as an integer.
+  // Therefore its radix point is to the right of intValue.
+  // HexFloat has the radix point to the left of the significand,
+  // therefore we initialize the exponent to the number of hexits
+  // intValue could contain.  We then normalize, decremeting exponent
+  // each time we shift.
 
-  // Avoid multiplication with a subnormal, it is not safe on all platforms and
-  // may be slower than a normal division.
-  if (Reciprocal.isDenormal())
-    return false;
+  APInt working_significand(sizeof(intValue) * 8, intValue);
+  APInt mask(working_significand.getBitWidth(), 0);
+  mask.setBit(mask.getBitWidth() - 4); // lowest bit of top hexit
+  // the corresponding constructor for IEEE seems to assume that the
+  // value cannot be negative.
+  sign = 0;
+  exponent = (sizeof(intValue) * 8) / 4;
+  // normalize
+  while (mask.ugt(working_significand)) {
+    working_significand <<= 4;
+    exponent--;
+  }
+  int delta_width =
+      working_significand.getBitWidth() - significand.getBitWidth();
+  if (delta_width > 0) {
+    // HexFloat always rounds towards 0, so truncate is adequate
+    // APInt:trunc truncates on left
+    working_significand = working_significand.lshr(delta_width);
+    working_significand = working_significand.trunc(significand.getBitWidth());
+  } else if (delta_width < 0) {
+    // APInt::zext extends on left
+    working_significand = working_significand.zext(significand.getBitWidth());
+    working_significand <<= -delta_width;
+  }
+  significand = working_significand;
+}
 
-  assert(Reciprocal.isFiniteNonZero());
+HexFloat::HexFloat(const fltSemantics &ourSemantics, uninitializedTag)
+    : semantics(&ourSemantics) {
+  initialize(&ourSemantics);
+}
 
-  if (Inv)
-    *Inv = std::move(Reciprocal);
+HexFloat::HexFloat(const fltSemantics &ourSemantics,
+                   const APInt &EncodedHexFloat)
+    : semantics(&ourSemantics) {
+  initialize(&ourSemantics);
+  assert(semantics == &ourSemantics && "semantics not initialized as 
expected");
 
-  return true;
-}
+  assert(EncodedHexFloat.getBitWidth() == semantics->sizeInBits &&
+         "EncodedHexFloat has unexpected size");
 
-APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
-                                   roundingMode RM, bool *losesInfo) {
-  if (&getSemantics() == &ToSemantics) {
-    *losesInfo = false;
-    return opOK;
-  }
-  if (usesLayout<IEEEFloat>(getSemantics()) &&
-      usesLayout<IEEEFloat>(ToSemantics))
-    return U.IEEE.convert(ToSemantics, RM, losesInfo);
-  if (usesLayout<IEEEFloat>(getSemantics()) &&
-      usesLayout<DoubleAPFloat>(ToSemantics)) {
-    assert(&ToSemantics == &APFloatBase::semPPCDoubleDouble);
-    auto Ret =
-        U.IEEE.convert(APFloatBase::semPPCDoubleDoubleLegacy, RM, losesInfo);
-    *this = APFloat(ToSemantics, U.IEEE.bitcastToAPInt());
-    return Ret;
-  }
-  if (usesLayout<DoubleAPFloat>(getSemantics()) &&
-      usesLayout<IEEEFloat>(ToSemantics)) {
-    auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
-    *this = APFloat(std::move(getIEEE()), ToSemantics);
-    return Ret;
+  auto get_sign_exponent = [](const APInt &i, int &s, int &e) {
+    auto left_byte = i.getHiBits(8).trunc(8).getLimitedValue();
+    s = (left_byte & 0x80) ? 1 : 0;
+    e = (left_byte & 0x7f) - 64;
+  };
+  int s, e;
+  get_sign_exponent(EncodedHexFloat, s, e);
+  sign = s;
+  exponent = e;
+  if (semantics == &APFloatBase::HexFP128()) {
+    // we need to remove the sign/exponent byte from the lower order 64 bit
+    // value, and save them.
+    // We then need to form the significand from the low 56 bits of each part.
+    APInt low(EncodedHexFloat.trunc(64));
+    APInt high(EncodedHexFloat.lshr(64).trunc(64));
+    APInt low_significand(low.trunc(56).zext(112));
+    APInt high_significand(high.trunc(56).zext(112));
+    high_significand <<= 56;
+    significand = high_significand | low_significand;
+    get_sign_exponent(low, s, e);
+    low_sign = s;
+    low_exponent = e;
+  } else {
+    auto NumPrecisionBits = getNumPrecisionBits(semantics);
+    significand =
+        EncodedHexFloat.getLoBits(NumPrecisionBits).trunc(NumPrecisionBits);
   }
-  llvm_unreachable("Unexpected semantics");
+  assert(significand.getBitWidth() == getNumPrecisionBits(semantics));
 }
 
-APFloat APFloat::getAllOnesValue(const fltSemantics &Semantics) {
-  return APFloat(Semantics, APInt::getAllOnes(Semantics.sizeInBits));
+HexFloat::HexFloat(double d) {
+  semantics = &APFloatBase::HexFP64();
+  initialize(semantics);
+  llvm_unreachable("HexFloat constructor double: cannot create from double\n");
 }
 
-void APFloat::print(raw_ostream &OS) const {
-  SmallVector<char, 16> Buffer;
-  toString(Buffer);
-  OS << Buffer;
+HexFloat::HexFloat(float f) {
+  semantics = &APFloatBase::HexFP32();
+  initialize(semantics);
+  llvm_unreachable("HexFloat constructor float: cannot create from float\n");
----------------
shafik wrote:

Is this unconditional unreachable intended?

https://github.com/llvm/llvm-project/pull/179771
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to