-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[IR][AsmParser] Revamp how floating-point literals work in LLVM IR. #121838
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
c78c953
3e76ef1
1e7908c
d0332f3
e070228
44be9d1
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 |
---|---|---|
|
@@ -4595,11 +4595,13 @@ Simple Constants | |
zeros. So '``s0x0001``' of type '``i16``' will be -1, not 1. | ||
**Floating-point constants** | ||
Floating-point constants use standard decimal notation (e.g. | ||
123.421), exponential notation (e.g. 1.23421e+2), or a more precise | ||
hexadecimal notation (see below). The assembler requires the exact | ||
decimal value of a floating-point constant. For example, the | ||
assembler accepts 1.25 but rejects 1.3 because 1.3 is a repeating | ||
decimal in binary. Floating-point constants must have a | ||
123.421), exponential notation (e.g. 1.23421e+2), standard hexadecimal | ||
notation (e.g., 0x1.3effp-43), one of several special values, or a | ||
precise bitstring for the underlying value. When converting decimal and | ||
hexadecimal literals to the floating-point type, the value is converted | ||
using the default rounding mode (round to nearest, half to even). String | ||
conversions that underflow to 0 or overflow to infinity are not permitted. | ||
Floating-point constants must have a | ||
:ref:`floating-point <t_floating>` type. | ||
**Null pointer constants** | ||
The identifier '``null``' is recognized as a null pointer constant | ||
|
@@ -4608,31 +4610,40 @@ Simple Constants | |
The identifier '``none``' is recognized as an empty token constant | ||
and must be of :ref:`token type <t_token>`. | ||
|
||
The one non-intuitive notation for constants is the hexadecimal form of | ||
floating-point constants. For example, the form | ||
'``double 0x432ff973cafa8000``' is equivalent to (but harder to read | ||
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. Are you removing this old 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. The original parsing code is still being kept, which is why this patch can go in without a few hundred test changes. The documentation I removed partially because it's deprecated, partially because it's flat out wrong, and partially because describing the correct behavior is annoying (e.g., |
||
than) '``double 4.5e+15``'. The only time hexadecimal floating-point | ||
constants are required (and the only time that they are generated by the | ||
disassembler) is when a floating-point constant must be emitted but it | ||
cannot be represented as a decimal floating-point number in a reasonable | ||
number of digits. For example, NaN's, infinities, and other special | ||
values are represented in their IEEE hexadecimal format so that assembly | ||
and disassembly do not cause any bits to change in the constants. | ||
|
||
When using the hexadecimal form, constants of types bfloat, half, float, and | ||
double are represented using the 16-digit form shown above (which matches the | ||
IEEE754 representation for double); bfloat, half and float values must, however, | ||
be exactly representable as bfloat, IEEE 754 half, and IEEE 754 single | ||
precision respectively. Hexadecimal format is always used for long double, and | ||
there are three forms of long double. The 80-bit format used by x86 is | ||
represented as ``0xK`` followed by 20 hexadecimal digits. The 128-bit format | ||
used by PowerPC (two adjacent doubles) is represented by ``0xM`` followed by 32 | ||
hexadecimal digits. The IEEE 128-bit format is represented by ``0xL`` followed | ||
by 32 hexadecimal digits. Long doubles will only work if they match the long | ||
double format on your target. The IEEE 16-bit format (half precision) is | ||
represented by ``0xH`` followed by 4 hexadecimal digits. The bfloat 16-bit | ||
format is represented by ``0xR`` followed by 4 hexadecimal digits. All | ||
hexadecimal formats are big-endian (sign bit at the left). | ||
Floating-point constants support the following kinds of strings: | ||
|
||
+----------------+---------------------------------------------------+ | ||
| Syntax | Description | | ||
+================+===================================================+ | ||
| ``+4.5e-13`` | Common decimal literal. Signs are optional, as is | | ||
| | the exponent portion. The decimal point is | | ||
| | required, as is one or more leading digits before | | ||
| | the decimal point. | | ||
+----------------+---------------------------------------------------+ | ||
| ``-0x1.fp13`` | Common hexadecimal literal. Signs are optional. | | ||
| | The decimal point is required, as is the exponent | | ||
| | portion of the literal (after the ``p``). | | ||
+----------------+---------------------------------------------------+ | ||
| ``+inf``, | Positive or negative infinity. The sign is | | ||
| ``-inf`` | required. | | ||
+----------------+---------------------------------------------------+ | ||
| ``+qnan``, | Positive or negative preferred quiet NaN, i.e., | | ||
| ``-qnan`` | the quiet bit is set, and all other payload bits | | ||
| | are 0. The sign is required. | | ||
+----------------+---------------------------------------------------+ | ||
| ``+nan(0x1)`` | qNaN value with a particular payload, specified | | ||
| | as hexadecimal (not including the quiet bit as | | ||
| | part of the payload). The sign is required. | | ||
+----------------+---------------------------------------------------+ | ||
| ``+snan(0x1)`` | sNaN value with a particular payload, specified | | ||
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. Why do 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. The original proposal was There's not much keeping FWIW, I also expect that virtually every NaN in practice ends up being 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. Should we spell out this assumes the 2008 snan quiet bit pattern? |
||
| | as hexadecimal (not including the quiet bit as | | ||
| | part of the payload). The sign is required. | | ||
+----------------+---------------------------------------------------+ | ||
| ``f0x3c00`` | Value of the floating-point number if bitcast to | | ||
| | an integer. The number must have exactly as many | | ||
| | hexadecimal digits as is necessary for the size | | ||
| | of the floating-point number. | | ||
+----------------+---------------------------------------------------+ | ||
|
||
There are no constants of type x86_amx. | ||
|
||
|
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.
Allowing rounding seems nice. Any particular reason not to allow overflow/underflow? Just being conservative?
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.
My main motivation was to keep the parsing code as strict as possible, so that if you saw a constant in the code, you could be certain you knew what it was. Despite the existing documentation, we already allow inexact conversions from decimal strings to
double
(we check for exactness on conversion of the resultingdouble
to the actual type, though).There's an argument to be made that allowing
0.1
as a constant, even if we didn't already allow it; I don't see a strong argument for allowing1e99999
or1e-99999
when we have easy syntax for infinity already.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 always thought the parser behavior was ensuring the constant was exact with no rounding. If it wasn't doing that, I'd consider it to be a bug and we shouldn't be more lax