[llvm] [LLVM] Add FP instruction intrinsics (PR #193588)
Princeton Ferro via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 29 02:59:22 PDT 2026
================
@@ -30256,6 +30277,659 @@ Semantics:
This function returns the same values as the libm ``trunc`` functions
would and handles error conditions in the same way.
+.. _fpintrin:
+
+FP Arithmetic Intrinsics
+------------------------
+
+These intrinsics are intrinsic variants of the standard floating-point
+instructions (:ref:`fadd <i_fadd>`, :ref:`fsub <i_fsub>`, :ref:`fmul <i_fmul>`,
+:ref:`fdiv <i_fdiv>`, :ref:`frem <i_frem>`, :ref:`fneg <i_fneg>`,
+:ref:`fcmp <i_fcmp>`, :ref:`fptrunc <i_fptrunc>`, :ref:`fpext <i_fpext>`,
+and the ``fptoui``, ``fptosi``, ``uitofp``, ``sitofp`` conversion instructions).
+They behave identically to the corresponding instruction and accept the same
+:ref:`fast-math flags <fastmath>`.
+
+``llvm.fcmps`` is always ``memory(inaccessiblemem: readwrite)`` and not
+speculatable because a signaling comparison raises an FP Invalid Operation
+exception whenever either operand is any NaN, including quiet NaNs.
+
+.. _int_fadd:
+
+'``llvm.fadd.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fadd`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.fadd.f16(half %op1, half %op2)
+ declare bfloat @llvm.fadd.bf16(bfloat %op1, bfloat %op2)
+ declare float @llvm.fadd.f32(float %op1, float %op2)
+ declare double @llvm.fadd.f64(double %op1, double %op2)
+ declare x86_fp80 @llvm.fadd.f80(x86_fp80 %op1, x86_fp80 %op2)
+ declare fp128 @llvm.fadd.f128(fp128 %op1, fp128 %op2)
+ declare ppc_fp128 @llvm.fadd.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fadd <i_fadd>` instruction. Returns the
+floating-point sum of its two operands.
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`fadd <i_fadd>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call float @llvm.fadd.f32(float %a, float %b)
+
+.. _int_fsub:
+
+'``llvm.fsub.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fsub`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.fsub.f16(half %op1, half %op2)
+ declare bfloat @llvm.fsub.bf16(bfloat %op1, bfloat %op2)
+ declare float @llvm.fsub.f32(float %op1, float %op2)
+ declare double @llvm.fsub.f64(double %op1, double %op2)
+ declare x86_fp80 @llvm.fsub.f80(x86_fp80 %op1, x86_fp80 %op2)
+ declare fp128 @llvm.fsub.f128(fp128 %op1, fp128 %op2)
+ declare ppc_fp128 @llvm.fsub.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fsub <i_fsub>` instruction. Returns the
+floating-point difference of its two operands.
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`fsub <i_fsub>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call double @llvm.fsub.f64(double %a, double %b)
+
+.. _int_fmul:
+
+'``llvm.fmul.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fmul`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.fmul.f16(half %op1, half %op2)
+ declare bfloat @llvm.fmul.bf16(bfloat %op1, bfloat %op2)
+ declare float @llvm.fmul.f32(float %op1, float %op2)
+ declare double @llvm.fmul.f64(double %op1, double %op2)
+ declare x86_fp80 @llvm.fmul.f80(x86_fp80 %op1, x86_fp80 %op2)
+ declare fp128 @llvm.fmul.f128(fp128 %op1, fp128 %op2)
+ declare ppc_fp128 @llvm.fmul.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fmul <i_fmul>` instruction. Returns the
+floating-point product of its two operands.
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`fmul <i_fmul>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call float @llvm.fmul.f32(float %a, float %b)
+
+.. _int_fdiv:
+
+'``llvm.fdiv.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fdiv`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.fdiv.f16(half %op1, half %op2)
+ declare bfloat @llvm.fdiv.bf16(bfloat %op1, bfloat %op2)
+ declare float @llvm.fdiv.f32(float %op1, float %op2)
+ declare double @llvm.fdiv.f64(double %op1, double %op2)
+ declare x86_fp80 @llvm.fdiv.f80(x86_fp80 %op1, x86_fp80 %op2)
+ declare fp128 @llvm.fdiv.f128(fp128 %op1, fp128 %op2)
+ declare ppc_fp128 @llvm.fdiv.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fdiv <i_fdiv>` instruction. Returns the
+floating-point quotient of its two operands.
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`fdiv <i_fdiv>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call double @llvm.fdiv.f64(double %a, double %b)
+
+.. _int_frem:
+
+'``llvm.frem.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.frem`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.frem.f16(half %op1, half %op2)
+ declare bfloat @llvm.frem.bf16(bfloat %op1, bfloat %op2)
+ declare float @llvm.frem.f32(float %op1, float %op2)
+ declare double @llvm.frem.f64(double %op1, double %op2)
+ declare x86_fp80 @llvm.frem.f80(x86_fp80 %op1, x86_fp80 %op2)
+ declare fp128 @llvm.frem.f128(fp128 %op1, fp128 %op2)
+ declare ppc_fp128 @llvm.frem.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`frem <i_frem>` instruction. Returns the
+floating-point remainder of dividing the first operand by the second.
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`frem <i_frem>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call float @llvm.frem.f32(float %a, float %b)
+
+.. _int_fneg:
+
+'``llvm.fneg.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fneg`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare half @llvm.fneg.f16(half %op1)
+ declare bfloat @llvm.fneg.bf16(bfloat %op1)
+ declare float @llvm.fneg.f32(float %op1)
+ declare double @llvm.fneg.f64(double %op1)
+ declare x86_fp80 @llvm.fneg.f80(x86_fp80 %op1)
+ declare fp128 @llvm.fneg.f128(fp128 %op1)
+ declare ppc_fp128 @llvm.fneg.ppcf128(ppc_fp128 %op1)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fneg <i_fneg>` instruction. Returns the
+floating-point negation of its operand.
+
+Arguments:
+""""""""""
+
+The argument and return value are floating-point numbers of the same type.
+
+Semantics:
+""""""""""
+
+Equivalent to the :ref:`fneg <i_fneg>` instruction. Always ``memory(none)``
+and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %r = call float @llvm.fneg.f32(float %x)
+
+.. _int_fcmp:
+
+'``llvm.fcmp.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fcmp`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare i1 @llvm.fcmp.f16(half %op1, half %op2, metadata %cc)
+ declare i1 @llvm.fcmp.bf16(bfloat %op1, bfloat %op2, metadata %cc)
+ declare i1 @llvm.fcmp.f32(float %op1, float %op2, metadata %cc)
+ declare i1 @llvm.fcmp.f64(double %op1, double %op2, metadata %cc)
+ declare i1 @llvm.fcmp.f80(x86_fp80 %op1, x86_fp80 %op2, metadata %cc)
+ declare i1 @llvm.fcmp.f128(fp128 %op1, fp128 %op2, metadata %cc)
+ declare i1 @llvm.fcmp.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2, metadata %cc)
+
+Overview:
+"""""""""
+
+Intrinsic form of the :ref:`fcmp <i_fcmp>` instruction. Performs a **quiet**
+floating-point comparison. For vector types the return type is a vector of
+``i1`` with the same number of elements as the operands.
+
+Arguments:
+""""""""""
+
+The two operands must be floating-point numbers of the same type. The third
+argument is a metadata string giving the comparison predicate; valid values are
+:ref:`the same as for the fcmp instruction <fcmp_md_cc>`: ``"oeq"``,
+``"ogt"``, ``"oge"``, ``"olt"``, ``"ole"``, ``"one"``, ``"ord"``, ``"ueq"``,
+``"ugt"``, ``"uge"``, ``"ult"``, ``"ule"``, ``"une"``, ``"uno"``, ``"true"``,
+and ``"false"``.
+
+Semantics:
+""""""""""
+
+The comparison semantics :ref:`follow those of the fcmp instruction
+<fcmp_md_cc_sem>`. Always ``memory(none)`` and speculatable.
+
+Example:
+""""""""
+
+::
+
+ %c = call i1 @llvm.fcmp.f32(float %a, float %b, metadata !"oeq")
+
+.. _int_fcmps:
+
+'``llvm.fcmps.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.fcmps`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare i1 @llvm.fcmps.f16(half %op1, half %op2, metadata %cc)
+ declare i1 @llvm.fcmps.bf16(bfloat %op1, bfloat %op2, metadata %cc)
+ declare i1 @llvm.fcmps.f32(float %op1, float %op2, metadata %cc)
+ declare i1 @llvm.fcmps.f64(double %op1, double %op2, metadata %cc)
+ declare i1 @llvm.fcmps.f80(x86_fp80 %op1, x86_fp80 %op2, metadata %cc)
+ declare i1 @llvm.fcmps.f128(fp128 %op1, fp128 %op2, metadata %cc)
+ declare i1 @llvm.fcmps.ppcf128(ppc_fp128 %op1, ppc_fp128 %op2, metadata %cc)
+
+Overview:
+"""""""""
+
+Performs a **signaling** floating-point comparison. Unlike
----------------
Prince781 wrote:
Updated the llvm.fcmps overview to clarify: the signaling vs. quiet distinction is only observable when FP exception tracking is active (e.g. via strictfp or a future operand bundle). In the default LLVM FP model (traps/status flags not observable) both intrinsics produce the same result. Also clarified that llvm.fcmps signals for ANY NaN (sNaN and qNaN), while llvm.fcmp signals only for sNaN.
https://github.com/llvm/llvm-project/pull/193588
More information about the llvm-commits
mailing list