Changeset View
Standalone View
docs/LangRef.rst
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 12,018 Lines • ▼ Show 20 Lines | |||||
the pointer to the memory for which the ``invariant.group`` no longer holds. | the pointer to the memory for which the ``invariant.group`` no longer holds. | ||||
Semantics: | Semantics: | ||||
"""""""""" | """""""""" | ||||
Returns another pointer that aliases its argument but which is considered different | Returns another pointer that aliases its argument but which is considered different | ||||
for the purposes of ``load``/``store`` ``invariant.group`` metadata. | for the purposes of ``load``/``store`` ``invariant.group`` metadata. | ||||
Constrained Floating Point Intrinsics | |||||
------------------------------------- | |||||
These intrinsics are used to provide special handling of floating point | |||||
operations when specific rounding mode or floating point exception behavior is | |||||
required. By default, LLVM optimization passes assume that the rounding mode is | |||||
round-to-nearest and that floating point exceptions will not be monitored. | |||||
Constrained FP intrinsics are used to support non-default rounding modes and | |||||
accurately preserve exception behavior without compromising LLVM's ability to | |||||
optimize FP code when the default behavior is used. | |||||
Each of these intrinsics corresponds to a normal floating point operation. The | |||||
first two arguments and the return value are the same as the corresponding FP | |||||
operation. | |||||
The third argument is a metadata argument specifying the rounding mode to be | |||||
assumed. This argument must be one of the following strings: | |||||
:: | |||||
"round.dynamic" | |||||
hfinkel: To engage in some bikeshedding, I really don't like this naming convention which reminds me of… | |||||
"round.tonearest" | |||||
"round.downward" | |||||
"round.upward" | |||||
"round.towardzero" | |||||
If this argument is "round.dynamic" optimization passes must assume that the | |||||
rounding mode is unknown and may change at runtime. No transformations that | |||||
depend on rounding mode may be performed in this case. | |||||
The other possible values for the rounding mode argument correspond to the | |||||
similarly named IEEE rounding modes. If the argument is any of these values | |||||
optimization passes may perform transformations as long as they are consistent | |||||
with the specified rounding mode. | |||||
For example, 'x-0'->'x' is not a valid transformation if the rounding mode is | |||||
"round.downward" or "round.dynamic" because if the value of 'x' is +0 then | |||||
'x-0' should evaluate to '-0' when rounding downward. However, this | |||||
transformation is legal for all other rounding modes. | |||||
For values other than "round.dynamic" optimization passes may assume that the | |||||
actual runtime rounding mode (as defined in a target-specific manner) matches | |||||
the specified rounding mode, but this is not guaranteed. Using a specific | |||||
non-dynamic rounding mode which does not match the actual rounding mode at | |||||
runtime results in undefined behavior. | |||||
The fourth argument to the constrained floating point intrinsics specifies the | |||||
required exception behavior. This argument must be one of the following | |||||
strings: | |||||
:: | |||||
"fpexcept.ignore" | |||||
"fpexcept.maytrap" | |||||
"fpexcept.strict" | |||||
If this argument is "fpexcept.ignore" optimization passes may assume that the | |||||
exception status flags will not be read and that floating point exceptions will | |||||
be masked. This allows transformations to be performed that may change the | |||||
Not Done ReplyInline Actions"not be unmasked" is a double negative. How about just saying will be masked? Or will not be enabled? hfinkel: "not be unmasked" is a double negative. How about just saying will be masked? Or will not be… | |||||
exception semantics of the original code. For example, FP operations may be | |||||
speculatively executed in this case whereas they must not be for either of the | |||||
other possible values of this argument. | |||||
If the exception behavior argument is "fpexcept.maytrap" optimization passes | |||||
must avoid transformations that may raise exceptions that would not have been | |||||
raised by the original code (such as speculatively executing FP operations), but | |||||
passes are not required to preserve all exceptions that are implied by the | |||||
original code. For example, exceptions may be potentially hidden by constant | |||||
folding. | |||||
If the exception behavior argument is "fpexcept.strict" all transformations must | |||||
strictly preserve the floating point exception semantics of the original code. | |||||
Any FP exception that would have been raised by the original code must be raised | |||||
by the transformed code, and the transformed code must not raise any FP | |||||
exceptions that would not have been raised by the original code. This is the | |||||
exception behavior argument that will be used if the code being compiled reads | |||||
the FP exception status flags, but this mode can also be used with code that | |||||
unmasks FP exceptions. | |||||
The number and order of floating point exceptions is NOT guaranteed. For | |||||
example, a series of FP operations that each may raise exceptions may be | |||||
vectorized into a single instruction that raises each unique exception a single | |||||
time. | |||||
'``llvm.experimental.constrained.fadd``' Intrinsic | |||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||||
Syntax: | |||||
""""""" | |||||
:: | |||||
declare <type> | |||||
@llvm.experimental.constrained.fadd(<type> <op1>, <type> <op2>, | |||||
metadata <rounding mode>, | |||||
metadata <exception behavior>) | |||||
Overview: | |||||
""""""""" | |||||
The '``llvm.experimental.constrained.fadd``' intrinsic returns the sum of its | |||||
Not Done ReplyInline ActionsTypo: lllvm (seems repeated a number of times) arsenm: Typo: lllvm (seems repeated a number of times) | |||||
two operands. | |||||
Arguments: | |||||
"""""""""" | |||||
The first two arguments to the '``llvm.experimental.constrained.fadd``' | |||||
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>` | |||||
of floating point values. Both arguments must have identical types. | |||||
The third and fourth arguments specify the rounding mode and exception | |||||
behavior as described above. | |||||
Semantics: | |||||
"""""""""" | |||||
The value produced is the floating point sum of the two value operands and has | |||||
the same type as the operands. | |||||
'``llvm.experimental.constrained.fsub``' Intrinsic | |||||
DavidKreitzerUnsubmitted Not Done ReplyInline ActionsThis question might be beyond the scope of this initial change set, but here goes. FP negation is currently handled using fsub -0, X. Is that sufficient in a constrained context? If we allow X to be a signaling NaN, -0-X should raise Invalid while -X should not, at least according to IEEE-754. DavidKreitzer: This question might be beyond the scope of this initial change set, but here goes.
FP negation… | |||||
scanonUnsubmitted Not Done ReplyInline ActionsProbably more importantly, -X has a defined signbit (the negation of whatever the signbit of X was), but -0-X does not [assuming the obvious binding of -X to the IEEE 754 negate operation and -0-X to the subtract operation]. scanon: Probably more importantly, -X has a defined signbit (the negation of whatever the signbit of X… | |||||
DavidKreitzerUnsubmitted Not Done ReplyInline ActionsSteve, are you referring to the fact that the sign of -0-X is unspecified when X is NaN or something else? I am trying to understand the implications of your comment - whether they are specific to the new constrained FP intrinsics or whether something needs to be done for normal FP LLVM IR. Another problem worth mentioning with implementing -X as -0-X in a constrained context is that -0-X will produce -0 when X is -0 and the rounding mode is toward -inf. DavidKreitzer: Steve, are you referring to the fact that the sign of -0-X is unspecified when X is NaN or… | |||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||||
Syntax: | |||||
""""""" | |||||
:: | |||||
declare <type> | |||||
@llvm.experimental.constrained.fsub(<type> <op1>, <type> <op2>, | |||||
metadata <rounding mode>, | |||||
metadata <exception behavior>) | |||||
Overview: | |||||
""""""""" | |||||
The '``llvm.experimental.constrained.fsub``' intrinsic returns the difference | |||||
of its two operands. | |||||
Arguments: | |||||
"""""""""" | |||||
The first two arguments to the '``llvm.experimental.constrained.fsub``' | |||||
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>` | |||||
of floating point values. Both arguments must have identical types. | |||||
The third and fourth arguments specify the rounding mode and exception | |||||
behavior as described above. | |||||
Semantics: | |||||
"""""""""" | |||||
The value produced is the floating point difference of the two value operands | |||||
and has the same type as the operands. | |||||
'``llvm.experimental.constrained.fmul``' Intrinsic | |||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||||
Syntax: | |||||
""""""" | |||||
:: | |||||
declare <type> | |||||
@llvm.experimental.constrained.fmul(<type> <op1>, <type> <op2>, | |||||
metadata <rounding mode>, | |||||
metadata <exception behavior>) | |||||
Overview: | |||||
""""""""" | |||||
The '``llvm.experimental.constrained.fmul``' intrinsic returns the product of | |||||
its two operands. | |||||
Arguments: | |||||
"""""""""" | |||||
The first two arguments to the '``llvm.experimental.constrained.fmul``' | |||||
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>` | |||||
of floating point values. Both arguments must have identical types. | |||||
The third and fourth arguments specify the rounding mode and exception | |||||
behavior as described above. | |||||
Semantics: | |||||
"""""""""" | |||||
The value produced is the floating point product of the two value operands and | |||||
has the same type as the operands. | |||||
'``llvm.experimental.constrained.fdiv``' Intrinsic | |||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||||
Syntax: | |||||
""""""" | |||||
:: | |||||
declare <type> | |||||
@llvm.experimental.constrained.fdiv(<type> <op1>, <type> <op2>, | |||||
metadata <rounding mode>, | |||||
metadata <exception behavior>) | |||||
Overview: | |||||
""""""""" | |||||
The '``llvm.experimental.constrained.fdiv``' intrinsic returns the quotient of | |||||
its two operands. | |||||
Arguments: | |||||
"""""""""" | |||||
The first two arguments to the '``llvm.experimental.constrained.fdiv``' | |||||
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>` | |||||
of floating point values. Both arguments must have identical types. | |||||
The third and fourth arguments specify the rounding mode and exception | |||||
behavior as described above. | |||||
Semantics: | |||||
"""""""""" | |||||
The value produced is the floating point quotient of the two value operands and | |||||
has the same type as the operands. | |||||
'``llvm.experimental.constrained.frem``' Intrinsic | |||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||||
Syntax: | |||||
""""""" | |||||
:: | |||||
declare <type> | |||||
@llvm.experimental.constrained.frem(<type> <op1>, <type> <op2>, | |||||
metadata <rounding mode>, | |||||
metadata <exception behavior>) | |||||
Overview: | |||||
""""""""" | |||||
The '``llvm.experimental.constrained.frem``' intrinsic returns the remainder | |||||
from the division of its two operands. | |||||
Arguments: | |||||
"""""""""" | |||||
The first two arguments to the '``llvm.experimental.constrained.frem``' | |||||
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>` | |||||
of floating point values. Both arguments must have identical types. | |||||
The third and fourth arguments specify the rounding mode and exception | |||||
behavior as described above. | |||||
Semantics: | |||||
"""""""""" | |||||
The value produced is the floating point remainder from the division of the two | |||||
value operands and has the same type as the operands. The remainder has the | |||||
same sign as the dividend. | |||||
General Intrinsics | General Intrinsics | ||||
------------------ | ------------------ | ||||
This class of intrinsics is designed to be generic and has no specific | This class of intrinsics is designed to be generic and has no specific | ||||
purpose. | purpose. | ||||
'``llvm.var.annotation``' Intrinsic | '``llvm.var.annotation``' Intrinsic | ||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
▲ Show 20 Lines • Show All 607 Lines • Show Last 20 Lines |
To engage in some bikeshedding, I really don't like this naming convention which reminds me of macro names. Not that we've been extremely consistent about the standardized metadata strings we already use, but this would be yet another choice; we should avoid that.
For controlling LLVM optimization passes, we use strings like this !"llvm.loop.vectorize.enable". We also use strings like !"function_entry_count" and !"branch_weights" for profiling info. We also have strings like !"ProfileFormat" and !"TotalCount" in other places. Of these choices, I prefer the one used by our basic profiling information (i.e. !"branch_weights"), and so I'd prefer these be named:
and similar for the fpexcept strings. We might also borrow the dot-based hierarchy scheme from our loop optimization metadata and use:
and similar for the fpexcept strings. I think that I like this slightly better than just using the underscore separators.
I specifically dislike having "llvm" in the name here, as it makes it seem as though the meaning of these things is somehow LLVM-specific. It is not (they come from IEEE if nothing else). Having "llvm" in the optimization metadata makes a bit more sense because those refer to specific LLVM optimization passes.