-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[clang] Enable constexpr handling for __builtin_elementwise_fma #152919
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
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
|
@@ -11658,6 +11658,29 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { | |
|
||
return Success(APValue(ResultElements.data(), ResultElements.size()), E); | ||
} | ||
case Builtin::BI__builtin_elementwise_fma: { | ||
APValue SourceX, SourceY, SourceZ; | ||
if (!EvaluateAsRValue(Info, E->getArg(0), SourceX) || | ||
!EvaluateAsRValue(Info, E->getArg(1), SourceY) || | ||
!EvaluateAsRValue(Info, E->getArg(2), SourceZ)) | ||
return false; | ||
|
||
unsigned SourceLen = SourceX.getVectorLength(); | ||
SmallVector<APValue> ResultElements; | ||
ResultElements.reserve(SourceLen); | ||
llvm::RoundingMode RM = getActiveRoundingMode(getEvalInfo(), E); | ||
|
||
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { | ||
APFloat X = SourceX.getVectorElt(EltNum).getFloat(); | ||
APFloat Y = SourceY.getVectorElt(EltNum).getFloat(); | ||
APFloat Z = SourceZ.getVectorElt(EltNum).getFloat(); | ||
APFloat Result(X); | ||
(void)Result.fusedMultiplyAdd(Y, Z, RM); | ||
ResultElements.push_back(APValue(Result)); | ||
} | ||
|
||
return Success(APValue(ResultElements.data(), ResultElements.size()), E); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -15878,6 +15901,22 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { | |
Result = minimumnum(Result, RHS); | ||
return true; | ||
} | ||
|
||
case Builtin::BI__builtin_elementwise_fma: { | ||
if(!E->getArg(0)->isPRValue() || | ||
!E->getArg(1)->isPRValue() || | ||
!E->getArg(2)->isPRValue()) { | ||
return false; | ||
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 a bit confused about this check. Without it, these statements in
When I dump the arguments, I see this; the first argument is not an r-value, leading to the assertion failure:
The arguments look different for some other builtins I checked, e.g. for fmax:
I'm not sure what code is responsible for the |
||
} | ||
APFloat SourceY(0.), SourceZ(0.); | ||
if (!EvaluateFloat(E->getArg(0), Result, Info) || | ||
!EvaluateFloat(E->getArg(1), SourceY, Info) || | ||
!EvaluateFloat(E->getArg(2), SourceZ, Info)) | ||
return false; | ||
llvm::RoundingMode RM = getActiveRoundingMode(getEvalInfo(), E); | ||
(void)Result.fusedMultiplyAdd(SourceY, SourceZ, RM); | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,55 @@ float V3 = func_01(1.0F, 2.0F); | |
// CHECK: @V1 = {{.*}}global float 1.000000e+00, align 4 | ||
// CHECK: @V2 = {{.*}}global float 1.000000e+00, align 4 | ||
// CHECK: @V3 = {{.*}}global float 3.000000e+00, align 4 | ||
|
||
void test_builtin_elementwise_fma_round_upward() { | ||
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. @arsenm Tests for different rounding modes. I chose this file rather than |
||
#pragma STDC FENV_ACCESS ON | ||
#pragma STDC FENV_ROUND FE_UPWARD | ||
|
||
// CHECK: store float 0x4018000100000000, ptr %f1 | ||
// CHECK: store float 0x4018000100000000, ptr %f2 | ||
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 sure if checking for a specific constant is a good idea. But I was using these to sanity check the result, so I put them here. 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. This should definitely be testing the specific constant 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. +1 all constexpr testing must test exact fp constant results (this includes +/-0.0) |
||
constexpr float f1 = __builtin_elementwise_fma(2.0F, 3.000001F, 0.000001F); | ||
constexpr float f2 = 2.0F * 3.000001F + 0.000001F; | ||
static_assert(f1 == f2); | ||
static_assert(f1 == 6.00000381F); | ||
// CHECK: store double 0x40180000C9539B89, ptr %d1 | ||
// CHECK: store double 0x40180000C9539B89, ptr %d2 | ||
constexpr double d1 = __builtin_elementwise_fma(2.0, 3.000001, 0.000001); | ||
constexpr double d2 = 2.0 * 3.000001 + 0.000001; | ||
static_assert(d1 == d2); | ||
static_assert(d1 == 6.0000030000000004); | ||
} | ||
|
||
void test_builtin_elementwise_fma_round_downward() { | ||
#pragma STDC FENV_ACCESS ON | ||
#pragma STDC FENV_ROUND FE_DOWNWARD | ||
|
||
// CHECK: store float 0x40180000C0000000, ptr %f3 | ||
// CHECK: store float 0x40180000C0000000, ptr %f4 | ||
constexpr float f3 = __builtin_elementwise_fma(2.0F, 3.000001F, 0.000001F); | ||
constexpr float f4 = 2.0F * 3.000001F + 0.000001F; | ||
static_assert(f3 == f4); | ||
// CHECK: store double 0x40180000C9539B87, ptr %d3 | ||
// CHECK: store double 0x40180000C9539B87, ptr %d4 | ||
constexpr double d3 = __builtin_elementwise_fma(2.0, 3.000001, 0.000001); | ||
constexpr double d4 = 2.0 * 3.000001 + 0.000001; | ||
static_assert(d3 == d4); | ||
} | ||
|
||
void test_builtin_elementwise_fma_round_nearest() { | ||
#pragma STDC FENV_ACCESS ON | ||
#pragma STDC FENV_ROUND FE_TONEAREST | ||
|
||
// CHECK: store float 0x40180000C0000000, ptr %f5 | ||
// CHECK: store float 0x40180000C0000000, ptr %f6 | ||
constexpr float f5 = __builtin_elementwise_fma(2.0F, 3.000001F, 0.000001F); | ||
constexpr float f6 = 2.0F * 3.000001F + 0.000001F; | ||
static_assert(f5 == f6); | ||
static_assert(f5 == 6.00000286F); | ||
// CHECK: store double 0x40180000C9539B89, ptr %d5 | ||
// CHECK: store double 0x40180000C9539B89, ptr %d6 | ||
constexpr double d5 = __builtin_elementwise_fma(2.0, 3.000001, 0.000001); | ||
constexpr double d6 = 2.0 * 3.000001 + 0.000001; | ||
static_assert(d5 == d6); | ||
static_assert(d5 == 6.0000030000000004); | ||
} |
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.
clang-format
would rather write this as:I like it less but I can change it if required.