Commit 47ee1b7c by David Malcolm Committed by David Malcolm

jit: add gcc_jit_type_get_vector

gcc/jit/ChangeLog:
	* docs/cp/topics/types.rst (Vector types): New section.
	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_8): New tag.
	* docs/topics/types.rst (gcc_jit_context_get_type): Fix typo in
	example.
	(Vector types): New section.
	* docs/_build/texinfo/libgccjit.texi: Regenerate.
	* jit-playback.c (gcc::jit::playback::type::get_vector): New
	method.
	* jit-playback.h (gcc::jit::playback::type::get_vector): New
	method.
	* jit-recording.c: In namespace gcc::jit::recording::
	(type::get_vector): New method.
	(memento_of_get_aligned::write_reproducer): Fix typo
	in leading comment.
	(memento_of_get_vector::replay_into): New method.
	(memento_of_get_vector::make_debug_string): New method.
	(memento_of_get_vector::write_reproducer): New method.
	* jit-recording.h: In namespace gcc::jit::recording::
	(type::get_vector): New
	 method.
	(class memento_of_get_vector): New class.
	* libgccjit++.h (gccjit::type::get_vector): New method.
	* libgccjit.c (gcc_jit_type_get_vector): New public entrypoint.
	* libgccjit.h (LIBGCCJIT_HAVE_gcc_jit_type_get_vector): New
	define.
	(gcc_jit_type_get_vector): New decl.
	* libgccjit.map (LIBGCCJIT_ABI_8): New ABI tag.

gcc/testsuite/ChangeLog:
	* jit.dg/all-non-failing-tests.h: Add note about
	test-vector-types.cc.
	* jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c: New test
	case.
	* jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c:
	New test case.
	* jit.dg/test-vector-types.cc: New test case.

From-SVN: r251018
parent b240c0e0
2017-08-09 David Malcolm <dmalcolm@redhat.com>
* docs/cp/topics/types.rst (Vector types): New section.
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_8): New tag.
* docs/topics/types.rst (gcc_jit_context_get_type): Fix typo in
example.
(Vector types): New section.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* jit-playback.c (gcc::jit::playback::type::get_vector): New
method.
* jit-playback.h (gcc::jit::playback::type::get_vector): New
method.
* jit-recording.c: In namespace gcc::jit::recording::
(type::get_vector): New method.
(memento_of_get_aligned::write_reproducer): Fix typo
in leading comment.
(memento_of_get_vector::replay_into): New method.
(memento_of_get_vector::make_debug_string): New method.
(memento_of_get_vector::write_reproducer): New method.
* jit-recording.h: In namespace gcc::jit::recording::
(type::get_vector): New
method.
(class memento_of_get_vector): New class.
* libgccjit++.h (gccjit::type::get_vector): New method.
* libgccjit.c (gcc_jit_type_get_vector): New public entrypoint.
* libgccjit.h (LIBGCCJIT_HAVE_gcc_jit_type_get_vector): New
define.
(gcc_jit_type_get_vector): New decl.
* libgccjit.map (LIBGCCJIT_ABI_8): New ABI tag.
2017-07-05 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -109,6 +109,20 @@ Pointers, `const`, and `volatile`
Param "loc" is optional.
Vector types
------------
.. function:: gccjit::type gccjit::type::get_vector (size_t num_units)
Given type "T", get type:
.. code-block:: c
T __attribute__ ((vector_size (sizeof(T) * num_units))
T must be integral or floating point; num_units must be a power of two.
Structures and unions
---------------------
......
......@@ -149,3 +149,10 @@ entrypoints:
-------------------
``LIBGCCJIT_ABI_7`` covers the addition of
:func:`gcc_jit_type_get_aligned`
.. _LIBGCCJIT_ABI_8:
``LIBGCCJIT_ABI_8``
-------------------
``LIBGCCJIT_ABI_8`` covers the addition of
:func:`gcc_jit_type_get_vector`
......@@ -35,7 +35,7 @@ Types can be created in several ways:
.. code-block:: c
gcc_jit_type *int_type = gcc_jit_context_get_type (GCC_JIT_TYPE_INT);
gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
See :func:`gcc_jit_context_get_type` for the available types.
......@@ -136,6 +136,47 @@ Pointers, `const`, and `volatile`
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned
Vector types
------------
.. function:: gcc_jit_type *\
gcc_jit_type_get_vector (gcc_jit_type *type, \
size_t num_units)
Given type "T", get type:
.. code-block:: c
T __attribute__ ((vector_size (sizeof(T) * num_units))
T must be integral or floating point; num_units must be a power of two.
This can be used to construct a vector type in which operations
are applied element-wise. The compiler will automatically
use SIMD instructions where possible. See:
https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
For example, assuming 4-byte ``ints``, then:
.. code-block:: c
typedef int v4si __attribute__ ((vector_size (16)));
can be obtained using:
.. code-block:: c
gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
GCC_JIT_TYPE_INT);
gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
This API entrypoint was added in :ref:`LIBGCCJIT_ABI_8`; you can test
for its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
Structures and unions
---------------------
......
......@@ -1110,6 +1110,17 @@ get_aligned (size_t alignment_in_bytes) const
return new type (t_new_type);
}
/* Construct a playback::type instance (wrapping a tree)
for the given vector type. */
playback::type *
playback::type::
get_vector (size_t num_units) const
{
tree t_new_type = build_vector_type (m_inner, num_units);
return new type (t_new_type);
}
/* Construct a playback::lvalue instance (wrapping a tree) for a
field access. */
......
......@@ -392,6 +392,7 @@ public:
}
type *get_aligned (size_t alignment_in_bytes) const;
type *get_vector (size_t num_units) const;
private:
tree m_inner;
......
......@@ -1988,6 +1988,20 @@ recording::type::get_aligned (size_t alignment_in_bytes)
return result;
}
/* Given a type, get a vector version of the type.
Implements the post-error-checking part of
gcc_jit_type_get_vector. */
recording::type *
recording::type::get_vector (size_t num_units)
{
recording::type *result
= new memento_of_get_vector (this, num_units);
m_ctxt->record (result);
return result;
}
const char *
recording::type::access_as_type (reproducer &r)
{
......@@ -2457,7 +2471,7 @@ recording::memento_of_get_aligned::make_debug_string ()
m_alignment_in_bytes);
}
/* Implementation of recording::memento::write_reproducer for volatile
/* Implementation of recording::memento::write_reproducer for aligned
types. */
void
......@@ -2471,6 +2485,46 @@ recording::memento_of_get_aligned::write_reproducer (reproducer &r)
m_alignment_in_bytes);
}
/* The implementation of class gcc::jit::recording::memento_of_get_vector. */
/* Implementation of pure virtual hook recording::memento::replay_into
for recording::memento_of_get_vector. */
void
recording::memento_of_get_vector::replay_into (replayer *)
{
set_playback_obj
(m_other_type->playback_type ()->get_vector (m_num_units));
}
/* Implementation of recording::memento::make_debug_string for
results of get_vector. */
recording::string *
recording::memento_of_get_vector::make_debug_string ()
{
return string::from_printf
(m_ctxt,
"%s __attribute__((vector_size(sizeof (%s) * %zi)))",
m_other_type->get_debug_string (),
m_other_type->get_debug_string (),
m_num_units);
}
/* Implementation of recording::memento::write_reproducer for volatile
types. */
void
recording::memento_of_get_vector::write_reproducer (reproducer &r)
{
const char *id = r.make_identifier (this, "type");
r.write (" gcc_jit_type *%s =\n"
" gcc_jit_type_get_vector (%s, %zi);\n",
id,
r.get_identifier_as_type (m_other_type),
m_num_units);
}
/* The implementation of class gcc::jit::recording::array_type */
/* Implementation of pure virtual hook recording::type::dereference for
......
......@@ -474,6 +474,7 @@ public:
type *get_const ();
type *get_volatile ();
type *get_aligned (size_t alignment_in_bytes);
type *get_vector (size_t num_units);
/* Get the type obtained when dereferencing this type.
......@@ -600,8 +601,8 @@ private:
type *m_other_type;
};
/* A decorated version of a type, for get_const, get_volatile and
get_aligned. */
/* A decorated version of a type, for get_const, get_volatile,
get_aligned, and get_vector. */
class decorated_type : public type
{
......@@ -683,6 +684,27 @@ private:
size_t m_alignment_in_bytes;
};
/* Result of "gcc_jit_type_get_vector". */
class memento_of_get_vector : public decorated_type
{
public:
memento_of_get_vector (type *other_type, size_t num_units)
: decorated_type (other_type),
m_num_units (num_units) {}
/* Strip off the alignment, giving the underlying type. */
type *unqualified () 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;
private:
size_t m_num_units;
};
class array_type : public type
{
public:
......
......@@ -333,6 +333,7 @@ namespace gccjit
type get_const ();
type get_volatile ();
type get_aligned (size_t alignment_in_bytes);
type get_vector (size_t num_units);
// Shortcuts for getting values of numeric types:
rvalue zero ();
......@@ -1306,6 +1307,13 @@ type::get_aligned (size_t alignment_in_bytes)
alignment_in_bytes));
}
inline type
type::get_vector (size_t num_units)
{
return type (gcc_jit_type_get_vector (get_inner_type (),
num_units));
}
inline rvalue
type::zero ()
{
......
......@@ -2994,3 +2994,31 @@ gcc_jit_type_get_aligned (gcc_jit_type *type,
return (gcc_jit_type *)type->get_aligned (alignment_in_bytes);
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
gcc::jit::recording::type::get_vector method, in
jit-recording.c. */
gcc_jit_type *
gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units)
{
RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
gcc::jit::recording::context *ctxt = type->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_PRINTF1
(type->is_int () || type->is_float (), ctxt, NULL,
"type is not integral or floating point: %s",
type->get_debug_string ());
RETURN_NULL_IF_FAIL_PRINTF1
(pow2_or_zerop (num_units), ctxt, NULL,
"num_units not a power of two: %zi",
num_units);
return (gcc_jit_type *)type->get_vector (num_units);
}
......@@ -1403,6 +1403,21 @@ extern gcc_jit_type *
gcc_jit_type_get_aligned (gcc_jit_type *type,
size_t alignment_in_bytes);
#define LIBGCCJIT_HAVE_gcc_jit_type_get_vector
/* Given type "T", get type:
T __attribute__ ((vector_size (sizeof(T) * num_units))
T must be integral/floating point; num_units must be a power of two.
This API entrypoint was added in LIBGCCJIT_ABI_8; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
*/
extern gcc_jit_type *
gcc_jit_type_get_vector (gcc_jit_type *type, size_t num_units);
#ifdef __cplusplus
}
#endif /* __cplusplus */
......
......@@ -155,3 +155,8 @@ LIBGCCJIT_ABI_7 {
global:
gcc_jit_type_get_aligned;
} LIBGCCJIT_ABI_6;
LIBGCCJIT_ABI_8 {
global:
gcc_jit_type_get_vector;
} LIBGCCJIT_ABI_7;
2017-08-09 David Malcolm <dmalcolm@redhat.com>
* jit.dg/all-non-failing-tests.h: Add note about
test-vector-types.cc.
* jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c: New test
case.
* jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c:
New test case.
* jit.dg/test-vector-types.cc: New test case.
2017-08-09 Andrew Pinski <apinski@cavium.com>
* gcc.target/aarch64/vect-xorsign_exec.c: Add
......
......@@ -228,6 +228,8 @@
of gcc_jit_context_set_bool_allow_unreachable_blocks affects the whole
context. */
/* test-vector-types.cc: We don't use this, since it's C++. */
/* test-volatile.c */
#define create_code create_code_volatile
#define verify_code verify_code_volatile
......
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_type *void_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
/* Trigger an API error by passing a bad type. */
(void)gcc_jit_type_get_vector (void_type, 4);
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* Ensure that the bad API usage prevents the API giving a bogus
result back. */
CHECK_VALUE (result, NULL);
/* Verify that the correct error message was emitted. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
("gcc_jit_type_get_vector:"
" type is not integral or floating point: void"));
}
#include <stdlib.h>
#include <stdio.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
/* Trigger an API error by passing a bad number of units. */
(void)gcc_jit_type_get_vector (int_type, 7);
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* Ensure that the bad API usage prevents the API giving a bogus
result back. */
CHECK_VALUE (result, NULL);
/* Verify that the correct error message was emitted. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
("gcc_jit_type_get_vector:"
" num_units not a power of two: 7"));
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libgccjit.h"
#include "harness.h"
typedef int v4si __attribute__ ((vector_size (16)));
typedef unsigned int v4ui __attribute__ ((vector_size (16)));
typedef float v4f __attribute__ ((vector_size (16)));
static void
create_vec_fn (gcc_jit_context *ctxt, const char *fnname,
gcc_jit_type *the_type, enum gcc_jit_binary_op op)
{
/* Create equivalent to:
static void
FNNAME (const T *a, const T *b, T *c)
{
*c = *a OP *b;
}
where T is "the_type" (e.g. v4si). */
gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (the_type);
gcc_jit_type *const_type = gcc_jit_type_get_const (the_type);
gcc_jit_type *ptr_to_const_type = gcc_jit_type_get_pointer (const_type);
gcc_jit_param *a =
gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "a");
gcc_jit_param *b =
gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "b");
gcc_jit_param *c =
gcc_jit_context_new_param (ctxt, NULL, ptr_type, "c");
gcc_jit_type *return_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
gcc_jit_param *params[3] = {a, b, c};
gcc_jit_function *func =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
return_type,
fnname,
3, params, 0);
gcc_jit_block *initial =
gcc_jit_function_new_block (func, "initial");
/* (*a OP *b) */
gcc_jit_rvalue *op_result =
gcc_jit_context_new_binary_op (
ctxt, NULL,
op,
the_type,
gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (a),
NULL)),
gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (b),
NULL)));
/* *c = *a OP *b; */
gcc_jit_block_add_assignment (
initial, NULL,
gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (c), NULL),
op_result);
gcc_jit_block_end_with_void_return (initial, NULL);
}
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
gcc_jit_type *unsigned_type
= gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);
gcc_jit_type *v4ui_type = gcc_jit_type_get_vector (unsigned_type, 4);
gcc_jit_type *v4f_type = gcc_jit_type_get_vector (float_type, 4);
create_vec_fn (ctxt, "jit_v4si_add",
v4si_type, GCC_JIT_BINARY_OP_PLUS);
create_vec_fn (ctxt, "jit_v4si_sub",
v4si_type, GCC_JIT_BINARY_OP_MINUS);
create_vec_fn (ctxt, "jit_v4si_mult",
v4si_type, GCC_JIT_BINARY_OP_MULT);
create_vec_fn (ctxt, "jit_v4si_div",
v4si_type, GCC_JIT_BINARY_OP_DIVIDE);
create_vec_fn (ctxt, "jit_v4ui_add",
v4ui_type, GCC_JIT_BINARY_OP_PLUS);
create_vec_fn (ctxt, "jit_v4ui_sub",
v4ui_type, GCC_JIT_BINARY_OP_MINUS);
create_vec_fn (ctxt, "jit_v4ui_mult",
v4ui_type, GCC_JIT_BINARY_OP_MULT);
create_vec_fn (ctxt, "jit_v4ui_div",
v4ui_type, GCC_JIT_BINARY_OP_DIVIDE);
create_vec_fn (ctxt, "jit_v4f_add",
v4f_type, GCC_JIT_BINARY_OP_PLUS);
create_vec_fn (ctxt, "jit_v4f_sub",
v4f_type, GCC_JIT_BINARY_OP_MINUS);
create_vec_fn (ctxt, "jit_v4f_mult",
v4f_type, GCC_JIT_BINARY_OP_MULT);
create_vec_fn (ctxt, "jit_v4f_div",
v4f_type, GCC_JIT_BINARY_OP_DIVIDE);
}
template <typename T>
void
check_add (const T &a, const T &b, const T &c)
{
for (int i = 0; i < 4; i++)
CHECK_VALUE (c[i], a[i] + b[i]);
}
template <typename T>
void
check_sub (const T &a, const T &b, const T &c)
{
for (int i = 0; i < 4; i++)
CHECK_VALUE (c[i], a[i] - b[i]);
}
template <typename T>
void
check_mult (const T &a, const T &b, const T &c)
{
for (int i = 0; i < 4; i++)
CHECK_VALUE (c[i], a[i] * b[i]);
}
template <typename T>
void
check_div (const T &a, const T &b, const T &c)
{
for (int i = 0; i < 4; i++)
CHECK_VALUE (c[i], a[i] / b[i]);
}
template <typename T>
void
verify_vec_code (gcc_jit_context *ctxt, gcc_jit_result *result,
const char *fnname,
void (*check_cb) (const T &a, const T &b, const T &c))
{
typedef void (*binop_type) (const T *a, const T *b, T *c);
CHECK_NON_NULL (result);
binop_type fn =
(binop_type)gcc_jit_result_get_code (result, fnname);
CHECK_NON_NULL (fn);
T a, b, c;
/* Init. */
for (int i = 0; i < 4; i++)
{
a[i] = i + 5;
b[i] = (i + 4) * 3;
}
/* Run jit-compiled code and verify result. */
fn (&a, &b, &c);
check_cb (a, b, c);
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
verify_vec_code<v4si> (ctxt, result, "jit_v4si_add", check_add);
verify_vec_code<v4si> (ctxt, result, "jit_v4si_sub", check_sub);
verify_vec_code<v4si> (ctxt, result, "jit_v4si_mult", check_mult);
verify_vec_code<v4si> (ctxt, result, "jit_v4si_div", check_div);
verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_add", check_add);
verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_sub", check_sub);
verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_mult", check_mult);
verify_vec_code<v4ui> (ctxt, result, "jit_v4ui_div", check_div);
verify_vec_code<v4f> (ctxt, result, "jit_v4f_add", check_add);
verify_vec_code<v4f> (ctxt, result, "jit_v4f_sub", check_sub);
verify_vec_code<v4f> (ctxt, result, "jit_v4f_mult", check_mult);
verify_vec_code<v4f> (ctxt, result, "jit_v4f_div", check_div);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment