================
@@ -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);
+ return checkFloatingPointResult(Info, E, St);
+ } else if (Result.isNaN() || RHS.isNaN()) {
+ Result = APFloat::getNaN(Result.getSemantics());
+ } else {
+ Result = APFloat::getZero(Result.getSemantics());
+ }
+ return true;
+ }
+
+ case Builtin::BI__builtin_fma:
+ case Builtin::BI__builtin_fmaf:
+ case Builtin::BI__builtin_fmal:
+ case Builtin::BI__builtin_fmaf16:
+ case Builtin::BI__builtin_fmaf128: {
+ APFloat RHS(0.), Third(0.);
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info) ||
+ !EvaluateFloat(E->getArg(2), Third, Info))
+ return false;
+
+ llvm::RoundingMode RM = getActiveRoundingMode(getEvalInfo(), E);
+ // fusedMultiplyAdd handles special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus St = Result.fusedMultiplyAdd(RHS, Third, RM);
+ return checkFloatingPointResult(Info, E, St);
+ }
+
+ case Builtin::BI__builtin_fmod:
+ case Builtin::BI__builtin_fmodf:
+ case Builtin::BI__builtin_fmodl:
+ case Builtin::BI__builtin_fmodf16:
+ case Builtin::BI__builtin_fmodf128: {
+ APFloat RHS(0.);
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info))
+ return false;
+ // mod handles special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus St = Result.mod(RHS);
+ return checkFloatingPointResult(Info, E, St);
+ }
+
+ case Builtin::BI__builtin_remainder:
+ case Builtin::BI__builtin_remainderf:
+ case Builtin::BI__builtin_remainderl:
+ case Builtin::BI__builtin_remainderf128: {
+ APFloat RHS(0.);
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info))
+ return false;
+ // remainder handles special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus St = Result.remainder(RHS);
+ return checkFloatingPointResult(Info, E, St);
+ }
+
+ case Builtin::BI__builtin_nextafter:
+ case Builtin::BI__builtin_nextafterf:
+ case Builtin::BI__builtin_nextafterl:
+ case Builtin::BI__builtin_nextafterf128:
+ case Builtin::BI__builtin_nexttoward:
+ case Builtin::BI__builtin_nexttowardf:
+ case Builtin::BI__builtin_nexttowardl:
+ case Builtin::BI__builtin_nexttowardf128: {
+ APFloat RHS(0.);
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info))
+ return false;
+
+ if (Result.isNaN())
+ return true;
+
+ if (RHS.isNaN()) {
+ bool LoseInfo = false;
+ Result = RHS;
+ Result.convert(Info.Ctx.getFloatTypeSemantics(E->getType()),
+ APFloat::rmNearestTiesToEven, &LoseInfo);
+ return true;
+ }
+
+ APFloat ResultCopy = Result;
+ bool LoseInfo = false;
+ ResultCopy.convert(RHS.getSemantics(), APFloat::rmNearestTiesToEven,
+ &LoseInfo);
+ APFloat::cmpResult Res = ResultCopy.compare(RHS);
+
+ if (Res == APFloat::cmpEqual)
+ return true;
+
+ Result.next(Res == APFloat::cmpGreaterThan);
+ return true;
+ }
+
+ case Builtin::BI__builtin_scalbn:
+ case Builtin::BI__builtin_scalbnf:
+ case Builtin::BI__builtin_scalbnl:
+ case Builtin::BI__builtin_scalbnf128:
+ case Builtin::BI__builtin_scalbln:
+ case Builtin::BI__builtin_scalblnf:
+ case Builtin::BI__builtin_scalblnl:
+ case Builtin::BI__builtin_scalblnf128:
+ case Builtin::BI__builtin_ldexp:
+ case Builtin::BI__builtin_ldexpf:
+ case Builtin::BI__builtin_ldexpl:
+ case Builtin::BI__builtin_ldexpf16:
+ case Builtin::BI__builtin_ldexpf128: {
+ APSInt Exp;
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateInteger(E->getArg(1), Exp, Info))
+ return false;
+
+ llvm::RoundingMode RM = getActiveRoundingMode(getEvalInfo(), E);
+ Result = scalbn(Result, Exp.getExtValue(), RM);
+ return true;
+ }
+
+ case Builtin::BI__builtin_frexp:
+ case Builtin::BI__builtin_frexpf:
+ case Builtin::BI__builtin_frexpl:
+ case Builtin::BI__builtin_frexpf16:
+ case Builtin::BI__builtin_frexpf128: {
+ LValue ExpLVal;
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluatePointer(E->getArg(1), ExpLVal, Info))
+ return false;
+
+ int Exp = 0;
+ // frexp handles special values (NaN, INF) per IEEE 754.
+ Result = frexp(Result, Exp, APFloat::rmNearestTiesToEven);
+
+ QualType PointeeType = E->getArg(1)->getType()->getPointeeType();
+ APValue APV{APSInt(Info.Ctx.getTypeSize(PointeeType), false)};
+ APV.getInt() = Exp;
+ if (!handleAssignment(Info, E, ExpLVal, PointeeType, APV))
+ return false;
+ return true;
+ }
+
+ case Builtin::BI__builtin_modf:
+ case Builtin::BI__builtin_modff:
+ case Builtin::BI__builtin_modfl:
+ case Builtin::BI__builtin_modff128: {
+ LValue IptrLVal;
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluatePointer(E->getArg(1), IptrLVal, Info))
+ return false;
+
+ APFloat Integral = Result;
+ Integral.roundToIntegral(APFloat::rmTowardZero);
+
+ QualType PointeeType = E->getArg(1)->getType()->getPointeeType();
+ APValue APV{Integral};
+ if (!handleAssignment(Info, E, IptrLVal, PointeeType, APV))
+ return false;
+
+ if (Result.isInfinity()) {
+ Result = APFloat::getZero(Result.getSemantics(), Result.isNegative());
+ } else {
+ Result.subtract(Integral, APFloat::rmNearestTiesToEven);
+ }
----------------
hubert-reinterpretcast wrote:
- Nit: Should not use braces here.
- This does not handle negative zero properly. The following should pass:
```cpp
constexpr double modf_ret(double a) {
double i;
return __builtin_modf(a, &i);
}
static_assert(__builtin_copysign(1., modf_ret(-0.)) == -1.);
```
https://github.com/llvm/llvm-project/pull/194327
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits