From patchwork Fri Nov 17 22:36:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoni Boucher X-Patchwork-Id: 80191 X-Patchwork-Delegate: dmalcolm@redhat.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3AAD83858297 for ; Fri, 17 Nov 2023 22:37:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from sender3-pp-o98.zoho.com (sender3-pp-o98.zoho.com [136.143.184.98]) by sourceware.org (Postfix) with ESMTPS id 1E9283858D32; Fri, 17 Nov 2023 22:36:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E9283858D32 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=zoho.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=zoho.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1E9283858D32 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=136.143.184.98 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1700260627; cv=pass; b=UWIsnxoy8O1V9p4KqkDpdVS0sJlTSqE4xJS/3xq1YNssnA0fy/gL3h4FtEH2LZp5SpKVpQz6n10K02B20xUGOn+q9ZDv92LHUmBlfqJ61DhHjtT/EuaVKvsS4xeb/OxeBbngxjuz7AXMwlFnG+IbYV0yBmRDfkcybmySa1IGMZM= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1700260627; c=relaxed/simple; bh=MrPmxVF28YI1X59PhZcV7A5vqurCAdgJ+wrt3csnMPE=; h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version; b=MIO2mqMVBpd2IzNrmT1tLskxnrJTGzLFYmXpqAeFA+Yich+ecOKpiYOHDoTWqRythug7Fcr5zhhqzanIJVFRhnU5FxRvLHgam4zRQUPJEaP3wMWdM5FCwBnB4nibcz3ArlZFo6GYomALMSWd7bEWreoX7luv96BaH/mS4OFKd2w= ARC-Authentication-Results: i=2; server2.sourceware.org ARC-Seal: i=1; a=rsa-sha256; t=1700260613; cv=none; d=zohomail.com; s=zohoarc; b=lNCeDH2SoYthrO7zZhXY6HRoeNIilvlbjzwdmXPKIhN5pTOJSHqnIpb3Kc88xCX1JQtVSRTiSYncnLg4sXq5XDDHBRRTmO1ZaatYcpSkNPJRDzfWFjpitkB/jv4yPTaUbYCNJGB58LKQNKNeaYpD9UOZmkQyDWkdlCutZoirzmQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1700260613; h=Content-Type:Cc:Cc:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=ZAIY1h9hEvGDEQyPkxd2yZlYV8wLl+1U0igXz2phmYg=; b=LkaCYsBBNnTTaus4SCLd+mCDpVbFUrmda45RF8uN07dNdpYl/71RvHWLGlbY7IAvFWIClBuc66xLB6IJEZye7EbzHZD0Fj9wASMMSzeM/IGhmmzpPXx/TiNlO6Kom3FptIwA0laI+MuTHFO+oet8EqD/a/9AbiLSYBpTXJTteuo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=zoho.com; spf=pass smtp.mailfrom=bouanto@zoho.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1700260613; s=zm2022; d=zoho.com; i=bouanto@zoho.com; h=Message-ID:Subject:Subject:From:From:To:To:Cc:Cc:Date:Date:Content-Type:MIME-Version:Feedback-ID:Message-Id:Reply-To; bh=ZAIY1h9hEvGDEQyPkxd2yZlYV8wLl+1U0igXz2phmYg=; b=hL7ZmNv3ExG3bny/0PsbFoQi2YSre4ZvvObUJyLuOdBiyTffJwN7GpTNH/oXwKCT Yt+YaZ/lMXitnTI8IccuVg1aDPDPnSVbhtBcXOUmZMgV1guJjKcAqjOY6NlmvWXCO+1 9THX/wOXXuIxerEVY4R1dVHxIePJvKAuuEV9EU84= Received: from [192.168.1.172] (38.87.11.6 [38.87.11.6]) by mx.zohomail.com with SMTPS id 1700260612829609.1175510434026; Fri, 17 Nov 2023 14:36:52 -0800 (PST) Message-ID: Subject: [PATCH] libgccjit: Add vector permutation and vector access operations From: Antoni Boucher To: jit@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: David Malcolm Date: Fri, 17 Nov 2023 17:36:50 -0500 Autocrypt: addr=bouanto@zoho.com; prefer-encrypt=mutual; keydata=mQENBFOSMLQBCADO5aw6Ys8thMQUNzrwAnfJX2wbgWiz0pQ01DjYj22eeIpChkoZn6LWdt4dieq30u2rFi/yQzJ02foHwI2+aL9rU6xz/x4TwqyRJQGMOqklNc3R+pdXmH4WDQkQDWmLxvc07vu+zb8Tx5A6pMDh4J2ncCEhLEUcH39Yq/yg4eBnFwUX6N7kakvHrnScGNqhnSFCacoJeMJUAR+1G7VBSBd++jmnHLnx3mj7QkRZVECJUw2zqiv1yReCC6GU4SvqLjdqm5ZGeoWOqD/NHjBRoEeOVjzp6M/qOjjWRbkJVqmvgfcD8UytSSqqboR35YFT4L+rZt2ri3T12MJb3i5syCAXABEBAAG0IUFudG9uaSBCb3VjaGVyIDxib3VhbnRvQHpvaG8uY29tPokBVgQTAQgAQAIbIwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAFiEEOELC4Uw1Jeb66YE6RVeGAwR4zcEFAlz4QM4FCRLMEZoACgkQRVeGAwR4zcFBQQf/afttJrA/puADQZhrDfkgr0MFvq6iB+GCy1b8BkXimk1TOXTPt87YLehSeijNu3JkYhl5eRc87BNfU9J87KfI/KIy6hZxqlDXk16FhW9bw/7wYEA0hpb3MUn7xLElXDT0ZHaD+KTe8Oun7qfzgx5RlL6r/WODf3CkSpO085R/rfeBqDEx9mVlhDWgq6Az3CZoD+3CqiCKVqmDuHTWz4kwrd9AM5eVcLvvLKnZIdoIp+G5Ao6BvaGlZyfenN1iOSjLy2NXNt4MnUt0lUYEP5KSIIRhHQ8xkUbj7eWUmaahkxhNb3fH3sAPwGnRZrPpb4rgYzNmSk63wWMh9M2xk+rLb7kBDQRTkjC0AQgAumZzsAV/UFWI+dpzebQfma36kKYZZFuseant5sq/HWP553XQ/U6ttJiKyN5MpCqtxvCAoRplf42YhlHuFqgf73WJxoJ6Y+sdyqoBSwlR+ gzAneAmsa8gmmY0wawH0Z2leazjKuS7mJjVEQZg0ZGsiCVRGeRnDqFGzDEzDc9ngWKSoTq0fKzlGy1X85OrtmUrvEbhSo6HP+FoeunHkIqrxu3w3vDoFEXxVQlKI6V3I4nCz5n6DB8WR3L7nsiiTnOiGirPw1ngvWFLW86kkA4FJpayc8Xl3va3SLY+2y4yuROboX2DVI4AC/Qeug/mDiBicPxkP6YfUartQRMe6obkEQARAQABiQE8BBgBCAAmAhsMFiEEOELC4Uw1Jeb66YE6RVeGAwR4zcEFAlz4QRsFCRLMEecACgkQRVeGAwR4zcE56ggAgTgrJInBKC+7552Dpccuo6Clh3wZfjlNLv9/6r5lKEbaNzaTrfhPiAP4WgnluIUmj8amOFLFJpj+BAVNOXpZ4D2R3o9ch8z7fot+fW4Yw+PKIxH4I2xEys8ndoEB3aiQwHjKcGIhkIU7uyMJFQr2aWjdTY0gmXw0YZueHOSLgo7uX4XKxB8fEO/yto/Tff2YBAAq+AtNwt+Gh5YS9rZw7rwUTWMi84yVOlc+zRE79E9NJkvdTwX7IJYo64VzIRNfgHsn7QNdVzuM1XIFHl+Glk6cIlI8s6BO7nEoCn3hTF104fQTAO3fEs+XXZOKXo2lk8faowEoPq5r58StrV0nyg== User-Agent: Evolution 3.50.1 MIME-Version: 1.0 X-Zoho-Virus-Status: 1 X-Zoho-AV-Stamp: zmail-av-1.1.0/200.232.44 Feedback-ID: rr080112288d7b5689326743a895f1f7bf000080fe5838f8a33c7c778cab9e5d850f99aadbfaa8b20bd9dd6061:zu08011226d411eac914405ebaa92ce67e00008b1d795735f992f6f294916333262c9bd4a04b72c13776f5:rf0801123262de6bd3d59ca48f9a02a82400008cb91294544454b560299b446e8a0aca0185c628260ca0bf75330ca9f18c4e62f46f094c:ZohoMail X-ZohoMailClient: External X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Hi. This patch adds a vector permutation and vector access operations (bug 112602). This was split from this patch: https://gcc.gnu.org/pipermail/jit/2023q1/001606.html Thanks for the review. From 25b386334f22845d7ba1b60658730373eb6ddbb3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 17 Nov 2023 17:23:28 -0500 Subject: [PATCH] libgccjit: Add vector permutation and vector access operations gcc/jit/ChangeLog: PR jit/112602 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag. * docs/topics/expressions.rst: Document gcc_jit_context_new_rvalue_vector_perm and gcc_jit_context_new_vector_access. * jit-playback.cc (playback::context::new_rvalue_vector_perm, common_mark_addressable_vec, gnu_vector_type_p, lvalue_p, convert_vector_to_array_for_subscript, new_vector_access): new functions. * jit-playback.h (new_rvalue_vector_perm, new_vector_access): New functions. * jit-recording.cc (recording::context::new_rvalue_vector_perm, recording::context::new_vector_access, memento_of_new_rvalue_vector_perm, recording::memento_of_new_rvalue_vector_perm::replay_into, recording::memento_of_new_rvalue_vector_perm::visit_children, recording::memento_of_new_rvalue_vector_perm::make_debug_string, recording::memento_of_new_rvalue_vector_perm::write_reproducer, recording::vector_access::replay_into, recording::vector_access::visit_children, recording::vector_access::make_debug_string, recording::vector_access::write_reproducer): New methods. * jit-recording.h (class memento_of_new_rvalue_vector_perm, class vector_access): New classes. * libgccjit.cc (gcc_jit_context_new_vector_access, gcc_jit_context_new_rvalue_vector_perm): New functions. * libgccjit.h (gcc_jit_context_new_rvalue_vector_perm, gcc_jit_context_new_vector_access): New functions. * libgccjit.map: New functions. gcc/testsuite/ChangeLog: PR jit/112602 * jit.dg/all-non-failing-tests.h: New test test-vector-perm.c. * jit.dg/test-vector-perm.c: New test. --- gcc/jit/docs/topics/compatibility.rst | 10 ++ gcc/jit/docs/topics/expressions.rst | 53 ++++++ gcc/jit/jit-playback.cc | 150 ++++++++++++++++ gcc/jit/jit-playback.h | 11 ++ gcc/jit/jit-recording.cc | 169 +++++++++++++++++++ gcc/jit/jit-recording.h | 72 ++++++++ gcc/jit/libgccjit.cc | 109 ++++++++++++ gcc/jit/libgccjit.h | 29 ++++ gcc/jit/libgccjit.map | 6 + gcc/testsuite/jit.dg/all-non-failing-tests.h | 12 +- gcc/testsuite/jit.dg/test-vector-perm.c | 96 +++++++++++ 11 files changed, 716 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/jit.dg/test-vector-perm.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index ebede440ee4..a764e3968d1 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -378,3 +378,13 @@ alignment of a variable: -------------------- ``LIBGCCJIT_ABI_25`` covers the addition of :func:`gcc_jit_type_get_restrict` + + +.. _LIBGCCJIT_ABI_26: + +``LIBGCCJIT_ABI_26`` +-------------------- +``LIBGCCJIT_ABI_26`` covers the addition of functions to manipulate vectors: + + * :func:`gcc_jit_context_new_rvalue_vector_perm` + * :func:`gcc_jit_context_new_vector_access` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index 42cfee36302..4a45aa13f5c 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -295,6 +295,35 @@ Vector expressions #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector +.. function:: gcc_jit_rvalue * \ + gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, \ + gcc_jit_location *loc, \ + gcc_jit_rvalue *elements1, \ + gcc_jit_rvalue *elements2, \ + gcc_jit_rvalue *mask); + + Build a permutation of two vectors. + + "elements1" and "elements2" should have the same type. + The length of "mask" and "elements1" should be the same. + The element type of "mask" should be integral. + The size of the element type of "mask" and "elements1" should be the same. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS + + Analogous to: + + .. code-block:: c + + __builtin_shuffle (elements1, elements2, mask) + + in C. + Unary Operations **************** @@ -1020,3 +1049,27 @@ Field access is provided separately for both lvalues and rvalues. PTR[INDEX] in C (or, indeed, to ``PTR + INDEX``). + +.. function:: gcc_jit_lvalue *\ + gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *vector,\ + gcc_jit_rvalue *index) + + Given an rvalue of vector type ``T __attribute__ ((__vector_size__ (SIZE)))``, get the element `T` at + the given index. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS + + Analogous to: + + .. code-block:: c + + VECTOR[INDEX] + + in C. diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index 18cc4da25b8..1aba0fb4a28 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -1011,6 +1011,26 @@ playback::context::new_rvalue_from_vector (location *, return new rvalue (this, t_ctor); } +/* Construct a playback::rvalue instance (wrapping a tree) for a + vector perm. */ + +playback::rvalue * +playback::context::new_rvalue_vector_perm (location *loc, + rvalue* elements1, + rvalue* elements2, + rvalue* mask) +{ + tree t_elements1 = elements1->as_tree (); + tree t_elements2 = elements2->as_tree (); + tree t_mask = mask->as_tree (); + + tree t_vector_perm = build3 (VEC_PERM_EXPR, TREE_TYPE (t_elements1), + t_elements1, t_elements2, t_mask); + if (loc) + set_tree_location (t_vector_perm, loc); + return new rvalue (this, t_vector_perm); +} + /* Coerce a tree expression into a boolean tree expression. */ tree @@ -1527,6 +1547,136 @@ new_array_access (location *loc, } } +/* The following functions come from c-common.h. */ +/* Like c_mark_addressable but don't check register qualifier. */ +void +common_mark_addressable_vec (tree t) +{ + while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR) + { + t = TREE_OPERAND (t, 0); + } + if (!VAR_P (t) + && TREE_CODE (t) != PARM_DECL + && TREE_CODE (t) != COMPOUND_LITERAL_EXPR + && TREE_CODE (t) != TARGET_EXPR) + return; + if (!VAR_P (t) || !DECL_HARD_REGISTER (t)) + TREE_ADDRESSABLE (t) = 1; + if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR) + TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1; + else if (TREE_CODE (t) == TARGET_EXPR) + TREE_ADDRESSABLE (TARGET_EXPR_SLOT (t)) = 1; +} + +/* Return true if TYPE is a vector type that should be subject to the GNU + vector extensions (as opposed to a vector type that is used only for + the purposes of defining target-specific built-in functions). */ + +inline bool +gnu_vector_type_p (const_tree type) +{ + return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type); +} + +/* Return nonzero if REF is an lvalue valid for this language. + Lvalues can be assigned, unless their type has TYPE_READONLY. + Lvalues can have their address taken, unless they have C_DECL_REGISTER. */ + +bool +lvalue_p (const_tree ref) +{ + const enum tree_code code = TREE_CODE (ref); + + switch (code) + { + case REALPART_EXPR: + case IMAGPART_EXPR: + case COMPONENT_REF: + return lvalue_p (TREE_OPERAND (ref, 0)); + + case C_MAYBE_CONST_EXPR: + return lvalue_p (TREE_OPERAND (ref, 1)); + + case COMPOUND_LITERAL_EXPR: + case STRING_CST: + return true; + + case MEM_REF: + case TARGET_MEM_REF: + /* MEM_REFs can appear from -fgimple parsing or folding, so allow them + here as well. */ + case INDIRECT_REF: + case ARRAY_REF: + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case ERROR_MARK: + return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); + + case BIND_EXPR: + return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; + + default: + return false; + } +} + +bool +convert_vector_to_array_for_subscript (tree *vecp) +{ + bool ret = false; + if (gnu_vector_type_p (TREE_TYPE (*vecp))) + { + tree type = TREE_TYPE (*vecp); + + ret = !lvalue_p (*vecp); + + /* We are building an ARRAY_REF so mark the vector as addressable + to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P + for function parameters. */ + /* NOTE: that was the missing piece for making vector access work with + optimizations enabled. */ + common_mark_addressable_vec (*vecp); + + *vecp = build1 (VIEW_CONVERT_EXPR, + build_array_type_nelts (TREE_TYPE (type), + TYPE_VECTOR_SUBPARTS (type)), + *vecp); + } + return ret; +} + +/* Construct a playback::lvalue instance (wrapping a tree) for a + vector access. */ + +playback::lvalue * +playback::context:: +new_vector_access (location *loc, + rvalue *vector, + rvalue *index) +{ + gcc_assert (vector); + gcc_assert (index); + + /* For comparison, see: + c/c-typeck.cc: build_array_ref + */ + + tree t_vector = vector->as_tree (); + bool non_lvalue = convert_vector_to_array_for_subscript (&t_vector); + tree type = TREE_TYPE (TREE_TYPE (t_vector)); + tree t_result = build4 (ARRAY_REF, type, t_vector, index->as_tree (), + NULL_TREE, NULL_TREE); + if (non_lvalue) + t_result = non_lvalue (t_result); + + if (loc) + set_tree_location (t_result, loc); + return new lvalue (this, t_result); +} + /* Construct a tree for a field access. */ tree diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index f9e29d0baec..a2d99331dbe 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -147,6 +147,12 @@ public: type *type, const auto_vec &elements); + rvalue * + new_rvalue_vector_perm (location *loc, + rvalue* elements1, + rvalue* elements2, + rvalue* mask); + rvalue * new_unary_op (location *loc, enum gcc_jit_unary_op op, @@ -191,6 +197,11 @@ public: rvalue *ptr, rvalue *index); + lvalue * + new_vector_access (location *loc, + rvalue *vector, + rvalue *index); + void set_str_option (enum gcc_jit_str_option opt, const char *value); diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 9b5b8005ebe..cf1319ec3bb 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -1108,6 +1108,19 @@ recording::context::new_rvalue_from_vector (location *loc, return result; } +recording::rvalue * +recording::context::new_rvalue_vector_perm (location *loc, + rvalue *elements1, + rvalue *elements2, + rvalue *mask) +{ + recording::rvalue *result + = new memento_of_new_rvalue_vector_perm (this, loc, elements1, elements2, + mask); + record (result); + return result; +} + recording::rvalue * recording::context::new_ctor (recording::location *loc, recording::type *type, @@ -1309,6 +1322,22 @@ recording::context::new_array_access (recording::location *loc, return result; } +/* Create a recording::vector_access instance and add it to this context's list + of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_vector_access. */ + +recording::lvalue * +recording::context::new_vector_access (recording::location *loc, + recording::rvalue *vector, + recording::rvalue *index) +{ + recording::lvalue *result = new vector_access (this, loc, vector, index); + record (result); + return result; +} + /* Create a recording::case_ instance and add it to this context's list of mementos. @@ -5437,6 +5466,90 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r) elements_id); } +/* The implementation of class + gcc::jit::recording::memento_of_new_rvalue_vector_perm. */ + +/* The constructor for + gcc::jit::recording::memento_of_new_rvalue_vector_perm. */ + +recording::memento_of_new_rvalue_vector_perm:: +memento_of_new_rvalue_vector_perm (context *ctxt, + location *loc, + rvalue *elements1, + rvalue *elements2, + rvalue *mask) +: rvalue (ctxt, loc, elements1->get_type ()), + m_elements1 (elements1), + m_elements2 (elements2), + m_mask (mask) +{ +} + +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::memento_of_new_rvalue_vector_perm. */ + +void +recording::memento_of_new_rvalue_vector_perm::replay_into (replayer *r) +{ + playback::rvalue *playback_elements1 = m_elements1->playback_rvalue (); + playback::rvalue *playback_elements2 = m_elements2->playback_rvalue (); + playback::rvalue *playback_mask = m_mask->playback_rvalue (); + + set_playback_obj (r->new_rvalue_vector_perm (playback_location (r, m_loc), + playback_elements1, + playback_elements2, + playback_mask)); +} + +/* Implementation of pure virtual hook recording::rvalue::visit_children + for recording::memento_of_new_rvalue_from_vector. */ + + void +recording::memento_of_new_rvalue_vector_perm::visit_children (rvalue_visitor *v) +{ + v->visit (m_elements1); + v->visit (m_elements2); + v->visit (m_mask); +} + +/* Implementation of recording::memento::make_debug_string for + vectors. */ + + recording::string * +recording::memento_of_new_rvalue_vector_perm::make_debug_string () +{ + /* Now build a string. */ + string *result = string::from_printf (m_ctxt, + "shufflevector (%s, %s, %s)", + m_elements1->get_debug_string (), + m_elements2->get_debug_string (), + m_mask->get_debug_string ()); + + return result; + +} + +/* Implementation of recording::memento::write_reproducer for + vectors. */ + + void +recording::memento_of_new_rvalue_vector_perm::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "vector"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_rvalue_vector_perm (%s, /* gcc_jit_context *ctxt */\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue **elements1*/\n" + " %s, /* gcc_jit_rvalue **elements2*/\n" + " %s); /* gcc_jit_rvalue **mask*/\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_elements1), + r.get_identifier_as_rvalue (m_elements2), + r.get_identifier_as_rvalue (m_mask)); +} + void recording::ctor::visit_children (rvalue_visitor *v) { @@ -6307,6 +6420,62 @@ recording::array_access::write_reproducer (reproducer &r) r.get_identifier_as_rvalue (m_index)); } +/* The implementation of class gcc::jit::recording::vector_access. */ + +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::vector_access. */ + +void +recording::vector_access::replay_into (replayer *r) +{ + set_playback_obj ( + r->new_vector_access (playback_location (r, m_loc), + m_vector->playback_rvalue (), + m_index->playback_rvalue ())); +} + +/* Implementation of pure virtual hook recording::rvalue::visit_children + for recording::vector_access. */ + +void +recording::vector_access::visit_children (rvalue_visitor *v) +{ + v->visit (m_vector); + v->visit (m_index); +} + +/* Implementation of recording::memento::make_debug_string for + array accesses. */ + +recording::string * +recording::vector_access::make_debug_string () +{ + enum precedence prec = get_precedence (); + return string::from_printf (m_ctxt, + "%s[%s]", + m_vector->get_debug_string_parens (prec), + m_index->get_debug_string_parens (prec)); +} + +/* Implementation of recording::memento::write_reproducer for + vector_access. */ + +void +recording::vector_access::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "lvalue"); + r.write (" gcc_jit_lvalue *%s = \n" + " gcc_jit_context_new_vector_access (%s, /* gcc_jit_context *ctxt */\n" + " %s, /*gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *vector */\n" + " %s); /* gcc_jit_rvalue *index */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_vector), + r.get_identifier_as_rvalue (m_index)); +} + /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */ /* Implementation of pure virtual hook recording::memento::replay_into diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 4a8082991fb..8669fdeb4a2 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -173,6 +173,12 @@ public: vector_type *type, rvalue **elements); + rvalue * + new_rvalue_vector_perm (location *loc, + rvalue *elements1, + rvalue *elements2, + rvalue *mask); + rvalue * new_unary_op (location *loc, enum gcc_jit_unary_op op, @@ -215,6 +221,11 @@ public: rvalue *ptr, rvalue *index); + lvalue * + new_vector_access (location *loc, + rvalue *vector, + rvalue *index); + case_ * new_case (rvalue *min_value, rvalue *max_value, @@ -810,6 +821,10 @@ public: void replay_into (replayer *) final override; + vector_type *dyn_cast_vector_type () final override { + return m_other_type->dyn_cast_vector_type (); + } + private: string * make_debug_string () final override; void write_reproducer (reproducer &r) final override; @@ -1625,6 +1640,33 @@ private: auto_vec m_elements; }; +class memento_of_new_rvalue_vector_perm : public rvalue +{ +public: + memento_of_new_rvalue_vector_perm (context *ctxt, + location *loc, + rvalue *elements1, + rvalue *elements2, + rvalue *mask); + + void replay_into (replayer *r) final override; + + void visit_children (rvalue_visitor *) final override; + +private: + string * make_debug_string () final override; + void write_reproducer (reproducer &r) final override; + enum precedence get_precedence () const final override + { + return PRECEDENCE_PRIMARY; + } + +private: + rvalue *m_elements1; + rvalue *m_elements2; + rvalue *m_mask; +}; + class ctor : public rvalue { public: @@ -1907,6 +1949,36 @@ private: rvalue *m_index; }; +class vector_access : public lvalue +{ +public: + vector_access (context *ctxt, + location *loc, + rvalue *vector, + rvalue *index) + : lvalue (ctxt, loc, vector->get_type ()->dyn_cast_vector_type () + ->get_element_type ()), + m_vector (vector), + m_index (index) + {} + + void replay_into (replayer *r) final override; + + void visit_children (rvalue_visitor *v) final override; + +private: + string * make_debug_string () final override; + void write_reproducer (reproducer &r) final override; + enum precedence get_precedence () const final override + { + return PRECEDENCE_POSTFIX; + } + +private: + rvalue *m_vector; + rvalue *m_index; +}; + class access_field_of_lvalue : public lvalue { public: diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 0451b4df7f9..3123e6075ec 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -2437,6 +2437,9 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt, /* LOC can be NULL. */ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); + gcc::jit::recording::vector_type *vector_type = type->dyn_cast_vector_type (); + RETURN_NULL_IF_FAIL (vector_type == NULL, ctxt, loc, + "cannot cast vector types"); RETURN_NULL_IF_FAIL_PRINTF3 ( is_valid_cast (rvalue->get_type (), type), ctxt, loc, @@ -2503,6 +2506,39 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt, return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::new_vector_access method in + jit-recording.cc. */ + +extern gcc_jit_lvalue * +gcc_jit_context_new_vector_access (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *vector, + gcc_jit_rvalue *index) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + /* LOC can be NULL. */ + RETURN_NULL_IF_FAIL (vector, ctxt, loc, "NULL vector"); + RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index"); + RETURN_NULL_IF_FAIL_PRINTF2 ( + vector->get_type ()->dyn_cast_vector_type (), + ctxt, loc, + "vector: %s (type: %s) is not a vector", + vector->get_debug_string (), + vector->get_type ()->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF2 ( + index->get_type ()->is_numeric (), + ctxt, loc, + "index: %s (type: %s) is not of numeric type", + index->get_debug_string (), + index->get_type ()->get_debug_string ()); + + return (gcc_jit_lvalue *)ctxt->new_vector_access (loc, vector, index); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the @@ -4071,6 +4107,79 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, (gcc::jit::recording::rvalue **)elements); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::new_rvalue_vector_perm method, in + jit-recording.cc. */ + +gcc_jit_rvalue * +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *elements1, + gcc_jit_rvalue *elements2, + gcc_jit_rvalue *mask) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt"); + JIT_LOG_FUNC (ctxt->get_logger ()); + + /* LOC can be NULL. */ + + gcc::jit::recording::type *elements1_type = elements1->get_type (); + gcc::jit::recording::type *elements2_type = elements2->get_type (); + RETURN_NULL_IF_FAIL_PRINTF4 ( + compatible_types (elements1->get_type ()->unqualified (), + elements2->get_type ()->unqualified ()), + ctxt, loc, + "mismatching types for vector perm:" + " elements1: %s (type: %s) elements2: %s (type: %s)", + elements1->get_debug_string (), + elements1_type->get_debug_string (), + elements2->get_debug_string (), + elements2_type->get_debug_string ()); + + gcc::jit::recording::type *mask_type = mask->get_type (); + gcc::jit::recording::vector_type *mask_vector_type = + mask_type->dyn_cast_vector_type (); + gcc::jit::recording::vector_type *elements1_vector_type = + elements1_type->dyn_cast_vector_type (); + + size_t mask_len = mask_vector_type->get_num_units (); + size_t elements1_len = elements1_vector_type->get_num_units (); + + RETURN_NULL_IF_FAIL_PRINTF2 ( + mask_len == elements1_len, + ctxt, loc, + "mismatching length for mask:" + " elements1 length: %ld mask length: %ld", + mask_len, + elements1_len); + + gcc::jit::recording::type *mask_element_type = + mask_vector_type->get_element_type (); + + RETURN_NULL_IF_FAIL ( + mask_element_type->is_int (), + ctxt, loc, + "elements of mask must be of an integer type"); + + gcc::jit::recording::type *elements1_element_type = + elements1_vector_type->get_element_type (); + size_t mask_element_size = mask_element_type->get_size (); + size_t elements1_element_size = elements1_element_type->get_size (); + + RETURN_NULL_IF_FAIL_PRINTF2 ( + mask_element_size == elements1_element_size, + ctxt, loc, + "mismatching size for mask element type:" + " elements1 element type: %ld mask element type: %ld", + mask_element_size, + elements1_element_size); + + return (gcc_jit_rvalue *)ctxt->new_rvalue_vector_perm (loc, elements1, + elements2, mask); +} + /* A mutex around the cached state in parse_basever. Ideally this would be within parse_basever, but the mutex is only needed by libgccjit. */ diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 749f6c24177..3a8af99a994 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1301,6 +1301,35 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt, gcc_jit_rvalue *ptr, gcc_jit_rvalue *index); +/* Build a permutation vector rvalue from an 3 arrays of elements. + + "vec_type" should be a vector type, created using gcc_jit_type_get_vector. + + This API entrypoint was added in LIBGCCJIT_ABI_26; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS +*/ +extern gcc_jit_rvalue * +gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *elements1, + gcc_jit_rvalue *elements2, + gcc_jit_rvalue *mask); + +#define LIBGCCJIT_HAVE_VECTOR_OPERATIONS + +/* Get the element at INDEX in VECTOR. + + This API entrypoint was added in LIBGCCJIT_ABI_26; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS +*/ +extern gcc_jit_lvalue * +gcc_jit_context_new_vector_access (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *vector, + gcc_jit_rvalue *index); + /* Field access is provided separately for both lvalues and rvalues. */ /* Accessing a field of an lvalue of struct type, analogous to: diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 8b90a0e2ff3..510c9386d7a 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -276,3 +276,9 @@ LIBGCCJIT_ABI_25 { global: gcc_jit_type_get_restrict; } LIBGCCJIT_ABI_24; + +LIBGCCJIT_ABI_26 { + global: + gcc_jit_context_new_vector_access; + gcc_jit_context_new_rvalue_vector_perm; +} LIBGCCJIT_ABI_25; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index e762563f9bd..8dbb582df61 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -377,6 +377,13 @@ #undef create_code #undef verify_code +/* test-vector-perm.c */ +#define create_code create_code_vector_perm +#define verify_code verify_code_vector_perm +#include "test-vector-perm.c" +#undef create_code +#undef verify_code + /* Now expose the individual testcases as instances of this struct. */ struct testcase @@ -529,7 +536,10 @@ const struct testcase testcases[] = { verify_code_version}, {"volatile", create_code_volatile, - verify_code_volatile} + verify_code_volatile}, + {"vector_perm", + create_code_vector_perm, + verify_code_vector_perm}, }; const int num_testcases = (sizeof (testcases) / sizeof (testcases[0])); diff --git a/gcc/testsuite/jit.dg/test-vector-perm.c b/gcc/testsuite/jit.dg/test-vector-perm.c new file mode 100644 index 00000000000..7cf193b1ef3 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-vector-perm.c @@ -0,0 +1,96 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +typedef int v4si __attribute__ ((vector_size (16))); + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *v4si = + gcc_jit_type_get_vector (int_type, 4); + + gcc_jit_function *func_vector = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + int_type, + "vector", + 0, NULL, + 0); + + gcc_jit_rvalue *elements[4] + = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 4), + }; + + gcc_jit_rvalue *vector + = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements); + + gcc_jit_rvalue *index + = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2); + + gcc_jit_block *block_a = gcc_jit_function_new_block (func_vector, NULL); + gcc_jit_lvalue *value + = gcc_jit_context_new_vector_access (ctxt, NULL, vector, index); + gcc_jit_block_end_with_return (block_a, NULL, gcc_jit_lvalue_as_rvalue (value)); + + gcc_jit_function *func_vector_perm = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + v4si, + "vector_perm", + 0, NULL, + 0); + + gcc_jit_rvalue *elements2[4] + = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 5), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 6), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 8), + }; + + gcc_jit_rvalue *vector2 + = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements2); + + gcc_jit_rvalue *mask_values[4] + = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3), + gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0), + }; + + gcc_jit_rvalue *mask + = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, mask_values); + + gcc_jit_block *block_b = gcc_jit_function_new_block (func_vector_perm, NULL); + gcc_jit_rvalue *result = gcc_jit_context_new_rvalue_vector_perm (ctxt, NULL, vector, vector2, mask); + gcc_jit_block_end_with_return (block_b, NULL, result); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); + + typedef int (*vector) (); + vector fn = (vector)gcc_jit_result_get_code (result, "vector"); + CHECK_NON_NULL (fn); + + int vector_access = fn (); + CHECK_VALUE (vector_access, 3); + + typedef v4si (*vector_perm) (); + vector_perm perm_fn = (vector_perm)gcc_jit_result_get_code (result, "vector_perm"); + CHECK_NON_NULL (perm_fn); + + v4si vector_perm_res = perm_fn (); + v4si expected_vec = { 8, 3, 4, 1 }; + CHECK_VECTOR_VALUE (4, vector_perm_res, expected_vec); +} -- 2.42.1