After more investigations, it seems like the fault was on our side as we were calling `gcc_jit_type_get_restrict` on types that weren't pointers. I added a check for that in `gcc_jit_type_get_restrict` directly as well.
We will continue our investigation to be sure we didn't miss anything. Le mar. 22 août 2023 à 17:26, Antoni Boucher <boua...@zoho.com> a écrit : > > Since the tests in the PR for rustc_codegen_gcc > (https://github.com/rust-lang/rustc_codegen_gcc/pull/312) currently > fails, let's wait a bit before merging the patch, in case it would need > some fixes. > > On Thu, 2023-08-17 at 20:09 +0200, Guillaume Gomez via Jit wrote: > > Quick question: do you plan to make the merge or should I ask Antoni? > > > > Le jeu. 17 août 2023 à 17:59, Guillaume Gomez > > <guillaume1.go...@gmail.com> > > a écrit : > > > > > Thanks for the review! > > > > > > Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalc...@redhat.com> a > > > écrit > > > : > > > > > > > > On Thu, 2023-08-17 at 17:41 +0200, Guillaume Gomez wrote: > > > > > And now I just discovered that a lot of commits from Antoni's > > > > > fork > > > > > haven't been sent upstream which is why the ABI count is so > > > > > high in > > > > > his repository. Fixed that as well. > > > > > > > > Thanks for the updated patch; I was about to comment on that. > > > > > > > > This version is good for gcc trunk. > > > > > > > > Dave > > > > > > > > > > > > > > Le jeu. 17 août 2023 à 17:26, Guillaume Gomez > > > > > <guillaume1.go...@gmail.com> a écrit : > > > > > > > > > > > > Antoni spot a typo I made: > > > > > > > > > > > > I added `LIBGCCJIT_HAVE_gcc_jit_type_get_size` instead of > > > > > > `LIBGCCJIT_HAVE_gcc_jit_type_get_restrict`. Fixed in this > > > > > > patch, > > > > > > sorry > > > > > > for the noise. > > > > > > > > > > > > Le jeu. 17 août 2023 à 11:30, Guillaume Gomez > > > > > > <guillaume1.go...@gmail.com> a écrit : > > > > > > > > > > > > > > Hi Dave, > > > > > > > > > > > > > > > What kind of testing has the patch had? (e.g. did you run > > > > > > > > "make > > > > > > > > check- > > > > > > > > jit" ? Has this been in use on real Rust code?) > > > > > > > > > > > > > > I tested it as Rust backend directly on this code: > > > > > > > > > > > > > > ``` > > > > > > > pub fn foo(a: &mut i32, b: &mut i32, c: &i32) { > > > > > > > *a += *c; > > > > > > > *b += *c; > > > > > > > } > > > > > > > ``` > > > > > > > > > > > > > > I ran it with `rustc` (and the GCC backend) with the > > > > > > > following > > > > > > > flags: > > > > > > > `-C link-args=-lc --emit=asm -O --crate-type=lib` which > > > > > > > gave the > > > > > > > diff > > > > > > > you can see in the attached file. Explanations: the diff on > > > > > > > the > > > > > > > right > > > > > > > has the `__restrict__` attribute used whereas on the left > > > > > > > it is > > > > > > > the > > > > > > > current version where we don't handle it. > > > > > > > > > > > > > > As for C testing, I used this code: > > > > > > > > > > > > > > ``` > > > > > > > void t(int *__restrict__ a, int *__restrict__ b, char > > > > > > > *__restrict__ c) { > > > > > > > *a += *c; > > > > > > > *b += *c; > > > > > > > } > > > > > > > ``` > > > > > > > > > > > > > > (without the `__restrict__` of course when I need to have a > > > > > > > witness > > > > > > > ASM). I attached the diff as well, this time the file with > > > > > > > the > > > > > > > use of > > > > > > > `__restrict__` in on the left. I compiled with the > > > > > > > following > > > > > > > flags: > > > > > > > `-S -O3`. > > > > > > > > > > > > > > > Please add a feature macro: > > > > > > > > #define LIBGCCJIT_HAVE_gcc_jit_type_get_restrict > > > > > > > > (see the similar ones in the header). > > > > > > > > > > > > > > I added `LIBGCCJIT_HAVE_gcc_jit_type_get_size` and extended > > > > > > > the > > > > > > > documentation as well to mention the ABI change. > > > > > > > > > > > > > > > Please add a new ABI tag (LIBGCCJIT_ABI_25 ?), rather > > > > > > > > than > > > > > > > > adding this > > > > > > > > to ABI_0. > > > > > > > > > > > > > > I added `LIBGCCJIT_ABI_34` as `LIBGCCJIT_ABI_33` was the > > > > > > > last > > > > > > > one. > > > > > > > > > > > > > > > This refers to a "cold attribute"; is this a vestige of a > > > > > > > > copy- > > > > > > > > and- > > > > > > > > paste from a different test case? > > > > > > > > > > > > > > It is a vestige indeed... Missed this one. > > > > > > > > > > > > > > > I see that the test scans the generated assembler. Does > > > > > > > > the > > > > > > > > test > > > > > > > > actually verify that restrict has an effect, or was that > > > > > > > > another > > > > > > > > vestige from a different test case? > > > > > > > > > > > > > > No, this time it's what I wanted. Please see the C diff I > > > > > > > provided > > > > > > > above to see that the ASM has a small diff that allowed me > > > > > > > to > > > > > > > confirm > > > > > > > that the `__restrict__` attribute was correctly set. > > > > > > > > > > > > > > > If this test is meant to run at -O3 and thus can't be > > > > > > > > part of > > > > > > > > test- > > > > > > > > combination.c, please add a comment about it to > > > > > > > > gcc/testsuite/jit.dg/all-non-failing-tests.h (in the > > > > > > > > alphabetical > > > > > > > > place). > > > > > > > > > > > > > > Below `-O3`, this ASM difference doesn't appear > > > > > > > unfortunately. > > > > > > > > > > > > > > > The patch also needs to add documentation for the new > > > > > > > > entrypoint (in > > > > > > > > topics/types.rst), and for the new ABI tag (in > > > > > > > > topics/compatibility.rst). > > > > > > > > > > > > > > Added! > > > > > > > > > > > > > > > Thanks again for the patch; hope the above is > > > > > > > > constructive > > > > > > > > > > > > > > It was incredibly useful! Thanks for taking time to writing > > > > > > > down > > > > > > > the > > > > > > > explanations. > > > > > > > > > > > > > > The new patch is attached to this email. > > > > > > > > > > > > > > Cordially. > > > > > > > > > > > > > > Le jeu. 17 août 2023 à 01:06, David Malcolm > > > > > > > <dmalc...@redhat.com> > > > > > > > a écrit : > > > > > > > > > > > > > > > > On Wed, 2023-08-16 at 22:06 +0200, Guillaume Gomez via > > > > > > > > Jit > > > > > > > > wrote: > > > > > > > > > My apologies, forgot to run the commit checkers. Here's > > > > > > > > > the > > > > > > > > > commit > > > > > > > > > with the errors fixed. > > > > > > > > > > > > > > > > > > Le mer. 16 août 2023 à 18:32, Guillaume Gomez > > > > > > > > > <guillaume1.go...@gmail.com> a écrit : > > > > > > > > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > > > Hi Guillaume, thanks for the patch. > > > > > > > > > > > > > > > > > > > > > > > > > > > > This patch adds the possibility to specify the > > > > > > > > > > __restrict__ > > > > > > > > > > attribute > > > > > > > > > > for function parameters. It is used by the Rust GCC > > > > > > > > > > backend. > > > > > > > > > > > > > > > > What kind of testing has the patch had? (e.g. did you run > > > > > > > > "make > > > > > > > > check- > > > > > > > > jit" ? Has this been in use on real Rust code?) > > > > > > > > > > > > > > > > Overall, this patch looks close to being ready, but some > > > > > > > > nits > > > > > > > > below... > > > > > > > > > > > > > > > > [...] > > > > > > > > > > > > > > > > > diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h > > > > > > > > > index 60eaf39bff6..2e0d08a06d8 100644 > > > > > > > > > --- a/gcc/jit/libgccjit.h > > > > > > > > > +++ b/gcc/jit/libgccjit.h > > > > > > > > > @@ -635,6 +635,10 @@ gcc_jit_type_get_const > > > > > > > > > (gcc_jit_type > > > > > > > > > *type); > > > > > > > > > extern gcc_jit_type * > > > > > > > > > gcc_jit_type_get_volatile (gcc_jit_type *type); > > > > > > > > > > > > > > > > > > +/* Given type "T", get type "restrict T". */ > > > > > > > > > +extern gcc_jit_type * > > > > > > > > > +gcc_jit_type_get_restrict (gcc_jit_type *type); > > > > > > > > > + > > > > > > > > > #define LIBGCCJIT_HAVE_SIZED_INTEGERS > > > > > > > > > > > > > > > > > > /* Given types LTYPE and RTYPE, return non-zero if > > > > > > > > > they are > > > > > > > > compatible. > > > > > > > > > > > > > > > > Please add a feature macro: > > > > > > > > #define LIBGCCJIT_HAVE_gcc_jit_type_get_restrict > > > > > > > > (see the similar ones in the header). > > > > > > > > > > > > > > > > > diff --git a/gcc/jit/libgccjit.map > > > > > > > > > b/gcc/jit/libgccjit.map > > > > > > > > > index e52de0057a5..b7289b13845 100644 > > > > > > > > > --- a/gcc/jit/libgccjit.map > > > > > > > > > +++ b/gcc/jit/libgccjit.map > > > > > > > > > @@ -104,6 +104,7 @@ LIBGCCJIT_ABI_0 > > > > > > > > > gcc_jit_type_as_object; > > > > > > > > > gcc_jit_type_get_const; > > > > > > > > > gcc_jit_type_get_pointer; > > > > > > > > > + gcc_jit_type_get_restrict; > > > > > > > > > gcc_jit_type_get_volatile; > > > > > > > > > > > > > > > > Please add a new ABI tag (LIBGCCJIT_ABI_25 ?), rather > > > > > > > > than > > > > > > > > adding this > > > > > > > > to ABI_0. > > > > > > > > > > > > > > > > > diff --git a/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > b/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > > new file mode 100644 > > > > > > > > > index 00000000000..4c8c4407f91 > > > > > > > > > --- /dev/null > > > > > > > > > +++ b/gcc/testsuite/jit.dg/test-restrict.c > > > > > > > > > @@ -0,0 +1,77 @@ > > > > > > > > > +/* { dg-do compile { target x86_64-*-* } } */ > > > > > > > > > + > > > > > > > > > +#include <stdlib.h> > > > > > > > > > +#include <stdio.h> > > > > > > > > > + > > > > > > > > > +#include "libgccjit.h" > > > > > > > > > + > > > > > > > > > +/* We don't want set_options() in harness.h to set -O3 > > > > > > > > > to > > > > > > > > > see that > > > > > > > > the cold > > > > > > > > > + attribute affects the optimizations. */ > > > > > > > > > > > > > > > > This refers to a "cold attribute"; is this a vestige of a > > > > > > > > copy- > > > > > > > > and- > > > > > > > > paste from a different test case? > > > > > > > > > > > > > > > > I see that the test scans the generated assembler. Does > > > > > > > > the > > > > > > > > test > > > > > > > > actually verify that restrict has an effect, or was that > > > > > > > > another > > > > > > > > vestige from a different test case? > > > > > > > > > > > > > > > > > +#define TEST_ESCHEWS_SET_OPTIONS > > > > > > > > > +static void set_options (gcc_jit_context *ctxt, const > > > > > > > > > char > > > > > > > > > *argv0) > > > > > > > > > +{ > > > > > > > > > + // Set "-O3". > > > > > > > > > + gcc_jit_context_set_int_option(ctxt, > > > > > > > > GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); > > > > > > > > > +} > > > > > > > > > + > > > > > > > > > +#define TEST_COMPILING_TO_FILE > > > > > > > > > +#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER > > > > > > > > > +#define OUTPUT_FILENAME "output-of-test-restrict.c.s" > > > > > > > > > +#include "harness.h" > > > > > > > > > + > > > > > > > > > +void > > > > > > > > > +create_code (gcc_jit_context *ctxt, void *user_data) > > > > > > > > > +{ > > > > > > > > > + /* Let's try to inject the equivalent of: > > > > > > > > > +void t(int *__restrict__ a, int *__restrict__ b, char > > > > > > > > > *__restrict__ > > > > > > > > c) { > > > > > > > > > + *a += *c; > > > > > > > > > + *b += *c; > > > > > > > > > +} > > > > > > > > > + */ > > > > > > > > > + gcc_jit_type *int_type = > > > > > > > > > + gcc_jit_context_get_type (ctxt, > > > > > > > > > GCC_JIT_TYPE_INT); > > > > > > > > > + gcc_jit_type *pint_type = > > > > > > > > > gcc_jit_type_get_pointer(int_type); > > > > > > > > > + gcc_jit_type *pint_restrict_type = > > > > > > > > gcc_jit_type_get_restrict(pint_type); > > > > > > > > > + > > > > > > > > > + gcc_jit_type *void_type = > > > > > > > > > + gcc_jit_context_get_type (ctxt, > > > > > > > > > GCC_JIT_TYPE_VOID); > > > > > > > > > + > > > > > > > > > + gcc_jit_param *a = > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > pint_restrict_type, "a"); > > > > > > > > > + gcc_jit_param *b = > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > pint_restrict_type, "b"); > > > > > > > > > + gcc_jit_param *c = > > > > > > > > > + gcc_jit_context_new_param (ctxt, NULL, > > > > > > > > pint_restrict_type, "c"); > > > > > > > > > + gcc_jit_param *params[3] = {a, b, c}; > > > > > > > > > + > > > > > > > > > + gcc_jit_function *func_t = > > > > > > > > > + gcc_jit_context_new_function (ctxt, NULL, > > > > > > > > > + > > > > > > > > > GCC_JIT_FUNCTION_EXPORTED, > > > > > > > > > + void_type, > > > > > > > > > + "t", > > > > > > > > > + 3, params, > > > > > > > > > + 0); > > > > > > > > > + > > > > > > > > > + gcc_jit_block *block = gcc_jit_function_new_block > > > > > > > > > (func_t, > > > > > > > > NULL); > > > > > > > > > + > > > > > > > > > + /* *a += *c; */ > > > > > > > > > + gcc_jit_block_add_assignment_op ( > > > > > > > > > + block, NULL, > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > (gcc_jit_param_as_rvalue > > > > > > > > (a), NULL), > > > > > > > > > + GCC_JIT_BINARY_OP_PLUS, > > > > > > > > > + gcc_jit_lvalue_as_rvalue ( > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > (gcc_jit_param_as_rvalue (c), NULL))); > > > > > > > > > + /* *b += *c; */ > > > > > > > > > + gcc_jit_block_add_assignment_op ( > > > > > > > > > + block, NULL, > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > > (gcc_jit_param_as_rvalue > > > > > > > > (b), NULL), > > > > > > > > > + GCC_JIT_BINARY_OP_PLUS, > > > > > > > > > + gcc_jit_lvalue_as_rvalue ( > > > > > > > > > + gcc_jit_rvalue_dereference > > > > > > > > (gcc_jit_param_as_rvalue (c), NULL))); > > > > > > > > > + > > > > > > > > > + gcc_jit_block_end_with_void_return (block, NULL); > > > > > > > > > +} > > > > > > > > > + > > > > > > > > > +/* { dg-final { jit-verify-output-file-was-created "" > > > > > > > > > } } */ > > > > > > > > > +/* { dg-final { jit-verify-assembler-output "addl > > > > > > > > > %eax, > > > > > > > > > (%rdi) > > > > > > > > > + addl %eax, (%rsi)" } } */ > > > > > > > > > -- > > > > > > > > > 2.34.1 > > > > > > > > > > > > > > > > > > > > > > > > > If this test is meant to run at -O3 and thus can't be > > > > > > > > part of > > > > > > > > test- > > > > > > > > combination.c, please add a comment about it to > > > > > > > > gcc/testsuite/jit.dg/all-non-failing-tests.h (in the > > > > > > > > alphabetical > > > > > > > > place). > > > > > > > > > > > > > > > > The patch also needs to add documentation for the new > > > > > > > > entrypoint (in > > > > > > > > topics/types.rst), and for the new ABI tag (in > > > > > > > > topics/compatibility.rst). > > > > > > > > > > > > > > > > > > > > > > > > Thanks again for the patch; hope the above is > > > > > > > > constructive > > > > > > > > Dave > > > > > > > > > > > > > > > >
From dcdcfdcb9d817ff59c6e1f448bc4e639049ed893 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.go...@gmail.com> Date: Fri, 11 Aug 2023 22:48:11 +0200 Subject: [PATCH] [PATCH] Add support for `restrict` attribute on function parameters gcc/jit/Changelog: * jit-playback.cc: Remove trailing whitespace characters. * jit-playback.h: Add get_restrict method. * jit-recording.cc: Add get_restrict methods. * jit-recording.h: Add get_restrict methods. * libgccjit++.h: Add get_restrict methods. * libgccjit.cc: Add gcc_jit_type_get_restrict. * libgccjit.h: Declare gcc_jit_type_get_restrict. * libgccjit.map: Declare gcc_jit_type_get_restrict. gcc/testsuite/ChangeLog: * jit.dg/test-restrict.c: Add test for __restrict__ attribute. * jit.dg/all-non-failing-tests.h: Add test-restrict.c to the list. gcc/jit/ChangeLog: * docs/topics/compatibility.rst: Add documentation for LIBGCCJIT_ABI_25. * docs/topics/types.rst: Add documentation for gcc_jit_type_get_restrict. Signed-off-by: Guillaume Gomez <guillaume1.go...@gmail.com> --- gcc/jit/docs/topics/compatibility.rst | 7 ++ gcc/jit/docs/topics/types.rst | 12 +++ gcc/jit/jit-playback.cc | 2 +- gcc/jit/jit-playback.h | 5 ++ gcc/jit/jit-recording.cc | 47 ++++++++++++ gcc/jit/jit-recording.h | 30 +++++++- gcc/jit/libgccjit++.h | 6 ++ gcc/jit/libgccjit.cc | 15 ++++ gcc/jit/libgccjit.h | 9 +++ gcc/jit/libgccjit.map | 5 ++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 3 + gcc/testsuite/jit.dg/test-restrict.c | 77 ++++++++++++++++++++ 12 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-restrict.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index f4ffa07ec48..ebede440ee4 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -371,3 +371,10 @@ 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 +:func:`gcc_jit_type_get_restrict` diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index f5f2aac1f0c..d8c1d15d69d 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -541,3 +541,15 @@ Reflection API .. code-block:: c #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS + +.. function:: gcc_jit_type *\ + gcc_jit_type_get_restrict (gcc_jit_type *type) + + Given type "T", get type "restrict T". + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_25`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_restrict diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index e06f161aad9..9b757382f7a 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -3393,7 +3393,7 @@ if (t) \ NAME_TYPE (complex_float_type_node, "complex float"); NAME_TYPE (complex_double_type_node, "complex double"); NAME_TYPE (complex_long_double_type_node, "complex long double"); - + m_const_char_ptr = build_pointer_type( build_qualified_type (char_type_node, TYPE_QUAL_CONST)); diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 883159f03c3..438f395f6d9 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -446,6 +446,11 @@ public: return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE)); } + type *get_restrict () const + { + return new type (build_qualified_type (m_inner, TYPE_QUAL_RESTRICT)); + } + type *get_aligned (size_t alignment_in_bytes) const; type *get_vector (size_t num_units) const; diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index df0368ff8f7..326c8c2809f 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -2267,6 +2267,19 @@ recording::type::get_const () return result; } +/* Given a type T, get the type restrict T. + + Implements the post-error-checking part of + gcc_jit_type_get_restrict. */ + +recording::type * +recording::type::get_restrict () +{ + recording::type *result = new memento_of_get_restrict (this); + m_ctxt->record (result); + return result; +} + /* Given a type T, get the type volatile T. Implements the post-error-checking part of @@ -2960,6 +2973,40 @@ recording::memento_of_get_volatile::write_reproducer (reproducer &r) r.get_identifier_as_type (m_other_type)); } +/* The implementation of class gcc::jit::recording::memento_of_get_restrict. */ + +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::memento_of_get_restrict. */ + +void +recording::memento_of_get_restrict::replay_into (replayer *) +{ + set_playback_obj (m_other_type->playback_type ()->get_restrict ()); +} + +/* Implementation of recording::memento::make_debug_string for + results of get_restrict, prepending "restrict ". */ + +recording::string * +recording::memento_of_get_restrict::make_debug_string () +{ + return string::from_printf (m_ctxt, + "restrict %s", m_other_type->get_debug_string ()); +} + +/* Implementation of recording::memento::write_reproducer for restrict + types. */ + +void +recording::memento_of_get_restrict::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s =\n" + " gcc_jit_type_get_restrict (%s);\n", + id, + r.get_identifier_as_type (m_other_type)); +} + /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */ /* Implementation of pure virtual hook recording::memento::replay_into diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 400cf345600..4a8082991fb 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -524,6 +524,7 @@ public: type *get_pointer (); type *get_const (); type *get_volatile (); + type *get_restrict (); type *get_aligned (size_t alignment_in_bytes); type *get_vector (size_t num_units); @@ -568,6 +569,7 @@ public: virtual bool is_bool () const = 0; virtual type *is_pointer () = 0; virtual type *is_volatile () { return NULL; } + virtual type *is_restrict () { return NULL; } virtual type *is_const () { return NULL; } virtual type *is_array () = 0; virtual struct_ *is_struct () { return NULL; } @@ -686,7 +688,7 @@ private: }; /* A decorated version of a type, for get_const, get_volatile, - get_aligned, and get_vector. */ + get_aligned, get_restrict, and get_vector. */ class decorated_type : public type { @@ -769,6 +771,32 @@ private: void write_reproducer (reproducer &r) final override; }; +/* Result of "gcc_jit_type_get_restrict". */ +class memento_of_get_restrict : public decorated_type +{ +public: + memento_of_get_restrict (type *other_type) + : decorated_type (other_type) {} + + bool is_same_type_as (type *other) final override + { + if (!other->is_restrict ()) + return false; + return m_other_type->is_same_type_as (other->is_restrict ()); + } + + /* Strip off the "restrict", giving the underlying type. */ + type *unqualified () final override { return m_other_type; } + + type *is_restrict () final override { return m_other_type; } + + void replay_into (replayer *) final override; + +private: + string * make_debug_string () final override; + void write_reproducer (reproducer &r) final override; +}; + /* Result of "gcc_jit_type_get_aligned". */ class memento_of_get_aligned : public decorated_type { diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index df07889be89..4a04db386e6 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -1410,6 +1410,12 @@ type::get_const () return type (gcc_jit_type_get_const (get_inner_type ())); } +inline type +type::get_restrict () +{ + return type (gcc_jit_type_get_restrict (get_inner_type ())); +} + inline type type::get_volatile () { diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 2def58f6aa7..0451b4df7f9 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -534,6 +534,21 @@ gcc_jit_type_get_volatile (gcc_jit_type *type) return (gcc_jit_type *)type->get_volatile (); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::get_restrict method, in + jit-recording.cc. */ + +gcc_jit_type * +gcc_jit_type_get_restrict (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + RETURN_NULL_IF_FAIL (type->is_pointer (), NULL, NULL, "not a pointer type"); + + return (gcc_jit_type *)type->get_restrict (); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 057d3e58e73..749f6c24177 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -630,6 +630,15 @@ gcc_jit_type_get_const (gcc_jit_type *type); extern gcc_jit_type * gcc_jit_type_get_volatile (gcc_jit_type *type); +#define LIBGCCJIT_HAVE_gcc_jit_type_get_restrict + +/* Given type "T", get type "restrict T". + This API entrypoint was added in LIBGCCJIT_ABI_25; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_restrict */ +extern gcc_jit_type * +gcc_jit_type_get_restrict (gcc_jit_type *type); + #define LIBGCCJIT_HAVE_SIZED_INTEGERS /* Given types LTYPE and RTYPE, return non-zero if they are compatible. diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 25463b94fe8..8b90a0e2ff3 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -271,3 +271,8 @@ LIBGCCJIT_ABI_24 { gcc_jit_lvalue_set_alignment; gcc_jit_lvalue_get_alignment; } LIBGCCJIT_ABI_23; + +LIBGCCJIT_ABI_25 { + global: + gcc_jit_type_get_restrict; +} 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..e762563f9bd 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -313,6 +313,9 @@ #undef create_code #undef verify_code +/* test-restrict.c: This can't be in the testcases array as it needs + the `-O3` flag. */ + /* test-register-variable.c: This can't be in the testcases array as it is target-specific. */ diff --git a/gcc/testsuite/jit.dg/test-restrict.c b/gcc/testsuite/jit.dg/test-restrict.c new file mode 100644 index 00000000000..a6ac96324d2 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-restrict.c @@ -0,0 +1,77 @@ +/* { dg-do compile { target x86_64-*-* } } */ + +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +/* We don't want set_options() in harness.h to set -O3 to see that the restrict + attribute affects the optimizations. */ +#define TEST_ESCHEWS_SET_OPTIONS +static void set_options (gcc_jit_context *ctxt, const char *argv0) +{ + // Set "-O3". + gcc_jit_context_set_int_option(ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); +} + +#define TEST_COMPILING_TO_FILE +#define OUTPUT_KIND GCC_JIT_OUTPUT_KIND_ASSEMBLER +#define OUTPUT_FILENAME "output-of-test-restrict.c.s" +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: +void t(int *__restrict__ a, int *__restrict__ b, char *__restrict__ c) { + *a += *c; + *b += *c; +} + */ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *pint_type = gcc_jit_type_get_pointer(int_type); + gcc_jit_type *pint_restrict_type = gcc_jit_type_get_restrict(pint_type); + + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + + gcc_jit_param *a = + gcc_jit_context_new_param (ctxt, NULL, pint_restrict_type, "a"); + gcc_jit_param *b = + gcc_jit_context_new_param (ctxt, NULL, pint_restrict_type, "b"); + gcc_jit_param *c = + gcc_jit_context_new_param (ctxt, NULL, pint_restrict_type, "c"); + gcc_jit_param *params[3] = {a, b, c}; + + gcc_jit_function *func_t = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "t", + 3, params, + 0); + + gcc_jit_block *block = gcc_jit_function_new_block (func_t, NULL); + + /* *a += *c; */ + gcc_jit_block_add_assignment_op ( + block, NULL, + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (a), NULL), + GCC_JIT_BINARY_OP_PLUS, + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (c), NULL))); + /* *b += *c; */ + gcc_jit_block_add_assignment_op ( + block, NULL, + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (b), NULL), + GCC_JIT_BINARY_OP_PLUS, + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (c), NULL))); + + gcc_jit_block_end_with_void_return (block, NULL); +} + +/* { dg-final { jit-verify-output-file-was-created "" } } */ +/* { dg-final { jit-verify-assembler-output "addl %eax, (%rdi) + addl %eax, (%rsi)" } } */ -- 2.34.1