* [PATCH] libgccjit: Add support for machine-dependent builtins
@ 2023-02-12 0:30 Antoni Boucher
2023-02-12 0:32 ` Antoni Boucher
2023-02-12 1:37 ` Andrew Pinski
0 siblings, 2 replies; 21+ messages in thread
From: Antoni Boucher @ 2023-02-12 0:30 UTC (permalink / raw)
To: jit, gcc-patches; +Cc: David Malcolm
Hi.
This patch adds support for machine-dependent builtins in libgccjit
(bug 108762).
There are two things I don't like in this patch:
1. There are a few functions copied from the C frontend
(common_mark_addressable_vec and a few others).
2. Getting a target builtin only works from the second compilation
since the type information is recorded at the first compilation. I
couldn't find a way to get the builtin data without using the langhook.
It is necessary to get the type information for type checking and
instrospection.
Any idea how to fix these issues?
Thanks for the review.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-02-12 0:30 [PATCH] libgccjit: Add support for machine-dependent builtins Antoni Boucher
@ 2023-02-12 0:32 ` Antoni Boucher
2023-02-12 1:37 ` Andrew Pinski
1 sibling, 0 replies; 21+ messages in thread
From: Antoni Boucher @ 2023-02-12 0:32 UTC (permalink / raw)
To: jit, gcc-patches; +Cc: David Malcolm
[-- Attachment #1: Type: text/plain, Size: 764 bytes --]
I forgot to attach the patch.
Here it is.
On Sat, 2023-02-11 at 19:30 -0500, Antoni Boucher via Jit wrote:
> Hi.
> This patch adds support for machine-dependent builtins in libgccjit
> (bug 108762).
>
> There are two things I don't like in this patch:
>
> 1. There are a few functions copied from the C frontend
> (common_mark_addressable_vec and a few others).
>
> 2. Getting a target builtin only works from the second compilation
> since the type information is recorded at the first compilation. I
> couldn't find a way to get the builtin data without using the
> langhook.
> It is necessary to get the type information for type checking and
> instrospection.
>
> Any idea how to fix these issues?
>
> Thanks for the review.
[-- Attachment #2: 0001-libgccjit-Add-support-for-machine-dependent-builtins.patch --]
[-- Type: text/x-patch, Size: 60738 bytes --]
From f1f4a113853b416776253b596d7feeb87e608bfd Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 23 Jan 2023 17:21:15 -0500
Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
gcc/config:
PR jit/108762
* i386/i386-builtins.cc: New function (clear_builtin_types).
gcc/jit:
PR jit/108762
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_25): New ABI tag.
* docs/topics/expressions.rst: Add documentation for the
functions gcc_jit_context_new_rvalue_vector_perm and
gcc_jit_context_new_vector_access.
* docs/topics/functions.rst: Add documentation for the function
gcc_jit_context_get_target_builtin_function.
* docs/topics/types.rst: Add documentation for GCC_JIT_TYPE_BFLOAT16.
* dummy-frontend.cc: Include headers target.h, jit-recording.h,
print-tree.h, unordered_map and string, new variables (target_builtins,
target_function_types, and target_builtins_ctxt), new function
(tree_type_to_jit_type).
* jit-builtins.cc: Specify that the function types are not from
target builtins.
* jit-playback.cc: New argument is_target_builtin to new_function, new
functions (new_rvalue_vector_perm, common_mark_addressable_vec,
gnu_vector_type_p, lvalue_p, convert_vector_to_array_for_subscript,
new_vector_access).
* jit-playback.h: New argument is_target_builtin to
new_function, new functions (new_rvalue_vector_perm,
new_vector_access).
* jit-recording.cc: New argument is_target_builtin to
new_function_type, function_type constructor and function
constructor, new functions
(get_target_builtin_function, new_rvalue_vector_perm,
new_vector_access, memento_of_new_rvalue_vector_perm,
memento_of_new_rvalue_vector_perm::replay_into,
memento_of_new_rvalue_vector_perm::visit_children,
memento_of_new_rvalue_vector_perm::make_debug_string,
memento_of_new_rvalue_vector_perm::write_reproducer,
vector_access::replay_into, vector_access::visit_children,
vector_access::make_debug_string, vector_access::write_reproducer).
* jit-recording.h: Include headers string and unordered_map, new
variable target_function_types, new argument is_target_builtin
to new_function_type, function_type and function, new classes
memento_of_new_rvalue_vector_perm and vector_access, new functions
(get_target_builtin_function, new_rvalue_vector_perm,
new_vector_access, copy, memento_of_new_rvalue_vector_perm,
memento_of_new_rvalue_vector_perm::replay_into,
memento_of_new_rvalue_vector_perm::visit_children,
memento_of_new_rvalue_vector_perm::make_debug_string,
memento_of_new_rvalue_vector_perm::write_reproducer,
vector_access::replay_into, vector_access::visit_children,
vector_access::make_debug_string, vector_access::write_reproducer).
* libgccjit.cc: New functions
(gcc_jit_context_get_target_builtin_function,
gcc_jit_context_new_vector_access,
gcc_jit_context_new_rvalue_vector_perm).
* libgccjit.h: New variant GCC_JIT_TYPE_BFLOAT16 en enum
gcc_jit_types, new functions
(gcc_jit_context_get_target_builtin_function,
gcc_jit_context_new_vector_access,
gcc_jit_context_new_rvalue_vector_perm).
* libgccjit.map: New functions
(gcc_jit_context_get_target_builtin_function,
gcc_jit_context_new_rvalue_vector_perm,
gcc_jit_context_new_vector_access).
gcc/testsuite:
PR jit/108762
* jit.dg/all-non-failing-tests.h: New test test-target-builtins.c.
* jit.dg/test-target-builtins.c: New test.
---
gcc/config/i386/i386-builtins.cc | 18 ++
gcc/jit/docs/topics/compatibility.rst | 10 +
gcc/jit/docs/topics/expressions.rst | 45 ++++
gcc/jit/docs/topics/functions.rst | 19 ++
gcc/jit/docs/topics/types.rst | 2 +
gcc/jit/dummy-frontend.cc | 203 ++++++++++++++-
gcc/jit/jit-builtins.cc | 6 +-
gcc/jit/jit-common.h | 2 +-
gcc/jit/jit-playback.cc | 166 +++++++++++-
gcc/jit/jit-playback.h | 16 +-
gcc/jit/jit-recording.cc | 255 ++++++++++++++++++-
gcc/jit/jit-recording.h | 176 ++++++++++++-
gcc/jit/libgccjit.cc | 127 +++++++++
gcc/jit/libgccjit.h | 44 +++-
gcc/jit/libgccjit.map | 7 +
gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 +
gcc/testsuite/jit.dg/test-target-builtins.c | 77 ++++++
17 files changed, 1153 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-target-builtins.c
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index fc0c82b156e..f9b9937a669 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -226,6 +226,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
+static void
+clear_builtin_types (void)
+{
+ for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
+ ix86_builtin_type_tab[i] = NULL;
+
+ for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
+ {
+ ix86_builtins[i] = NULL;
+ ix86_builtins_isa[i].set_and_not_built_p = true;
+ }
+
+ for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
+ ix86_builtin_func_type_tab[i] = NULL;
+}
+
tree get_ix86_builtin (enum ix86_builtins c)
{
return ix86_builtins[c];
@@ -1443,6 +1459,8 @@ ix86_init_builtins (void)
{
tree ftype, decl;
+ clear_builtin_types ();
+
ix86_init_builtin_types ();
/* Builtins to get CPU type and features. */
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index f4ffa07ec48..402df5b60b7 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -371,3 +371,13 @@ alignment of a variable:
* :func:`gcc_jit_lvalue_set_alignment`
* :func:`gcc_jit_lvalue_get_alignment`
+
+.. _LIBGCCJIT_ABI_25:
+
+``LIBGCCJIT_ABI_25``
+--------------------
+``LIBGCCJIT_ABI_25`` covers the addition of functions to get target builtins and manipulate vectors:
+
+ * :func:`gcc_jit_context_get_target_builtin_function`
+ * :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..57905959634 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_TARGET_BUILTIN
+
+ Analogous to:
+
+ .. code-block:: c
+
+ __builtin_shuffle (elements1, elements2, mask)
+
+ in C.
+
Unary Operations
****************
@@ -1020,3 +1049,19 @@ 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.
+ Analogous to:
+
+ .. code-block:: c
+
+ VECTOR[INDEX]
+
+ in C.
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index cf5cb716daf..e9b77fdb892 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -140,6 +140,25 @@ Functions
uses such a parameter will lead to an error being emitted within
the context.
+.. function:: gcc_jit_function *\
+ gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,\
+ const char *name)
+
+ Get the :type:`gcc_jit_function` for the built-in function with the
+ given name. For example:
+
+ .. code-block:: c
+
+ gcc_jit_function *fn
+ = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_pmuldq512_mask");
+
+ .. note:: Due to technical limitations with how libgccjit interacts with
+ the insides of GCC, not all built-in functions are supported. More
+ precisely, not all types are supported for parameters of built-in
+ functions from libgccjit. Attempts to get a built-in function that
+ uses such a parameter will lead to an error being emitted within
+ the context.
+
.. function:: gcc_jit_object *\
gcc_jit_function_as_object (gcc_jit_function *func)
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index f5f2aac1f0c..e7db00779cc 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -129,6 +129,8 @@ Standard types
- C99's ``_Complex double``
* - :c:data:`GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE`
- C99's ``_Complex long double``
+ * - :c:data:`GCC_JIT_TYPE_BFLOAT16`
+ -
.. function:: gcc_jit_type *\
gcc_jit_context_get_int_type (gcc_jit_context *ctxt, \
diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
index 8b7294e32cc..cf7ef66d5b8 100644
--- a/gcc/jit/dummy-frontend.cc
+++ b/gcc/jit/dummy-frontend.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "target.h"
#include "jit-playback.h"
#include "stor-layout.h"
#include "debug.h"
@@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "stringpool.h"
#include "attribs.h"
+#include "jit-recording.h"
+#include "print-tree.h"
#include <mpfr.h>
+#include <unordered_map>
+#include <string>
+
+using namespace gcc::jit;
/* Attribute handling. */
@@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
ATTR_EXCL (NULL, false, false, false)
};
+hash_map<nofree_string_hash, tree> target_builtins{};
+std::unordered_map<std::string, recording::function_type*> target_function_types
+{};
+recording::context target_builtins_ctxt{NULL};
+
/* Table of machine-independent attributes supported in libgccjit. */
const struct attribute_spec jit_attribute_table[] =
{
@@ -594,6 +606,7 @@ jit_langhook_init (void)
build_common_tree_nodes (false);
+ target_builtins.empty ();
build_common_builtin_nodes ();
/* The default precision for floating point numbers. This is used
@@ -601,6 +614,8 @@ jit_langhook_init (void)
eventually be controllable by a command line option. */
mpfr_set_default_prec (256);
+ targetm.init_builtins ();
+
return true;
}
@@ -668,11 +683,197 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
return NULL;
}
-/* Record a builtin function. We just ignore builtin functions. */
+recording::type* tree_type_to_jit_type (tree type)
+{
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
+ long constant_size = size.to_constant ();
+ if (element_type != NULL)
+ return element_type->get_vector (constant_size);
+ return NULL;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ // For __builtin_ms_va_start.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ // For __builtin_sysv_va_copy.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (type == FLOATN_NX_TYPE_NODE (i))
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (type == void_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == ptr_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ else if (type == const_ptr_type_node)
+ {
+ // Void const ptr.
+ recording::type* result =
+ new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ return new recording::memento_of_get_const (result);
+ }
+ else if (type == unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_INT);
+ else if (type == long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG);
+ else if (type == integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_INT);
+ else if (type == long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG);
+ else if (type == long_long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_LONG);
+ else if (type == signed_char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIGNED_CHAR);
+ else if (type == char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_CHAR);
+ else if (type == unsigned_intQI_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UINT8_T);
+ else if (type == short_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SHORT);
+ else if (type == short_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_SHORT);
+ else if (type == complex_float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_FLOAT);
+ else if (type == complex_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_DOUBLE);
+ else if (type == complex_long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
+ else if (type == float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_FLOAT);
+ else if (type == double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_DOUBLE);
+ else if (type == long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_DOUBLE);
+ else if (type == bfloat16_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_BFLOAT16);
+ else if (type == dfloat128_type_node)
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == long_long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ else if (type == boolean_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_BOOL);
+ else if (type == size_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIZE_T);
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ return element_type->get_pointer ();
+ }
+ else
+ {
+ // Attempt to find an unqualified type when the current type has qualifiers.
+ tree tp = TYPE_MAIN_VARIANT (type);
+ for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
+ {
+ if (TYPE_QUALS (tp) == 0 && type != tp)
+ {
+ recording::type* result = tree_type_to_jit_type (tp);
+ if (result != NULL)
+ {
+ if (TYPE_READONLY (tp))
+ result = new recording::memento_of_get_const (result);
+ if (TYPE_VOLATILE (tp))
+ result = new recording::memento_of_get_volatile (result);
+ return result;
+ }
+ }
+ }
+
+ fprintf (stderr, "Unknown type:\n");
+ debug_tree (type);
+ abort ();
+ }
+
+ return NULL;
+}
+
+/* Record a builtin function. We save their types to be able to check types
+ in recording and for reflection. */
static tree
jit_langhook_builtin_function (tree decl)
{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ target_builtins.put (name, decl);
+
+ std::string string_name (name);
+ if (target_function_types.count (string_name) == 0)
+ {
+ tree function_type = TREE_TYPE (decl);
+ tree arg = TYPE_ARG_TYPES (function_type);
+ bool is_variadic = false;
+
+ auto_vec <recording::type *> param_types;
+
+ while (arg != void_list_node)
+ {
+ if (arg == NULL)
+ {
+ is_variadic = true;
+ break;
+ }
+ if (arg != void_list_node)
+ {
+ recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
+ if (arg_type == NULL)
+ return decl;
+ param_types.safe_push (arg_type);
+ }
+ arg = TREE_CHAIN (arg);
+ }
+
+ tree result_type = TREE_TYPE (function_type);
+ recording::type* return_type = tree_type_to_jit_type (result_type);
+
+ if (return_type == NULL)
+ return decl;
+
+ recording::function_type* func_type =
+ new recording::function_type (&target_builtins_ctxt, return_type,
+ param_types.length (),
+ param_types.address (), is_variadic,
+ false);
+
+ target_function_types[string_name] = func_type;
+ }
+ }
return decl;
}
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index fdd0739789d..63628beac81 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
param_types.length (),
params,
func_type->is_variadic (),
- builtin_id);
+ builtin_id,
+ false);
delete[] params;
/* PR/64020 - If the client code is using builtin cos or sin,
@@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
result = m_ctxt->new_function_type (return_type,
num_args,
param_types,
- is_variadic);
+ is_variadic,
+ false);
error:
delete[] param_types;
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 80c1618da96..983c9190d44 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#endif
-const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_INT128_T + 1;
+const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_BFLOAT16 + 1;
/* This comment is included by the docs.
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index e06f161aad9..209b4cca191 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -280,6 +280,8 @@ get_tree_node_for_type (enum gcc_jit_types type_)
case GCC_JIT_TYPE_FLOAT:
return float_type_node;
+ case GCC_JIT_TYPE_BFLOAT16:
+ return bfloat16_type_node;
case GCC_JIT_TYPE_DOUBLE:
return double_type_node;
case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -509,7 +511,8 @@ new_function (location *loc,
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ int is_target_builtin)
{
int i;
param *param;
@@ -543,6 +546,14 @@ new_function (location *loc,
DECL_RESULT (fndecl) = resdecl;
DECL_CONTEXT (resdecl) = fndecl;
+ if (is_target_builtin)
+ {
+ tree *decl = target_builtins.get (name);
+ if (decl != NULL)
+ fndecl = *decl;
+ else
+ add_error (loc, "cannot find target builtin %s", name);
+ }
if (builtin_id)
{
gcc_assert (loc == NULL);
@@ -1007,10 +1018,31 @@ playback::context::new_rvalue_from_vector (location *,
vec_alloc (v, elements.length ());
for (unsigned i = 0; i < elements.length (); ++i)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elements[i]->as_tree ());
- tree t_ctor = build_constructor (type->as_tree (), v);
+ tree t_ctor;
+ t_ctor = build_constructor (type->as_tree (), v);
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 +1559,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 883159f03c3..648dd2bc058 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -104,7 +104,8 @@ public:
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ int is_target_builtin);
lvalue *
new_global (location *loc,
@@ -147,6 +148,12 @@ public:
type *type,
const auto_vec<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,
@@ -191,6 +198,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);
@@ -813,4 +825,6 @@ extern playback::context *active_playback_ctxt;
} // namespace gcc
+extern hash_map<nofree_string_hash, tree> target_builtins;
+
#endif /* JIT_PLAYBACK_H */
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index df0368ff8f7..0c3ea8ec423 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -933,14 +933,16 @@ recording::function_type *
recording::context::new_function_type (recording::type *return_type,
int num_params,
recording::type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
{
recording::function_type *fn_type
= new function_type (this,
return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ is_target_builtin);
record (fn_type);
return fn_type;
}
@@ -962,7 +964,8 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc
= new_function_type (return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ false);
/* Return a pointer-type to the function type. */
return fn_type->get_pointer ();
@@ -1005,7 +1008,7 @@ recording::context::new_function (recording::location *loc,
loc, kind, return_type,
new_string (name),
num_params, params, is_variadic,
- builtin_id);
+ builtin_id, false);
record (result);
m_functions.safe_push (result);
@@ -1044,6 +1047,53 @@ recording::context::get_builtin_function (const char *name)
return bm->get_builtin_function (name);
}
+/* Create a recording::function instance for a target-specific builtin.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_target_builtin_function. */
+
+recording::function *
+recording::context::get_target_builtin_function (const char *name)
+{
+ const char *asm_name = name;
+ if (target_function_types.count (name) == 0)
+ {
+ fprintf (stderr, "Cannot find target builtin %s\n", name);
+ return NULL;
+ }
+
+ recording::function_type* func_type = target_function_types[name]
+ ->copy (this)->dyn_cast_function_type ();
+ const vec<type *>& param_types = func_type->get_param_types ();
+ recording::param **params = new recording::param *[param_types.length ()];
+
+ int i;
+ recording::type *param_type;
+ FOR_EACH_VEC_ELT (param_types, i, param_type)
+ {
+ char buf[16];
+ snprintf (buf, 16, "arg%d", i);
+ params[i] = new_param (NULL,
+ param_type,
+ buf);
+ }
+
+ recording::function *result =
+ new recording::function (this,
+ NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ func_type->get_return_type (),
+ new_string (asm_name),
+ param_types.length (),
+ params,
+ func_type->is_variadic (),
+ BUILT_IN_NONE,
+ true);
+ record (result);
+
+ return result;
+}
+
/* Create a recording::global instance and add it to this context's list
of mementos.
@@ -1108,6 +1158,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 +1372,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.
@@ -2372,6 +2451,8 @@ recording::memento_of_get_type::get_size ()
case GCC_JIT_TYPE_FLOAT:
size = FLOAT_TYPE_SIZE;
break;
+ case GCC_JIT_TYPE_BFLOAT16:
+ return GET_MODE_UNIT_SIZE (BFmode);
case GCC_JIT_TYPE_DOUBLE:
size = DOUBLE_TYPE_SIZE;
break;
@@ -2431,6 +2512,7 @@ recording::memento_of_get_type::dereference ()
case GCC_JIT_TYPE_INT64_T:
case GCC_JIT_TYPE_INT128_T:
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
case GCC_JIT_TYPE_COMPLEX_FLOAT:
@@ -2495,6 +2577,7 @@ recording::memento_of_get_type::is_int () const
return true;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
@@ -2553,6 +2636,7 @@ recording::memento_of_get_type::is_signed () const
case GCC_JIT_TYPE_UINT128_T:
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2612,6 +2696,7 @@ recording::memento_of_get_type::is_float () const
return false;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return true;
@@ -2675,6 +2760,7 @@ recording::memento_of_get_type::is_bool () const
return false;
case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_BFLOAT16:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
return false;
@@ -2754,6 +2840,7 @@ static const char * const get_type_strings[] = {
"__int32_t", /* GCC_JIT_TYPE_INT32_T */
"__int64_t", /* GCC_JIT_TYPE_INT64_T */
"__int128_t", /* GCC_JIT_TYPE_INT128_T */
+ "bfloat16", /* GCC_JIT_TYPE_BFLOAT16 */
};
@@ -2800,6 +2887,7 @@ static const char * const get_type_enum_strings[] = {
"GCC_JIT_TYPE_INT32_T",
"GCC_JIT_TYPE_INT64_T",
"GCC_JIT_TYPE_INT128_T",
+ "GCC_JIT_TYPE_BFLOAT16",
};
void
@@ -3098,11 +3186,13 @@ recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
: type (ctxt),
m_return_type (return_type),
m_param_types (),
- m_is_variadic (is_variadic)
+ m_is_variadic (is_variadic),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
m_param_types.safe_push (param_types[i]);
@@ -4044,7 +4134,8 @@ recording::function::function (context *ctxt,
int num_params,
recording::param **params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ int is_target_builtin)
: memento (ctxt),
m_loc (loc),
m_kind (kind),
@@ -4055,7 +4146,8 @@ recording::function::function (context *ctxt,
m_builtin_id (builtin_id),
m_locals (),
m_blocks (),
- m_fn_ptr_type (NULL)
+ m_fn_ptr_type (NULL),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
{
@@ -4114,7 +4206,8 @@ recording::function::replay_into (replayer *r)
m_name->c_str (),
¶ms,
m_is_variadic,
- m_builtin_id));
+ m_builtin_id,
+ m_is_target_builtin));
}
/* Create a recording::local instance and add it to
@@ -4347,7 +4440,8 @@ recording::function::get_address (recording::location *loc)
= m_ctxt->new_function_type (m_return_type,
m_params.length (),
param_types.address (),
- m_is_variadic);
+ m_is_variadic,
+ m_is_target_builtin);
m_fn_ptr_type = fn_type->get_pointer ();
}
gcc_assert (m_fn_ptr_type);
@@ -5390,6 +5484,91 @@ 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)
{
@@ -6260,6 +6439,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 2dc9448d7c9..4d704e800c3 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -24,12 +24,17 @@ along with GCC; see the file COPYING3. If not see
#include "jit-common.h"
#include "jit-logging.h"
+#include <string>
+#include <unordered_map>
+
class timer;
+extern std::unordered_map<std::string, gcc::jit::recording::function_type*>
+ target_function_types;
+
namespace gcc {
namespace jit {
-
extern const char * const unary_op_reproducer_strings[];
extern const char * const binary_op_reproducer_strings[];
@@ -116,7 +121,8 @@ public:
new_function_type (type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *
new_function_ptr_type (location *loc,
@@ -143,6 +149,9 @@ public:
function *
get_builtin_function (const char *name);
+ function *
+ get_target_builtin_function (const char *name);
+
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
@@ -173,6 +182,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 +230,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,
@@ -539,6 +559,8 @@ public:
these types. */
virtual size_t get_size () { gcc_unreachable (); }
+ virtual type* copy (context* ctxt) = 0;
+
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
@@ -613,6 +635,11 @@ public:
size_t get_size () final override;
+ type* copy (context* ctxt) final override
+ {
+ return ctxt->get_type (m_kind);
+ }
+
bool accepts_writes_from (type *rtype) final override
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
@@ -664,6 +691,13 @@ public:
type *dereference () final override { return m_other_type; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_pointer (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_size () final override;
bool accepts_writes_from (type *rtype) final override;
@@ -724,6 +758,13 @@ public:
return false;
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_const (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "const", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -757,6 +798,13 @@ public:
return m_other_type->is_same_type_as (other->is_volatile ());
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_volatile (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -777,11 +825,23 @@ public:
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_aligned (m_other_type->copy (ctxt),
+ m_alignment_in_bytes);
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the alignment, giving the underlying type. */
type *unqualified () final override { return m_other_type; }
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;
@@ -798,6 +858,13 @@ public:
: decorated_type (other_type),
m_num_units (num_units) {}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new vector_type (m_other_type->copy (ctxt), m_num_units);
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_num_units () const { return m_num_units; }
vector_type *dyn_cast_vector_type () final override { return this; }
@@ -840,6 +907,14 @@ class array_type : public type
type *dereference () final override;
+ type* copy (context* ctxt) final override
+ {
+ type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt),
+ m_num_elements);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -867,7 +942,8 @@ public:
type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *dereference () final override;
function_type *dyn_cast_function_type () final override { return this; }
@@ -875,6 +951,20 @@ public:
bool is_same_type_as (type *other) final override;
+ type* copy (context* ctxt) final override
+ {
+ auto_vec<type *> new_params{};
+ for (size_t i = 0; i < m_param_types.length (); i++)
+ new_params.safe_push (m_param_types[i]->copy (ctxt));
+
+ type* result = new function_type (ctxt, m_return_type->copy (ctxt),
+ m_param_types.length (),
+ new_params.address (),
+ m_is_variadic, m_is_target_builtin);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -903,6 +993,7 @@ private:
type *m_return_type;
auto_vec<type *> m_param_types;
int m_is_variadic;
+ int m_is_target_builtin;
};
class field : public memento
@@ -1004,9 +1095,11 @@ public:
return static_cast <playback::compound_type *> (m_playback_obj);
}
-private:
+protected:
location *m_loc;
string *m_name;
+
+private:
fields *m_fields;
};
@@ -1019,6 +1112,13 @@ public:
struct_ *dyn_cast_struct () final override { return this; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new struct_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
type *
as_type () { return this; }
@@ -1066,6 +1166,13 @@ public:
void replay_into (replayer *r) final override;
+ type* copy (context* ctxt) final override
+ {
+ type* result = new union_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_union () const final override { return true; }
private:
@@ -1274,7 +1381,8 @@ public:
int num_params,
param **params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ int is_target_builtin);
void replay_into (replayer *r) final override;
@@ -1329,6 +1437,7 @@ private:
auto_vec<local *> m_locals;
auto_vec<block *> m_blocks;
type *m_fn_ptr_type;
+ int m_is_target_builtin;
};
class block : public memento
@@ -1597,6 +1706,33 @@ private:
auto_vec<rvalue *> 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:
@@ -1879,6 +2015,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 2def58f6aa7..8056d0c7052 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -1745,6 +1745,24 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
reinterpret_cast<gcc::jit::recording::rvalue**>(values));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::get_target_builtin_function method, in
+ jit-recording.c. */
+
+gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name");
+
+ return static_cast <gcc_jit_function *> (
+ ctxt->get_target_builtin_function (name));
+}
+
/* Public entrypoint. See description in libgccjit.h. */
extern gcc_jit_lvalue *
@@ -2422,6 +2440,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,
@@ -2488,6 +2509,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
@@ -4056,6 +4110,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 057d3e58e73..821ae0f7a56 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -604,7 +604,9 @@ enum gcc_jit_types
GCC_JIT_TYPE_INT16_T,
GCC_JIT_TYPE_INT32_T,
GCC_JIT_TYPE_INT64_T,
- GCC_JIT_TYPE_INT128_T
+ GCC_JIT_TYPE_INT128_T,
+
+ GCC_JIT_TYPE_BFLOAT16,
};
extern gcc_jit_type *
@@ -1021,6 +1023,17 @@ extern gcc_jit_lvalue *
gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
gcc_jit_rvalue *init_value);
+/* Create a reference to a machine-specific builtin function (sometimes called
+ intrinsic functions).
+
+ This API entrypoint was added in LIBGCCJIT_ABI_25; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_TARGET_BUILTIN
+*/
+extern gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name);
+
#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
/* Set an initial value for a global, which must be an array of
@@ -1292,6 +1305,20 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index);
+#define LIBGCCJIT_HAVE_TARGET_BUILTIN
+
+/* Get the element at INDEX in VECTOR.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_25; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_TARGET_BUILTIN
+*/
+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:
@@ -1806,6 +1833,21 @@ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
size_t num_elements,
gcc_jit_rvalue **elements);
+/* 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_25; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_TARGET_BUILTIN
+*/
+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_gcc_jit_version
/* Functions to retrieve libgccjit version.
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 25463b94fe8..57750e298e4 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -271,3 +271,10 @@ LIBGCCJIT_ABI_24 {
gcc_jit_lvalue_set_alignment;
gcc_jit_lvalue_get_alignment;
} LIBGCCJIT_ABI_23;
+
+LIBGCCJIT_ABI_25 {
+ global:
+ gcc_jit_context_get_target_builtin_function;
+ gcc_jit_context_new_rvalue_vector_perm;
+ gcc_jit_context_new_vector_access;
+} LIBGCCJIT_ABI_24;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 80606076e78..988e14ae9bc 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -319,6 +319,9 @@
/* test-setting-alignment.c: This can't be in the testcases array as it
is target-specific. */
+/* test-target-builtins.c: This can't be in the testcases array as it
+ is target-specific. */
+
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
diff --git a/gcc/testsuite/jit.dg/test-target-builtins.c b/gcc/testsuite/jit.dg/test-target-builtins.c
new file mode 100644
index 00000000000..0ffb48e97f6
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-target-builtins.c
@@ -0,0 +1,77 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#define TEST_PROVIDES_MAIN
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ CHECK_NON_NULL (gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_xgetbv"));
+ gcc_jit_function *builtin_eh_pointer = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_eh_pointer");
+ CHECK_NON_NULL (builtin_eh_pointer);
+
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *void_ptr =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);
+ gcc_jit_function *func_main =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "main",
+ 0, NULL,
+ 0);
+ gcc_jit_rvalue *zero = gcc_jit_context_zero (ctxt, int_type);
+ gcc_jit_block *block = gcc_jit_function_new_block (func_main, NULL);
+ gcc_jit_lvalue *variable = gcc_jit_function_new_local(func_main, NULL, void_ptr, "variable");
+ gcc_jit_block_add_assignment (block, NULL, variable,
+ gcc_jit_context_new_call (ctxt, NULL, builtin_eh_pointer, 1, &zero));
+ gcc_jit_block_end_with_return (block, NULL, zero);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+}
+
+int
+main (int argc, char **argv)
+{
+ /* This is the same as the main provided by harness.h, but it first create a dummy context and compile
+ in order to add the target builtins to libgccjit's internal state. */
+ gcc_jit_context *ctxt;
+ ctxt = gcc_jit_context_acquire ();
+ if (!ctxt)
+ {
+ fail ("gcc_jit_context_acquire failed");
+ return -1;
+ }
+ gcc_jit_result *result;
+ result = gcc_jit_context_compile (ctxt);
+ gcc_jit_result_release (result);
+ gcc_jit_context_release (ctxt);
+
+ int i;
+
+ for (i = 1; i <= 5; i++)
+ {
+ snprintf (test, sizeof (test),
+ "%s iteration %d of %d",
+ extract_progname (argv[0]),
+ i, 5);
+
+ //printf ("ITERATION %d\n", i);
+ test_jit (argv[0], NULL);
+ //printf ("\n");
+ }
+
+ totals ();
+
+ return 0;
+}
--
2.26.2.7.g19db9cfb68.dirty
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-02-12 0:30 [PATCH] libgccjit: Add support for machine-dependent builtins Antoni Boucher
2023-02-12 0:32 ` Antoni Boucher
@ 2023-02-12 1:37 ` Andrew Pinski
2023-11-23 22:17 ` Antoni Boucher
2024-01-10 23:29 ` Antoni Boucher
1 sibling, 2 replies; 21+ messages in thread
From: Andrew Pinski @ 2023-02-12 1:37 UTC (permalink / raw)
To: Antoni Boucher; +Cc: jit, gcc-patches, David Malcolm
On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi.
> This patch adds support for machine-dependent builtins in libgccjit
> (bug 108762).
>
> There are two things I don't like in this patch:
>
> 1. There are a few functions copied from the C frontend
> (common_mark_addressable_vec and a few others).
>
> 2. Getting a target builtin only works from the second compilation
> since the type information is recorded at the first compilation. I
> couldn't find a way to get the builtin data without using the langhook.
> It is necessary to get the type information for type checking and
> instrospection.
>
> Any idea how to fix these issues?
Seems like you should do this patch in a few steps; that is split it up.
Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
I also think the vector support should be in a different patch too.
Splitting out these parts would definitely make it easier for review
and make incremental improvements.
Thanks,
Andrew Pinski
>
> Thanks for the review.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-02-12 1:37 ` Andrew Pinski
@ 2023-11-23 22:17 ` Antoni Boucher
2023-11-23 22:21 ` Antoni Boucher
2024-06-26 22:49 ` David Malcolm
2024-01-10 23:29 ` Antoni Boucher
1 sibling, 2 replies; 21+ messages in thread
From: Antoni Boucher @ 2023-11-23 22:17 UTC (permalink / raw)
To: Andrew Pinski; +Cc: jit, gcc-patches, David Malcolm
[-- Attachment #1: Type: text/plain, Size: 1407 bytes --]
Hi.
I did split the patch and sent one for the bfloat16 support and another
one for the vector support.
Here's the updated patch for the machine-dependent builtins.
Regards.
On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > Hi.
> > This patch adds support for machine-dependent builtins in libgccjit
> > (bug 108762).
> >
> > There are two things I don't like in this patch:
> >
> > 1. There are a few functions copied from the C frontend
> > (common_mark_addressable_vec and a few others).
> >
> > 2. Getting a target builtin only works from the second compilation
> > since the type information is recorded at the first compilation. I
> > couldn't find a way to get the builtin data without using the
> > langhook.
> > It is necessary to get the type information for type checking and
> > instrospection.
> >
> > Any idea how to fix these issues?
>
> Seems like you should do this patch in a few steps; that is split it
> up.
> Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> I also think the vector support should be in a different patch too.
>
> Splitting out these parts would definitely make it easier for review
> and make incremental improvements.
>
> Thanks,
> Andrew Pinski
>
>
>
> >
> > Thanks for the review.
[-- Attachment #2: 0001-libgccjit-Add-support-for-machine-dependent-builtins.patch --]
[-- Type: text/x-patch, Size: 33504 bytes --]
From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 23 Jan 2023 17:21:15 -0500
Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
gcc/ChangeLog:
PR jit/108762
* config/i386/i386-builtins.cc: New function (clear_builtin_types).
gcc/jit/ChangeLog:
PR jit/108762
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag.
* docs/topics/functions.rst: Add documentation for the function
gcc_jit_context_get_target_builtin_function.
* dummy-frontend.cc: Include headers target.h, jit-recording.h,
print-tree.h, unordered_map and string, new variables (target_builtins,
target_function_types, and target_builtins_ctxt), new function
(tree_type_to_jit_type).
* jit-builtins.cc: Specify that the function types are not from
target builtins.
* jit-playback.cc: New argument is_target_builtin to new_function.
* jit-playback.h: New argument is_target_builtin to
new_function.
* jit-recording.cc: New argument is_target_builtin to
new_function_type, function_type constructor and function
constructor, new function
(get_target_builtin_function).
* jit-recording.h: Include headers string and unordered_map, new
variable target_function_types, new argument is_target_builtin
to new_function_type, function_type and function, new functions
(get_target_builtin_function, copy).
* libgccjit.cc: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.h: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.map: New functions
(gcc_jit_context_get_target_builtin_function).
gcc/testsuite:
PR jit/108762
* jit.dg/all-non-failing-tests.h: New test test-target-builtins.c.
* jit.dg/test-target-builtins.c: New test.
---
gcc/config/i386/i386-builtins.cc | 18 ++
gcc/jit/docs/topics/compatibility.rst | 9 +
gcc/jit/docs/topics/functions.rst | 19 ++
gcc/jit/dummy-frontend.cc | 204 ++++++++++++++++++-
gcc/jit/jit-builtins.cc | 6 +-
gcc/jit/jit-playback.cc | 11 +-
gcc/jit/jit-playback.h | 5 +-
gcc/jit/jit-recording.cc | 76 ++++++-
gcc/jit/jit-recording.h | 111 +++++++++-
gcc/jit/libgccjit.cc | 18 ++
gcc/jit/libgccjit.h | 13 ++
gcc/jit/libgccjit.map | 4 +
gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 +
gcc/testsuite/jit.dg/test-target-builtins.c | 77 +++++++
14 files changed, 554 insertions(+), 20 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-target-builtins.c
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index 42fc3751676..5cc1d6f4d2e 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
+static void
+clear_builtin_types (void)
+{
+ for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
+ ix86_builtin_type_tab[i] = NULL;
+
+ for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
+ {
+ ix86_builtins[i] = NULL;
+ ix86_builtins_isa[i].set_and_not_built_p = true;
+ }
+
+ for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
+ ix86_builtin_func_type_tab[i] = NULL;
+}
+
tree get_ix86_builtin (enum ix86_builtins c)
{
return ix86_builtins[c];
@@ -1483,6 +1499,8 @@ ix86_init_builtins (void)
{
tree ftype, decl;
+ clear_builtin_types ();
+
ix86_init_builtin_types ();
/* Builtins to get CPU type and features. */
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index ebede440ee4..764de23341e 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -378,3 +378,12 @@ 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 a function to get target builtins:
+
+ * :func:`gcc_jit_context_get_target_builtin_function`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index cf5cb716daf..e9b77fdb892 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -140,6 +140,25 @@ Functions
uses such a parameter will lead to an error being emitted within
the context.
+.. function:: gcc_jit_function *\
+ gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,\
+ const char *name)
+
+ Get the :type:`gcc_jit_function` for the built-in function with the
+ given name. For example:
+
+ .. code-block:: c
+
+ gcc_jit_function *fn
+ = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_pmuldq512_mask");
+
+ .. note:: Due to technical limitations with how libgccjit interacts with
+ the insides of GCC, not all built-in functions are supported. More
+ precisely, not all types are supported for parameters of built-in
+ functions from libgccjit. Attempts to get a built-in function that
+ uses such a parameter will lead to an error being emitted within
+ the context.
+
.. function:: gcc_jit_object *\
gcc_jit_function_as_object (gcc_jit_function *func)
diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
index a729086bafb..3ca9702d429 100644
--- a/gcc/jit/dummy-frontend.cc
+++ b/gcc/jit/dummy-frontend.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "target.h"
#include "jit-playback.h"
#include "stor-layout.h"
#include "debug.h"
@@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "stringpool.h"
#include "attribs.h"
+#include "jit-recording.h"
+#include "print-tree.h"
#include <mpfr.h>
+#include <unordered_map>
+#include <string>
+
+using namespace gcc::jit;
/* Attribute handling. */
@@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
ATTR_EXCL (NULL, false, false, false)
};
+hash_map<nofree_string_hash, tree> target_builtins{};
+std::unordered_map<std::string, recording::function_type*> target_function_types
+{};
+recording::context target_builtins_ctxt{NULL};
+
/* Table of machine-independent attributes supported in libgccjit. */
const struct attribute_spec jit_attribute_table[] =
{
@@ -594,6 +606,7 @@ jit_langhook_init (void)
build_common_tree_nodes (false);
+ target_builtins.empty ();
build_common_builtin_nodes ();
/* The default precision for floating point numbers. This is used
@@ -601,6 +614,8 @@ jit_langhook_init (void)
eventually be controllable by a command line option. */
mpfr_set_default_prec (256);
+ targetm.init_builtins ();
+
return true;
}
@@ -668,11 +683,198 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
return NULL;
}
-/* Record a builtin function. We just ignore builtin functions. */
+recording::type* tree_type_to_jit_type (tree type)
+{
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
+ long constant_size = size.to_constant ();
+ if (element_type != NULL)
+ return element_type->get_vector (constant_size);
+ return NULL;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ // For __builtin_ms_va_start.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ // For __builtin_sysv_va_copy.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (type == FLOATN_NX_TYPE_NODE (i))
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (type == void_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == ptr_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ else if (type == const_ptr_type_node)
+ {
+ // Void const ptr.
+ recording::type* result =
+ new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ return new recording::memento_of_get_const (result);
+ }
+ else if (type == unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_INT);
+ else if (type == long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG);
+ else if (type == integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_INT);
+ else if (type == long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG);
+ else if (type == long_long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_LONG);
+ else if (type == signed_char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIGNED_CHAR);
+ else if (type == char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_CHAR);
+ else if (type == unsigned_intQI_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UINT8_T);
+ else if (type == short_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SHORT);
+ else if (type == short_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_SHORT);
+ else if (type == complex_float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_FLOAT);
+ else if (type == complex_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_DOUBLE);
+ else if (type == complex_long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
+ else if (type == float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_FLOAT);
+ else if (type == double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_DOUBLE);
+ else if (type == long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_DOUBLE);
+ else if (type == bfloat16_type_node)
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == dfloat128_type_node)
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == long_long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ else if (type == boolean_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_BOOL);
+ else if (type == size_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIZE_T);
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ return element_type->get_pointer ();
+ }
+ else
+ {
+ // Attempt to find an unqualified type when the current type has qualifiers.
+ tree tp = TYPE_MAIN_VARIANT (type);
+ for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
+ {
+ if (TYPE_QUALS (tp) == 0 && type != tp)
+ {
+ recording::type* result = tree_type_to_jit_type (tp);
+ if (result != NULL)
+ {
+ if (TYPE_READONLY (tp))
+ result = new recording::memento_of_get_const (result);
+ if (TYPE_VOLATILE (tp))
+ result = new recording::memento_of_get_volatile (result);
+ return result;
+ }
+ }
+ }
+
+ fprintf (stderr, "Unknown type:\n");
+ debug_tree (type);
+ abort ();
+ }
+
+ return NULL;
+}
+
+/* Record a builtin function. We save their types to be able to check types
+ in recording and for reflection. */
static tree
jit_langhook_builtin_function (tree decl)
{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ target_builtins.put (name, decl);
+
+ std::string string_name (name);
+ if (target_function_types.count (string_name) == 0)
+ {
+ tree function_type = TREE_TYPE (decl);
+ tree arg = TYPE_ARG_TYPES (function_type);
+ bool is_variadic = false;
+
+ auto_vec <recording::type *> param_types;
+
+ while (arg != void_list_node)
+ {
+ if (arg == NULL)
+ {
+ is_variadic = true;
+ break;
+ }
+ if (arg != void_list_node)
+ {
+ recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
+ if (arg_type == NULL)
+ return decl;
+ param_types.safe_push (arg_type);
+ }
+ arg = TREE_CHAIN (arg);
+ }
+
+ tree result_type = TREE_TYPE (function_type);
+ recording::type* return_type = tree_type_to_jit_type (result_type);
+
+ if (return_type == NULL)
+ return decl;
+
+ recording::function_type* func_type =
+ new recording::function_type (&target_builtins_ctxt, return_type,
+ param_types.length (),
+ param_types.address (), is_variadic,
+ false);
+
+ target_function_types[string_name] = func_type;
+ }
+ }
return decl;
}
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index fdd0739789d..63628beac81 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
param_types.length (),
params,
func_type->is_variadic (),
- builtin_id);
+ builtin_id,
+ false);
delete[] params;
/* PR/64020 - If the client code is using builtin cos or sin,
@@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
result = m_ctxt->new_function_type (return_type,
num_args,
param_types,
- is_variadic);
+ is_variadic,
+ false);
error:
delete[] param_types;
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 18cc4da25b8..d71ee2b61a7 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -509,7 +509,8 @@ new_function (location *loc,
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ int is_target_builtin)
{
int i;
param *param;
@@ -543,6 +544,14 @@ new_function (location *loc,
DECL_RESULT (fndecl) = resdecl;
DECL_CONTEXT (resdecl) = fndecl;
+ if (is_target_builtin)
+ {
+ tree *decl = target_builtins.get (name);
+ if (decl != NULL)
+ fndecl = *decl;
+ else
+ add_error (loc, "cannot find target builtin %s", name);
+ }
if (builtin_id)
{
gcc_assert (loc == NULL);
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index f9e29d0baec..06128b4d640 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -104,7 +104,8 @@ public:
const char *name,
const auto_vec<param *> *params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ int is_target_builtin);
lvalue *
new_global (location *loc,
@@ -818,4 +819,6 @@ extern playback::context *active_playback_ctxt;
} // namespace gcc
+extern hash_map<nofree_string_hash, tree> target_builtins;
+
#endif /* JIT_PLAYBACK_H */
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index 9b5b8005ebe..d63293bd642 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -933,14 +933,16 @@ recording::function_type *
recording::context::new_function_type (recording::type *return_type,
int num_params,
recording::type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
{
recording::function_type *fn_type
= new function_type (this,
return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ is_target_builtin);
record (fn_type);
return fn_type;
}
@@ -962,7 +964,8 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc
= new_function_type (return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ false);
/* Return a pointer-type to the function type. */
return fn_type->get_pointer ();
@@ -1005,7 +1008,7 @@ recording::context::new_function (recording::location *loc,
loc, kind, return_type,
new_string (name),
num_params, params, is_variadic,
- builtin_id);
+ builtin_id, false);
record (result);
m_functions.safe_push (result);
@@ -1044,6 +1047,53 @@ recording::context::get_builtin_function (const char *name)
return bm->get_builtin_function (name);
}
+/* Create a recording::function instance for a target-specific builtin.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_target_builtin_function. */
+
+recording::function *
+recording::context::get_target_builtin_function (const char *name)
+{
+ const char *asm_name = name;
+ if (target_function_types.count (name) == 0)
+ {
+ fprintf (stderr, "Cannot find target builtin %s\n", name);
+ return NULL;
+ }
+
+ recording::function_type* func_type = target_function_types[name]
+ ->copy (this)->dyn_cast_function_type ();
+ const vec<type *>& param_types = func_type->get_param_types ();
+ recording::param **params = new recording::param *[param_types.length ()];
+
+ int i;
+ recording::type *param_type;
+ FOR_EACH_VEC_ELT (param_types, i, param_type)
+ {
+ char buf[16];
+ snprintf (buf, 16, "arg%d", i);
+ params[i] = new_param (NULL,
+ param_type,
+ buf);
+ }
+
+ recording::function *result =
+ new recording::function (this,
+ NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ func_type->get_return_type (),
+ new_string (asm_name),
+ param_types.length (),
+ params,
+ func_type->is_variadic (),
+ BUILT_IN_NONE,
+ true);
+ record (result);
+
+ return result;
+}
+
/* Create a recording::global instance and add it to this context's list
of mementos.
@@ -3145,11 +3195,13 @@ recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
type **param_types,
- int is_variadic)
+ int is_variadic,
+ int is_target_builtin)
: type (ctxt),
m_return_type (return_type),
m_param_types (),
- m_is_variadic (is_variadic)
+ m_is_variadic (is_variadic),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
m_param_types.safe_push (param_types[i]);
@@ -4091,7 +4143,8 @@ recording::function::function (context *ctxt,
int num_params,
recording::param **params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ int is_target_builtin)
: memento (ctxt),
m_loc (loc),
m_kind (kind),
@@ -4102,7 +4155,8 @@ recording::function::function (context *ctxt,
m_builtin_id (builtin_id),
m_locals (),
m_blocks (),
- m_fn_ptr_type (NULL)
+ m_fn_ptr_type (NULL),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
{
@@ -4161,7 +4215,8 @@ recording::function::replay_into (replayer *r)
m_name->c_str (),
¶ms,
m_is_variadic,
- m_builtin_id));
+ m_builtin_id,
+ m_is_target_builtin));
}
/* Create a recording::local instance and add it to
@@ -4394,7 +4449,8 @@ recording::function::get_address (recording::location *loc)
= m_ctxt->new_function_type (m_return_type,
m_params.length (),
param_types.address (),
- m_is_variadic);
+ m_is_variadic,
+ m_is_target_builtin);
m_fn_ptr_type = fn_type->get_pointer ();
}
gcc_assert (m_fn_ptr_type);
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 4a8082991fb..81544d6f005 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -24,12 +24,17 @@ along with GCC; see the file COPYING3. If not see
#include "jit-common.h"
#include "jit-logging.h"
+#include <string>
+#include <unordered_map>
+
class timer;
+extern std::unordered_map<std::string, gcc::jit::recording::function_type*>
+ target_function_types;
+
namespace gcc {
namespace jit {
-
extern const char * const unary_op_reproducer_strings[];
extern const char * const binary_op_reproducer_strings[];
@@ -116,7 +121,8 @@ public:
new_function_type (type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *
new_function_ptr_type (location *loc,
@@ -143,6 +149,9 @@ public:
function *
get_builtin_function (const char *name);
+ function *
+ get_target_builtin_function (const char *name);
+
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
@@ -540,6 +549,8 @@ public:
these types. */
virtual size_t get_size () { gcc_unreachable (); }
+ virtual type* copy (context* ctxt) = 0;
+
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
@@ -615,6 +626,11 @@ public:
size_t get_size () final override;
+ type* copy (context* ctxt) final override
+ {
+ return ctxt->get_type (m_kind);
+ }
+
bool accepts_writes_from (type *rtype) final override
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
@@ -666,6 +682,13 @@ public:
type *dereference () final override { return m_other_type; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_pointer (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_size () final override;
bool accepts_writes_from (type *rtype) final override;
@@ -726,6 +749,13 @@ public:
return false;
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_const (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "const", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -759,6 +789,13 @@ public:
return m_other_type->is_same_type_as (other->is_volatile ());
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_volatile (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -785,6 +822,13 @@ public:
return m_other_type->is_same_type_as (other->is_restrict ());
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_restrict (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "restrict", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -805,6 +849,14 @@ public:
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_aligned (m_other_type->copy (ctxt),
+ m_alignment_in_bytes);
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the alignment, giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -826,6 +878,13 @@ public:
: decorated_type (other_type),
m_num_units (num_units) {}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new vector_type (m_other_type->copy (ctxt), m_num_units);
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_num_units () const { return m_num_units; }
vector_type *dyn_cast_vector_type () final override { return this; }
@@ -868,6 +927,14 @@ class array_type : public type
type *dereference () final override;
+ type* copy (context* ctxt) final override
+ {
+ type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt),
+ m_num_elements);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -895,7 +962,8 @@ public:
type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ int is_target_builtin);
type *dereference () final override;
function_type *dyn_cast_function_type () final override { return this; }
@@ -903,6 +971,20 @@ public:
bool is_same_type_as (type *other) final override;
+ type* copy (context* ctxt) final override
+ {
+ auto_vec<type *> new_params{};
+ for (size_t i = 0; i < m_param_types.length (); i++)
+ new_params.safe_push (m_param_types[i]->copy (ctxt));
+
+ type* result = new function_type (ctxt, m_return_type->copy (ctxt),
+ m_param_types.length (),
+ new_params.address (),
+ m_is_variadic, m_is_target_builtin);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -931,6 +1013,7 @@ private:
type *m_return_type;
auto_vec<type *> m_param_types;
int m_is_variadic;
+ int m_is_target_builtin;
};
class field : public memento
@@ -1032,9 +1115,11 @@ public:
return static_cast <playback::compound_type *> (m_playback_obj);
}
-private:
+protected:
location *m_loc;
string *m_name;
+
+private:
fields *m_fields;
};
@@ -1047,6 +1132,13 @@ public:
struct_ *dyn_cast_struct () final override { return this; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new struct_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
type *
as_type () { return this; }
@@ -1094,6 +1186,13 @@ public:
void replay_into (replayer *r) final override;
+ type* copy (context* ctxt) final override
+ {
+ type* result = new union_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_union () const final override { return true; }
private:
@@ -1302,7 +1401,8 @@ public:
int num_params,
param **params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ int is_target_builtin);
void replay_into (replayer *r) final override;
@@ -1357,6 +1457,7 @@ private:
auto_vec<local *> m_locals;
auto_vec<block *> m_blocks;
type *m_fn_ptr_type;
+ int m_is_target_builtin;
};
class block : public memento
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index 0451b4df7f9..9ce4941e6b9 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -1760,6 +1760,24 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
reinterpret_cast<gcc::jit::recording::rvalue**>(values));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::get_target_builtin_function method, in
+ jit-recording.c. */
+
+gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name");
+
+ return static_cast <gcc_jit_function *> (
+ ctxt->get_target_builtin_function (name));
+}
+
/* Public entrypoint. See description in libgccjit.h. */
extern gcc_jit_lvalue *
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 749f6c24177..b70723fd1f6 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1030,6 +1030,19 @@ extern gcc_jit_lvalue *
gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
gcc_jit_rvalue *init_value);
+#define LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function
+
+/* Create a reference to a machine-specific builtin function (sometimes called
+ intrinsic functions).
+
+ This API entrypoint was added in LIBGCCJIT_ABI_25; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function
+*/
+extern gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name);
+
#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
/* Set an initial value for a global, which must be an array of
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 8b90a0e2ff3..5be7a63557b 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -276,3 +276,7 @@ LIBGCCJIT_ABI_25 {
global:
gcc_jit_type_get_restrict;
} LIBGCCJIT_ABI_24;
+
+LIBGCCJIT_ABI_26 {
+ gcc_jit_context_get_target_builtin_function;
+} 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..9875cbe623c 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -322,6 +322,9 @@
/* test-setting-alignment.c: This can't be in the testcases array as it
is target-specific. */
+/* test-target-builtins.c: This can't be in the testcases array as it
+ is target-specific. */
+
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
diff --git a/gcc/testsuite/jit.dg/test-target-builtins.c b/gcc/testsuite/jit.dg/test-target-builtins.c
new file mode 100644
index 00000000000..0ffb48e97f6
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-target-builtins.c
@@ -0,0 +1,77 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#define TEST_PROVIDES_MAIN
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ CHECK_NON_NULL (gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_xgetbv"));
+ gcc_jit_function *builtin_eh_pointer = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_eh_pointer");
+ CHECK_NON_NULL (builtin_eh_pointer);
+
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *void_ptr =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);
+ gcc_jit_function *func_main =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "main",
+ 0, NULL,
+ 0);
+ gcc_jit_rvalue *zero = gcc_jit_context_zero (ctxt, int_type);
+ gcc_jit_block *block = gcc_jit_function_new_block (func_main, NULL);
+ gcc_jit_lvalue *variable = gcc_jit_function_new_local(func_main, NULL, void_ptr, "variable");
+ gcc_jit_block_add_assignment (block, NULL, variable,
+ gcc_jit_context_new_call (ctxt, NULL, builtin_eh_pointer, 1, &zero));
+ gcc_jit_block_end_with_return (block, NULL, zero);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+}
+
+int
+main (int argc, char **argv)
+{
+ /* This is the same as the main provided by harness.h, but it first create a dummy context and compile
+ in order to add the target builtins to libgccjit's internal state. */
+ gcc_jit_context *ctxt;
+ ctxt = gcc_jit_context_acquire ();
+ if (!ctxt)
+ {
+ fail ("gcc_jit_context_acquire failed");
+ return -1;
+ }
+ gcc_jit_result *result;
+ result = gcc_jit_context_compile (ctxt);
+ gcc_jit_result_release (result);
+ gcc_jit_context_release (ctxt);
+
+ int i;
+
+ for (i = 1; i <= 5; i++)
+ {
+ snprintf (test, sizeof (test),
+ "%s iteration %d of %d",
+ extract_progname (argv[0]),
+ i, 5);
+
+ //printf ("ITERATION %d\n", i);
+ test_jit (argv[0], NULL);
+ //printf ("\n");
+ }
+
+ totals ();
+
+ return 0;
+}
--
2.42.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-11-23 22:17 ` Antoni Boucher
@ 2023-11-23 22:21 ` Antoni Boucher
2024-06-26 22:49 ` David Malcolm
1 sibling, 0 replies; 21+ messages in thread
From: Antoni Boucher @ 2023-11-23 22:21 UTC (permalink / raw)
To: Andrew Pinski; +Cc: jit, gcc-patches, David Malcolm
I will need to not forget to update the function tree_type_to_jit_type
in dummy-frontend.cc to add back the support for bfloat16 when the
patch for it is merged.
On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote:
> Hi.
> I did split the patch and sent one for the bfloat16 support and
> another
> one for the vector support.
>
> Here's the updated patch for the machine-dependent builtins.
>
> Regards.
>
> On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> > >
> > > Hi.
> > > This patch adds support for machine-dependent builtins in
> > > libgccjit
> > > (bug 108762).
> > >
> > > There are two things I don't like in this patch:
> > >
> > > 1. There are a few functions copied from the C frontend
> > > (common_mark_addressable_vec and a few others).
> > >
> > > 2. Getting a target builtin only works from the second
> > > compilation
> > > since the type information is recorded at the first compilation.
> > > I
> > > couldn't find a way to get the builtin data without using the
> > > langhook.
> > > It is necessary to get the type information for type checking and
> > > instrospection.
> > >
> > > Any idea how to fix these issues?
> >
> > Seems like you should do this patch in a few steps; that is split
> > it
> > up.
> > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > I also think the vector support should be in a different patch too.
> >
> > Splitting out these parts would definitely make it easier for
> > review
> > and make incremental improvements.
> >
> > Thanks,
> > Andrew Pinski
> >
> >
> >
> > >
> > > Thanks for the review.
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-02-12 1:37 ` Andrew Pinski
2023-11-23 22:17 ` Antoni Boucher
@ 2024-01-10 23:29 ` Antoni Boucher
2024-01-10 23:44 ` David Malcolm
1 sibling, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-01-10 23:29 UTC (permalink / raw)
To: Andrew Pinski; +Cc: jit, gcc-patches, David Malcolm
David: Ping in case you missed this patch.
On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > Hi.
> > This patch adds support for machine-dependent builtins in libgccjit
> > (bug 108762).
> >
> > There are two things I don't like in this patch:
> >
> > 1. There are a few functions copied from the C frontend
> > (common_mark_addressable_vec and a few others).
> >
> > 2. Getting a target builtin only works from the second compilation
> > since the type information is recorded at the first compilation. I
> > couldn't find a way to get the builtin data without using the
> > langhook.
> > It is necessary to get the type information for type checking and
> > instrospection.
> >
> > Any idea how to fix these issues?
>
> Seems like you should do this patch in a few steps; that is split it
> up.
> Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> I also think the vector support should be in a different patch too.
>
> Splitting out these parts would definitely make it easier for review
> and make incremental improvements.
>
> Thanks,
> Andrew Pinski
>
>
>
> >
> > Thanks for the review.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-01-10 23:29 ` Antoni Boucher
@ 2024-01-10 23:44 ` David Malcolm
2024-01-10 23:58 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: David Malcolm @ 2024-01-10 23:44 UTC (permalink / raw)
To: Antoni Boucher, Andrew Pinski; +Cc: jit, gcc-patches
On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
> David: Ping in case you missed this patch.
For some reason it's not showing up in patchwork (or, at least, I can't
find it there). Do you have a URL for it there?
Sorry about this
Dave
>
> On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> > >
> > > Hi.
> > > This patch adds support for machine-dependent builtins in
> > > libgccjit
> > > (bug 108762).
> > >
> > > There are two things I don't like in this patch:
> > >
> > > 1. There are a few functions copied from the C frontend
> > > (common_mark_addressable_vec and a few others).
> > >
> > > 2. Getting a target builtin only works from the second
> > > compilation
> > > since the type information is recorded at the first compilation.
> > > I
> > > couldn't find a way to get the builtin data without using the
> > > langhook.
> > > It is necessary to get the type information for type checking and
> > > instrospection.
> > >
> > > Any idea how to fix these issues?
> >
> > Seems like you should do this patch in a few steps; that is split
> > it
> > up.
> > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > I also think the vector support should be in a different patch too.
> >
> > Splitting out these parts would definitely make it easier for
> > review
> > and make incremental improvements.
> >
> > Thanks,
> > Andrew Pinski
> >
> >
> >
> > >
> > > Thanks for the review.
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-01-10 23:44 ` David Malcolm
@ 2024-01-10 23:58 ` Antoni Boucher
2024-02-08 13:59 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-01-10 23:58 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski; +Cc: jit, gcc-patches
Here it is: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html
On Wed, 2024-01-10 at 18:44 -0500, David Malcolm wrote:
> On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
> > David: Ping in case you missed this patch.
>
> For some reason it's not showing up in patchwork (or, at least, I
> can't
> find it there). Do you have a URL for it there?
>
> Sorry about this
> Dave
>
> >
> > On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> > > <gcc-patches@gcc.gnu.org> wrote:
> > > >
> > > > Hi.
> > > > This patch adds support for machine-dependent builtins in
> > > > libgccjit
> > > > (bug 108762).
> > > >
> > > > There are two things I don't like in this patch:
> > > >
> > > > 1. There are a few functions copied from the C frontend
> > > > (common_mark_addressable_vec and a few others).
> > > >
> > > > 2. Getting a target builtin only works from the second
> > > > compilation
> > > > since the type information is recorded at the first
> > > > compilation.
> > > > I
> > > > couldn't find a way to get the builtin data without using the
> > > > langhook.
> > > > It is necessary to get the type information for type checking
> > > > and
> > > > instrospection.
> > > >
> > > > Any idea how to fix these issues?
> > >
> > > Seems like you should do this patch in a few steps; that is split
> > > it
> > > up.
> > > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > > I also think the vector support should be in a different patch
> > > too.
> > >
> > > Splitting out these parts would definitely make it easier for
> > > review
> > > and make incremental improvements.
> > >
> > > Thanks,
> > > Andrew Pinski
> > >
> > >
> > >
> > > >
> > > > Thanks for the review.
> >
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-01-10 23:58 ` Antoni Boucher
@ 2024-02-08 13:59 ` Antoni Boucher
2024-02-15 14:32 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-02-08 13:59 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski; +Cc: jit, gcc-patches
David: Ping.
On Wed, 2024-01-10 at 18:58 -0500, Antoni Boucher wrote:
> Here it is: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html
>
> On Wed, 2024-01-10 at 18:44 -0500, David Malcolm wrote:
> > On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
> > > David: Ping in case you missed this patch.
> >
> > For some reason it's not showing up in patchwork (or, at least, I
> > can't
> > find it there). Do you have a URL for it there?
> >
> > Sorry about this
> > Dave
> >
> > >
> > > On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > > > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-patches
> > > > <gcc-patches@gcc.gnu.org> wrote:
> > > > >
> > > > > Hi.
> > > > > This patch adds support for machine-dependent builtins in
> > > > > libgccjit
> > > > > (bug 108762).
> > > > >
> > > > > There are two things I don't like in this patch:
> > > > >
> > > > > 1. There are a few functions copied from the C frontend
> > > > > (common_mark_addressable_vec and a few others).
> > > > >
> > > > > 2. Getting a target builtin only works from the second
> > > > > compilation
> > > > > since the type information is recorded at the first
> > > > > compilation.
> > > > > I
> > > > > couldn't find a way to get the builtin data without using the
> > > > > langhook.
> > > > > It is necessary to get the type information for type checking
> > > > > and
> > > > > instrospection.
> > > > >
> > > > > Any idea how to fix these issues?
> > > >
> > > > Seems like you should do this patch in a few steps; that is
> > > > split
> > > > it
> > > > up.
> > > > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > > > I also think the vector support should be in a different patch
> > > > too.
> > > >
> > > > Splitting out these parts would definitely make it easier for
> > > > review
> > > > and make incremental improvements.
> > > >
> > > > Thanks,
> > > > Andrew Pinski
> > > >
> > > >
> > > >
> > > > >
> > > > > Thanks for the review.
> > >
> >
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-02-08 13:59 ` Antoni Boucher
@ 2024-02-15 14:32 ` Antoni Boucher
2024-02-29 15:34 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-02-15 14:32 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski; +Cc: jit, gcc-patches
David: Ping
On Thu, 2024-02-08 at 08:59 -0500, Antoni Boucher wrote:
> David: Ping.
>
> On Wed, 2024-01-10 at 18:58 -0500, Antoni Boucher wrote:
> > Here it is: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html
> >
> > On Wed, 2024-01-10 at 18:44 -0500, David Malcolm wrote:
> > > On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
> > > > David: Ping in case you missed this patch.
> > >
> > > For some reason it's not showing up in patchwork (or, at least, I
> > > can't
> > > find it there). Do you have a URL for it there?
> > >
> > > Sorry about this
> > > Dave
> > >
> > > >
> > > > On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > > > > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-
> > > > > patches
> > > > > <gcc-patches@gcc.gnu.org> wrote:
> > > > > >
> > > > > > Hi.
> > > > > > This patch adds support for machine-dependent builtins in
> > > > > > libgccjit
> > > > > > (bug 108762).
> > > > > >
> > > > > > There are two things I don't like in this patch:
> > > > > >
> > > > > > 1. There are a few functions copied from the C frontend
> > > > > > (common_mark_addressable_vec and a few others).
> > > > > >
> > > > > > 2. Getting a target builtin only works from the second
> > > > > > compilation
> > > > > > since the type information is recorded at the first
> > > > > > compilation.
> > > > > > I
> > > > > > couldn't find a way to get the builtin data without using
> > > > > > the
> > > > > > langhook.
> > > > > > It is necessary to get the type information for type
> > > > > > checking
> > > > > > and
> > > > > > instrospection.
> > > > > >
> > > > > > Any idea how to fix these issues?
> > > > >
> > > > > Seems like you should do this patch in a few steps; that is
> > > > > split
> > > > > it
> > > > > up.
> > > > > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > > > > I also think the vector support should be in a different
> > > > > patch
> > > > > too.
> > > > >
> > > > > Splitting out these parts would definitely make it easier for
> > > > > review
> > > > > and make incremental improvements.
> > > > >
> > > > > Thanks,
> > > > > Andrew Pinski
> > > > >
> > > > >
> > > > >
> > > > > >
> > > > > > Thanks for the review.
> > > >
> > >
> >
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-02-15 14:32 ` Antoni Boucher
@ 2024-02-29 15:34 ` Antoni Boucher
2024-04-19 12:35 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-02-29 15:34 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski; +Cc: jit, gcc-patches
David: Ping.
On Thu, 2024-02-15 at 09:32 -0500, Antoni Boucher wrote:
> David: Ping
>
> On Thu, 2024-02-08 at 08:59 -0500, Antoni Boucher wrote:
> > David: Ping.
> >
> > On Wed, 2024-01-10 at 18:58 -0500, Antoni Boucher wrote:
> > > Here it is: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html
> > >
> > > On Wed, 2024-01-10 at 18:44 -0500, David Malcolm wrote:
> > > > On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
> > > > > David: Ping in case you missed this patch.
> > > >
> > > > For some reason it's not showing up in patchwork (or, at least,
> > > > I
> > > > can't
> > > > find it there). Do you have a URL for it there?
> > > >
> > > > Sorry about this
> > > > Dave
> > > >
> > > > >
> > > > > On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
> > > > > > On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-
> > > > > > patches
> > > > > > <gcc-patches@gcc.gnu.org> wrote:
> > > > > > >
> > > > > > > Hi.
> > > > > > > This patch adds support for machine-dependent builtins in
> > > > > > > libgccjit
> > > > > > > (bug 108762).
> > > > > > >
> > > > > > > There are two things I don't like in this patch:
> > > > > > >
> > > > > > > 1. There are a few functions copied from the C frontend
> > > > > > > (common_mark_addressable_vec and a few others).
> > > > > > >
> > > > > > > 2. Getting a target builtin only works from the second
> > > > > > > compilation
> > > > > > > since the type information is recorded at the first
> > > > > > > compilation.
> > > > > > > I
> > > > > > > couldn't find a way to get the builtin data without using
> > > > > > > the
> > > > > > > langhook.
> > > > > > > It is necessary to get the type information for type
> > > > > > > checking
> > > > > > > and
> > > > > > > instrospection.
> > > > > > >
> > > > > > > Any idea how to fix these issues?
> > > > > >
> > > > > > Seems like you should do this patch in a few steps; that is
> > > > > > split
> > > > > > it
> > > > > > up.
> > > > > > Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
> > > > > > I also think the vector support should be in a different
> > > > > > patch
> > > > > > too.
> > > > > >
> > > > > > Splitting out these parts would definitely make it easier
> > > > > > for
> > > > > > review
> > > > > > and make incremental improvements.
> > > > > >
> > > > > > Thanks,
> > > > > > Andrew Pinski
> > > > > >
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > Thanks for the review.
> > > > >
> > > >
> > >
> >
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-02-29 15:34 ` Antoni Boucher
@ 2024-04-19 12:35 ` Antoni Boucher
0 siblings, 0 replies; 21+ messages in thread
From: Antoni Boucher @ 2024-04-19 12:35 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski; +Cc: jit, gcc-patches
David: Ping.
Le 2024-02-29 à 10 h 34, Antoni Boucher a écrit :
> David: Ping.
>
> On Thu, 2024-02-15 at 09:32 -0500, Antoni Boucher wrote:
>> David: Ping
>>
>> On Thu, 2024-02-08 at 08:59 -0500, Antoni Boucher wrote:
>>> David: Ping.
>>>
>>> On Wed, 2024-01-10 at 18:58 -0500, Antoni Boucher wrote:
>>>> Here it is: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html
>>>>
>>>> On Wed, 2024-01-10 at 18:44 -0500, David Malcolm wrote:
>>>>> On Wed, 2024-01-10 at 18:29 -0500, Antoni Boucher wrote:
>>>>>> David: Ping in case you missed this patch.
>>>>>
>>>>> For some reason it's not showing up in patchwork (or, at least,
>>>>> I
>>>>> can't
>>>>> find it there). Do you have a URL for it there?
>>>>>
>>>>> Sorry about this
>>>>> Dave
>>>>>
>>>>>>
>>>>>> On Sat, 2023-02-11 at 17:37 -0800, Andrew Pinski wrote:
>>>>>>> On Sat, Feb 11, 2023 at 4:31 PM Antoni Boucher via Gcc-
>>>>>>> patches
>>>>>>> <gcc-patches@gcc.gnu.org> wrote:
>>>>>>>>
>>>>>>>> Hi.
>>>>>>>> This patch adds support for machine-dependent builtins in
>>>>>>>> libgccjit
>>>>>>>> (bug 108762).
>>>>>>>>
>>>>>>>> There are two things I don't like in this patch:
>>>>>>>>
>>>>>>>> 1. There are a few functions copied from the C frontend
>>>>>>>> (common_mark_addressable_vec and a few others).
>>>>>>>>
>>>>>>>> 2. Getting a target builtin only works from the second
>>>>>>>> compilation
>>>>>>>> since the type information is recorded at the first
>>>>>>>> compilation.
>>>>>>>> I
>>>>>>>> couldn't find a way to get the builtin data without using
>>>>>>>> the
>>>>>>>> langhook.
>>>>>>>> It is necessary to get the type information for type
>>>>>>>> checking
>>>>>>>> and
>>>>>>>> instrospection.
>>>>>>>>
>>>>>>>> Any idea how to fix these issues?
>>>>>>>
>>>>>>> Seems like you should do this patch in a few steps; that is
>>>>>>> split
>>>>>>> it
>>>>>>> up.
>>>>>>> Definitely split out GCC_JIT_TYPE_BFLOAT16 support.
>>>>>>> I also think the vector support should be in a different
>>>>>>> patch
>>>>>>> too.
>>>>>>>
>>>>>>> Splitting out these parts would definitely make it easier
>>>>>>> for
>>>>>>> review
>>>>>>> and make incremental improvements.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Andrew Pinski
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks for the review.
>>>>>>
>>>>>
>>>>
>>>
>>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2023-11-23 22:17 ` Antoni Boucher
2023-11-23 22:21 ` Antoni Boucher
@ 2024-06-26 22:49 ` David Malcolm
2024-06-27 16:35 ` Uros Bizjak
2024-11-14 20:27 ` Antoni Boucher
1 sibling, 2 replies; 21+ messages in thread
From: David Malcolm @ 2024-06-26 22:49 UTC (permalink / raw)
To: Antoni Boucher, Andrew Pinski, Jan Hubicka, Uros Bizjak; +Cc: jit, gcc-patches
On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote:
> Hi.
> I did split the patch and sent one for the bfloat16 support and
> another
> one for the vector support.
>
> Here's the updated patch for the machine-dependent builtins.
>
Thanks for the patch; sorry about the long delay in reviewing it.
CCing Jan and Uros re the i386 part of that patch; for reference the
patch being discussed is here:
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638027.html
> From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17 00:00:00 2001
> From: Antoni Boucher <bouanto@zoho.com>
> Date: Mon, 23 Jan 2023 17:21:15 -0500
> Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
[...snip...]
> diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
> index 42fc3751676..5cc1d6f4d2e 100644
> --- a/gcc/config/i386/i386-builtins.cc
> +++ b/gcc/config/i386/i386-builtins.cc
> @@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
>
> struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
>
> +static void
> +clear_builtin_types (void)
> +{
> + for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
> + ix86_builtin_type_tab[i] = NULL;
> +
> + for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
> + {
> + ix86_builtins[i] = NULL;
> + ix86_builtins_isa[i].set_and_not_built_p = true;
> + }
> +
> + for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
> + ix86_builtin_func_type_tab[i] = NULL;
> +}
> +
> tree get_ix86_builtin (enum ix86_builtins c)
> {
> return ix86_builtins[c];
> @@ -1483,6 +1499,8 @@ ix86_init_builtins (void)
> {
> tree ftype, decl;
>
> + clear_builtin_types ();
> +
> ix86_init_builtin_types ();
>
> /* Builtins to get CPU type and features. */
Please can one of the i386 maintainers check this?
(CCing Jan and Uros: this is for the case where the compiler code runs
multiple times in-process due to being linked into libgccjit.so. We
want to restore state within i386-builtins.cc to an initial state, and
ensure that no GC-managed objects persist from previous in-memory
compiles).
> diff --git a/gcc/jit/docs/topics/compatibility.rst
b/gcc/jit/docs/topics/compatibility.rst
> index ebede440ee4..764de23341e 100644
> --- a/gcc/jit/docs/topics/compatibility.rst
> +++ b/gcc/jit/docs/topics/compatibility.rst
> @@ -378,3 +378,12 @@ 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 a function to get target builtins:
> +
> + * :func:`gcc_jit_context_get_target_builtin_function`
> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
> index cf5cb716daf..e9b77fdb892 100644
> --- a/gcc/jit/docs/topics/functions.rst
> +++ b/gcc/jit/docs/topics/functions.rst
> @@ -140,6 +140,25 @@ Functions
> uses such a parameter will lead to an error being emitted within
> the context.
>
> +.. function:: gcc_jit_function *\
> + gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,\
> + const char *name)
> +
> + Get the :type:`gcc_jit_function` for the built-in function with the
> + given name. For example:
Might be nice to add the "(sometimes called intrinsic functions)" text
you have in the header here.
[...snip....]
> diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
> index a729086bafb..3ca9702d429 100644
> --- a/gcc/jit/dummy-frontend.cc
> +++ b/gcc/jit/dummy-frontend.cc
[...]
> @@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
> #include "options.h"
> #include "stringpool.h"
> #include "attribs.h"
> +#include "jit-recording.h"
> +#include "print-tree.h"
>
> #include <mpfr.h>
> +#include <unordered_map>
> +#include <string>
> +
> +using namespace gcc::jit;
>
> /* Attribute handling. */
>
> @@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
> ATTR_EXCL (NULL, false, false, false)
> };
>
> +hash_map<nofree_string_hash, tree> target_builtins{};
I was wondering if this needs a GTY marker, but I don't think it does:
presumably it's only used within jit_langhook_parse_file where no GC
can happen - unless jit_langhook_write_globals makes use of it?
> +std::unordered_map<std::string, recording::function_type*>
target_function_types
> +{};
> +recording::context target_builtins_ctxt{NULL};
Please add a comment to target_builtins_ctxt saying what it's for. As
far as I can tell, it's for getting at recording::types from
tree_type_to_jit_type; we then use a new "copy" mechanism to copy
objects from target_builtins_ctxt for use with the real
recording::context.
This feels ugly, but maybe it's the only way to make it work.
Could tree_type_to_jit_type take a recording::context as a param? The
only non-recursive uses of tree_type_to_jit_type seem to be in
jit_langhook_builtin_function. Could that use the recording::context
of the current playback::context? You can get the current
playback::context from gcc::jit::active_playback_ctxt and then access
that playback::context's m_recording_ctxt.
Or is there some need to have this work as a global cache? (which is
what the target_builtins_ctxt effectively does).
It looks like target_function_types might be a cache...
> +
> /* Table of machine-independent attributes supported in libgccjit. */
> const struct attribute_spec jit_attribute_table[] =
> {
> @@ -594,6 +606,7 @@ jit_langhook_init (void)
>
> build_common_tree_nodes (false);
>
> + target_builtins.empty ();
> build_common_builtin_nodes ();
>
> /* The default precision for floating point numbers. This is used
> @@ -601,6 +614,8 @@ jit_langhook_init (void)
> eventually be controllable by a command line option. */
> mpfr_set_default_prec (256);
>
> + targetm.init_builtins ();
> +
> return true;
> }
>
> @@ -668,11 +683,198 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
> return NULL;
> }
>
> -/* Record a builtin function. We just ignore builtin functions. */
> +recording::type* tree_type_to_jit_type (tree type)
> +{
> + if (TREE_CODE (type) == VECTOR_TYPE)
> + {
> + tree inner_type = TREE_TYPE (type);
> + recording::type* element_type = tree_type_to_jit_type (inner_type);
> + poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
> + long constant_size = size.to_constant ();
> + if (element_type != NULL)
> + return element_type->get_vector (constant_size);
> + return NULL;
> + }
> + if (TREE_CODE (type) == REFERENCE_TYPE)
> + // For __builtin_ms_va_start.
> + // FIXME: wrong type.
> + return new recording::memento_of_get_type (&target_builtins_ctxt,
> + GCC_JIT_TYPE_VOID);
The various "// FIXME: wrong type" cases in this function feel like a
timebomb; could we instead fail hard on them, rather than potentially
silently generate bad code?
[...snip...]
> +/* Record a builtin function. We save their types to be able to check types
> + in recording and for reflection. */
Aha! This comment makes it clearer that the stuff above is a cache, so
maybe it has to be done the way you have it above (with the recursive
copying to the appropriate recording::context).
> static tree
> jit_langhook_builtin_function (tree decl)
> {
> + if (TREE_CODE (decl) == FUNCTION_DECL)
> + {
> + const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
> + target_builtins.put (name, decl);
> +
> + std::string string_name (name);
> + if (target_function_types.count (string_name) == 0)
> + {
> + tree function_type = TREE_TYPE (decl);
> + tree arg = TYPE_ARG_TYPES (function_type);
> + bool is_variadic = false;
> +
> + auto_vec <recording::type *> param_types;
> +
> + while (arg != void_list_node)
> + {
> + if (arg == NULL)
> + {
> + is_variadic = true;
> + break;
> + }
> + if (arg != void_list_node)
> + {
> + recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
> + if (arg_type == NULL)
> + return decl;
> + param_types.safe_push (arg_type);
> + }
> + arg = TREE_CHAIN (arg);
> + }
> +
> + tree result_type = TREE_TYPE (function_type);
> + recording::type* return_type = tree_type_to_jit_type (result_type);
> +
> + if (return_type == NULL)
> + return decl;
> +
> + recording::function_type* func_type =
> + new recording::function_type (&target_builtins_ctxt, return_type,
> + param_types.length (),
> + param_types.address (), is_variadic,
> + false);
> +
> + target_function_types[string_name] = func_type;
> + }
> + }
> return decl;
> }
>
[...snip...]
> diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
> index 18cc4da25b8..d71ee2b61a7 100644
> --- a/gcc/jit/jit-playback.cc
> +++ b/gcc/jit/jit-playback.cc
> @@ -509,7 +509,8 @@ new_function (location *loc,
> const char *name,
> const auto_vec<param *> *params,
> int is_variadic,
> - enum built_in_function builtin_id)
> + enum built_in_function builtin_id,
> + int is_target_builtin)
> {
> int i;
> param *param;
> @@ -543,6 +544,14 @@ new_function (location *loc,
> DECL_RESULT (fndecl) = resdecl;
> DECL_CONTEXT (resdecl) = fndecl;
>
> + if (is_target_builtin)
> + {
> + tree *decl = target_builtins.get (name);
> + if (decl != NULL)
> + fndecl = *decl;
> + else
> + add_error (loc, "cannot find target builtin %s", name);
> + }
It looks like is_target_builtin is only ever used as a flag, so for
clarity's sake, can it and the various m_is_target_builtin be a bool
rather than an int?
> if (builtin_id)
> {
> gcc_assert (loc == NULL);
> diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
> index f9e29d0baec..06128b4d640 100644
> --- a/gcc/jit/jit-playback.h
> +++ b/gcc/jit/jit-playback.h
> @@ -104,7 +104,8 @@ public:
> const char *name,
> const auto_vec<param *> *params,
> int is_variadic,
> - enum built_in_function builtin_id);
> + enum built_in_function builtin_id,
> + int is_target_builtin);
>
> lvalue *
> new_global (location *loc,
> @@ -818,4 +819,6 @@ extern playback::context *active_playback_ctxt;
>
> } // namespace gcc
>
> +extern hash_map<nofree_string_hash, tree> target_builtins;
> +
> #endif /* JIT_PLAYBACK_H */
[...snip...]
Assuming that the i386 maintainers are OK with the change to i386-
builtins.cc, this is OK for trunk if you fix the various nitpicks I
mention above (and you'll probably need to do the usual refreshing of
the ABI version)
On Thu, 2023-11-23 at 17:21 -0500, Antoni Boucher wrote:
> I will need to not forget to update the function
> tree_type_to_jit_type
> in dummy-frontend.cc to add back the support for bfloat16 when the
> patch for it is merged.
Adding this here as a reminder.
Thanks again for the patch.
Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-06-26 22:49 ` David Malcolm
@ 2024-06-27 16:35 ` Uros Bizjak
2024-11-14 20:27 ` Antoni Boucher
1 sibling, 0 replies; 21+ messages in thread
From: Uros Bizjak @ 2024-06-27 16:35 UTC (permalink / raw)
To: David Malcolm
Cc: Antoni Boucher, Andrew Pinski, Jan Hubicka, jit, gcc-patches
On Thu, Jun 27, 2024 at 12:49 AM David Malcolm <dmalcolm@redhat.com> wrote:
>
> On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote:
> > Hi.
> > I did split the patch and sent one for the bfloat16 support and
> > another
> > one for the vector support.
> >
> > Here's the updated patch for the machine-dependent builtins.
> >
>
> Thanks for the patch; sorry about the long delay in reviewing it.
>
> CCing Jan and Uros re the i386 part of that patch; for reference the
> patch being discussed is here:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638027.html
>
> > From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17 00:00:00 2001
> > From: Antoni Boucher <bouanto@zoho.com>
> > Date: Mon, 23 Jan 2023 17:21:15 -0500
> > Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
>
> [...snip...]
>
> > diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
> > index 42fc3751676..5cc1d6f4d2e 100644
> > --- a/gcc/config/i386/i386-builtins.cc
> > +++ b/gcc/config/i386/i386-builtins.cc
> > @@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
> >
> > struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
> >
> > +static void
> > +clear_builtin_types (void)
> > +{
> > + for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
> > + ix86_builtin_type_tab[i] = NULL;
> > +
> > + for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
> > + {
> > + ix86_builtins[i] = NULL;
> > + ix86_builtins_isa[i].set_and_not_built_p = true;
> > + }
> > +
> > + for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
> > + ix86_builtin_func_type_tab[i] = NULL;
> > +}
> > +
> > tree get_ix86_builtin (enum ix86_builtins c)
> > {
> > return ix86_builtins[c];
> > @@ -1483,6 +1499,8 @@ ix86_init_builtins (void)
> > {
> > tree ftype, decl;
> >
> > + clear_builtin_types ();
> > +
> > ix86_init_builtin_types ();
> >
> > /* Builtins to get CPU type and features. */
>
> Please can one of the i386 maintainers check this?
> (CCing Jan and Uros: this is for the case where the compiler code runs
> multiple times in-process due to being linked into libgccjit.so. We
> want to restore state within i386-builtins.cc to an initial state, and
> ensure that no GC-managed objects persist from previous in-memory
> compiles).
Can we rather introduce TARGET_CLEANUP_BUILTINS hook and call it from
the JIT compiler at some appropriate time? IMO, this burdens
unnecessarily non-JIT compilation.
Uros.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-06-26 22:49 ` David Malcolm
2024-06-27 16:35 ` Uros Bizjak
@ 2024-11-14 20:27 ` Antoni Boucher
2024-11-19 16:14 ` David Malcolm
1 sibling, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-11-14 20:27 UTC (permalink / raw)
To: David Malcolm, Andrew Pinski, Jan Hubicka, Uros Bizjak
Cc: jit, gcc-patches, Jose E. Marchesi
[-- Attachment #1: Type: text/plain, Size: 12410 bytes --]
It seems we don't need to do the cleanup in i386-builtins.cc anymore, so
I removed it.
David: Is it possible that your recent fixes for the GC within libgccjit
also fixed the issue here?
Here's the updated patch and answers below.
(GitHub link if you find it easier for review:
https://github.com/antoyo/libgccjit/pull/5)
Thanks.
Le 2024-06-26 à 18 h 49, David Malcolm a écrit :
> On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote:
>> Hi.
>> I did split the patch and sent one for the bfloat16 support and
>> another
>> one for the vector support.
>>
>> Here's the updated patch for the machine-dependent builtins.
>>
>
> Thanks for the patch; sorry about the long delay in reviewing it.
>
> CCing Jan and Uros re the i386 part of that patch; for reference the
> patch being discussed is here:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638027.html
>
>> From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17 00:00:00 2001
>> From: Antoni Boucher <bouanto@zoho.com>
>> Date: Mon, 23 Jan 2023 17:21:15 -0500
>> Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
>
> [...snip...]
>
>> diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
>> index 42fc3751676..5cc1d6f4d2e 100644
>> --- a/gcc/config/i386/i386-builtins.cc
>> +++ b/gcc/config/i386/i386-builtins.cc
>> @@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int) IX86_BUILTIN_MAX];
>>
>> struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
>>
>> +static void
>> +clear_builtin_types (void)
>> +{
>> + for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
>> + ix86_builtin_type_tab[i] = NULL;
>> +
>> + for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
>> + {
>> + ix86_builtins[i] = NULL;
>> + ix86_builtins_isa[i].set_and_not_built_p = true;
>> + }
>> +
>> + for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
>> + ix86_builtin_func_type_tab[i] = NULL;
>> +}
>> +
>> tree get_ix86_builtin (enum ix86_builtins c)
>> {
>> return ix86_builtins[c];
>> @@ -1483,6 +1499,8 @@ ix86_init_builtins (void)
>> {
>> tree ftype, decl;
>>
>> + clear_builtin_types ();
>> +
>> ix86_init_builtin_types ();
>>
>> /* Builtins to get CPU type and features. */
>
> Please can one of the i386 maintainers check this?
> (CCing Jan and Uros: this is for the case where the compiler code runs
> multiple times in-process due to being linked into libgccjit.so. We
> want to restore state within i386-builtins.cc to an initial state, and
> ensure that no GC-managed objects persist from previous in-memory
> compiles).
>
>> diff --git a/gcc/jit/docs/topics/compatibility.rst
> b/gcc/jit/docs/topics/compatibility.rst
>> index ebede440ee4..764de23341e 100644
>> --- a/gcc/jit/docs/topics/compatibility.rst
>> +++ b/gcc/jit/docs/topics/compatibility.rst
>> @@ -378,3 +378,12 @@ 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 a function to get target builtins:
>> +
>> + * :func:`gcc_jit_context_get_target_builtin_function`
>> diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
>> index cf5cb716daf..e9b77fdb892 100644
>> --- a/gcc/jit/docs/topics/functions.rst
>> +++ b/gcc/jit/docs/topics/functions.rst
>> @@ -140,6 +140,25 @@ Functions
>> uses such a parameter will lead to an error being emitted within
>> the context.
>>
>> +.. function:: gcc_jit_function *\
>> + gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,\
>> + const char *name)
>> +
>> + Get the :type:`gcc_jit_function` for the built-in function with the
>> + given name. For example:
>
> Might be nice to add the "(sometimes called intrinsic functions)" text
> you have in the header here.
Done
>
> [...snip....]
>
>> diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
>> index a729086bafb..3ca9702d429 100644
>> --- a/gcc/jit/dummy-frontend.cc
>> +++ b/gcc/jit/dummy-frontend.cc
>
> [...]
>
>> @@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not see
>> #include "options.h"
>> #include "stringpool.h"
>> #include "attribs.h"
>> +#include "jit-recording.h"
>> +#include "print-tree.h"
>>
>> #include <mpfr.h>
>> +#include <unordered_map>
>> +#include <string>
>> +
>> +using namespace gcc::jit;
>>
>> /* Attribute handling. */
>>
>> @@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
>> ATTR_EXCL (NULL, false, false, false)
>> };
>>
>> +hash_map<nofree_string_hash, tree> target_builtins{};
>
> I was wondering if this needs a GTY marker, but I don't think it does:
> presumably it's only used within jit_langhook_parse_file where no GC
> can happen - unless jit_langhook_write_globals makes use of it?
It is also used in jit-playback.cc: does that mean it needs a GTY marker?
>
>> +std::unordered_map<std::string, recording::function_type*>
> target_function_types
>> +{};
>> +recording::context target_builtins_ctxt{NULL};
>
> Please add a comment to target_builtins_ctxt saying what it's for. As
> far as I can tell, it's for getting at recording::types from
> tree_type_to_jit_type; we then use a new "copy" mechanism to copy
> objects from target_builtins_ctxt for use with the real
> recording::context.
I added a comment.
>
> This feels ugly, but maybe it's the only way to make it work.
>
> Could tree_type_to_jit_type take a recording::context as a param? The
> only non-recursive uses of tree_type_to_jit_type seem to be in
> jit_langhook_builtin_function. Could that use the recording::context
> of the current playback::context? You can get the current
> playback::context from gcc::jit::active_playback_ctxt and then access
> that playback::context's m_recording_ctxt.
>
> Or is there some need to have this work as a global cache? (which is
> what the target_builtins_ctxt effectively does).
> It looks like target_function_types might be a cache...
Indeed, this is used as a global cache, as you noticed below.
>
>> +
>> /* Table of machine-independent attributes supported in libgccjit. */
>> const struct attribute_spec jit_attribute_table[] =
>> {
>> @@ -594,6 +606,7 @@ jit_langhook_init (void)
>>
>> build_common_tree_nodes (false);
>>
>> + target_builtins.empty ();
>> build_common_builtin_nodes ();
>>
>> /* The default precision for floating point numbers. This is used
>> @@ -601,6 +614,8 @@ jit_langhook_init (void)
>> eventually be controllable by a command line option. */
>> mpfr_set_default_prec (256);
>>
>> + targetm.init_builtins ();
>> +
>> return true;
>> }
>>
>> @@ -668,11 +683,198 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
>> return NULL;
>> }
>>
>> -/* Record a builtin function. We just ignore builtin functions. */
>> +recording::type* tree_type_to_jit_type (tree type)
>> +{
>> + if (TREE_CODE (type) == VECTOR_TYPE)
>> + {
>> + tree inner_type = TREE_TYPE (type);
>> + recording::type* element_type = tree_type_to_jit_type (inner_type);
>> + poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
>> + long constant_size = size.to_constant ();
>> + if (element_type != NULL)
>> + return element_type->get_vector (constant_size);
>> + return NULL;
>> + }
>> + if (TREE_CODE (type) == REFERENCE_TYPE)
>> + // For __builtin_ms_va_start.
>> + // FIXME: wrong type.
>> + return new recording::memento_of_get_type (&target_builtins_ctxt,
>> + GCC_JIT_TYPE_VOID);
>
> The various "// FIXME: wrong type" cases in this function feel like a
> timebomb; could we instead fail hard on them, rather than potentially
> silently generate bad code?
While it is a timebomb, we cannot error out here as this process all the
builtins, so any unsupported type needs to be processed.
The current way allows to use most builtins and usage of a few builtins
will have incorrect type checking.
>
> [...snip...]
>
>> +/* Record a builtin function. We save their types to be able to check types
>> + in recording and for reflection. */
>
> Aha! This comment makes it clearer that the stuff above is a cache, so
> maybe it has to be done the way you have it above (with the recursive
> copying to the appropriate recording::context).
>
>> static tree
>> jit_langhook_builtin_function (tree decl)
>> {
>> + if (TREE_CODE (decl) == FUNCTION_DECL)
>> + {
>> + const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
>> + target_builtins.put (name, decl);
>> +
>> + std::string string_name (name);
>> + if (target_function_types.count (string_name) == 0)
>> + {
>> + tree function_type = TREE_TYPE (decl);
>> + tree arg = TYPE_ARG_TYPES (function_type);
>> + bool is_variadic = false;
>> +
>> + auto_vec <recording::type *> param_types;
>> +
>> + while (arg != void_list_node)
>> + {
>> + if (arg == NULL)
>> + {
>> + is_variadic = true;
>> + break;
>> + }
>> + if (arg != void_list_node)
>> + {
>> + recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
>> + if (arg_type == NULL)
>> + return decl;
>> + param_types.safe_push (arg_type);
>> + }
>> + arg = TREE_CHAIN (arg);
>> + }
>> +
>> + tree result_type = TREE_TYPE (function_type);
>> + recording::type* return_type = tree_type_to_jit_type (result_type);
>> +
>> + if (return_type == NULL)
>> + return decl;
>> +
>> + recording::function_type* func_type =
>> + new recording::function_type (&target_builtins_ctxt, return_type,
>> + param_types.length (),
>> + param_types.address (), is_variadic,
>> + false);
>> +
>> + target_function_types[string_name] = func_type;
>> + }
>> + }
>> return decl;
>> }
>>
>
> [...snip...]
>
>> diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
>> index 18cc4da25b8..d71ee2b61a7 100644
>> --- a/gcc/jit/jit-playback.cc
>> +++ b/gcc/jit/jit-playback.cc
>> @@ -509,7 +509,8 @@ new_function (location *loc,
>> const char *name,
>> const auto_vec<param *> *params,
>> int is_variadic,
>> - enum built_in_function builtin_id)
>> + enum built_in_function builtin_id,
>> + int is_target_builtin)
>> {
>> int i;
>> param *param;
>> @@ -543,6 +544,14 @@ new_function (location *loc,
>> DECL_RESULT (fndecl) = resdecl;
>> DECL_CONTEXT (resdecl) = fndecl;
>>
>> + if (is_target_builtin)
>> + {
>> + tree *decl = target_builtins.get (name);
>> + if (decl != NULL)
>> + fndecl = *decl;
>> + else
>> + add_error (loc, "cannot find target builtin %s", name);
>> + }
>
> It looks like is_target_builtin is only ever used as a flag, so for
> clarity's sake, can it and the various m_is_target_builtin be a bool
> rather than an int?
Done.
>
>
>> if (builtin_id)
>> {
>> gcc_assert (loc == NULL);
>> diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
>> index f9e29d0baec..06128b4d640 100644
>> --- a/gcc/jit/jit-playback.h
>> +++ b/gcc/jit/jit-playback.h
>> @@ -104,7 +104,8 @@ public:
>> const char *name,
>> const auto_vec<param *> *params,
>> int is_variadic,
>> - enum built_in_function builtin_id);
>> + enum built_in_function builtin_id,
>> + int is_target_builtin);
>>
>> lvalue *
>> new_global (location *loc,
>> @@ -818,4 +819,6 @@ extern playback::context *active_playback_ctxt;
>>
>> } // namespace gcc
>>
>> +extern hash_map<nofree_string_hash, tree> target_builtins;
>> +
>> #endif /* JIT_PLAYBACK_H */
>
> [...snip...]
>
> Assuming that the i386 maintainers are OK with the change to i386-
> builtins.cc, this is OK for trunk if you fix the various nitpicks I
> mention above (and you'll probably need to do the usual refreshing of
> the ABI version)
>
> On Thu, 2023-11-23 at 17:21 -0500, Antoni Boucher wrote:
>> I will need to not forget to update the function
>> tree_type_to_jit_type
>> in dummy-frontend.cc to add back the support for bfloat16 when the
>> patch for it is merged.
>
> Adding this here as a reminder.
Done as well.
>
> Thanks again for the patch.
> Dave
[-- Attachment #2: 0001-libgccjit-Add-support-for-machine-dependent-builtins.patch --]
[-- Type: text/x-patch, Size: 32803 bytes --]
From 801caae52908c6e2680aaad674108cbfa3925e17 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Mon, 23 Jan 2023 17:21:15 -0500
Subject: [PATCH] libgccjit: Add support for machine-dependent builtins
gcc/jit/ChangeLog:
PR jit/108762
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): New ABI tag.
* docs/topics/functions.rst: Add documentation for the function
gcc_jit_context_get_target_builtin_function.
* dummy-frontend.cc: Include headers target.h, jit-recording.h,
print-tree.h, unordered_map and string, new variables (target_builtins,
target_function_types, and target_builtins_ctxt), new function
(tree_type_to_jit_type).
* jit-builtins.cc: Specify that the function types are not from
target builtins.
* jit-playback.cc: New argument is_target_builtin to new_function.
* jit-playback.h: New argument is_target_builtin to
new_function.
* jit-recording.cc: New argument is_target_builtin to
new_function_type, function_type constructor and function
constructor, new function
(get_target_builtin_function).
* jit-recording.h: Include headers string and unordered_map, new
variable target_function_types, new argument is_target_builtin
to new_function_type, function_type and function, new functions
(get_target_builtin_function, copy).
* libgccjit.cc: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.h: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.map: New functions
(gcc_jit_context_get_target_builtin_function).
gcc/testsuite:
PR jit/108762
* jit.dg/all-non-failing-tests.h: New test test-target-builtins.c.
* jit.dg/test-target-builtins.c: New test.
---
gcc/jit/docs/topics/compatibility.rst | 9 +
gcc/jit/docs/topics/functions.rst | 19 ++
gcc/jit/dummy-frontend.cc | 206 ++++++++++++++++++-
gcc/jit/jit-builtins.cc | 6 +-
gcc/jit/jit-playback.cc | 12 +-
gcc/jit/jit-playback.h | 5 +-
gcc/jit/jit-recording.cc | 76 ++++++-
gcc/jit/jit-recording.h | 110 +++++++++-
gcc/jit/libgccjit.cc | 18 ++
gcc/jit/libgccjit.h | 13 ++
gcc/jit/libgccjit.map | 5 +
gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 +
gcc/testsuite/jit.dg/test-target-builtins.c | 77 +++++++
13 files changed, 539 insertions(+), 20 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-target-builtins.c
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 92c3ed24c89..1d65e6f4b54 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -404,3 +404,12 @@ on functions and variables:
--------------------
``LIBGCCJIT_ABI_28`` covers the addition of
:func:`gcc_jit_context_new_alignof`
+
+.. _LIBGCCJIT_ABI_29:
+
+``LIBGCCJIT_ABI_29``
+--------------------
+
+``LIBGCCJIT_ABI_29`` covers the addition of a function to get target builtins:
+
+ * :func:`gcc_jit_context_get_target_builtin_function`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index 804605ea939..16e82a34c21 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -140,6 +140,25 @@ Functions
uses such a parameter will lead to an error being emitted within
the context.
+.. function:: gcc_jit_function *\
+ gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,\
+ const char *name)
+
+ Get the :type:`gcc_jit_function` for the built-in function (sometimes called
+ intrinsic functions) with the given name. For example:
+
+ .. code-block:: c
+
+ gcc_jit_function *fn
+ = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_pmuldq512_mask");
+
+ .. note:: Due to technical limitations with how libgccjit interacts with
+ the insides of GCC, not all built-in functions are supported. More
+ precisely, not all types are supported for parameters of built-in
+ functions from libgccjit. Attempts to get a built-in function that
+ uses such a parameter will lead to an error being emitted within
+ the context.
+
.. function:: gcc_jit_object *\
gcc_jit_function_as_object (gcc_jit_function *func)
diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
index 17f37a3f405..c4097150171 100644
--- a/gcc/jit/dummy-frontend.cc
+++ b/gcc/jit/dummy-frontend.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "target.h"
#include "jit-playback.h"
#include "stor-layout.h"
#include "debug.h"
@@ -32,8 +33,13 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "target.h"
#include "diagnostic-format-text.h"
+#include "jit-recording.h"
+#include "print-tree.h"
#include <mpfr.h>
+#include <unordered_map>
+
+using namespace gcc::jit;
/* Attribute handling. */
@@ -138,6 +144,14 @@ static const struct attribute_spec::exclusions attr_target_exclusions[] =
ATTR_EXCL (NULL, false, false, false),
};
+/* These variables act as a cache for the target builtins. This is needed in
+ order to be able to type-check the calls since we can only get those types
+ in the playback phase while we need them in the recording phase. */
+hash_map<nofree_string_hash, tree> target_builtins{};
+std::unordered_map<std::string, recording::function_type*> target_function_types
+{};
+recording::context target_builtins_ctxt{NULL};
+
/* Table of machine-independent attributes supported in libgccjit. */
static const attribute_spec jit_gnu_attributes[] =
{
@@ -1032,6 +1046,7 @@ jit_langhook_init (void)
build_common_tree_nodes (false);
+ target_builtins.empty ();
build_common_builtin_nodes ();
/* The default precision for floating point numbers. This is used
@@ -1039,6 +1054,8 @@ jit_langhook_init (void)
eventually be controllable by a command line option. */
mpfr_set_default_prec (256);
+ targetm.init_builtins ();
+
return true;
}
@@ -1106,11 +1123,198 @@ jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
return NULL;
}
-/* Record a builtin function. We just ignore builtin functions. */
+recording::type* tree_type_to_jit_type (tree type)
+{
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
+ long constant_size = size.to_constant ();
+ if (element_type != NULL)
+ return element_type->get_vector (constant_size);
+ return NULL;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ // For __builtin_ms_va_start.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ // For __builtin_sysv_va_copy.
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ /* TODO: Remove when we add support for sized floating-point types. */
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (type == FLOATN_NX_TYPE_NODE (i))
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ if (type == void_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == ptr_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ else if (type == const_ptr_type_node)
+ {
+ // Void const ptr.
+ recording::type* result =
+ new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID_PTR);
+ return new recording::memento_of_get_const (result);
+ }
+ else if (type == unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_INT);
+ else if (type == long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG);
+ else if (type == integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_INT);
+ else if (type == long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG);
+ else if (type == long_long_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_LONG);
+ else if (type == signed_char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIGNED_CHAR);
+ else if (type == char_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_CHAR);
+ else if (type == unsigned_intQI_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UINT8_T);
+ else if (type == short_integer_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SHORT);
+ else if (type == short_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_SHORT);
+ else if (type == complex_float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_FLOAT);
+ else if (type == complex_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_DOUBLE);
+ else if (type == complex_long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
+ else if (type == float_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_FLOAT);
+ else if (type == double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_DOUBLE);
+ else if (type == long_double_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_LONG_DOUBLE);
+ else if (type == bfloat16_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_BFLOAT16);
+ else if (type == dfloat128_type_node)
+ // FIXME: wrong type.
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_VOID);
+ else if (type == long_long_unsigned_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ else if (type == boolean_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_BOOL);
+ else if (type == size_type_node)
+ return new recording::memento_of_get_type (&target_builtins_ctxt,
+ GCC_JIT_TYPE_SIZE_T);
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ tree inner_type = TREE_TYPE (type);
+ recording::type* element_type = tree_type_to_jit_type (inner_type);
+ return element_type->get_pointer ();
+ }
+ else
+ {
+ // Attempt to find an unqualified type when the current type has qualifiers.
+ tree tp = TYPE_MAIN_VARIANT (type);
+ for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp))
+ {
+ if (TYPE_QUALS (tp) == 0 && type != tp)
+ {
+ recording::type* result = tree_type_to_jit_type (tp);
+ if (result != NULL)
+ {
+ if (TYPE_READONLY (tp))
+ result = new recording::memento_of_get_const (result);
+ if (TYPE_VOLATILE (tp))
+ result = new recording::memento_of_get_volatile (result);
+ return result;
+ }
+ }
+ }
+
+ fprintf (stderr, "Unknown type:\n");
+ debug_tree (type);
+ abort ();
+ }
+
+ return NULL;
+}
+
+/* Record a builtin function. We save their types to be able to check types
+ in recording and for reflection. */
static tree
jit_langhook_builtin_function (tree decl)
{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ target_builtins.put (name, decl);
+
+ std::string string_name (name);
+ if (target_function_types.count (string_name) == 0)
+ {
+ tree function_type = TREE_TYPE (decl);
+ tree arg = TYPE_ARG_TYPES (function_type);
+ bool is_variadic = false;
+
+ auto_vec <recording::type *> param_types;
+
+ while (arg != void_list_node)
+ {
+ if (arg == NULL)
+ {
+ is_variadic = true;
+ break;
+ }
+ if (arg != void_list_node)
+ {
+ recording::type* arg_type = tree_type_to_jit_type (TREE_VALUE (arg));
+ if (arg_type == NULL)
+ return decl;
+ param_types.safe_push (arg_type);
+ }
+ arg = TREE_CHAIN (arg);
+ }
+
+ tree result_type = TREE_TYPE (function_type);
+ recording::type* return_type = tree_type_to_jit_type (result_type);
+
+ if (return_type == NULL)
+ return decl;
+
+ recording::function_type* func_type =
+ new recording::function_type (&target_builtins_ctxt, return_type,
+ param_types.length (),
+ param_types.address (), is_variadic,
+ false);
+
+ target_function_types[string_name] = func_type;
+ }
+ }
return decl;
}
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc
index e0bb24738dd..b9f52db15e7 100644
--- a/gcc/jit/jit-builtins.cc
+++ b/gcc/jit/jit-builtins.cc
@@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
param_types.length (),
params,
func_type->is_variadic (),
- builtin_id);
+ builtin_id,
+ false);
delete[] params;
/* PR/64020 - If the client code is using builtin cos or sin,
@@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
result = m_ctxt->new_function_type (return_type,
num_args,
param_types,
- is_variadic);
+ is_variadic,
+ false);
error:
delete[] param_types;
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 583956fb463..ac8d7681837 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -570,7 +570,8 @@ new_function (location *loc,
std::string>> &string_attributes,
const std::vector<std::pair<gcc_jit_fn_attribute,
std::vector<int>>>
- &int_array_attributes)
+ &int_array_attributes,
+ bool is_target_builtin)
{
int i;
param *param;
@@ -606,6 +607,15 @@ new_function (location *loc,
tree fn_attributes = NULL_TREE;
+ if (is_target_builtin)
+ {
+ tree *decl = target_builtins.get (name);
+ if (decl != NULL)
+ fndecl = *decl;
+ else
+ add_error (loc, "cannot find target builtin %s", name);
+ }
+
if (builtin_id)
{
gcc_assert (loc == NULL);
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 6e97b389cbb..23f686a6300 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -121,7 +121,8 @@ public:
std::string>> &string_attributes,
const std::vector<std::pair<gcc_jit_fn_attribute,
std::vector<int>>>
- &int_array_attributes);
+ &int_array_attributes,
+ bool is_target_builtin);
lvalue *
new_global (location *loc,
@@ -851,4 +852,6 @@ extern playback::context *active_playback_ctxt;
} // namespace gcc
+extern hash_map<nofree_string_hash, tree> target_builtins;
+
#endif /* JIT_PLAYBACK_H */
diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc
index cc7f529c9e8..0dedc3acf57 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -934,14 +934,16 @@ recording::function_type *
recording::context::new_function_type (recording::type *return_type,
int num_params,
recording::type **param_types,
- int is_variadic)
+ int is_variadic,
+ bool is_target_builtin)
{
recording::function_type *fn_type
= new function_type (this,
return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ is_target_builtin);
record (fn_type);
return fn_type;
}
@@ -963,7 +965,8 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc
= new_function_type (return_type,
num_params,
param_types,
- is_variadic);
+ is_variadic,
+ false);
/* Return a pointer-type to the function type. */
return fn_type->get_pointer ();
@@ -1006,7 +1009,7 @@ recording::context::new_function (recording::location *loc,
loc, kind, return_type,
new_string (name),
num_params, params, is_variadic,
- builtin_id);
+ builtin_id, false);
record (result);
m_functions.safe_push (result);
@@ -1045,6 +1048,53 @@ recording::context::get_builtin_function (const char *name)
return bm->get_builtin_function (name);
}
+/* Create a recording::function instance for a target-specific builtin.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_target_builtin_function. */
+
+recording::function *
+recording::context::get_target_builtin_function (const char *name)
+{
+ const char *asm_name = name;
+ if (target_function_types.count (name) == 0)
+ {
+ fprintf (stderr, "Cannot find target builtin %s\n", name);
+ return NULL;
+ }
+
+ recording::function_type* func_type = target_function_types[name]
+ ->copy (this)->dyn_cast_function_type ();
+ const vec<type *>& param_types = func_type->get_param_types ();
+ recording::param **params = new recording::param *[param_types.length ()];
+
+ int i;
+ recording::type *param_type;
+ FOR_EACH_VEC_ELT (param_types, i, param_type)
+ {
+ char buf[16];
+ snprintf (buf, 16, "arg%d", i);
+ params[i] = new_param (NULL,
+ param_type,
+ buf);
+ }
+
+ recording::function *result =
+ new recording::function (this,
+ NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ func_type->get_return_type (),
+ new_string (asm_name),
+ param_types.length (),
+ params,
+ func_type->is_variadic (),
+ BUILT_IN_NONE,
+ true);
+ record (result);
+
+ return result;
+}
+
/* Create a recording::global instance and add it to this context's list
of mementos.
@@ -3191,11 +3241,13 @@ recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
type **param_types,
- int is_variadic)
+ int is_variadic,
+ bool is_target_builtin)
: type (ctxt),
m_return_type (return_type),
m_param_types (),
- m_is_variadic (is_variadic)
+ m_is_variadic (is_variadic),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
m_param_types.safe_push (param_types[i]);
@@ -4144,7 +4196,8 @@ recording::function::function (context *ctxt,
int num_params,
recording::param **params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ bool is_target_builtin)
: memento (ctxt),
m_loc (loc),
m_kind (kind),
@@ -4158,7 +4211,8 @@ recording::function::function (context *ctxt,
m_fn_ptr_type (NULL),
m_attributes (),
m_string_attributes (),
- m_int_array_attributes ()
+ m_int_array_attributes (),
+ m_is_target_builtin (is_target_builtin)
{
for (int i = 0; i< num_params; i++)
{
@@ -4220,7 +4274,8 @@ recording::function::replay_into (replayer *r)
m_builtin_id,
m_attributes,
m_string_attributes,
- m_int_array_attributes));
+ m_int_array_attributes,
+ m_is_target_builtin));
}
/* Create a recording::local instance and add it to
@@ -4487,7 +4542,8 @@ recording::function::get_address (recording::location *loc)
= m_ctxt->new_function_type (m_return_type,
m_params.length (),
param_types.address (),
- m_is_variadic);
+ m_is_variadic,
+ m_is_target_builtin);
m_fn_ptr_type = fn_type->get_pointer ();
}
gcc_assert (m_fn_ptr_type);
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index abd4f6f8bb3..8ba9ebdf01c 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -28,12 +28,16 @@ along with GCC; see the file COPYING3. If not see
#include <string>
#include <vector>
+#include <unordered_map>
+
class timer;
+extern std::unordered_map<std::string, gcc::jit::recording::function_type*>
+ target_function_types;
+
namespace gcc {
namespace jit {
-
extern const char * const unary_op_reproducer_strings[];
extern const char * const binary_op_reproducer_strings[];
@@ -125,7 +129,8 @@ public:
new_function_type (type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ bool is_target_builtin);
type *
new_function_ptr_type (location *loc,
@@ -152,6 +157,9 @@ public:
function *
get_builtin_function (const char *name);
+ function *
+ get_target_builtin_function (const char *name);
+
lvalue *
new_global (location *loc,
enum gcc_jit_global_kind kind,
@@ -555,6 +563,8 @@ public:
these types. */
virtual size_t get_size () { gcc_unreachable (); }
+ virtual type* copy (context* ctxt) = 0;
+
/* Dynamic casts. */
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
@@ -632,6 +642,11 @@ public:
size_t get_size () final override;
+ type* copy (context* ctxt) final override
+ {
+ return ctxt->get_type (m_kind);
+ }
+
bool accepts_writes_from (type *rtype) final override
{
if (m_kind == GCC_JIT_TYPE_VOID_PTR)
@@ -683,6 +698,13 @@ public:
type *dereference () final override { return m_other_type; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_pointer (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_size () final override;
bool accepts_writes_from (type *rtype) final override;
@@ -746,6 +768,13 @@ public:
return false;
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_const (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "const", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -779,6 +808,13 @@ public:
return m_other_type->is_same_type_as (other->is_volatile ());
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_volatile (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -805,6 +841,13 @@ public:
return m_other_type->is_same_type_as (other->is_restrict ());
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_restrict (m_other_type->copy (ctxt));
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the "restrict", giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -825,6 +868,14 @@ public:
: decorated_type (other_type),
m_alignment_in_bytes (alignment_in_bytes) {}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new memento_of_get_aligned (m_other_type->copy (ctxt),
+ m_alignment_in_bytes);
+ ctxt->record (result);
+ return result;
+ }
+
/* Strip off the alignment, giving the underlying type. */
type *unqualified () final override { return m_other_type; }
@@ -859,6 +910,13 @@ public:
return true;
}
+ type* copy (context* ctxt) final override
+ {
+ type* result = new vector_type (m_other_type->copy (ctxt), m_num_units);
+ ctxt->record (result);
+ return result;
+ }
+
size_t get_num_units () const { return m_num_units; }
vector_type *dyn_cast_vector_type () final override { return this; }
@@ -912,6 +970,14 @@ class array_type : public type
array_type *dyn_cast_array_type () final override { return this; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt),
+ m_num_elements);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -939,7 +1005,8 @@ public:
type *return_type,
int num_params,
type **param_types,
- int is_variadic);
+ int is_variadic,
+ bool is_target_builtin);
type *dereference () final override;
function_type *dyn_cast_function_type () final override { return this; }
@@ -947,6 +1014,20 @@ public:
bool is_same_type_as (type *other) final override;
+ type* copy (context* ctxt) final override
+ {
+ auto_vec<type *> new_params{};
+ for (size_t i = 0; i < m_param_types.length (); i++)
+ new_params.safe_push (m_param_types[i]->copy (ctxt));
+
+ type* result = new function_type (ctxt, m_return_type->copy (ctxt),
+ m_param_types.length (),
+ new_params.address (),
+ m_is_variadic, m_is_target_builtin);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_int () const final override { return false; }
bool is_float () const final override { return false; }
bool is_bool () const final override { return false; }
@@ -975,6 +1056,7 @@ private:
type *m_return_type;
auto_vec<type *> m_param_types;
int m_is_variadic;
+ bool m_is_target_builtin;
};
class field : public memento
@@ -1076,9 +1158,11 @@ public:
return static_cast <playback::compound_type *> (m_playback_obj);
}
-private:
+protected:
location *m_loc;
string *m_name;
+
+private:
fields *m_fields;
};
@@ -1091,6 +1175,13 @@ public:
struct_ *dyn_cast_struct () final override { return this; }
+ type* copy (context* ctxt) final override
+ {
+ type* result = new struct_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
type *
as_type () { return this; }
@@ -1138,6 +1229,13 @@ public:
void replay_into (replayer *r) final override;
+ type* copy (context* ctxt) final override
+ {
+ type* result = new union_ (ctxt, m_loc, m_name);
+ ctxt->record (result);
+ return result;
+ }
+
bool is_union () const final override { return true; }
private:
@@ -1353,7 +1451,8 @@ public:
int num_params,
param **params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ bool is_target_builtin);
void replay_into (replayer *r) final override;
@@ -1415,6 +1514,7 @@ private:
std::vector<gcc_jit_fn_attribute> m_attributes;
std::vector<std::pair<gcc_jit_fn_attribute, std::string>> m_string_attributes;
std::vector<std::pair<gcc_jit_fn_attribute, std::vector<int>>> m_int_array_attributes;
+ bool m_is_target_builtin;
};
class block : public memento
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index eb38da91df1..d7476fc8129 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -1760,6 +1760,24 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,
reinterpret_cast<gcc::jit::recording::rvalue**>(values));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::get_target_builtin_function method, in
+ jit-recording.c. */
+
+gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name");
+
+ return static_cast <gcc_jit_function *> (
+ ctxt->get_target_builtin_function (name));
+}
+
/* Public entrypoint. See description in libgccjit.h. */
extern gcc_jit_lvalue *
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 03bfc0f58a5..eddf52c9e7e 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1037,6 +1037,19 @@ extern gcc_jit_lvalue *
gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,
gcc_jit_rvalue *init_value);
+#define LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function
+
+/* Create a reference to a machine-specific builtin function (sometimes called
+ intrinsic functions).
+
+ This API entrypoint was added in LIBGCCJIT_ABI_29; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function
+*/
+extern gcc_jit_function *
+gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt,
+ const char *name);
+
#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
/* Set an initial value for a global, which must be an array of
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index b02783ebfb2..d26b90b0e1c 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -294,3 +294,8 @@ LIBGCCJIT_ABI_28 {
global:
gcc_jit_context_new_alignof;
} LIBGCCJIT_ABI_27;
+
+LIBGCCJIT_ABI_29 {
+ global:
+ gcc_jit_context_get_target_builtin_function;
+} LIBGCCJIT_ABI_28;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 75721329ab5..3609318369f 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -370,6 +370,9 @@
#undef create_code
#undef verify_code
+/* test-target-builtins.c: This can't be in the testcases array as it
+ is target-specific. */
+
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
diff --git a/gcc/testsuite/jit.dg/test-target-builtins.c b/gcc/testsuite/jit.dg/test-target-builtins.c
new file mode 100644
index 00000000000..0ffb48e97f6
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-target-builtins.c
@@ -0,0 +1,77 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#define TEST_PROVIDES_MAIN
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ CHECK_NON_NULL (gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_xgetbv"));
+ gcc_jit_function *builtin_eh_pointer = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_eh_pointer");
+ CHECK_NON_NULL (builtin_eh_pointer);
+
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *void_ptr =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);
+ gcc_jit_function *func_main =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "main",
+ 0, NULL,
+ 0);
+ gcc_jit_rvalue *zero = gcc_jit_context_zero (ctxt, int_type);
+ gcc_jit_block *block = gcc_jit_function_new_block (func_main, NULL);
+ gcc_jit_lvalue *variable = gcc_jit_function_new_local(func_main, NULL, void_ptr, "variable");
+ gcc_jit_block_add_assignment (block, NULL, variable,
+ gcc_jit_context_new_call (ctxt, NULL, builtin_eh_pointer, 1, &zero));
+ gcc_jit_block_end_with_return (block, NULL, zero);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+}
+
+int
+main (int argc, char **argv)
+{
+ /* This is the same as the main provided by harness.h, but it first create a dummy context and compile
+ in order to add the target builtins to libgccjit's internal state. */
+ gcc_jit_context *ctxt;
+ ctxt = gcc_jit_context_acquire ();
+ if (!ctxt)
+ {
+ fail ("gcc_jit_context_acquire failed");
+ return -1;
+ }
+ gcc_jit_result *result;
+ result = gcc_jit_context_compile (ctxt);
+ gcc_jit_result_release (result);
+ gcc_jit_context_release (ctxt);
+
+ int i;
+
+ for (i = 1; i <= 5; i++)
+ {
+ snprintf (test, sizeof (test),
+ "%s iteration %d of %d",
+ extract_progname (argv[0]),
+ i, 5);
+
+ //printf ("ITERATION %d\n", i);
+ test_jit (argv[0], NULL);
+ //printf ("\n");
+ }
+
+ totals ();
+
+ return 0;
+}
--
2.47.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-14 20:27 ` Antoni Boucher
@ 2024-11-19 16:14 ` David Malcolm
2024-11-19 20:45 ` Mark Wielaard
0 siblings, 1 reply; 21+ messages in thread
From: David Malcolm @ 2024-11-19 16:14 UTC (permalink / raw)
To: Antoni Boucher, Andrew Pinski, Jan Hubicka, Uros Bizjak
Cc: jit, gcc-patches, Jose E. Marchesi
On Thu, 2024-11-14 at 15:27 -0500, Antoni Boucher wrote:
> It seems we don't need to do the cleanup in i386-builtins.cc anymore,
> so
> I removed it.
> David: Is it possible that your recent fixes for the GC within
> libgccjit
> also fixed the issue here?
>
> Here's the updated patch and answers below.
>
> (GitHub link if you find it easier for review:
> https://github.com/antoyo/libgccjit/pull/5)
>
> Thanks.
Thanks; I looked over the patch via the above link and it looks good to
me for trunk.
Dave
>
> Le 2024-06-26 à 18 h 49, David Malcolm a écrit :
> > On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote:
> > > Hi.
> > > I did split the patch and sent one for the bfloat16 support and
> > > another
> > > one for the vector support.
> > >
> > > Here's the updated patch for the machine-dependent builtins.
> > >
> >
> > Thanks for the patch; sorry about the long delay in reviewing it.
> >
> > CCing Jan and Uros re the i386 part of that patch; for reference
> > the
> > patch being discussed is here:
> >
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638027.html
> >
> > > From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17
> > > 00:00:00 2001
> > > From: Antoni Boucher <bouanto@zoho.com>
> > > Date: Mon, 23 Jan 2023 17:21:15 -0500
> > > Subject: [PATCH] libgccjit: Add support for machine-dependent
> > > builtins
> >
> > [...snip...]
> >
> > > diff --git a/gcc/config/i386/i386-builtins.cc
> > > b/gcc/config/i386/i386-builtins.cc
> > > index 42fc3751676..5cc1d6f4d2e 100644
> > > --- a/gcc/config/i386/i386-builtins.cc
> > > +++ b/gcc/config/i386/i386-builtins.cc
> > > @@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int)
> > > IX86_BUILTIN_MAX];
> > >
> > > struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX];
> > >
> > > +static void
> > > +clear_builtin_types (void)
> > > +{
> > > + for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++)
> > > + ix86_builtin_type_tab[i] = NULL;
> > > +
> > > + for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++)
> > > + {
> > > + ix86_builtins[i] = NULL;
> > > + ix86_builtins_isa[i].set_and_not_built_p = true;
> > > + }
> > > +
> > > + for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++)
> > > + ix86_builtin_func_type_tab[i] = NULL;
> > > +}
> > > +
> > > tree get_ix86_builtin (enum ix86_builtins c)
> > > {
> > > return ix86_builtins[c];
> > > @@ -1483,6 +1499,8 @@ ix86_init_builtins (void)
> > > {
> > > tree ftype, decl;
> > >
> > > + clear_builtin_types ();
> > > +
> > > ix86_init_builtin_types ();
> > >
> > > /* Builtins to get CPU type and features. */
> >
> > Please can one of the i386 maintainers check this?
> > (CCing Jan and Uros: this is for the case where the compiler code
> > runs
> > multiple times in-process due to being linked into libgccjit.so.
> > We
> > want to restore state within i386-builtins.cc to an initial state,
> > and
> > ensure that no GC-managed objects persist from previous in-memory
> > compiles).
> >
> > > diff --git a/gcc/jit/docs/topics/compatibility.rst
> > b/gcc/jit/docs/topics/compatibility.rst
> > > index ebede440ee4..764de23341e 100644
> > > --- a/gcc/jit/docs/topics/compatibility.rst
> > > +++ b/gcc/jit/docs/topics/compatibility.rst
> > > @@ -378,3 +378,12 @@ 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 a function to get
> > > target builtins:
> > > +
> > > + * :func:`gcc_jit_context_get_target_builtin_function`
> > > diff --git a/gcc/jit/docs/topics/functions.rst
> > > b/gcc/jit/docs/topics/functions.rst
> > > index cf5cb716daf..e9b77fdb892 100644
> > > --- a/gcc/jit/docs/topics/functions.rst
> > > +++ b/gcc/jit/docs/topics/functions.rst
> > > @@ -140,6 +140,25 @@ Functions
> > > uses such a parameter will lead to an error being emitted
> > > within
> > > the context.
> > >
> > > +.. function:: gcc_jit_function *\
> > > + gcc_jit_context_get_target_builtin_function
> > > (gcc_jit_context *ctxt,\
> > > +
> > > const char *name)
> > > +
> > > + Get the :type:`gcc_jit_function` for the built-in function
> > > with the
> > > + given name. For example:
> >
> > Might be nice to add the "(sometimes called intrinsic functions)"
> > text
> > you have in the header here.
>
> Done
>
> >
> > [...snip....]
> >
> > > diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-
> > > frontend.cc
> > > index a729086bafb..3ca9702d429 100644
> > > --- a/gcc/jit/dummy-frontend.cc
> > > +++ b/gcc/jit/dummy-frontend.cc
> >
> > [...]
> >
> > > @@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not
> > > see
> > > #include "options.h"
> > > #include "stringpool.h"
> > > #include "attribs.h"
> > > +#include "jit-recording.h"
> > > +#include "print-tree.h"
> > >
> > > #include <mpfr.h>
> > > +#include <unordered_map>
> > > +#include <string>
> > > +
> > > +using namespace gcc::jit;
> > >
> > > /* Attribute handling. */
> > >
> > > @@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions
> > > attr_const_pure_exclusions[] =
> > > ATTR_EXCL (NULL, false, false, false)
> > > };
> > >
> > > +hash_map<nofree_string_hash, tree> target_builtins{};
> >
> > I was wondering if this needs a GTY marker, but I don't think it
> > does:
> > presumably it's only used within jit_langhook_parse_file where no
> > GC
> > can happen - unless jit_langhook_write_globals makes use of it?
>
> It is also used in jit-playback.cc: does that mean it needs a GTY
> marker?
>
> >
> > > +std::unordered_map<std::string, recording::function_type*>
> > target_function_types
> > > +{};
> > > +recording::context target_builtins_ctxt{NULL};
> >
> > Please add a comment to target_builtins_ctxt saying what it's for.
> > As
> > far as I can tell, it's for getting at recording::types from
> > tree_type_to_jit_type; we then use a new "copy" mechanism to copy
> > objects from target_builtins_ctxt for use with the real
> > recording::context.
>
> I added a comment.
>
> >
> > This feels ugly, but maybe it's the only way to make it work.
> >
> > Could tree_type_to_jit_type take a recording::context as a param?
> > The
> > only non-recursive uses of tree_type_to_jit_type seem to be in
> > jit_langhook_builtin_function. Could that use the
> > recording::context
> > of the current playback::context? You can get the current
> > playback::context from gcc::jit::active_playback_ctxt and then
> > access
> > that playback::context's m_recording_ctxt.
> >
> > Or is there some need to have this work as a global cache? (which
> > is
> > what the target_builtins_ctxt effectively does).
> > It looks like target_function_types might be a cache...
>
> Indeed, this is used as a global cache, as you noticed below.
>
> >
> > > +
> > > /* Table of machine-independent attributes supported in
> > > libgccjit. */
> > > const struct attribute_spec jit_attribute_table[] =
> > > {
> > > @@ -594,6 +606,7 @@ jit_langhook_init (void)
> > >
> > > build_common_tree_nodes (false);
> > >
> > > + target_builtins.empty ();
> > > build_common_builtin_nodes ();
> > >
> > > /* The default precision for floating point numbers. This is
> > > used
> > > @@ -601,6 +614,8 @@ jit_langhook_init (void)
> > > eventually be controllable by a command line option. */
> > > mpfr_set_default_prec (256);
> > >
> > > + targetm.init_builtins ();
> > > +
> > > return true;
> > > }
> > >
> > > @@ -668,11 +683,198 @@ jit_langhook_type_for_mode (machine_mode
> > > mode, int unsignedp)
> > > return NULL;
> > > }
> > >
> > > -/* Record a builtin function. We just ignore builtin
> > > functions. */
> > > +recording::type* tree_type_to_jit_type (tree type)
> > > +{
> > > + if (TREE_CODE (type) == VECTOR_TYPE)
> > > + {
> > > + tree inner_type = TREE_TYPE (type);
> > > + recording::type* element_type = tree_type_to_jit_type
> > > (inner_type);
> > > + poly_uint64 size = TYPE_VECTOR_SUBPARTS (type);
> > > + long constant_size = size.to_constant ();
> > > + if (element_type != NULL)
> > > + return element_type->get_vector (constant_size);
> > > + return NULL;
> > > + }
> > > + if (TREE_CODE (type) == REFERENCE_TYPE)
> > > + // For __builtin_ms_va_start.
> > > + // FIXME: wrong type.
> > > + return new recording::memento_of_get_type
> > > (&target_builtins_ctxt,
> > > +
> > > GCC_JIT_TYPE_VOID);
> >
> > The various "// FIXME: wrong type" cases in this function feel like
> > a
> > timebomb; could we instead fail hard on them, rather than
> > potentially
> > silently generate bad code?
>
> While it is a timebomb, we cannot error out here as this process all
> the
> builtins, so any unsupported type needs to be processed.
> The current way allows to use most builtins and usage of a few
> builtins
> will have incorrect type checking.
>
> >
> > [...snip...]
> >
> > > +/* Record a builtin function. We save their types to be able to
> > > check types
> > > + in recording and for reflection. */
> >
> > Aha! This comment makes it clearer that the stuff above is a
> > cache, so
> > maybe it has to be done the way you have it above (with the
> > recursive
> > copying to the appropriate recording::context).
> >
> > > static tree
> > > jit_langhook_builtin_function (tree decl)
> > > {
> > > + if (TREE_CODE (decl) == FUNCTION_DECL)
> > > + {
> > > + const char* name = IDENTIFIER_POINTER (DECL_NAME (decl));
> > > + target_builtins.put (name, decl);
> > > +
> > > + std::string string_name (name);
> > > + if (target_function_types.count (string_name) == 0)
> > > + {
> > > + tree function_type = TREE_TYPE (decl);
> > > + tree arg = TYPE_ARG_TYPES (function_type);
> > > + bool is_variadic = false;
> > > +
> > > + auto_vec <recording::type *> param_types;
> > > +
> > > + while (arg != void_list_node)
> > > + {
> > > + if (arg == NULL)
> > > + {
> > > + is_variadic = true;
> > > + break;
> > > + }
> > > + if (arg != void_list_node)
> > > + {
> > > + recording::type* arg_type = tree_type_to_jit_type
> > > (TREE_VALUE (arg));
> > > + if (arg_type == NULL)
> > > + return decl;
> > > + param_types.safe_push (arg_type);
> > > + }
> > > + arg = TREE_CHAIN (arg);
> > > + }
> > > +
> > > + tree result_type = TREE_TYPE (function_type);
> > > + recording::type* return_type = tree_type_to_jit_type
> > > (result_type);
> > > +
> > > + if (return_type == NULL)
> > > + return decl;
> > > +
> > > + recording::function_type* func_type =
> > > + new recording::function_type (&target_builtins_ctxt,
> > > return_type,
> > > + param_types.length (),
> > > + param_types.address (),
> > > is_variadic,
> > > + false);
> > > +
> > > + target_function_types[string_name] = func_type;
> > > + }
> > > + }
> > > return decl;
> > > }
> > >
> >
> > [...snip...]
> >
> > > diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
> > > index 18cc4da25b8..d71ee2b61a7 100644
> > > --- a/gcc/jit/jit-playback.cc
> > > +++ b/gcc/jit/jit-playback.cc
> > > @@ -509,7 +509,8 @@ new_function (location *loc,
> > > const char *name,
> > > const auto_vec<param *> *params,
> > > int is_variadic,
> > > - enum built_in_function builtin_id)
> > > + enum built_in_function builtin_id,
> > > + int is_target_builtin)
> > > {
> > > int i;
> > > param *param;
> > > @@ -543,6 +544,14 @@ new_function (location *loc,
> > > DECL_RESULT (fndecl) = resdecl;
> > > DECL_CONTEXT (resdecl) = fndecl;
> > >
> > > + if (is_target_builtin)
> > > + {
> > > + tree *decl = target_builtins.get (name);
> > > + if (decl != NULL)
> > > + fndecl = *decl;
> > > + else
> > > + add_error (loc, "cannot find target builtin %s", name);
> > > + }
> >
> > It looks like is_target_builtin is only ever used as a flag, so for
> > clarity's sake, can it and the various m_is_target_builtin be a
> > bool
> > rather than an int?
>
> Done.
>
> >
> >
> > > if (builtin_id)
> > > {
> > > gcc_assert (loc == NULL);
> > > diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
> > > index f9e29d0baec..06128b4d640 100644
> > > --- a/gcc/jit/jit-playback.h
> > > +++ b/gcc/jit/jit-playback.h
> > > @@ -104,7 +104,8 @@ public:
> > > const char *name,
> > > const auto_vec<param *> *params,
> > > int is_variadic,
> > > - enum built_in_function builtin_id);
> > > + enum built_in_function builtin_id,
> > > + int is_target_builtin);
> > >
> > > lvalue *
> > > new_global (location *loc,
> > > @@ -818,4 +819,6 @@ extern playback::context
> > > *active_playback_ctxt;
> > >
> > > } // namespace gcc
> > >
> > > +extern hash_map<nofree_string_hash, tree> target_builtins;
> > > +
> > > #endif /* JIT_PLAYBACK_H */
> >
> > [...snip...]
> >
> > Assuming that the i386 maintainers are OK with the change to i386-
> > builtins.cc, this is OK for trunk if you fix the various nitpicks I
> > mention above (and you'll probably need to do the usual refreshing
> > of
> > the ABI version)
> >
> > On Thu, 2023-11-23 at 17:21 -0500, Antoni Boucher wrote:
> > > I will need to not forget to update the function
> > > tree_type_to_jit_type
> > > in dummy-frontend.cc to add back the support for bfloat16 when
> > > the
> > > patch for it is merged.
> >
> > Adding this here as a reminder.
>
> Done as well.
>
> >
> > Thanks again for the patch.
> > Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-19 16:14 ` David Malcolm
@ 2024-11-19 20:45 ` Mark Wielaard
2024-11-20 16:11 ` Antoni Boucher
2024-11-20 16:15 ` David Malcolm
0 siblings, 2 replies; 21+ messages in thread
From: Mark Wielaard @ 2024-11-19 20:45 UTC (permalink / raw)
To: David Malcolm
Cc: Antoni Boucher, Andrew Pinski, Jan Hubicka, Uros Bizjak, jit,
gcc-patches, Jose E. Marchesi
Hi,
Random request...
On Tue, Nov 19, 2024 at 11:14:38AM -0500, David Malcolm wrote:
> > Here's the updated patch and answers below.
> >
> > (GitHub link if you find it easier for review:
> > https://github.com/antoyo/libgccjit/pull/5)
> >
> > Thanks.
>
> Thanks; I looked over the patch via the above link and it looks good to
> me for trunk.
Since we now have an experimental forge at https://forge.sourceware.org
would it be an idea to use that for such reviews?
We would love to get feedback on the forge idea (but ideally one based
on Free Software and under community control).
See for some more background:
https://gcc.gnu.org/wiki/ForgeExperiment
You could sign up with your gcc ids (antoyo@gcc... or dmalcolm@gcc...).
Please sent requests for help, feedback (good or bad) to the forge
mailinglist: https://sourceware.org/mailman/listinfo/forge (You don't
need to subscribe unless you want to be part of the forge community.)
Thanks,
Mark
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-19 20:45 ` Mark Wielaard
@ 2024-11-20 16:11 ` Antoni Boucher
2024-11-20 22:35 ` Mark Wielaard
2024-11-20 16:15 ` David Malcolm
1 sibling, 1 reply; 21+ messages in thread
From: Antoni Boucher @ 2024-11-20 16:11 UTC (permalink / raw)
To: Mark Wielaard, David Malcolm
Cc: Andrew Pinski, Jan Hubicka, Uros Bizjak, jit, gcc-patches,
Jose E. Marchesi
Hi Mark.
I've been following this forge experiment with great interest; thanks
for doing this.
I first created this GitHub repo as a way to keep track of the different
status of my patches.
From what I understand, pull requests on forge.sourceware.org can be
removed at any time, so I could lose track of the status of my patches.
I really like forgejo and use it for some of my personal projects. If
you still think there would be benefit in me sending patches to
forge.sourceware.org, please tell me and I'll try.
Regards.
Le 2024-11-19 à 15 h 45, Mark Wielaard a écrit :
> Hi,
>
> Random request...
>
> On Tue, Nov 19, 2024 at 11:14:38AM -0500, David Malcolm wrote:
>>> Here's the updated patch and answers below.
>>>
>>> (GitHub link if you find it easier for review:
>>> https://github.com/antoyo/libgccjit/pull/5)
>>>
>>> Thanks.
>>
>> Thanks; I looked over the patch via the above link and it looks good to
>> me for trunk.
>
> Since we now have an experimental forge at https://forge.sourceware.org
> would it be an idea to use that for such reviews?
>
> We would love to get feedback on the forge idea (but ideally one based
> on Free Software and under community control).
>
> See for some more background:
> https://gcc.gnu.org/wiki/ForgeExperiment
>
> You could sign up with your gcc ids (antoyo@gcc... or dmalcolm@gcc...).
>
> Please sent requests for help, feedback (good or bad) to the forge
> mailinglist: https://sourceware.org/mailman/listinfo/forge (You don't
> need to subscribe unless you want to be part of the forge community.)
>
> Thanks,
>
> Mark
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-19 20:45 ` Mark Wielaard
2024-11-20 16:11 ` Antoni Boucher
@ 2024-11-20 16:15 ` David Malcolm
1 sibling, 0 replies; 21+ messages in thread
From: David Malcolm @ 2024-11-20 16:15 UTC (permalink / raw)
To: Mark Wielaard
Cc: Antoni Boucher, Andrew Pinski, Jan Hubicka, Uros Bizjak, jit,
gcc-patches, Jose E. Marchesi
On Tue, 2024-11-19 at 21:45 +0100, Mark Wielaard wrote:
> Hi,
>
> Random request...
>
> On Tue, Nov 19, 2024 at 11:14:38AM -0500, David Malcolm wrote:
> > > Here's the updated patch and answers below.
> > >
> > > (GitHub link if you find it easier for review:
> > > https://github.com/antoyo/libgccjit/pull/5)
> > >
> > > Thanks.
> >
> > Thanks; I looked over the patch via the above link and it looks
> > good to
> > me for trunk.
>
> Since we now have an experimental forge at
> https://forge.sourceware.org
> would it be an idea to use that for such reviews?
>
> We would love to get feedback on the forge idea (but ideally one
> based
> on Free Software and under community control).
>
> See for some more background:
> https://gcc.gnu.org/wiki/ForgeExperiment
>
> You could sign up with your gcc ids (antoyo@gcc... or
> dmalcolm@gcc...).
>
> Please sent requests for help, feedback (good or bad) to the forge
> mailinglist: https://sourceware.org/mailman/listinfo/forge (You don't
> need to subscribe unless you want to be part of the forge community.)
Thanks Mark.
I'm finding it a *lot* easier to manage patch reviews using github
rather than mailing list threads: specifically: the github web UI has:
(a) convenient metadata tags that make it clear "who has the ball" for
each patch, integrated with:
(b) really nice UX for viewing and commenting on patches
which the mailing-list plus patchwork approach is far inferior to IMHO.
I hope the forge instance has similar capabilities for both (a) and
(b).
One downside of the https://github.com/antoyo/libgccjit/pull workflow
for (a) is that I can't edit the labels when I review things (though
maybe Antoni can give me access to that?)
...but yeah, it's not ideal to be using a closed source site for this.
That said, Antoni and I have things split between two places already:
the mailing lists and his github. I'd be up for doing it in the forge
instance instead, but arguably we'd then be splitting things into
*three* places... gahhh!!!!
AIUI Antoni is already using github for interacting with the rustc
project, so it might be considerably easier for him to stick to github;
I'm feeling guilty about my crappiness at patch review so I feel I
don't have much of a moral high ground here to push for a non-
proprietary tool.
Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-20 16:11 ` Antoni Boucher
@ 2024-11-20 22:35 ` Mark Wielaard
2024-11-29 14:12 ` Antoni Boucher
0 siblings, 1 reply; 21+ messages in thread
From: Mark Wielaard @ 2024-11-20 22:35 UTC (permalink / raw)
To: Antoni Boucher
Cc: David Malcolm, Andrew Pinski, Jan Hubicka, Uros Bizjak, jit,
gcc-patches, Jose E. Marchesi
Hi Antoni,
On Wed, Nov 20, 2024 at 11:11:01AM -0500, Antoni Boucher wrote:
> From what I understand, pull requests on forge.sourceware.org can be
> removed at any time, so I could lose track of the status of my
> patches.
It is an experiment, and the experiment could fail for various
reasons. At that point we could decide to just throw everything
away. But we wouldn't do that randomly and I think people are willing
to let the experiment run for at least a year before deciding it does
or doesn't work. And we would of course give people the chance to
migrate the work they want to preserve somewhere else (forgejo has
good import/export to various other forges).
We could also decide the current setup is not good (and admittedly the
-mirror/-test thing is a little odd) and change those names and/or
resetup those repos.
But interestingly it seems that wouldn't impact your workflow. Which I
hadn't even thought was possible. But I just tried on our forgejo
setup and of course it works. You can do pull request to your own fork
from one branch to another.
Seeing this already thought me something I didn't know was possible or
useful. But I can totally see now how these "self pull requests" help
someone keep track of their work.
> I really like forgejo and use it for some of my personal projects.
> If you still think there would be benefit in me sending patches to
> forge.sourceware.org, please tell me and I'll try.
If another developer/maintainer like David is happy to try what you
already have been doing through github I think it would be
useful. Even if it doesn't work out for you that would be very
valuable feedback.
I do have to note that there are people a little nervous about reviews
completely "bypassing" the mailinglists. But that would be even more a
concern with using github for this.
Cheers,
Mark
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH] libgccjit: Add support for machine-dependent builtins
2024-11-20 22:35 ` Mark Wielaard
@ 2024-11-29 14:12 ` Antoni Boucher
0 siblings, 0 replies; 21+ messages in thread
From: Antoni Boucher @ 2024-11-29 14:12 UTC (permalink / raw)
To: Mark Wielaard
Cc: David Malcolm, Andrew Pinski, Jan Hubicka, Uros Bizjak, jit,
gcc-patches, Jose E. Marchesi
Oh, nice.
I'll send my future patches on the forgejo instance, then.
Le 2024-11-20 à 17 h 35, Mark Wielaard a écrit :
> Hi Antoni,
>
> On Wed, Nov 20, 2024 at 11:11:01AM -0500, Antoni Boucher wrote:
>> From what I understand, pull requests on forge.sourceware.org can be
>> removed at any time, so I could lose track of the status of my
>> patches.
>
> It is an experiment, and the experiment could fail for various
> reasons. At that point we could decide to just throw everything
> away. But we wouldn't do that randomly and I think people are willing
> to let the experiment run for at least a year before deciding it does
> or doesn't work. And we would of course give people the chance to
> migrate the work they want to preserve somewhere else (forgejo has
> good import/export to various other forges).
>
> We could also decide the current setup is not good (and admittedly the
> -mirror/-test thing is a little odd) and change those names and/or
> resetup those repos.
>
> But interestingly it seems that wouldn't impact your workflow. Which I
> hadn't even thought was possible. But I just tried on our forgejo
> setup and of course it works. You can do pull request to your own fork
> from one branch to another.
>
> Seeing this already thought me something I didn't know was possible or
> useful. But I can totally see now how these "self pull requests" help
> someone keep track of their work.
>
>> I really like forgejo and use it for some of my personal projects.
>> If you still think there would be benefit in me sending patches to
>> forge.sourceware.org, please tell me and I'll try.
>
> If another developer/maintainer like David is happy to try what you
> already have been doing through github I think it would be
> useful. Even if it doesn't work out for you that would be very
> valuable feedback.
>
> I do have to note that there are people a little nervous about reviews
> completely "bypassing" the mailinglists. But that would be even more a
> concern with using github for this.
>
> Cheers,
>
> Mark
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2024-11-29 14:13 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-12 0:30 [PATCH] libgccjit: Add support for machine-dependent builtins Antoni Boucher
2023-02-12 0:32 ` Antoni Boucher
2023-02-12 1:37 ` Andrew Pinski
2023-11-23 22:17 ` Antoni Boucher
2023-11-23 22:21 ` Antoni Boucher
2024-06-26 22:49 ` David Malcolm
2024-06-27 16:35 ` Uros Bizjak
2024-11-14 20:27 ` Antoni Boucher
2024-11-19 16:14 ` David Malcolm
2024-11-19 20:45 ` Mark Wielaard
2024-11-20 16:11 ` Antoni Boucher
2024-11-20 22:35 ` Mark Wielaard
2024-11-29 14:12 ` Antoni Boucher
2024-11-20 16:15 ` David Malcolm
2024-01-10 23:29 ` Antoni Boucher
2024-01-10 23:44 ` David Malcolm
2024-01-10 23:58 ` Antoni Boucher
2024-02-08 13:59 ` Antoni Boucher
2024-02-15 14:32 ` Antoni Boucher
2024-02-29 15:34 ` Antoni Boucher
2024-04-19 12:35 ` Antoni Boucher
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).