================
@@ -19962,10 +20032,303 @@ bool FloatExprEvaluator::VisitCallExpr(const 
CallExpr *E) {
     if (!EvaluateFloat(E->getArg(0), Result, Info) ||
         !EvaluateFloat(E->getArg(1), RHS, Info))
       return false;
+    // minimumnum handles special values (NaN, INF) per IEEE 754.
     Result = minimumnum(Result, RHS);
     return true;
   }
 
+  case Builtin::BI__builtin_nearbyint:
+  case Builtin::BI__builtin_nearbyintf:
+  case Builtin::BI__builtin_nearbyintl:
+  case Builtin::BI__builtin_nearbyintf16:
+  case Builtin::BI__builtin_nearbyintf128:
+  case Builtin::BI__builtin_rint:
+  case Builtin::BI__builtin_rintf:
+  case Builtin::BI__builtin_rintl:
+  case Builtin::BI__builtin_rintf16:
+  case Builtin::BI__builtin_rintf128:
+  case Builtin::BI__builtin_round:
+  case Builtin::BI__builtin_roundf:
+  case Builtin::BI__builtin_roundl:
+  case Builtin::BI__builtin_roundf16:
+  case Builtin::BI__builtin_roundf128:
+  case Builtin::BI__builtin_ceil:
+  case Builtin::BI__builtin_ceilf:
+  case Builtin::BI__builtin_ceill:
+  case Builtin::BI__builtin_ceilf16:
+  case Builtin::BI__builtin_ceilf128:
+  case Builtin::BI__builtin_floor:
+  case Builtin::BI__builtin_floorf:
+  case Builtin::BI__builtin_floorl:
+  case Builtin::BI__builtin_floorf16:
+  case Builtin::BI__builtin_floorf128:
+  case Builtin::BI__builtin_trunc:
+  case Builtin::BI__builtin_truncf:
+  case Builtin::BI__builtin_truncl:
+  case Builtin::BI__builtin_truncf16:
+  case Builtin::BI__builtin_truncf128:
+  case Builtin::BI__builtin_roundeven:
+  case Builtin::BI__builtin_roundevenf:
+  case Builtin::BI__builtin_roundevenl:
+  case Builtin::BI__builtin_roundevenf16:
+  case Builtin::BI__builtin_roundevenf128: {
+    if (!EvaluateFloat(E->getArg(0), Result, Info))
+      return false;
+    llvm::RoundingMode RM;
+    switch (E->getBuiltinCallee()) {
+    case Builtin::BI__builtin_nearbyint:
+    case Builtin::BI__builtin_nearbyintf:
+    case Builtin::BI__builtin_nearbyintl:
+    case Builtin::BI__builtin_nearbyintf16:
+    case Builtin::BI__builtin_nearbyintf128:
+    case Builtin::BI__builtin_rint:
+    case Builtin::BI__builtin_rintf:
+    case Builtin::BI__builtin_rintl:
+    case Builtin::BI__builtin_rintf16:
+    case Builtin::BI__builtin_rintf128:
+      RM = getActiveRoundingMode(getEvalInfo(), E);
+      break;
+    case Builtin::BI__builtin_round:
+    case Builtin::BI__builtin_roundf:
+    case Builtin::BI__builtin_roundl:
+    case Builtin::BI__builtin_roundf16:
+    case Builtin::BI__builtin_roundf128:
+      RM = llvm::RoundingMode::NearestTiesToAway;
+      break;
+    case Builtin::BI__builtin_ceil:
+    case Builtin::BI__builtin_ceilf:
+    case Builtin::BI__builtin_ceill:
+    case Builtin::BI__builtin_ceilf16:
+    case Builtin::BI__builtin_ceilf128:
+      RM = llvm::RoundingMode::TowardPositive;
+      break;
+    case Builtin::BI__builtin_floor:
+    case Builtin::BI__builtin_floorf:
+    case Builtin::BI__builtin_floorl:
+    case Builtin::BI__builtin_floorf16:
+    case Builtin::BI__builtin_floorf128:
+      RM = llvm::RoundingMode::TowardNegative;
+      break;
+    case Builtin::BI__builtin_roundeven:
+    case Builtin::BI__builtin_roundevenf:
+    case Builtin::BI__builtin_roundevenl:
+    case Builtin::BI__builtin_roundevenf16:
+    case Builtin::BI__builtin_roundevenf128:
+      RM = llvm::RoundingMode::NearestTiesToEven;
+      break;
+    default:
+      RM = llvm::RoundingMode::TowardZero;
+      break;
+    }
+    // roundToIntegral handles special values (NaN, INF) per IEEE 754.
+    APFloat::opStatus St = Result.roundToIntegral(RM);
+    return checkFloatingPointResult(Info, E, St);
+  }
+
+  case Builtin::BI__builtin_fdim:
+  case Builtin::BI__builtin_fdimf:
+  case Builtin::BI__builtin_fdiml:
+  case Builtin::BI__builtin_fdimf128: {
+    APFloat RHS(0.);
+    if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+        !EvaluateFloat(E->getArg(1), RHS, Info))
+      return false;
+    if (Result.compare(RHS) == APFloat::cmpGreaterThan) {
+      APFloat::opStatus St = Result.subtract(RHS, 
APFloat::rmNearestTiesToEven);
----------------
hubert-reinterpretcast wrote:

The consensus from 
https://github.com/llvm/llvm-project/pull/158048#issuecomment-3313760151 for 
handling `FENV_ROUND` was to respect it for manifestly constant-evaluated cases 
even for functions with "weak rounding mode dependence".

Thus, this should pass:
```cpp
#pragma STDC FENV_ROUND FE_TONEARESTFROMZERO
static_assert(__builtin_fdim(__DBL_EPSILON__ / 2., -1.) == 1. + 
__DBL_EPSILON__);
```

At least one non-default `FENV_ROUND` setting should be tested—with input 
values that produce a result, under said rounding mode, different from the one 
under the default rounding mode—with every function with such input 
values.

However (from the comment linked above), for non-manifestly constant-evaluated 
cases, we should fold (when `FENV_ACCESS` is `OFF`) using the default rounding 
mode (regardless of the `FENV_ROUND` setting). This should also be tested, for 
the same functions and for the same values, in a codegen test.

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

Reply via email to