Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit e6f10d3

Browse files
author
Andrew Kaylor
committed
Add intrinsics for constrained floating point operations
This commit introduces a set of experimental intrinsics intended to prevent optimizations that make assumptions about the rounding mode and floating point exception behavior. These intrinsics will later be extended to specify flush-to-zero behavior. More work is also required to model instruction dependencies in machine code and to generate these instructions from clang (when required by pragmas and/or command line options that are not currently supported). Differential Revision: https://reviews.llvm.org/D27028 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293226 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e1c01cc commit e6f10d3

File tree

13 files changed

+768
-0
lines changed

13 files changed

+768
-0
lines changed

docs/LangRef.rst

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12064,6 +12064,277 @@ Semantics:
1206412064
Returns another pointer that aliases its argument but which is considered different
1206512065
for the purposes of ``load``/``store`` ``invariant.group`` metadata.
1206612066

12067+
Constrained Floating Point Intrinsics
12068+
-------------------------------------
12069+
12070+
These intrinsics are used to provide special handling of floating point
12071+
operations when specific rounding mode or floating point exception behavior is
12072+
required. By default, LLVM optimization passes assume that the rounding mode is
12073+
round-to-nearest and that floating point exceptions will not be monitored.
12074+
Constrained FP intrinsics are used to support non-default rounding modes and
12075+
accurately preserve exception behavior without compromising LLVM's ability to
12076+
optimize FP code when the default behavior is used.
12077+
12078+
Each of these intrinsics corresponds to a normal floating point operation. The
12079+
first two arguments and the return value are the same as the corresponding FP
12080+
operation.
12081+
12082+
The third argument is a metadata argument specifying the rounding mode to be
12083+
assumed. This argument must be one of the following strings:
12084+
12085+
::
12086+
"round.dynamic"
12087+
"round.tonearest"
12088+
"round.downward"
12089+
"round.upward"
12090+
"round.towardzero"
12091+
12092+
If this argument is "round.dynamic" optimization passes must assume that the
12093+
rounding mode is unknown and may change at runtime. No transformations that
12094+
depend on rounding mode may be performed in this case.
12095+
12096+
The other possible values for the rounding mode argument correspond to the
12097+
similarly named IEEE rounding modes. If the argument is any of these values
12098+
optimization passes may perform transformations as long as they are consistent
12099+
with the specified rounding mode.
12100+
12101+
For example, 'x-0'->'x' is not a valid transformation if the rounding mode is
12102+
"round.downward" or "round.dynamic" because if the value of 'x' is +0 then
12103+
'x-0' should evaluate to '-0' when rounding downward. However, this
12104+
transformation is legal for all other rounding modes.
12105+
12106+
For values other than "round.dynamic" optimization passes may assume that the
12107+
actual runtime rounding mode (as defined in a target-specific manner) matches
12108+
the specified rounding mode, but this is not guaranteed. Using a specific
12109+
non-dynamic rounding mode which does not match the actual rounding mode at
12110+
runtime results in undefined behavior.
12111+
12112+
The fourth argument to the constrained floating point intrinsics specifies the
12113+
required exception behavior. This argument must be one of the following
12114+
strings:
12115+
12116+
::
12117+
"fpexcept.ignore"
12118+
"fpexcept.maytrap"
12119+
"fpexcept.strict"
12120+
12121+
If this argument is "fpexcept.ignore" optimization passes may assume that the
12122+
exception status flags will not be read and that floating point exceptions will
12123+
be masked. This allows transformations to be performed that may change the
12124+
exception semantics of the original code. For example, FP operations may be
12125+
speculatively executed in this case whereas they must not be for either of the
12126+
other possible values of this argument.
12127+
12128+
If the exception behavior argument is "fpexcept.maytrap" optimization passes
12129+
must avoid transformations that may raise exceptions that would not have been
12130+
raised by the original code (such as speculatively executing FP operations), but
12131+
passes are not required to preserve all exceptions that are implied by the
12132+
original code. For example, exceptions may be potentially hidden by constant
12133+
folding.
12134+
12135+
If the exception behavior argument is "fpexcept.strict" all transformations must
12136+
strictly preserve the floating point exception semantics of the original code.
12137+
Any FP exception that would have been raised by the original code must be raised
12138+
by the transformed code, and the transformed code must not raise any FP
12139+
exceptions that would not have been raised by the original code. This is the
12140+
exception behavior argument that will be used if the code being compiled reads
12141+
the FP exception status flags, but this mode can also be used with code that
12142+
unmasks FP exceptions.
12143+
12144+
The number and order of floating point exceptions is NOT guaranteed. For
12145+
example, a series of FP operations that each may raise exceptions may be
12146+
vectorized into a single instruction that raises each unique exception a single
12147+
time.
12148+
12149+
12150+
'``llvm.experimental.constrained.fadd``' Intrinsic
12151+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12152+
12153+
Syntax:
12154+
"""""""
12155+
12156+
::
12157+
12158+
declare <type>
12159+
@llvm.experimental.constrained.fadd(<type> <op1>, <type> <op2>,
12160+
metadata <rounding mode>,
12161+
metadata <exception behavior>)
12162+
12163+
Overview:
12164+
"""""""""
12165+
12166+
The '``llvm.experimental.constrained.fadd``' intrinsic returns the sum of its
12167+
two operands.
12168+
12169+
12170+
Arguments:
12171+
""""""""""
12172+
12173+
The first two arguments to the '``llvm.experimental.constrained.fadd``'
12174+
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>`
12175+
of floating point values. Both arguments must have identical types.
12176+
12177+
The third and fourth arguments specify the rounding mode and exception
12178+
behavior as described above.
12179+
12180+
Semantics:
12181+
""""""""""
12182+
12183+
The value produced is the floating point sum of the two value operands and has
12184+
the same type as the operands.
12185+
12186+
12187+
'``llvm.experimental.constrained.fsub``' Intrinsic
12188+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12189+
12190+
Syntax:
12191+
"""""""
12192+
12193+
::
12194+
12195+
declare <type>
12196+
@llvm.experimental.constrained.fsub(<type> <op1>, <type> <op2>,
12197+
metadata <rounding mode>,
12198+
metadata <exception behavior>)
12199+
12200+
Overview:
12201+
"""""""""
12202+
12203+
The '``llvm.experimental.constrained.fsub``' intrinsic returns the difference
12204+
of its two operands.
12205+
12206+
12207+
Arguments:
12208+
""""""""""
12209+
12210+
The first two arguments to the '``llvm.experimental.constrained.fsub``'
12211+
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>`
12212+
of floating point values. Both arguments must have identical types.
12213+
12214+
The third and fourth arguments specify the rounding mode and exception
12215+
behavior as described above.
12216+
12217+
Semantics:
12218+
""""""""""
12219+
12220+
The value produced is the floating point difference of the two value operands
12221+
and has the same type as the operands.
12222+
12223+
12224+
'``llvm.experimental.constrained.fmul``' Intrinsic
12225+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12226+
12227+
Syntax:
12228+
"""""""
12229+
12230+
::
12231+
12232+
declare <type>
12233+
@llvm.experimental.constrained.fmul(<type> <op1>, <type> <op2>,
12234+
metadata <rounding mode>,
12235+
metadata <exception behavior>)
12236+
12237+
Overview:
12238+
"""""""""
12239+
12240+
The '``llvm.experimental.constrained.fmul``' intrinsic returns the product of
12241+
its two operands.
12242+
12243+
12244+
Arguments:
12245+
""""""""""
12246+
12247+
The first two arguments to the '``llvm.experimental.constrained.fmul``'
12248+
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>`
12249+
of floating point values. Both arguments must have identical types.
12250+
12251+
The third and fourth arguments specify the rounding mode and exception
12252+
behavior as described above.
12253+
12254+
Semantics:
12255+
""""""""""
12256+
12257+
The value produced is the floating point product of the two value operands and
12258+
has the same type as the operands.
12259+
12260+
12261+
'``llvm.experimental.constrained.fdiv``' Intrinsic
12262+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12263+
12264+
Syntax:
12265+
"""""""
12266+
12267+
::
12268+
12269+
declare <type>
12270+
@llvm.experimental.constrained.fdiv(<type> <op1>, <type> <op2>,
12271+
metadata <rounding mode>,
12272+
metadata <exception behavior>)
12273+
12274+
Overview:
12275+
"""""""""
12276+
12277+
The '``llvm.experimental.constrained.fdiv``' intrinsic returns the quotient of
12278+
its two operands.
12279+
12280+
12281+
Arguments:
12282+
""""""""""
12283+
12284+
The first two arguments to the '``llvm.experimental.constrained.fdiv``'
12285+
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>`
12286+
of floating point values. Both arguments must have identical types.
12287+
12288+
The third and fourth arguments specify the rounding mode and exception
12289+
behavior as described above.
12290+
12291+
Semantics:
12292+
""""""""""
12293+
12294+
The value produced is the floating point quotient of the two value operands and
12295+
has the same type as the operands.
12296+
12297+
12298+
'``llvm.experimental.constrained.frem``' Intrinsic
12299+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12300+
12301+
Syntax:
12302+
"""""""
12303+
12304+
::
12305+
12306+
declare <type>
12307+
@llvm.experimental.constrained.frem(<type> <op1>, <type> <op2>,
12308+
metadata <rounding mode>,
12309+
metadata <exception behavior>)
12310+
12311+
Overview:
12312+
"""""""""
12313+
12314+
The '``llvm.experimental.constrained.frem``' intrinsic returns the remainder
12315+
from the division of its two operands.
12316+
12317+
12318+
Arguments:
12319+
""""""""""
12320+
12321+
The first two arguments to the '``llvm.experimental.constrained.frem``'
12322+
intrinsic must be :ref:`floating point <t_floating>` or :ref:`vector <t_vector>`
12323+
of floating point values. Both arguments must have identical types.
12324+
12325+
The third and fourth arguments specify the rounding mode and exception
12326+
behavior as described above. The rounding mode argument has no effect, since
12327+
the result of frem is never rounded, but the argument is included for
12328+
consistency with the other constrained floating point intrinsics.
12329+
12330+
Semantics:
12331+
""""""""""
12332+
12333+
The value produced is the floating point remainder from the division of the two
12334+
value operands and has the same type as the operands. The remainder has the
12335+
same sign as the dividend.
12336+
12337+
1206712338
General Intrinsics
1206812339
------------------
1206912340

include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ namespace ISD {
245245
/// Simple binary floating point operators.
246246
FADD, FSUB, FMUL, FDIV, FREM,
247247

248+
/// Constrained versions of the binary floating point operators.
249+
/// These will be lowered to the simple operators before final selection.
250+
/// They are used to limit optimizations while the DAG is being
251+
/// optimized.
252+
STRICT_FADD, STRICT_FSUB, STRICT_FMUL, STRICT_FDIV, STRICT_FREM,
253+
248254
/// FMA - Perform a * b + c with no intermediate rounding step.
249255
FMA,
250256

include/llvm/CodeGen/SelectionDAGISel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ class SelectionDAGISel : public MachineFunctionPass {
270270
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs,
271271
ArrayRef<SDValue> Ops, unsigned EmitNodeInfo);
272272

273+
SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc);
274+
273275
/// Prepares the landing pad to take incoming values or do other EH
274276
/// personality specific tasks. Returns true if the block should be
275277
/// instruction selected, false if no code should be emitted for it.

include/llvm/IR/IntrinsicInst.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,45 @@ namespace llvm {
152152
}
153153
};
154154

155+
/// This is the common base class for constrained floating point intrinsics.
156+
class ConstrainedFPIntrinsic : public IntrinsicInst {
157+
public:
158+
enum RoundingMode {
159+
rmInvalid,
160+
rmDynamic,
161+
rmToNearest,
162+
rmDownward,
163+
rmUpward,
164+
rmTowardZero
165+
};
166+
167+
enum ExceptionBehavior {
168+
ebInvalid,
169+
ebIgnore,
170+
ebMayTrap,
171+
ebStrict
172+
};
173+
174+
RoundingMode getRoundingMode() const;
175+
ExceptionBehavior getExceptionBehavior() const;
176+
177+
// Methods for support type inquiry through isa, cast, and dyn_cast:
178+
static inline bool classof(const IntrinsicInst *I) {
179+
switch (I->getIntrinsicID()) {
180+
case Intrinsic::experimental_constrained_fadd:
181+
case Intrinsic::experimental_constrained_fsub:
182+
case Intrinsic::experimental_constrained_fmul:
183+
case Intrinsic::experimental_constrained_fdiv:
184+
case Intrinsic::experimental_constrained_frem:
185+
return true;
186+
default: return false;
187+
}
188+
}
189+
static inline bool classof(const Value *V) {
190+
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
191+
}
192+
};
193+
155194
/// This is the common base class for memset/memcpy/memmove.
156195
class MemIntrinsic : public IntrinsicInst {
157196
public:

include/llvm/IR/Intrinsics.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,9 @@ def int_memset : Intrinsic<[],
389389
llvm_i32_ty, llvm_i1_ty],
390390
[IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
391391

392+
// FIXME: Add version of these floating point intrinsics which allow non-default
393+
// rounding modes and FP exception handling.
394+
392395
let IntrProperties = [IntrNoMem] in {
393396
def int_fma : Intrinsic<[llvm_anyfloat_ty],
394397
[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -442,6 +445,39 @@ def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty],
442445
[IntrNoMem]>,
443446
GCCBuiltin<"__builtin_object_size">;
444447

448+
//===--------------- Constrained Floating Point Intrinsics ----------------===//
449+
//
450+
451+
let IntrProperties = [IntrInaccessibleMemOnly] in {
452+
def int_experimental_constrained_fadd : Intrinsic<[ llvm_anyfloat_ty ],
453+
[ LLVMMatchType<0>,
454+
LLVMMatchType<0>,
455+
llvm_metadata_ty,
456+
llvm_metadata_ty ]>;
457+
def int_experimental_constrained_fsub : Intrinsic<[ llvm_anyfloat_ty ],
458+
[ LLVMMatchType<0>,
459+
LLVMMatchType<0>,
460+
llvm_metadata_ty,
461+
llvm_metadata_ty ]>;
462+
def int_experimental_constrained_fmul : Intrinsic<[ llvm_anyfloat_ty ],
463+
[ LLVMMatchType<0>,
464+
LLVMMatchType<0>,
465+
llvm_metadata_ty,
466+
llvm_metadata_ty ]>;
467+
def int_experimental_constrained_fdiv : Intrinsic<[ llvm_anyfloat_ty ],
468+
[ LLVMMatchType<0>,
469+
LLVMMatchType<0>,
470+
llvm_metadata_ty,
471+
llvm_metadata_ty ]>;
472+
def int_experimental_constrained_frem : Intrinsic<[ llvm_anyfloat_ty ],
473+
[ LLVMMatchType<0>,
474+
LLVMMatchType<0>,
475+
llvm_metadata_ty,
476+
llvm_metadata_ty ]>;
477+
}
478+
// FIXME: Add intrinsic for fcmp, fptrunc, fpext, fptoui and fptosi.
479+
480+
445481
//===------------------------- Expect Intrinsics --------------------------===//
446482
//
447483
def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>,

0 commit comments

Comments
 (0)