public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libgccjit: Add convert vector
@ 2023-12-21 21:01 Antoni Boucher
  2024-01-19 21:00 ` Antoni Boucher
  2024-01-24 17:33 ` David Malcolm
  0 siblings, 2 replies; 3+ messages in thread
From: Antoni Boucher @ 2023-12-21 21:01 UTC (permalink / raw)
  To: jit, gcc-patches; +Cc: David Malcolm

[-- Attachment #1: Type: text/plain, Size: 173 bytes --]

Hi.
This patch adds the support for the convert vector internal function.
I'll need to double-check that making the decl a register is necessary.
Thanks for the review.

[-- Attachment #2: 0001-libgccjit-Add-convert-vector.patch --]
[-- Type: text/x-patch, Size: 14717 bytes --]

From ca4b3606c853b3425cf4ef9e88fbd5939f0e8f7c Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 14 May 2022 17:24:29 -0400
Subject: [PATCH] libgccjit: Add convert vector

gcc/jit/ChangeLog:

	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag.
	* docs/topics/expressions.rst: Document gcc_jit_context_convert_vector.
	* jit-playback.cc (convert_vector): New method.
	* jit-playback.h: New method.
	* jit-recording.cc (recording::context::new_convert_vector,
	recording::convert_vector::replay_into,
	recording::convert_vector::visit_children,
	recording::convert_vector::make_debug_string,
	recording::convert_vector::write_reproducer): New methods.
	* jit-recording.h (class convert_vector): New class.
	(context::new_convert_vector): New method.
	* libgccjit.cc (gcc_jit_context_convert_vector): New function.
	* libgccjit.h (gcc_jit_context_convert_vector): New function.
	* libgccjit.map: New function.

gcc/testsuite/ChangeLog:

	* jit.dg/all-non-failing-tests.h: New test.
	* jit.dg/test-convert-vector.c: New test.
---
 gcc/jit/docs/topics/compatibility.rst        |  7 ++
 gcc/jit/docs/topics/expressions.rst          | 18 +++++
 gcc/jit/jit-playback.cc                      | 31 +++++++++
 gcc/jit/jit-playback.h                       |  5 ++
 gcc/jit/jit-recording.cc                     | 72 ++++++++++++++++++++
 gcc/jit/jit-recording.h                      | 34 +++++++++
 gcc/jit/libgccjit.cc                         | 36 ++++++++++
 gcc/jit/libgccjit.h                          |  8 +++
 gcc/jit/libgccjit.map                        |  5 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++
 gcc/testsuite/jit.dg/test-convert-vector.c   | 56 +++++++++++++++
 11 files changed, 282 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-convert-vector.c

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index ebede440ee4..33eb1a0bc06 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -378,3 +378,10 @@ 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
+:func:`gcc_jit_context_convert_vector`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 42cfee36302..a75e69bf1f4 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -699,6 +699,24 @@ Type-coercion
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
 
+.. function:: gcc_jit_rvalue *
+              gcc_jit_context_convert_vector (gcc_jit_context *ctxt, \
+                                              gcc_jit_location *loc, \
+                                              gcc_jit_rvalue *vector, \
+                                              gcc_jit_type *type)
+
+   Given a vector rvalue, cast it to the type ``type``.
+
+   The number of elements in ``vector`` and ``type`` must match.
+   The ``type`` must be a vector type.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_convert_vector
+
 Lvalues
 -------
 
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index dddd537f3b1..48901d71418 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -1527,6 +1527,37 @@ new_array_access (location *loc,
     }
 }
 
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+   vector conversion.  */
+
+playback::rvalue *
+playback::context::
+convert_vector (location *loc,
+		   rvalue *vector,
+		   type *type)
+{
+  gcc_assert (vector);
+  gcc_assert (type);
+
+  /* For comparison, see:
+       c/c-common.cc: c_build_vec_convert
+  */
+
+  tree t_vector = vector->as_tree ();
+
+  /* It seems IFN_VEC_CONVERT only work on registers, not on memory.  */
+  if (TREE_CODE (t_vector) == VAR_DECL)
+    DECL_REGISTER (t_vector) = 1;
+  tree t_result =
+    build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_VEC_CONVERT,
+      type->as_tree (), 1, t_vector);
+
+  if (loc)
+    set_tree_location (t_result, loc);
+
+  return new rvalue (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 b0166f8f6ce..59ffd739875 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -191,6 +191,11 @@ public:
 		    rvalue *ptr,
 		    rvalue *index);
 
+  rvalue *
+  convert_vector (location *loc,
+		  rvalue *vector,
+		  type *type);
+
   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..a0ce834a610 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -1309,6 +1309,23 @@ recording::context::new_array_access (recording::location *loc,
   return result;
 }
 
+/* Create a recording::convert_vector instance and add it to this context's list
+   of mementos.
+
+   Implements the post-error-checking part of
+   gcc_jit_context_convert_vector.  */
+
+recording::rvalue *
+recording::context::new_convert_vector (recording::location *loc,
+				    recording::rvalue *vector,
+				    recording::type *type)
+{
+  // TODO: instead have an "internal function" memento?
+  recording::rvalue *result = new convert_vector (this, loc, vector, type);
+  record (result);
+  return result;
+}
+
 /* Create a recording::case_ instance and add it to this context's list
    of mementos.
 
@@ -6307,6 +6324,61 @@ recording::array_access::write_reproducer (reproducer &r)
 	   r.get_identifier_as_rvalue (m_index));
 }
 
+/* The implementation of class gcc::jit::recording::convert_vector.  */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::convert_vector.  */
+
+void
+recording::convert_vector::replay_into (replayer *r)
+{
+  set_playback_obj (
+    r->convert_vector (playback_location (r, m_loc),
+			  m_vector->playback_rvalue (),
+			  m_type->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+   for recording::convert_vector.  */
+
+void
+recording::convert_vector::visit_children (rvalue_visitor *v)
+{
+  v->visit (m_vector);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   array accesses.  */
+
+recording::string *
+recording::convert_vector::make_debug_string ()
+{
+  enum precedence prec = get_precedence ();
+  return string::from_printf (m_ctxt,
+			      "(%s)%s",
+			      m_type->get_debug_string (),
+			      m_vector->get_debug_string_parens (prec));
+}
+
+/* Implementation of recording::memento::write_reproducer for
+   convert_vector.  */
+
+void
+recording::convert_vector::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "lvalue");
+  r.write ("  gcc_jit_rvalue *%s = \n"
+	   "    gcc_jit_context_convert_vector (%s, /* gcc_jit_context *ctxt */\n"
+	   "                                    %s, /*gcc_jit_location *loc */\n"
+	   "                                    %s, /* gcc_jit_rvalue *vector */\n"
+	   "                                    %s); /* gcc_jit_type *type */\n",
+	   id,
+	   r.get_identifier (get_context ()),
+	   r.get_identifier (m_loc),
+	   r.get_identifier_as_rvalue (m_vector),
+	   r.get_identifier_as_type (m_type));
+}
+
 /* 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..7650e2a8241 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -215,6 +215,11 @@ public:
 		    rvalue *ptr,
 		    rvalue *index);
 
+  rvalue *
+  new_convert_vector (location *loc,
+		  rvalue *vector,
+		  type *type);
+
   case_ *
   new_case (rvalue *min_value,
 	    rvalue *max_value,
@@ -1907,6 +1912,35 @@ private:
   rvalue *m_index;
 };
 
+class convert_vector : public rvalue
+{
+public:
+  convert_vector (context *ctxt,
+		  location *loc,
+		  rvalue *vector,
+		  type *type)
+  : rvalue (ctxt, loc, type),
+    m_vector (vector),
+    m_type (type)
+  {}
+
+  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;
+  type *m_type;
+};
+
 class access_field_of_lvalue : public lvalue
 {
 public:
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 0451b4df7f9..517ef46628c 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -2503,6 +2503,42 @@ 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_convert_vector method in
+   jit-recording.cc.  */
+
+gcc_jit_rvalue *
+gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
+				gcc_jit_location *loc,
+				gcc_jit_rvalue *vector,
+				gcc_jit_type *type)
+{
+  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 (type, ctxt, loc, "NULL type");
+
+  gcc::jit::recording::vector_type *value_vec_type
+    = vector->get_type ()->dyn_cast_vector_type ();
+  RETURN_NULL_IF_FAIL_PRINTF1 (value_vec_type, ctxt, loc,
+			       "%s is not a value of a vector type",
+			       vector->get_debug_string ());
+  gcc::jit::recording::vector_type *as_vec_type
+    = type->dyn_cast_vector_type ();
+  RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc,
+			       "%s is not a vector type",
+			       type->get_debug_string ());
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    as_vec_type->get_num_units () == value_vec_type->get_num_units (), ctxt,
+    loc, "%s should contain the same number of elements as %s",
+    vector->get_debug_string (), type->get_debug_string ());
+
+  return (gcc_jit_rvalue *)ctxt->new_convert_vector (loc, vector, type);
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 749f6c24177..00beab8f397 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1301,6 +1301,14 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
 				  gcc_jit_rvalue *ptr,
 				  gcc_jit_rvalue *index);
 
