-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] constexpr built-in fma function. #113020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -142,6 +142,19 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, | |
#undef RET_CASE | ||
} | ||
|
||
/// Get rounding mode to use in evaluation of the specified expression. | ||
/// | ||
/// If rounding mode is unknown at compile time, still try to evaluate the | ||
/// expression. If the result is exact, it does not depend on rounding mode. | ||
/// So return "tonearest" mode instead of "dynamic". | ||
static llvm::RoundingMode getActiveRoundingMode(InterpState &S, const Expr *E) { | ||
llvm::RoundingMode RM = | ||
E->getFPFeaturesInEffect(S.getLangOpts()).getRoundingMode(); | ||
if (RM == llvm::RoundingMode::Dynamic) | ||
RM = llvm::RoundingMode::NearestTiesToEven; | ||
return RM; | ||
} | ||
|
||
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, | ||
const InterpFrame *Frame, | ||
const CallExpr *Call) { | ||
|
@@ -549,6 +562,22 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, | |
return true; | ||
} | ||
|
||
static bool interp__builtin_fma(InterpState &S, CodePtr OpPC, | ||
const InterpFrame *Frame, const Function *Func, | ||
const CallExpr *Call) { | ||
const Floating &X = getParam<Floating>(Frame, 0); | ||
const Floating &Y = getParam<Floating>(Frame, 1); | ||
const Floating &Z = getParam<Floating>(Frame, 2); | ||
Floating Result; | ||
|
||
llvm::RoundingMode RM = getActiveRoundingMode(S, Call); | ||
Floating::mul(X, Y, RM, &Result); | ||
Floating::add(Result, Z, RM, &Result); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I'm not so familiar with A simple example of double rounding errors for floating point type
then for the default rounding mode:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely sure about this either, thanks for pointing it out! Regarding the type, |
||
|
||
S.Stk.push<Floating>(Result); | ||
return true; | ||
} | ||
|
||
// The C standard says "fabs raises no floating-point exceptions, | ||
// even if x is a signaling NaN. The returned value is independent of | ||
// the current rounding direction mode." Therefore constant folding can | ||
|
@@ -1814,6 +1843,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, | |
return false; | ||
break; | ||
|
||
case Builtin::BI__builtin_fma: | ||
case Builtin::BI__builtin_fmaf: | ||
case Builtin::BI__builtin_fmal: | ||
case Builtin::BI__builtin_fmaf128: | ||
if (!interp__builtin_fma(S, OpPC, Frame, F, Call)) | ||
return false; | ||
break; | ||
|
||
case Builtin::BI__builtin_fabs: | ||
case Builtin::BI__builtin_fabsf: | ||
case Builtin::BI__builtin_fabsl: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have questions about the rounding mode. Is getActiveRoundingMode() trying to account for the FE_ROUND pragma setting? If that pragma isn't used and we aren't compiling in strict mode, this should give us "NearestTiesToEven", right?
But if the rounding mode is dynamic, then I think we need to know if the call is in a constexpr. Consider:
I'm not 100% certain about the language rules here, but at least in C my understanding is that initialization of non-static, non-constexp expressions should be done "as if" evaluated at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
llvm-project/clang/lib/AST/ExprConstant.cpp
Lines 2776 to 2782 in 61a456b
I actually obtained this from the old constant evaluator, but I'm not sure if it has the same rounding issue.