diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -20132,6 +20132,64 @@ %also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> undef +.. _int_vp_fcmp: + +'``llvm.vp.fcmp.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. + +:: + + declare <16 x i1> @llvm.vp.fcmp.v16f32(<16 x float> , <16 x float> , metadata , <16 x i1> , i32 ) + declare @llvm.vp.fcmp.nxv4f32( , , metadata , , i32 ) + declare <256 x i1> @llvm.vp.fcmp.v256f64(<256 x double> , <256 x double> , metadata , <256 x i1> , i32 ) + +Overview: +""""""""" + +The '``llvm.vp.fcmp``' intrinsic returns a boolean value or vector of boolean +values based on the comparison of its operands. The operation has a mask and an +explicit vector length parameter. + + +Arguments: +"""""""""" + +The '``llvm.vp.fcmp``' intrinsic takes the two values to compare as its first +and second operands. These two values must be vectors of :ref:`floating-point +` types. +The return type is the result of the comparison. The return type must be vector +of :ref:`i1 ` type. The fourth operand is the vector mask. The +return type, the values to compare, and the vector mask have the same number of +elements. The third operand is the condition code indicating the kind of +comparison to perform. It must be a metadata string with :ref:`one of the +supported floating-point condition code values `. The fifth operand +is the explicit vector length of the operation. + +Semantics: +"""""""""" + +The '``llvm.vp.fcmp``' compares its first two operands according to the +condition code given as the third operand. The operands are compared element by +element on each enabled lane, where the the semantics of the comparison are +defined :ref:`according to the condition code `. Masked-off +lanes are undefined. + +Examples: +""""""""" + +.. code-block:: llvm + + %r = call <4 x i1> @llvm.vp.fcmp.v4f32(<4 x float> %a, <4 x float> %b, metadata !"oeq", <4 x i1> %mask, i32 %evl) + ;; For all lanes below %evl, %r is lane-wise equivalent to %also.r + + %t = fcmp oeq <4 x float> %a, %b + %also.r = select <4 x i1> %mask, <4 x float> %t, <4 x float> undef + + .. _int_mload_mstore: Masked Vector Load and Store Intrinsics @@ -21272,6 +21330,8 @@ The third argument is the condition code indicating the kind of comparison to perform. It must be a metadata string with one of the following values: +.. _fcmp_md_cc: + - "``oeq``": ordered and equal - "``ogt``": ordered and greater than - "``oge``": ordered and greater than or equal @@ -21300,6 +21360,8 @@ vectors are compared element by element. Each comparison performed always yields an :ref:`i1 ` result, as follows: +.. _fcmp_md_cc_sem: + - "``oeq``": yields ``true`` if both operands are not a NAN and ``op1`` is equal to ``op2``. - "``ogt``": yields ``true`` if both operands are not a NAN and ``op1`` diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1547,6 +1547,14 @@ LLVMMatchType<0>, llvm_i32_ty]>; +// Comparisons. +def int_vp_fcmp : DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], + [ llvm_anyvector_ty, + LLVMMatchType<0>, + llvm_metadata_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, + llvm_i32_ty]>; + // Reductions let IntrProperties = [IntrSpeculatable, IntrNoMem, IntrNoSync, IntrWillReturn] in { def int_vp_reduce_fadd : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], diff --git a/llvm/include/llvm/IR/VPIntrinsics.def b/llvm/include/llvm/IR/VPIntrinsics.def --- a/llvm/include/llvm/IR/VPIntrinsics.def +++ b/llvm/include/llvm/IR/VPIntrinsics.def @@ -252,6 +252,15 @@ ///// } Type Casts +///// Comparisons { +// llvm.vp.fcmp(x,y,cc,mask,vlen) +BEGIN_REGISTER_VP(vp_fcmp, 3, 4, VP_FCMP, -1) +VP_PROPERTY_FUNCTIONAL_OPC(FCmp) +VP_PROPERTY_CONSTRAINEDFP(0, 1, experimental_constrained_fcmp) +END_REGISTER_VP(vp_fcmp, VP_FCMP) + +///// } Comparisons + ///// Memory Operations { // llvm.vp.store(val,ptr,mask,vlen) BEGIN_REGISTER_VP_INTRINSIC(vp_store, 2, 3) diff --git a/llvm/test/Verifier/vp-intrinsics.ll b/llvm/test/Verifier/vp-intrinsics.ll --- a/llvm/test/Verifier/vp-intrinsics.ll +++ b/llvm/test/Verifier/vp-intrinsics.ll @@ -63,6 +63,11 @@ ret void } +define void @test_vp_comparisons(<8 x float> %f0, <8 x float> %f1, <8 x i1> %mask, i32 %evl) { + %r0 = call <8 x i1> @llvm.vp.fcmp.v8f32(<8 x float> %f0, <8 x float> %f1, metadata !"oeq", <8 x i1> %mask, i32 %evl) + ret void +} + ; integer arith declare <8 x i32> @llvm.vp.add.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.sub.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) @@ -101,6 +106,8 @@ ; casts declare <8 x float> @llvm.vp.sitofp.v8f32.v8i32(<8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.fptosi.v8i32.v8f32(<8 x float>, <8 x i1>, i32) +; compares +declare <8 x i1> @llvm.vp.fcmp.v8f32(<8 x float>, <8 x float>, metadata, <8 x i1>, i32) ; shuffles declare <8 x i32> @llvm.experimental.vp.splice.v8i32(<8 x i32>, <8 x i32>, i32, <8 x i1>, i32, i32) declare @llvm.experimental.vp.splice.nxv8i32(, , i32, , i32, i32) diff --git a/llvm/unittests/IR/VPIntrinsicTest.cpp b/llvm/unittests/IR/VPIntrinsicTest.cpp --- a/llvm/unittests/IR/VPIntrinsicTest.cpp +++ b/llvm/unittests/IR/VPIntrinsicTest.cpp @@ -85,6 +85,9 @@ Str << " declare <8 x float> @llvm.vp.sitofp.v8f32" << ".v8i32(<8 x i32>, <8 x i1>, i32) "; + Str << " declare <8 x i1> @llvm.vp.fcmp.v8f32" + << ".v8f32(<8 x float>, <8 x float>, metadata, <8 x i1>, i32) "; + return parseAssemblyString(Str.str(), Err, C); } };