This is an archive of the discontinued LLVM Phabricator instance.

[clang] Add __builtin_isfpclass
ClosedPublic

Authored by sepavloff on Jun 7 2023, 2:09 AM.

Details

Summary

A new builtin function __builtin_isfpclass is added. It is called as:

__builtin_isfpclass(<floating point value>, <test>)

and returns an integer value, which is non-zero if the floating point
argument falls into one of the classes specified by the second argument,
and zero otherwise. The set of classes is an integer value, where each
value class is represented by a bit. There are ten data classes, as
defined by the IEEE-754 standard, they are represented by bits:

0x0001 (__FPCLASS_SNAN)         - Signaling NaN
0x0002 (__FPCLASS_QNAN)         - Quiet NaN
0x0004 (__FPCLASS_NEGINF)       - Negative infinity
0x0008 (__FPCLASS_NEGNORMAL)    - Negative normal
0x0010 (__FPCLASS_NEGSUBNORMAL) - Negative subnormal
0x0020 (__FPCLASS_NEGZERO)      - Negative zero
0x0040 (__FPCLASS_POSZERO)      - Positive zero
0x0080 (__FPCLASS_POSSUBNORMAL) - Positive subnormal
0x0100 (__FPCLASS_POSNORMAL)    - Positive normal
0x0200 (__FPCLASS_POSINF)       - Positive infinity

They have corresponding builtin macros to facilitate using the builtin
function:

if (__builtin_isfpclass(x, __FPCLASS_NEGZERO | __FPCLASS_POSZERO) {
  // x is any zero.
}

The data class encoding is identical to that used in llvm.is.fpclass
function.

Diff Detail

Event Timeline

sepavloff created this revision.Jun 7 2023, 2:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 7 2023, 2:09 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
sepavloff requested review of this revision.Jun 7 2023, 2:09 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 7 2023, 2:09 AM
qiucf added a comment.Jun 7 2023, 3:06 AM

It's necessary to check range of first argument in SemaChecking.cpp using SemaBuiltinConstantArgRange.

_Bool check_isfpclass_1(float x) { return __builtin_isfpclass(123456, x); } // ICE

int g;
// error: cannot compile this builtin function yet
// there's better diagnostics when 1st argument is not constant
_Bool check_isfpclass_2(float x) { return __builtin_isfpclass(g, x); }
clang/include/clang/Basic/Builtins.def
491

Why these intrinsics' type spec end with dot? I thought they are for vaargs.

sepavloff updated this revision to Diff 529243.Jun 7 2023, 4:16 AM

Add check for test bit mask value

It's necessary to check range of first argument in SemaChecking.cpp using SemaBuiltinConstantArgRange.

_Bool check_isfpclass_1(float x) { return __builtin_isfpclass(123456, x); } // ICE

int g;
// error: cannot compile this builtin function yet
// there's better diagnostics when 1st argument is not constant
_Bool check_isfpclass_2(float x) { return __builtin_isfpclass(g, x); }

Added the check and a test for it. Thanks!

clang/include/clang/Basic/Builtins.def
491

It is a hack to have polymorphic builtin function. The argument . represents one argument but it can be of any type. So no need to have separate functions for every type.

arsenm added inline comments.Jun 7 2023, 4:29 AM
clang/test/CodeGen/isfpclass.c
2

Use generated checks?

3

Can you also add a half test, also vectors

12

These operands are backwards, the test should be second

clang/test/Sema/builtins.c
383 ↗(On Diff #529243)

Need a test for non-immediate class mask. Also a negative value

384 ↗(On Diff #529243)

What happens if you pass complex?

llvm/lib/IR/IRBuilder.cpp
1379

Use IRBuilder::getInt32

arsenm added a comment.Jun 7 2023, 4:34 AM

Also should get mentioned in the builtin docs and release notes

Also should get mentioned in the builtin docs and release notes

+1, also, should there be named constants for the mask values?

clang/include/clang/Basic/Builtins.def
491

E in the third arguments means it can be constant evaluated in the frontend, but I don't see any code or tests for that.

clang/lib/Sema/SemaChecking.cpp
2776–2778 ↗(On Diff #529243)

Do we diagnose if the second argument to the call isn't a floating-point value? e.g., __builtin_isfpclass(0x1, some_struct)

clang/test/Sema/builtins.c
384 ↗(On Diff #529243)

What happens if you pass a non-float second argument, or a bit mask that doesn't match any of the valid values, or a bit mask that matches multiple valid values?

sepavloff updated this revision to Diff 530041.Jun 9 2023, 11:48 AM

Updated patch

Typo builting in commit message

clang/docs/LanguageExtensions.rst
3418 ↗(On Diff #530041)

Maybe also mention it doesn't canonicalize its input

clang/test/CodeGen/isfpclass.c
55

Also tests without fenv access

57

Test some vectors?

clang/test/Sema/builtins.c
384 ↗(On Diff #530041)

For any other float argument, 3 would accept implicit conversion. Do we just not do that for these type inferring intrinsics?

sepavloff marked 8 inline comments as done.Jun 9 2023, 11:56 AM

Also should get mentioned in the builtin docs and release notes

+1, also, should there be named constants for the mask values?

I don't know where these constants could be placed.

clang/test/CodeGen/isfpclass.c
3

Half is added. But vectors cannot, because in this case result is also a vector.

Also should get mentioned in the builtin docs and release notes

+1, also, should there be named constants for the mask values?

I don't know where these constants could be placed.

The preprocessor predefines a bunch of macros, so I was thinking along those same lines. e.g., https://github.com/llvm/llvm-project/blob/main/clang/lib/Frontend/InitPreprocessor.cpp#L737

arsenm added inline comments.Jun 9 2023, 12:05 PM
clang/test/CodeGen/isfpclass.c
3

Could copy what builtin_elementwise does. Should that be in this builtin, or should there be a separate builtin_elementwise_isfpclass?

Could Clang offer a builtin.h file? It is always included. You place named constants and enums inside.

Updated patch

  • Added named constants for data classes,
  • Fixed documentation,
  • Changed test for generated IR.
sepavloff marked 2 inline comments as done.Jun 12 2023, 10:26 PM
sepavloff added inline comments.
clang/test/CodeGen/isfpclass.c
3

Other math functions have separate elementwise functions. It looks natural to have separate elementwise function for this function as well.

clang/test/Sema/builtins.c
384 ↗(On Diff #530041)

As any other classification function, this one is evaluated with semantic type. The test CodeGen/isfpclass.c demonstrates that type promotion is absent for _Float16.

sepavloff edited the summary of this revision. (Show Details)Jun 13 2023, 5:06 AM
aaron.ballman accepted this revision.Jun 15 2023, 9:34 AM

Clang bits LGTM, thank you!

This revision is now accepted and ready to land.Jun 15 2023, 9:34 AM
arsenm accepted this revision.Jun 15 2023, 9:38 AM
This revision was automatically updated to reflect the committed changes.