Izaron created this revision.
Izaron added reviewers: cor3ntin, aaron.ballman.
Herald added a subscriber: hiraditya.
Herald added a project: All.
Izaron requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Support constexpr versions of __builtin_fmax, __builtin_fmin,
__builtin_ilogb, __builtin_logb, __builtin_scalbn and their
variations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134136

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-math.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp

Index: llvm/lib/Support/APFloat.cpp
===================================================================
--- llvm/lib/Support/APFloat.cpp
+++ llvm/lib/Support/APFloat.cpp
@@ -4198,6 +4198,19 @@
   return Normalized.exponent - SignificandBits;
 }
 
+IEEEFloat logb(const IEEEFloat &Arg) {
+  IEEEFloat Result(Arg.getSemantics());
+  if (Arg.isNaN())
+    Result.makeNaN();
+  else if (Arg.isZero())
+    Result.makeInf(/* Negative = */ true);
+  else if (Arg.isInfinity())
+    Result.makeInf(/* Negative = */ false);
+  else
+    Result = IEEEFloat(static_cast<double>(ilogb(Arg)));
+  return Result;
+}
+
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) {
   auto MaxExp = X.getSemantics().maxExponent;
   auto MinExp = X.getSemantics().minExponent;
Index: llvm/include/llvm/ADT/APFloat.h
===================================================================
--- llvm/include/llvm/ADT/APFloat.h
+++ llvm/include/llvm/ADT/APFloat.h
@@ -592,6 +592,7 @@
 
 hash_code hash_value(const IEEEFloat &Arg);
 int ilogb(const IEEEFloat &Arg);
+IEEEFloat logb(const IEEEFloat &Arg);
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
 IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
 
@@ -1248,6 +1249,9 @@
 
   friend hash_code hash_value(const APFloat &Arg);
   friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
+  friend APFloat logb(const APFloat &Arg) {
+    return APFloat(logb(Arg.getIEEE()), Arg.getSemantics());
+  }
   friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
   friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
   friend IEEEFloat;
Index: clang/test/Sema/constant-builtins-math.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/constant-builtins-math.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(__builtin_fmax(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf(12.34f, 56.78f) == 56.78f);
+static_assert(__builtin_fmaxl(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf16(12.0, 56.0) == 56.0);
+static_assert(__builtin_fmaxf128(12.34, 56.78) == 56.78);
+
+static_assert(__builtin_fmin(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf(12.34f, 56.78f) == 12.34f);
+static_assert(__builtin_fminl(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf16(12.0, 56.0) == 12.0);
+static_assert(__builtin_fminf128(12.34, 56.78) == 12.34);
+
+// TODO: investigate why this is `INT_MIN + 1` instead of `INT_MIN`
+static_assert(__builtin_ilogb(0.0) == -2147483647);
+static_assert(__builtin_ilogb(__builtin_inf()) == 2147483647);
+static_assert(__builtin_ilogb(__builtin_nan("")) == -2147483648);
+static_assert(__builtin_ilogb(1.0) == 0);
+static_assert(__builtin_ilogb(32.0) == 5);
+static_assert(__builtin_ilogb(1024.0) == 10);
+static_assert(__builtin_ilogb(-1024.0) == 10);
+static_assert(__builtin_ilogb(0.1) == -4);
+static_assert(__builtin_ilogb(0.0000000000001) == -44);
+
+static_assert(__builtin_logb(0.0) == -__builtin_inf());
+static_assert(__builtin_logb(__builtin_inf()) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_logb(__builtin_nan(""))));
+static_assert(__builtin_logb(1.0) == 0.0);
+static_assert(__builtin_logb(32.0) == 5.0);
+static_assert(__builtin_logb(1024.0) == 10.0);
+static_assert(__builtin_logb(-1024.0) == 10.0);
+static_assert(__builtin_logb(0.1) == -4.0);
+static_assert(__builtin_logb(0.0000000000001) == -44.0);
+
+static_assert(__builtin_scalbn(12.5, 0) == 12.5);
+static_assert(__builtin_scalbn(12.5, 1) == 25);
+static_assert(__builtin_scalbn(12.5, 3) == 100.0);
+static_assert(__builtin_scalbn(0.0, 100) == 0);
+static_assert(__builtin_scalbn(__builtin_inf(), 100) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_scalbn(__builtin_nan(""), 100)));
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -12410,6 +12410,19 @@
       return false;
     return Success(DidOverflow, E);
   }
+
+  case Builtin::BI__builtin_ilogb:
+  case Builtin::BI__builtin_ilogbf:
+  case Builtin::BI__builtin_ilogbl:
+  case Builtin::BI__builtin_ilogbf128: {
+    APFloat F(0.0);
+    if (!EvaluateFloat(E->getArg(0), F, Info))
+      return false;
+    APSInt Logb(llvm::APInt(32, ilogb(F), /* isSigned = */ true),
+                /* isUnsigned = */ false);
+    Result = APValue(std::move(Logb));
+    return true;
+  }
   }
 }
 
@@ -14021,6 +14034,58 @@
     Result.copySign(RHS);
     return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+    APFloat RHS(0.);
+    if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+        !EvaluateFloat(E->getArg(1), RHS, Info))
+      return false;
+    if (RHS > Result)
+      Result = RHS;
+    return true;
+  }
+
+  case Builtin::BI__builtin_fmin:
+  case Builtin::BI__builtin_fminf:
+  case Builtin::BI__builtin_fminl:
+  case Builtin::BI__builtin_fminf16:
+  case Builtin::BI__builtin_fminf128: {
+    APFloat RHS(0.);
+    if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+        !EvaluateFloat(E->getArg(1), RHS, Info))
+      return false;
+    if (RHS < Result)
+      Result = RHS;
+    return true;
+  }
+
+  case Builtin::BI__builtin_logb:
+  case Builtin::BI__builtin_logbf:
+  case Builtin::BI__builtin_logbl:
+  case Builtin::BI__builtin_logbf128: {
+    APFloat F(0.0);
+    if (!EvaluateFloat(E->getArg(0), F, Info))
+      return false;
+    Result = logb(F);
+    return true;
+  }
+
+  case Builtin::BI__builtin_scalbn:
+  case Builtin::BI__builtin_scalbnf:
+  case Builtin::BI__builtin_scalbnl:
+  case Builtin::BI__builtin_scalbnf128: {
+    APFloat X(0.0);
+    APSInt Exp;
+    if (!EvaluateFloat(E->getArg(0), X, Info) ||
+        !EvaluateInteger(E->getArg(1), Exp, Info))
+      return false;
+    Result = scalbn(X, Exp.getExtValue(), APFloat::rmNearestTiesToEven);
+    return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4659,13 +4659,17 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
+* ``__builtin_fmin``
 * ``__builtin_fpclassify``
+* ``__builtin_ilogb``
 * ``__builtin_inf``
 * ``__builtin_isinf``
 * ``__builtin_isinf_sign``
 * ``__builtin_isfinite``
 * ``__builtin_isnan``
 * ``__builtin_isnormal``
+* ``__builtin_logb``
 * ``__builtin_nan``
 * ``__builtin_nans``
 * ``__builtin_parity``
@@ -4682,6 +4686,7 @@
 * ``__builtin_rotateright16``
 * ``__builtin_rotateright32``
 * ``__builtin_rotateright64``
+* ``__builtin_scalbn``
 
 The following x86-specific intrinsics can be used in constant expressions:
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to