[committed] jit: implement gcc_jit_context_new_rvalue_from_vector
David Malcolm
dmalcolm@redhat.com
Wed Oct 4 13:45:00 GMT 2017
This patch implements a new API entrypoint:
/* Build a vector rvalue from an array of elements.
"vec_type" should be a vector type, created using gcc_jit_type_get_vector.
This API entrypoint was added in LIBGCCJIT_ABI_10; you can test for its
presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
*/
extern gcc_jit_rvalue *
gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_type *vec_type,
size_t num_elements,
gcc_jit_rvalue **elements);
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu;
takes jit.sum from 9909 to 10294 PASS results.
Committed to trunk as r253409.
gcc/jit/ChangeLog:
* docs/cp/topics/expressions.rst (Vector expressions): New
section.
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_10): New ABI tag.
* docs/topics/expressions.rst (Vector expressions): New section.
* docs/topics/types.rst (gcc_jit_type_get_vector): Add link to
gcc_jit_context_new_rvalue_from_vector.
* jit-common.h (gcc::jit:recording::vector_type): New forward
decl.
* jit-playback.c
(gcc::jit::playback::context::new_rvalue_from_vector): New method.
* jit-playback.h
(gcc::jit::playback::context::new_rvalue_from_vector): New method.
* jit-recording.c: In namespace gcc::jit::
(class comma_separated_string): New class.
(comma_separated_string::comma_separated_string): New ctor,
adapted from recording::call::make_debug_string.
(comma_separated_string::~comma_separated_string): New dtor.
In namespace gcc::jit::recording::
(context::new_rvalue_from_vector): New method.
(type::get_vector): Update for renaming of memento_of_get_vector.
(class memento_of_get_vector): Rename to...
(class vector_type): ..this.
(memento_of_new_rvalue_from_vector::memento_of_new_rvalue_from_vector):
New ctor.
(memento_of_new_rvalue_from_vector::replay_into): New method.
(memento_of_new_rvalue_from_vector::visit_children): New method.
(memento_of_new_rvalue_from_vector::make_debug_string): New
method.
(memento_of_new_rvalue_from_vector::write_reproducer): New method.
(call::make_debug_string): Split out arg-printing code into ctor
for comma_separated_string.
* jit-recording.h: In namespace gcc::jit::recording::
(context::new_rvalue_from_vector): New method.
(type::dyn_cast_vector_type): New virtual function.
(class memento_of_get_vector): Rename to...
(class vector_type): ...this.
(vector_type::unqualified): Remove this vfunc override in favor
of...
(vector_type::get_element_type): ...this new method.
(vector_type::get_num_units): New method.
(vector_type::dyn_cast_vector_type): New vfunc override.
(class memento_of_new_rvalue_from_vector): New class.
* libgccjit++.h (gccjit::context::new_rvalue): Add overload for
vector of rvalue.
* libgccjit.c (gcc_jit_context_new_binary_op): Strip off type
qualifications when checking that both operands have same type.
(gcc_jit_context_new_rvalue_from_vector): New API entrypoint.
* libgccjit.h
(LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector): New
macro.
(gcc_jit_context_new_rvalue_from_vector): New API entrypoint.
* libgccjit.map (LIBGCCJIT_ABI_10): New ABI tag.
gcc/testsuite/ChangeLog:
* jit.dg/test-expressions.c (make_test_of_vectors): New function.
(create_code): Call it.
* jit.dg/test-vector-rvalues.cc: New test case.
---
gcc/jit/docs/cp/topics/expressions.rst | 11 ++
gcc/jit/docs/topics/compatibility.rst | 8 ++
gcc/jit/docs/topics/expressions.rst | 24 ++++
gcc/jit/docs/topics/types.rst | 3 +
gcc/jit/jit-common.h | 1 +
gcc/jit/jit-playback.c | 16 +++
gcc/jit/jit-playback.h | 5 +
gcc/jit/jit-recording.c | 207 ++++++++++++++++++++++-----
gcc/jit/jit-recording.h | 42 +++++-
gcc/jit/libgccjit++.h | 22 +++
gcc/jit/libgccjit.c | 60 +++++++-
gcc/jit/libgccjit.h | 17 +++
gcc/jit/libgccjit.map | 5 +
gcc/testsuite/jit.dg/test-expressions.c | 30 ++++
gcc/testsuite/jit.dg/test-vector-rvalues.cc | 211 ++++++++++++++++++++++++++++
15 files changed, 622 insertions(+), 40 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-vector-rvalues.cc
diff --git a/gcc/jit/docs/cp/topics/expressions.rst b/gcc/jit/docs/cp/topics/expressions.rst
index 147d065..b0081f6 100644
--- a/gcc/jit/docs/cp/topics/expressions.rst
+++ b/gcc/jit/docs/cp/topics/expressions.rst
@@ -105,6 +105,17 @@ Simple expressions
Generate an rvalue of type :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` for
the given string. This is akin to a string literal.
+Vector expressions
+******************
+
+.. function:: gccjit::rvalue \
+ gccjit::context::new_rvalue (gccjit::type vector_type, \
+ std::vector<gccjit::rvalue> elements) const
+
+ Given a vector type, and a vector of scalar rvalue elements, generate a
+ vector rvalue.
+
+ The number of elements needs to match that of the vector type.
Unary Operations
****************
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 8408939..84d342b 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -163,3 +163,11 @@ entrypoints:
-------------------
``LIBGCCJIT_ABI_9`` covers the addition of
:func:`gcc_jit_function_get_address`
+
+.. _LIBGCCJIT_ABI_10:
+
+``LIBGCCJIT_ABI_10``
+--------------------
+
+``LIBGCCJIT_ABI_10`` covers the addition of
+:func:`gcc_jit_context_new_rvalue_from_vector`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 76aa4eb..e6e09dd 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -126,6 +126,30 @@ Simple expressions
underlying string, so it is valid to pass in a pointer to an on-stack
buffer.
+Vector expressions
+******************
+
+.. function:: gcc_jit_rvalue * \
+ gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, \
+ gcc_jit_location *loc, \
+ gcc_jit_type *vec_type, \
+ size_t num_elements, \
+ gcc_jit_rvalue **elements)
+
+ Build a vector rvalue from an array of elements.
+
+ "vec_type" should be a vector type, created using
+ :func:`gcc_jit_type_get_vector`.
+
+ "num_elements" should match that of the vector type.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_10`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+
Unary Operations
****************
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 35a8231..a9ab9b3 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -177,6 +177,9 @@ Vector types
#ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector
+ Vector rvalues can be generated using
+ :func:`gcc_jit_context_new_rvalue_from_vector`.
+
Structures and unions
---------------------
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index c931b3f..daf94a0 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -117,6 +117,7 @@ namespace recording {
class compound_type;
class struct_;
class union_;
+ class vector_type;
class field;
class fields;
class function;
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 5798179..95126c9 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -629,6 +629,22 @@ new_string_literal (const char *value)
return new rvalue (this, t_addr);
}
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ vector. */
+
+playback::rvalue *
+playback::context::new_rvalue_from_vector (location *,
+ type *type,
+ const auto_vec<rvalue *> &elements)
+{
+ vec<constructor_elt, va_gc> *v;
+ vec_alloc (v, elements.length ());
+ for (unsigned i = 0; i < elements.length (); ++i)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elements[i]->as_tree ());
+ tree t_ctor = build_constructor (type->as_tree (), v);
+ return new rvalue (this, t_ctor);
+}
+
/* Coerce a tree expression into a boolean tree expression. */
tree
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 746f5da..b45f6d5 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -114,6 +114,11 @@ public:
new_string_literal (const char *value);
rvalue *
+ new_rvalue_from_vector (location *loc,
+ type *type,
+ const auto_vec<rvalue *> &elements);
+
+ rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
type *result_type,
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 6d7dc80..bd8f116 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -447,6 +447,62 @@ reproducer::xstrdup_printf (const char *fmt, ...)
return result;
}
+/* A helper class for implementing make_debug_string, for building
+ a temporary string from a vec of rvalues. */
+
+class comma_separated_string
+{
+ public:
+ comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
+ enum recording::precedence prec);
+ ~comma_separated_string ();
+
+ const char *as_char_ptr () const { return m_buf; }
+
+ private:
+ char *m_buf;
+};
+
+/* comma_separated_string's ctor
+ Build m_buf. */
+
+comma_separated_string::comma_separated_string
+ (const auto_vec<recording::rvalue *> &rvalues,
+ enum recording::precedence prec)
+: m_buf (NULL)
+{
+ /* Calculate length of said buffer. */
+ size_t sz = 1; /* nil terminator */
+ for (unsigned i = 0; i< rvalues.length (); i++)
+ {
+ sz += strlen (rvalues[i]->get_debug_string_parens (prec));
+ sz += 2; /* ", " separator */
+ }
+
+ /* Now allocate and populate the buffer. */
+ m_buf = new char[sz];
+ size_t len = 0;
+
+ for (unsigned i = 0; i< rvalues.length (); i++)
+ {
+ strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
+ len += strlen (rvalues[i]->get_debug_string_parens (prec));
+ if (i + 1 < rvalues.length ())
+ {
+ strcpy (m_buf + len, ", ");
+ len += 2;
+ }
+ }
+ m_buf[len] = '\0';
+}
+
+/* comma_separated_string's dtor. */
+
+comma_separated_string::~comma_separated_string ()
+{
+ delete[] m_buf;
+}
+
/**********************************************************************
Recording.
**********************************************************************/
@@ -1001,6 +1057,23 @@ recording::context::new_string_literal (const char *value)
return result;
}
+/* Create a recording::memento_of_new_rvalue_from_vector instance and add it
+ to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_vector. */
+
+recording::rvalue *
+recording::context::new_rvalue_from_vector (location *loc,
+ vector_type *type,
+ rvalue **elements)
+{
+ recording::rvalue *result
+ = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
+ record (result);
+ return result;
+}
+
/* Create a recording::unary_op instance and add it to this context's
list of mementos.
@@ -2035,7 +2108,7 @@ recording::type *
recording::type::get_vector (size_t num_units)
{
recording::type *result
- = new memento_of_get_vector (this, num_units);
+ = new vector_type (this, num_units);
m_ctxt->record (result);
return result;
}
@@ -2523,13 +2596,13 @@ recording::memento_of_get_aligned::write_reproducer (reproducer &r)
m_alignment_in_bytes);
}
-/* The implementation of class gcc::jit::recording::memento_of_get_vector. */
+/* The implementation of class gcc::jit::recording::vector_type. */
/* Implementation of pure virtual hook recording::memento::replay_into
- for recording::memento_of_get_vector. */
+ for recording::vector_type. */
void
-recording::memento_of_get_vector::replay_into (replayer *)
+recording::vector_type::replay_into (replayer *)
{
set_playback_obj
(m_other_type->playback_type ()->get_vector (m_num_units));
@@ -2539,7 +2612,7 @@ recording::memento_of_get_vector::replay_into (replayer *)
results of get_vector. */
recording::string *
-recording::memento_of_get_vector::make_debug_string ()
+recording::vector_type::make_debug_string ()
{
return string::from_printf
(m_ctxt,
@@ -2549,11 +2622,10 @@ recording::memento_of_get_vector::make_debug_string ()
m_num_units);
}
-/* Implementation of recording::memento::write_reproducer for volatile
- types. */
+/* Implementation of recording::memento::write_reproducer for vector types. */
void
-recording::memento_of_get_vector::write_reproducer (reproducer &r)
+recording::vector_type::write_reproducer (reproducer &r)
{
const char *id = r.make_identifier (this, "type");
r.write (" gcc_jit_type *%s =\n"
@@ -4569,6 +4641,96 @@ recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
m_value->get_debug_string ());
}
+/* The implementation of class
+ gcc::jit::recording::memento_of_new_rvalue_from_vector. */
+
+/* The constructor for
+ gcc::jit::recording::memento_of_new_rvalue_from_vector. */
+
+recording::memento_of_new_rvalue_from_vector::
+memento_of_new_rvalue_from_vector (context *ctxt,
+ location *loc,
+ vector_type *type,
+ rvalue **elements)
+: rvalue (ctxt, loc, type),
+ m_vector_type (type),
+ m_elements ()
+{
+ for (unsigned i = 0; i < type->get_num_units (); i++)
+ m_elements.safe_push (elements[i]);
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_vector. */
+
+void
+recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
+{
+ auto_vec<playback::rvalue *> playback_elements;
+ playback_elements.create (m_elements.length ());
+ for (unsigned i = 0; i< m_elements.length (); i++)
+ playback_elements.safe_push (m_elements[i]->playback_rvalue ());
+
+ set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
+ m_type->playback_type (),
+ playback_elements));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::memento_of_new_rvalue_from_vector. */
+
+void
+recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
+{
+ for (unsigned i = 0; i< m_elements.length (); i++)
+ v->visit (m_elements[i]);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ vectors. */
+
+recording::string *
+recording::memento_of_new_rvalue_from_vector::make_debug_string ()
+{
+ comma_separated_string elements (m_elements, get_precedence ());
+
+ /* Now build a string. */
+ string *result = string::from_printf (m_ctxt,
+ "{%s}",
+ elements.as_char_ptr ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vectors. */
+
+void
+recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "vector");
+ const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
+ r.write (" gcc_jit_rvalue *%s[%i] = {\n",
+ elements_id,
+ m_elements.length ());
+ for (unsigned i = 0; i< m_elements.length (); i++)
+ r.write (" %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
+ r.write (" };\n");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_type *vec_type */\n"
+ " %i, /* size_t num_elements */ \n"
+ " %s); /* gcc_jit_rvalue **elements*/\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier (m_vector_type),
+ m_elements.length (),
+ elements_id);
+}
+
/* The implementation of class gcc::jit::recording::unary_op. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -4982,39 +5144,14 @@ recording::call::visit_children (rvalue_visitor *v)
recording::string *
recording::call::make_debug_string ()
{
- enum precedence prec = get_precedence ();
/* First, build a buffer for the arguments. */
- /* Calculate length of said buffer. */
- size_t sz = 1; /* nil terminator */
- for (unsigned i = 0; i< m_args.length (); i++)
- {
- sz += strlen (m_args[i]->get_debug_string_parens (prec));
- sz += 2; /* ", " separator */
- }
-
- /* Now allocate and populate the buffer. */
- char *argbuf = new char[sz];
- size_t len = 0;
-
- for (unsigned i = 0; i< m_args.length (); i++)
- {
- strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
- len += strlen (m_args[i]->get_debug_string_parens (prec));
- if (i + 1 < m_args.length ())
- {
- strcpy (argbuf + len, ", ");
- len += 2;
- }
- }
- argbuf[len] = '\0';
+ comma_separated_string args (m_args, get_precedence ());
/* ...and use it to get the string for the call as a whole. */
string *result = string::from_printf (m_ctxt,
"%s (%s)",
m_func->get_debug_string (),
- argbuf);
-
- delete[] argbuf;
+ args.as_char_ptr ());
return result;
}
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 9123645..6a3fd5d 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -149,6 +149,11 @@ public:
new_string_literal (const char *value);
rvalue *
+ new_rvalue_from_vector (location *loc,
+ vector_type *type,
+ rvalue **elements);
+
+ rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
type *result_type,
@@ -486,6 +491,7 @@ public:
virtual function_type *dyn_cast_function_type () { return NULL; }
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
virtual struct_ *dyn_cast_struct () { return NULL; }
+ virtual vector_type *dyn_cast_vector_type () { return NULL; }
/* Is it typesafe to copy to this type from rtype? */
virtual bool accepts_writes_from (type *rtype)
@@ -690,15 +696,18 @@ private:
};
/* Result of "gcc_jit_type_get_vector". */
-class memento_of_get_vector : public decorated_type
+class vector_type : public decorated_type
{
public:
- memento_of_get_vector (type *other_type, size_t num_units)
+ vector_type (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; }
+ size_t get_num_units () const { return m_num_units; }
+
+ vector_type *dyn_cast_vector_type () FINAL OVERRIDE { return this; }
+
+ type *get_element_type () { return m_other_type; }
void replay_into (replayer *) FINAL OVERRIDE;
@@ -1358,6 +1367,31 @@ private:
string *m_value;
};
+class memento_of_new_rvalue_from_vector : public rvalue
+{
+public:
+ memento_of_new_rvalue_from_vector (context *ctxt,
+ location *loc,
+ vector_type *type,
+ rvalue **elements);
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_PRIMARY;
+ }
+
+private:
+ vector_type *m_vector_type;
+ auto_vec<rvalue *> m_elements;
+};
+
class unary_op : public rvalue
{
public:
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 82997c3..9e3c179 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -187,6 +187,8 @@ namespace gccjit
rvalue new_rvalue (type pointer_type,
void *value) const;
rvalue new_rvalue (const std::string &value) const;
+ rvalue new_rvalue (type vector_type,
+ std::vector<rvalue> elements) const;
/* Generic unary operations... */
rvalue new_unary_op (enum gcc_jit_unary_op op,
@@ -897,6 +899,26 @@ context::new_rvalue (const std::string &value) const
}
inline rvalue
+context::new_rvalue (type vector_type,
+ std::vector<rvalue> elements) const
+{
+ /* Treat std::vector as an array, relying on it not being resized: */
+ rvalue *as_array_of_wrappers = &elements[0];
+
+ /* Treat the array as being of the underlying pointers, relying on
+ the wrapper type being such a pointer internally. */
+ gcc_jit_rvalue **as_array_of_ptrs =
+ reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers);
+
+ return rvalue (
+ gcc_jit_context_new_rvalue_from_vector (m_inner_ctxt,
+ NULL,
+ vector_type.get_inner_type (),
+ elements.size (),
+ as_array_of_ptrs));
+}
+
+inline rvalue
context::new_unary_op (enum gcc_jit_unary_op op,
type result_type,
rvalue a,
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 37cb695..c00acbf 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1335,7 +1335,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
RETURN_NULL_IF_FAIL_PRINTF4 (
- a->get_type () == b->get_type (),
+ a->get_type ()->unqualified () == b->get_type ()->unqualified (),
ctxt, loc,
"mismatching types for binary op:"
" a: %s (type: %s) b: %s (type: %s)",
@@ -3042,3 +3042,61 @@ gcc_jit_function_get_address (gcc_jit_function *fn,
return (gcc_jit_rvalue *)fn->get_address (loc);
}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_rvalue_from_vector method, in
+ jit-recording.c. */
+
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *vec_type,
+ size_t num_elements,
+ gcc_jit_rvalue **elements)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (vec_type, ctxt, loc, "NULL vec_type");
+
+ /* "vec_type" must be a vector type. */
+ gcc::jit::recording::vector_type *as_vec_type
+ = vec_type->dyn_cast_vector_type ();
+ RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc,
+ "%s is not a vector type",
+ vec_type->get_debug_string ());
+
+ /* "num_elements" must match. */
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ num_elements == as_vec_type->get_num_units (), ctxt, loc,
+ "num_elements != %zi", as_vec_type->get_num_units ());
+
+ /* "elements must be non-NULL. */
+ RETURN_NULL_IF_FAIL (elements, ctxt, loc, "NULL elements");
+
+ /* Each of "elements" must be non-NULL and of the correct type. */
+ gcc::jit::recording::type *element_type
+ = as_vec_type->get_element_type ();
+ for (size_t i = 0; i < num_elements; i++)
+ {
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ elements[i], ctxt, loc, "NULL elements[%zi]", i);
+ RETURN_NULL_IF_FAIL_PRINTF4 (
+ compatible_types (element_type,
+ elements[i]->get_type ()),
+ ctxt, loc,
+ "mismatching type for element[%zi] (expected type: %s): %s (type: %s)",
+ i,
+ element_type->get_debug_string (),
+ elements[i]->get_debug_string (),
+ elements[i]->get_type ()->get_debug_string ());
+ }
+
+ return (gcc_jit_rvalue *)ctxt->new_rvalue_from_vector
+ (loc,
+ as_vec_type,
+ (gcc::jit::recording::rvalue **)elements);
+}
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 18c03fb..f955eb2 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1433,6 +1433,23 @@ gcc_jit_function_get_address (gcc_jit_function *fn,
gcc_jit_location *loc);
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+
+/* Build a vector rvalue from an array of elements.
+
+ "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_10; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *vec_type,
+ size_t num_elements,
+ gcc_jit_rvalue **elements);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 616e364..03f65fd 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -165,3 +165,8 @@ LIBGCCJIT_ABI_9 {
global:
gcc_jit_function_get_address;
} LIBGCCJIT_ABI_8;
+
+LIBGCCJIT_ABI_10 {
+ global:
+ gcc_jit_context_new_rvalue_from_vector;
+} LIBGCCJIT_ABI_9;
diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c
index 548cfa2..f9cc64f 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -920,6 +920,35 @@ verify_get_address (gcc_jit_result *result)
}
/**********************************************************************
+ Vector values
+ **********************************************************************/
+
+static void
+make_test_of_vectors (gcc_jit_context *ctxt)
+{
+ gcc_jit_type *scalar_type;
+ gcc_jit_type *vec_type;
+ gcc_jit_rvalue *elements[4];
+
+ scalar_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ vec_type = gcc_jit_type_get_vector (scalar_type, 4);
+
+ elements[0] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, 1);
+ elements[1] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, -2);
+ elements[2] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, 3);
+ elements[3] = gcc_jit_context_new_rvalue_from_int (ctxt, scalar_type, -4);
+
+ gcc_jit_rvalue *vec_rvalue
+ = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, vec_type,
+ 4, elements);
+ CHECK_STRING_VALUE (
+ gcc_jit_object_get_debug_string (
+ gcc_jit_rvalue_as_object (vec_rvalue)),
+ "{(int)1, (int)-2, (int)3, (int)-4}");
+}
+
+/**********************************************************************
Code for harness
**********************************************************************/
@@ -932,6 +961,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
make_tests_of_casts (ctxt);
make_tests_of_dereferences (ctxt);
make_test_of_get_address (ctxt);
+ make_test_of_vectors (ctxt);
}
void
diff --git a/gcc/testsuite/jit.dg/test-vector-rvalues.cc b/gcc/testsuite/jit.dg/test-vector-rvalues.cc
new file mode 100644
index 0000000..ac230bf7
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-vector-rvalues.cc
@@ -0,0 +1,211 @@
+#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 *vec_type,
+ gcc_jit_type *elem_type,
+ enum gcc_jit_binary_op op)
+{
+ /* Create equivalent to:
+
+ static void
+ FNNAME (V *dst, const V *lhs, E p, E q, E r, E s)
+ {
+ V pqrs;
+ pqrs = {p, q, r, s};
+ *dst = *lhs OP pqrs;
+ }
+
+ where V is "vec_type" (e.g. v4si)
+ and E is "elem_type" (e.g. int). */
+
+ gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (vec_type);
+
+ gcc_jit_type *const_type = gcc_jit_type_get_const (vec_type);
+ gcc_jit_type *ptr_to_const_type = gcc_jit_type_get_pointer (const_type);
+
+ gcc_jit_param *dst =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "dst");
+ gcc_jit_param *lhs =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_to_const_type, "lhs");
+ gcc_jit_param *p =
+ gcc_jit_context_new_param (ctxt, NULL, elem_type, "p");
+ gcc_jit_param *q =
+ gcc_jit_context_new_param (ctxt, NULL, elem_type, "q");
+ gcc_jit_param *r =
+ gcc_jit_context_new_param (ctxt, NULL, elem_type, "r");
+ gcc_jit_param *s =
+ gcc_jit_context_new_param (ctxt, NULL, elem_type, "s");
+
+ gcc_jit_type *return_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+ gcc_jit_param *params[6] = {dst, lhs, p, q, r, s};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ fnname,
+ 6, params, 0);
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ /* V pqrs; */
+ gcc_jit_lvalue *pqrs
+ = gcc_jit_function_new_local (func, NULL,
+ vec_type, "pqrs");
+
+ /* pqrs = {p, q, r, s}; */
+ gcc_jit_rvalue *elems[4];
+ elems[0] = gcc_jit_param_as_rvalue (p);
+ elems[1] = gcc_jit_param_as_rvalue (q);
+ elems[2] = gcc_jit_param_as_rvalue (r);
+ elems[3] = gcc_jit_param_as_rvalue (s);
+ gcc_jit_block_add_assignment (
+ initial, NULL,
+ pqrs,
+ gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, vec_type, 4, elems));
+
+ /* (*lhs OP pqrs) */
+ gcc_jit_rvalue *op_result =
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
+ op,
+ vec_type,
+ gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (lhs),
+ NULL)),
+ gcc_jit_lvalue_as_rvalue (pqrs));
+ /* *dst = *lhs OP pqrs; */
+ gcc_jit_block_add_assignment (
+ initial, NULL,
+ gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (dst), 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, int_type, GCC_JIT_BINARY_OP_PLUS);
+ create_vec_fn (ctxt, "jit_v4si_sub",
+ v4si_type, int_type, GCC_JIT_BINARY_OP_MINUS);
+ create_vec_fn (ctxt, "jit_v4si_mult",
+ v4si_type, int_type, GCC_JIT_BINARY_OP_MULT);
+ create_vec_fn (ctxt, "jit_v4si_div",
+ v4si_type, int_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+ create_vec_fn (ctxt, "jit_v4ui_add",
+ v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_PLUS);
+ create_vec_fn (ctxt, "jit_v4ui_sub",
+ v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MINUS);
+ create_vec_fn (ctxt, "jit_v4ui_mult",
+ v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_MULT);
+ create_vec_fn (ctxt, "jit_v4ui_div",
+ v4ui_type, unsigned_type, GCC_JIT_BINARY_OP_DIVIDE);
+
+ create_vec_fn (ctxt, "jit_v4f_add",
+ v4f_type, float_type, GCC_JIT_BINARY_OP_PLUS);
+ create_vec_fn (ctxt, "jit_v4f_sub",
+ v4f_type, float_type, GCC_JIT_BINARY_OP_MINUS);
+ create_vec_fn (ctxt, "jit_v4f_mult",
+ v4f_type, float_type, GCC_JIT_BINARY_OP_MULT);
+ create_vec_fn (ctxt, "jit_v4f_div",
+ v4f_type, float_type, GCC_JIT_BINARY_OP_DIVIDE);
+}
+
+template <typename V>
+void
+check_add (const V &a, const V &b, const V &c)
+{
+ for (int i = 0; i < 4; i++)
+ CHECK_VALUE (c[i], a[i] + b[i]);
+}
+
+template <typename V>
+void
+check_sub (const V &a, const V &b, const V &c)
+{
+ for (int i = 0; i < 4; i++)
+ CHECK_VALUE (c[i], a[i] - b[i]);
+}
+
+template <typename V>
+void
+check_mult (const V &a, const V &b, const V &c)
+{
+ for (int i = 0; i < 4; i++)
+ CHECK_VALUE (c[i], a[i] * b[i]);
+}
+
+template <typename V>
+void
+check_div (const V &a, const V &b, const V &c)
+{
+ for (int i = 0; i < 4; i++)
+ CHECK_VALUE (c[i], a[i] / b[i]);
+}
+
+template <typename V, typename E>
+void
+verify_vec_code (gcc_jit_context *ctxt, gcc_jit_result *result,
+ const char *fnname,
+ void (*check_cb) (const V &a, const V &b, const V &c))
+{
+ typedef void (*binop_type) (const V *a, V *b, E p, E q, E r, E s);
+ CHECK_NON_NULL (result);
+ binop_type fn =
+ (binop_type)gcc_jit_result_get_code (result, fnname);
+ CHECK_NON_NULL (fn);
+
+ V dst, lhs, pqrs;
+
+ /* Init. */
+ for (int i = 0; i < 4; i++)
+ {
+ lhs[i] = i + 5;
+ pqrs[i] = (i + 4) * 3;
+ }
+
+ /* Run jit-compiled code and verify result. */
+ fn (&dst, &lhs, pqrs[0], pqrs[1], pqrs[2], pqrs[3]);
+ check_cb (lhs, pqrs, dst);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_add", check_add);
+ verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_sub", check_sub);
+ verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_mult", check_mult);
+ verify_vec_code<v4si, int> (ctxt, result, "jit_v4si_div", check_div);
+
+ verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_add", check_add);
+ verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_sub", check_sub);
+ verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_mult", check_mult);
+ verify_vec_code<v4ui, unsigned int> (ctxt, result, "jit_v4ui_div", check_div);
+
+ verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_add", check_add);
+ verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_sub", check_sub);
+ verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_mult", check_mult);
+ verify_vec_code<v4f, float> (ctxt, result, "jit_v4f_div", check_div);
+}
--
1.8.5.3
More information about the Gcc-patches
mailing list