diff mbox series

libgccjit: Add support for `restrict` attribute on function parameters

Message ID CAAOQCfS94kca5MUXS=DQaoLqeCsEY57bwo=JVz8wrn2sb4Z=Dg@mail.gmail.com
State New
Headers show
Series libgccjit: Add support for `restrict` attribute on function parameters | expand

Commit Message

Guillaume Gomez Aug. 16, 2023, 4:32 p.m. UTC
Hi,

This patch adds the possibility to specify the __restrict__ attribute
for function parameters. It is used by the Rust GCC backend.

Thanks in advance for the review.

Comments

Guillaume Gomez Aug. 16, 2023, 8:06 p.m. UTC | #1
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.gomez@gmail.com> a écrit :
>
> Hi,
>
> This patch adds the possibility to specify the __restrict__ attribute
> for function parameters. It is used by the Rust GCC backend.
>
> Thanks in advance for the review.
David Malcolm Aug. 16, 2023, 11:06 p.m. UTC | #2
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.gomez@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
Guillaume Gomez Aug. 17, 2023, 9:30 a.m. UTC | #3
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 <dmalcolm@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.gomez@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
>
Guillaume Gomez Aug. 17, 2023, 3:26 p.m. UTC | #4
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.gomez@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 <dmalcolm@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.gomez@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
> >
Guillaume Gomez Aug. 17, 2023, 3:41 p.m. UTC | #5
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.

Le jeu. 17 août 2023 à 17:26, Guillaume Gomez
<guillaume1.gomez@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.gomez@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 <dmalcolm@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.gomez@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
> > >
David Malcolm Aug. 17, 2023, 3:50 p.m. UTC | #6
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.gomez@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.gomez@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 <dmalcolm@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.gomez@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
> > > >
Guillaume Gomez Aug. 17, 2023, 3:59 p.m. UTC | #7
Thanks for the review!

Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalcolm@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.gomez@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.gomez@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 <dmalcolm@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.gomez@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
> > > > >
>
Guillaume Gomez Aug. 17, 2023, 6:09 p.m. UTC | #8
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.gomez@gmail.com>
a écrit :

> Thanks for the review!
>
> Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalcolm@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.gomez@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.gomez@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 <dmalcolm@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.gomez@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
> > > > > >
> >
>
Antoni Boucher Aug. 22, 2023, 3:26 p.m. UTC | #9
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.gomez@gmail.com>
> a écrit :
> 
> > Thanks for the review!
> > 
> > Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalcolm@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.gomez@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.gomez@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
> > > > > > <dmalcolm@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.gomez@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
> > > > > > > 
> > > 
> >
Guillaume Gomez Aug. 25, 2023, 8:47 p.m. UTC | #10
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 <bouanto@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.gomez@gmail.com>
> > a écrit :
> >
> > > Thanks for the review!
> > >
> > > Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalcolm@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.gomez@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.gomez@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
> > > > > > > <dmalcolm@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.gomez@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
> > > > > > > >
> > > >
> > >
>
Guillaume Gomez Aug. 29, 2023, 3:15 p.m. UTC | #11
We finished the investigation and found out the issue: when passing
arguments by value to functions, rustc still provides "NoAlias" as
attribute to the argument whereas it should never be passed in this
case. Luckily for us, in case the argument is a function pointer
coming from a struct field, it crashes GCC, which is what allowed us
to figure out about this. A code which reproduces this bug:

```
use std::mem;

#[repr(C)]
pub struct Buffer {
    data: *mut u8,
    len: usize,
    drop: extern "C" fn(Buffer),
}

impl Default for Buffer {
    #[inline]
    fn default() -> Self {
        Self::from(vec![])
    }
}

impl Buffer {
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }

    #[inline]
    pub fn push(&mut self, v: u8) {}
}

impl From<Vec<u8>> for Buffer {
    fn from(mut v: Vec<u8>) -> Self {
        let (data, len) = (v.as_mut_ptr(), v.len());
        mem::forget(v);

        extern "C" fn drop(b: Buffer) {}

        Buffer { data, len, drop }
    }
}

fn main() {
    let mut buffer = Buffer::new();
}
```

So in short: the patch in the previous mail which added this check:

```
RETURN_NULL_IF_FAIL (type->is_pointer (), NULL, NULL, "not a pointer type");
```

is correct and ready. We fixed the bug on our side in
https://github.com/rust-lang/rustc_codegen_gcc/pull/312.

For more information about the "ByValue" attributes issue, there were
some discussions about it in LLVM:
 * https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20171218/512066.html
 * https://reviews.llvm.org/D40118


Le ven. 25 août 2023 à 22:47, Guillaume Gomez
<guillaume1.gomez@gmail.com> a écrit :
>
> 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 <bouanto@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.gomez@gmail.com>
> > > a écrit :
> > >
> > > > Thanks for the review!
> > > >
> > > > Le jeu. 17 août 2023 à 17:50, David Malcolm <dmalcolm@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.gomez@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.gomez@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
> > > > > > > > <dmalcolm@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.gomez@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
> > > > > > > > >
> > > > >
> > > >
> >
David Malcolm Aug. 29, 2023, 3:34 p.m. UTC | #12
On Tue, 2023-08-29 at 17:15 +0200, Guillaume Gomez wrote:
> We finished the investigation and found out the issue: when passing
> arguments by value to functions, rustc still provides "NoAlias" as
> attribute to the argument whereas it should never be passed in this
> case. Luckily for us, in case the argument is a function pointer
> coming from a struct field, it crashes GCC, which is what allowed us
> to figure out about this. A code which reproduces this bug:

[...snip...]

> So in short: the patch in the previous mail which added this check:
> 
> ```
> RETURN_NULL_IF_FAIL (type->is_pointer (), NULL, NULL, "not a pointer
> type");
> ```
> 
> is correct and ready. 

Thanks.  I've gone ahead and pushed it to gcc trunk for you as r14-
3552-g29763b002459cb.

[...snip...]

Dave
Guillaume Gomez Aug. 29, 2023, 3:35 p.m. UTC | #13
Thanks a lot!

Le mar. 29 août 2023 à 17:35, David Malcolm <dmalcolm@redhat.com> a écrit :
>
> On Tue, 2023-08-29 at 17:15 +0200, Guillaume Gomez wrote:
> > We finished the investigation and found out the issue: when passing
> > arguments by value to functions, rustc still provides "NoAlias" as
> > attribute to the argument whereas it should never be passed in this
> > case. Luckily for us, in case the argument is a function pointer
> > coming from a struct field, it crashes GCC, which is what allowed us
> > to figure out about this. A code which reproduces this bug:
>
> [...snip...]
>
> > So in short: the patch in the previous mail which added this check:
> >
> > ```
> > RETURN_NULL_IF_FAIL (type->is_pointer (), NULL, NULL, "not a pointer
> > type");
> > ```
> >
> > is correct and ready.
>
> Thanks.  I've gone ahead and pushed it to gcc trunk for you as r14-
> 3552-g29763b002459cb.
>
> [...snip...]
>
> Dave
>
diff mbox series

Patch

From 8cafadb8409094c7fc66a1073397942a60cb27b3 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Fri, 11 Aug 2023 22:48:11 +0200
Subject: [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.

Signed-off-by: Guillaume Gomez <guillaume1.gomez@gmail.com>
---
 gcc/jit/jit-playback.cc              |  2 +-
 gcc/jit/jit-playback.h               |  5 ++
 gcc/jit/jit-recording.cc             | 47 +++++++++++++++++
 gcc/jit/jit-recording.h              | 37 ++++++++++++-
 gcc/jit/libgccjit++.h                |  6 +++
 gcc/jit/libgccjit.cc                 | 14 +++++
 gcc/jit/libgccjit.h                  |  4 ++
 gcc/jit/libgccjit.map                |  1 +
 gcc/testsuite/jit.dg/test-restrict.c | 77 ++++++++++++++++++++++++++++
 9 files changed, 191 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-restrict.c

diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc
index 88e1b212030..0eb4e94fdc4 100644
--- a/gcc/jit/jit-playback.cc
+++ b/gcc/jit/jit-playback.cc
@@ -3793,7 +3793,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 d153f4945d8..fb4f7b8b65b 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -490,6 +490,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 f962c9748c4..c5f50349311 100644
--- a/gcc/jit/jit-recording.cc
+++ b/gcc/jit/jit-recording.cc
@@ -2380,6 +2380,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
@@ -3090,6 +3103,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 929bbe37c3f..1aff22ff689 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -555,6 +555,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);
 
@@ -603,6 +604,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; }
@@ -737,7 +739,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
 {
@@ -829,6 +831,39 @@  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 ());
+  }
+
+  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; }
+
+  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 4b88e877bc9..b430f7eb049 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 050e68b738c..9b87e0569d6 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -539,6 +539,20 @@  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 (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 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.
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;
 
   local: *;
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. */
+#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