Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for restrict attribute on function parameters #26

Merged
merged 1 commit into from Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion gcc/jit/jit-playback.cc
Expand Up @@ -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));

Expand Down
5 changes: 5 additions & 0 deletions gcc/jit/jit-playback.h
Expand Up @@ -490,6 +490,11 @@ class type : public wrapper
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));
}
Comment on lines +493 to +496

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure how relevant this is to libgccjit, but we got patches "rejected" because of implementations in header files, despite having existing implementations in the same header file. I see that get_aligned and get_vector are declared here, so I assume there's a corresponding jit-playback.cc file where the implementation could live? just a little nit but it could help get the patch approved on the GCC side

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the information! I'll give a try like this and if needed, I'll move the function in the source file. But for the time being, for coherency I'll leave it here. :)


type *get_aligned (size_t alignment_in_bytes) const;
type *get_vector (size_t num_units) const;

Expand Down
47 changes: 47 additions & 0 deletions gcc/jit/jit-recording.cc
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
39 changes: 37 additions & 2 deletions gcc/jit/jit-recording.h
Expand Up @@ -555,6 +555,7 @@ class type : public memento
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);

Expand Down Expand Up @@ -603,6 +604,7 @@ class type : public memento
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; }
Expand Down Expand Up @@ -737,7 +739,7 @@ class memento_of_get_pointer : public type
};

/* 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
{
Expand Down Expand Up @@ -810,7 +812,7 @@ class memento_of_get_volatile : public decorated_type
return m_other_type->is_same_type_as (other->is_volatile ());
}

type* copy(context* ctxt) final override
type* copy (context* ctxt) final override
{
type* result = new memento_of_get_volatile (m_other_type->copy (ctxt));
ctxt->record (result);
Expand All @@ -829,6 +831,39 @@ class memento_of_get_volatile : public decorated_type
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
{
Expand Down
6 changes: 6 additions & 0 deletions gcc/jit/libgccjit++.h
Expand Up @@ -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 ()
{
Expand Down
14 changes: 14 additions & 0 deletions gcc/jit/libgccjit.cc
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions gcc/jit/libgccjit.h
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions gcc/jit/libgccjit.map
Expand Up @@ -326,3 +326,8 @@ LIBGCCJIT_ABI_33 {
gcc_jit_target_info_arch;
gcc_jit_target_info_supports_128bit_int;
} LIBGCCJIT_ABI_32;

LIBGCCJIT_ABI_34 {
global:
gcc_jit_type_get_restrict;
} LIBGCCJIT_ABI_33;
77 changes: 77 additions & 0 deletions 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)" } } */