================
@@ -717,6 +738,354 @@ static inline Floating abs(InterpState &S, const Floating
&In) {
return Output;
}
+static bool interp__builtin_roundToIntegral(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call,
+ unsigned BuiltinOp) {
+ const Floating &Val = S.Stk.pop<Floating>();
+ Floating Result = S.allocFloat(Val.getSemantics());
+ APFloat F = Val.getAPFloat();
+
+ llvm::RoundingMode RM;
+ switch (BuiltinOp) {
+ 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_trunc:
+ case Builtin::BI__builtin_truncf:
+ case Builtin::BI__builtin_truncl:
+ case Builtin::BI__builtin_truncf16:
+ case Builtin::BI__builtin_truncf128:
+ RM = llvm::RoundingMode::TowardZero;
+ 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_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;
+ 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 = getRoundingMode(Call->getFPFeaturesInEffect(S.getLangOpts()));
+ break;
+ default:
+ llvm_unreachable("invalid builtin ID");
+ }
+
+ // roundToIntegral handles special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus Status = F.roundToIntegral(RM);
+ if (!CheckFloatResult(S, OpPC, F, Status))
+ return false;
+
+ Result.copy(F);
+ S.Stk.push<Floating>(Result);
+ return true;
+}
+
+static bool interp__builtin_fdim(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
+ APFloat L = LHS.getAPFloat();
+ APFloat R = RHS.getAPFloat();
+ APFloat Result(L.getSemantics());
+
+ if (L.isNaN() || R.isNaN()) {
+ Result = APFloat::getNaN(L.getSemantics());
+ } else if (L.compare(R) == APFloat::cmpGreaterThan) {
+ APFloat::opStatus Status = L.subtract(R, APFloat::rmNearestTiesToEven);
+ if (!CheckFloatResult(S, OpPC, L, Status))
+ return false;
+ Result = L;
+ } else {
+ Result = APFloat::getZero(L.getSemantics());
+ }
+
+ Floating F = S.allocFloat(Result.getSemantics());
+ F.copy(Result);
+ S.Stk.push<Floating>(F);
+ return true;
+}
+
+static bool interp__builtin_fma(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ const Floating &Z = S.Stk.pop<Floating>();
+ const Floating &Y = S.Stk.pop<Floating>();
+ const Floating &X = S.Stk.pop<Floating>();
+ APFloat Result = X.getAPFloat();
+
+ llvm::RoundingMode RM =
+ getRoundingMode(Call->getFPFeaturesInEffect(S.getLangOpts()));
+
+ // fusedMultiplyAdd handles special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus Status =
+ Result.fusedMultiplyAdd(Y.getAPFloat(), Z.getAPFloat(), RM);
+ if (!CheckFloatResult(S, OpPC, Result, Status))
+ return false;
+
+ Floating F = S.allocFloat(Result.getSemantics());
+ F.copy(Result);
+ S.Stk.push<Floating>(F);
+ return true;
+}
+
+static bool interp__builtin_frexp(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
+ const Floating &Val = S.Stk.pop<Floating>();
+
+ int Exp = 0;
+ // frexp handles special values (NaN, INF) per IEEE 754.
+ APFloat F = frexp(Val.getAPFloat(), Exp, APFloat::rmNearestTiesToEven);
+
+ if (Ptr.isDummy())
+ return false;
+
+ QualType ExpType = Call->getArg(1)->getType()->getPointeeType();
+ PrimType ExpT = *S.getContext().classify(ExpType);
+ assignIntegral(S, Ptr, ExpT, APSInt::get(Exp));
+ Ptr.initialize();
+
+ Floating Result = S.allocFloat(F.getSemantics());
+ Result.copy(F);
+ S.Stk.push<Floating>(Result);
+ return true;
+}
+
+static bool interp__builtin_modf(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
+ const Floating &Val = S.Stk.pop<Floating>();
+ const APFloat &F = Val.getAPFloat();
+
+ APFloat Integral = F;
+ Integral.roundToIntegral(APFloat::rmTowardZero);
+
+ if (Ptr.isDummy())
+ return false;
+
+ Ptr.deref<Floating>().copy(Integral);
+ Ptr.initialize();
+
+ if (F.isInfinity()) {
+ Floating Fraction = S.allocFloat(F.getSemantics());
+ Fraction.copy(APFloat::getZero(F.getSemantics(), F.isNegative()));
+ S.Stk.push<Floating>(Fraction);
+ return true;
+ }
+
+ APFloat Fraction = F;
+ Fraction.subtract(Integral, APFloat::rmNearestTiesToEven);
+
+ Floating Result = S.allocFloat(Fraction.getSemantics());
+ Result.copy(Fraction);
+ S.Stk.push<Floating>(Result);
+ return true;
+}
+
+static bool interp__builtin_fmod(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame, const CallExpr
*Call,
+ unsigned BuiltinOp) {
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
+ const APFloat &L = LHS.getAPFloat();
+ const APFloat &R = RHS.getAPFloat();
+ APFloat ResF = L;
+
+ // mod and remainder handle special values (NaN, INF) per IEEE 754.
+ APFloat::opStatus Status;
+ if (BuiltinOp == Builtin::BI__builtin_remainder ||
+ BuiltinOp == Builtin::BI__builtin_remainderf ||
+ BuiltinOp == Builtin::BI__builtin_remainderl ||
+ BuiltinOp == Builtin::BI__builtin_remainderf128)
+ Status = ResF.remainder(R);
+ else
+ Status = ResF.mod(R);
+
+ if (!CheckFloatResult(S, OpPC, ResF, Status))
+ return false;
+
+ Floating F = S.allocFloat(ResF.getSemantics());
+ F.copy(ResF);
+ S.Stk.push<Floating>(F);
+ return true;
+}
+
+static bool interp__builtin_nextafter(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
+ const APFloat &L = LHS.getAPFloat();
+ const APFloat &R = RHS.getAPFloat();
+
+ if (L.isNaN()) {
+ S.Stk.push<Floating>(LHS);
+ return true;
+ }
+
+ // nexttoward(x, y) takes y as long double, so if y is NaN we must
+ // convert it to x's semantics before returning.
+ if (R.isNaN()) {
+ bool LoseInfo = false;
+ APFloat NaN = R;
+ NaN.convert(L.getSemantics(), APFloat::rmNearestTiesToEven, &LoseInfo);
+ Floating Result = S.allocFloat(NaN.getSemantics());
+ Result.copy(NaN);
+ S.Stk.push<Floating>(Result);
+ return true;
+ }
+
+ APFloat LCopy = L;
+ bool LoseInfo = false;
+ LCopy.convert(R.getSemantics(), APFloat::rmNearestTiesToEven, &LoseInfo);
+ APFloat::cmpResult Res = LCopy.compare(R);
+
+ APFloat Next = L;
+ if (Res != APFloat::cmpEqual)
+ Next.next(Res == APFloat::cmpGreaterThan);
----------------
Serosh-commits wrote:
> Missing error checks. In addition to infinities, watch for subnormal and zero
> results.
done
https://github.com/llvm/llvm-project/pull/194327
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits