From: David Malcolm <dmalcolm@redhat.com>
To: Michael Cree <mcree@orcon.net.nz>
Cc: jit@gcc.gnu.org, gcc-patches@gcc.gnu.org,
David Malcolm <dmalcolm@redhat.com>
Subject: [committed] jit: add gcc_jit_type_get_vector
Date: Sun, 01 Jan 2017 00:00:00 -0000 [thread overview]
Message-ID: <1502326873-58234-1-git-send-email-dmalcolm@redhat.com> (raw)
In-Reply-To: <20170809084227.s23odfpcdyjvrtin@tower>
On Wed, 2017-08-09 at 20:42 +1200, Michael Cree wrote:
> On Mon, Aug 07, 2017 at 10:28:57AM -0400, David Malcolm wrote:
> > On Mon, 2017-08-07 at 20:12 +1200, Michael Cree wrote:
> >
> > Hi Michael
> >
> > > I am wondering if libgccjit supports vector types, i.e., can one
> > > attach attribute __vector_size__ to the base types? There does
> > > not
> > > seem to be any indication of this in the manual.
> >
> > Currently this isn't supported.
> >
> > Is this a blocker for you using libgccjit?
>
> Yeah, it is. The idea is to generate image processing operators
> on the fly. There are opportunities for various optimisations that
> can only be decided on at runtime.
>
> > What would the ideal API
> > look like?
> >
> > Maybe something like:
> >
> > extern gcc_jit_type *
> > gcc_jit_type_get_vector (gcc_jit_type *type, unsigned nunits);
> >
> > with various requirements (type must be integral/floating point;
> > nunits
> > must be a power of two).
>
> I suspect that would do the job nicely.
>
> Cheers
> Michael.
I implemented the above (although I switched the 2nd arg to be
"size_t num_units").
It looks like you may not need to explicitly use builtins to
access machine specific simd intrinsics; for example, on x86_64
when I tried multiplying two of these together for float, with
GCC_JIT_BINARY_OP_MULT, which led to this gimple:
jit_v4f_mult (const vector(4) <float:32> * a, const vector(4) <float:32> * b, vector(4) <float:32> * c)
{
initial:
_1 = *a;
_2 = *b;
_3 = _1 * _2;
*c = _3;
return;
}
on this x86_64 box it compiled to:
movaps (%rdi), %xmm0
mulps (%rsi), %xmm0
movaps %xmm0, (%rdx)
ret
(i.e. using the "mulps" SIMD instruction).
Successfully bootstrapped®rtested on x86_64-pc-linux-gnu;
takes jit.sum from 9349 passes to 9759.
Committed to trunk as r251018.
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.
---
gcc/jit/docs/cp/topics/types.rst | 14 ++
gcc/jit/docs/topics/compatibility.rst | 7 +
gcc/jit/docs/topics/types.rst | 43 ++++-
gcc/jit/jit-playback.c | 11 ++
gcc/jit/jit-playback.h | 1 +
gcc/jit/jit-recording.c | 56 ++++++-
gcc/jit/jit-recording.h | 26 ++-
gcc/jit/libgccjit++.h | 8 +
gcc/jit/libgccjit.c | 28 ++++
gcc/jit/libgccjit.h | 15 ++
gcc/jit/libgccjit.map | 5 +
gcc/testsuite/jit.dg/all-non-failing-tests.h | 2 +
.../test-error-gcc_jit_type_get_vector-bad-type.c | 30 ++++
...rror-gcc_jit_type_get_vector-non-power-of-two.c | 29 ++++
gcc/testsuite/jit.dg/test-vector-types.cc | 185 +++++++++++++++++++++
15 files changed, 456 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
create mode 100644 gcc/testsuite/jit.dg/test-vector-types.cc
diff --git a/gcc/jit/docs/cp/topics/types.rst b/gcc/jit/docs/cp/topics/types.rst
index e85a492..1df896e 100644
--- a/gcc/jit/docs/cp/topics/types.rst
+++ b/gcc/jit/docs/cp/topics/types.rst
@@ -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
---------------------
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 5a13653..1d5fbc2 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -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`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 119f10e..c279222 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -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
---------------------
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 76cc88f..19b6fe2 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -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. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 0a83390..7dc7315 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -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;
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 723ddb3..ea4ebb1 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -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
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 5faf35e..248765d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -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:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index ea277f8..a83ccf6 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -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 ()
{
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 9b003e3..6e352c6 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -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);
+}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 898ee98..b863b07 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -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 */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 160f4cd..08760e3 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -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;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 58e0c30..4af704a 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -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
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
new file mode 100644
index 0000000..59aed33
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-bad-type.c
@@ -0,0 +1,30 @@
+#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"));
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
new file mode 100644
index 0000000..aa3bdbd
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_type_get_vector-non-power-of-two.c
@@ -0,0 +1,29 @@
+#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"));
+}
diff --git a/gcc/testsuite/jit.dg/test-vector-types.cc b/gcc/testsuite/jit.dg/test-vector-types.cc
new file mode 100644
index 0000000..3389e04
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-vector-types.cc
@@ -0,0 +1,185 @@
+#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);
+}
--
1.8.5.3
next prev parent reply other threads:[~2017-08-10 0:26 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-01 0:00 does libgccjit support vector types? Michael Cree
2017-01-01 0:00 ` David Malcolm
2017-01-01 0:00 ` Michael Cree
2017-01-01 0:00 ` David Malcolm [this message]
2017-01-01 0:00 ` [committed] jit: add gcc_jit_type_get_vector Michael Cree
2017-01-01 0:00 ` David Malcolm
2017-01-01 0:00 ` Michael Cree
2017-01-01 0:00 ` David Malcolm
2017-01-01 0:00 ` [committed] jit: fix segfault with autovectorization (PR tree-optimization/46805) David Malcolm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1502326873-58234-1-git-send-email-dmalcolm@redhat.com \
--to=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jit@gcc.gnu.org \
--cc=mcree@orcon.net.nz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).