+#define LIBGCCJIT_HAVE_gcc_jit_context_convert_vector
+
+extern gcc_jit_rvalue *
+gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
+				gcc_jit_location *loc,
+				gcc_jit_rvalue *vector,
+				gcc_jit_type *type);
+
 /* 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..e95d7be5d09 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -276,3 +276,8 @@ LIBGCCJIT_ABI_25 {
   global:
     gcc_jit_type_get_restrict;
 } LIBGCCJIT_ABI_24;
+
+LIBGCCJIT_ABI_26 {
+  global:
+    gcc_jit_context_convert_vector;
+} 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..528e5b4f921 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -126,6 +126,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-convert-vector.c */
+#define create_code create_code_convert_vector
+#define verify_code verify_code_convert_vector
+#include "test-convert-vector.c"
+#undef create_code
+#undef verify_code
+
 /* test-debug-strings.c */
 #define create_code create_code_debug_strings
 #define verify_code verify_code_debug_strings
@@ -437,6 +444,9 @@ const struct testcase testcases[] = {
   {"constants",
    create_code_constants,
    verify_code_constants},
+  {"convert_vector",
+   create_code_convert_vector,
+   verify_code_convert_vector},
   {"debug_strings",
    create_code_debug_strings,
    verify_code_debug_strings},
diff --git a/gcc/testsuite/jit.dg/test-convert-vector.c b/gcc/testsuite/jit.dg/test-convert-vector.c
new file mode 100644
index 00000000000..b9bf648cd9a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-convert-vector.c
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+     int __attribute__ ((__vector_size__ (8))) convert_vec(double __attribute__ ((__vector_size__ (16))) double_vec)
+     {
+      return __builtin_convertvector (double_vec, int __attribute__ ((__vector_size__ (8))));
+     }
+  */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *int_vector_type =
+    gcc_jit_type_get_vector (int_type, 2);
+  gcc_jit_type *double_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+  gcc_jit_type *double_vector_type =
+    gcc_jit_type_get_vector (double_type, 2);
+
+  /* Build the convert_vec.  */
+  gcc_jit_param *param =
+    gcc_jit_context_new_param (ctxt, NULL, double_vector_type, "double_vec");
+  gcc_jit_function *convert_vec =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  int_vector_type,
+				  "convert_vec",
+				  1, &param,
+				  0);
+  gcc_jit_block *block = gcc_jit_function_new_block (convert_vec, NULL);
+  gcc_jit_block_end_with_return (block,
+    NULL,
+    gcc_jit_context_convert_vector (ctxt, NULL, gcc_jit_param_as_rvalue (param), int_vector_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_NON_NULL (result);
+
+  typedef int __attribute__ ((__vector_size__ (8))) (*convert_vec)(double __attribute__ ((__vector_size__ (16))) double_vec);
+  double __attribute__ ((__vector_size__ (16))) double_vec = { 3.2, 7.9 };
+  convert_vec func = (convert_vec)gcc_jit_result_get_code (result, "convert_vec");
+  int __attribute__ ((__vector_size__ (8))) res = func (double_vec);
+  int __attribute__ ((__vector_size__ (8))) expected = { 3, 7 };
+  CHECK_VECTOR_VALUE (2, res, expected);
+}
-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libgccjit: Add convert vector
  2023-12-21 21:01 [PATCH] libgccjit: Add convert vector Antoni Boucher
@ 2024-01-19 21:00 ` Antoni Boucher
  2024-01-24 17:33 ` David Malcolm
  1 sibling, 0 replies; 3+ messages in thread
From: Antoni Boucher @ 2024-01-19 21:00 UTC (permalink / raw)
  To: jit, gcc-patches; +Cc: David Malcolm

David: Ping.

On Thu, 2023-12-21 at 16:01 -0500, Antoni Boucher wrote:
> Hi.
> This patch adds the support for the convert vector internal function.
> I'll need to double-check that making the decl a register is
> necessary.
> Thanks for the review.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libgccjit: Add convert vector
  2023-12-21 21:01 [PATCH] libgccjit: Add convert vector Antoni Boucher
  2024-01-19 21:00 ` Antoni Boucher
@ 2024-01-24 17:33 ` David Malcolm
  1 sibling, 0 replies; 3+ messages in thread
From: David Malcolm @ 2024-01-24 17:33 UTC (permalink / raw)
  To: Antoni Boucher, jit, gcc-patches

On Thu, 2023-12-21 at 16:01 -0500, Antoni Boucher wrote:
> Hi.
> This patch adds the support for the convert vector internal function.

Thanks for the patch.

> I'll need to double-check that making the decl a register is
> necessary.

I confess I don't know anything about this aspect of the patch, but
presumably you have this working within the rustc backend as well as in
the testcase.

Am I right in thinking that this is an elementwise conversion?  Might
be good to specify this in the docs and header file.

Otherwise looks good to me (with usual comment about updating the ABI
numbering as necessary)

Thanks
Dave


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-01-24 17:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-21 21:01 [PATCH] libgccjit: Add convert vector Antoni Boucher
2024-01-19 21:00 ` Antoni Boucher
2024-01-24 17:33 ` David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).