libgccjit: Add convert vector

gcc/jit/ChangeLog:

	* docs/topics/compatibility.rst (LIBGCCJIT_ABI_30): New ABI tag.
	* docs/topics/expressions.rst: Document gcc_jit_context_convert_vector.
	* jit-playback.cc (convert_vector): New method.
	* jit-playback.h: New method.
	* jit-recording.cc (recording::context::new_convert_vector,
	recording::convert_vector::replay_into,
	recording::convert_vector::visit_children,
	recording::convert_vector::make_debug_string,
	recording::convert_vector::write_reproducer): New methods.
	* jit-recording.h (class convert_vector): New class.
	(context::new_convert_vector): New method.
	* libgccjit.cc (gcc_jit_context_convert_vector): New function.
	* libgccjit.h (gcc_jit_context_convert_vector): New function.
	* libgccjit.map: New function.

gcc/testsuite/ChangeLog:

	* jit.dg/all-non-failing-tests.h: New test.
	* jit.dg/test-convert-vector.c: New test.
This commit is contained in:
Antoni Boucher 2022-05-14 17:24:29 -04:00
parent b8ac365db7
commit fe97ac43e0
11 changed files with 286 additions and 0 deletions

View file

@ -411,3 +411,10 @@ on functions and variables:
--------------------
``LIBGCCJIT_ABI_29`` covers the addition of
:func:`gcc_jit_global_set_readonly`
.. _LIBGCCJIT_ABI_30:
``LIBGCCJIT_ABI_30``
--------------------
``LIBGCCJIT_ABI_30`` covers the addition of
:func:`gcc_jit_context_convert_vector`

View file

@ -727,6 +727,25 @@ Type-coercion
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
.. function:: gcc_jit_rvalue *
gcc_jit_context_convert_vector (gcc_jit_context *ctxt, \
gcc_jit_location *loc, \
gcc_jit_rvalue *vector, \
gcc_jit_type *type)
Given a vector rvalue, cast it to the type ``type``, doing an element-wise
conversion.
The number of elements in ``vector`` and ``type`` must match.
The ``type`` must be a vector type.
This entrypoint was added in :ref:`LIBGCCJIT_ABI_30`; you can test for
its presence using
.. code-block:: c
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_convert_vector
Lvalues
-------

View file

@ -1694,6 +1694,34 @@ new_array_access (location *loc,
}
}
/* Construct a playback::rvalue instance (wrapping a tree) for a
vector conversion. */
playback::rvalue *
playback::context::
convert_vector (location *loc,
rvalue *vector,
type *type)
{
gcc_assert (vector);
gcc_assert (type);
/* For comparison, see:
c/c-common.cc: c_build_vec_convert
*/
tree t_vector = vector->as_tree ();
tree t_result =
build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_VEC_CONVERT,
type->as_tree (), 1, t_vector);
if (loc)
set_tree_location (t_result, loc);
return new rvalue (this, t_result);
}
/* Construct a tree for a field access. */
tree

View file

@ -222,6 +222,11 @@ public:
rvalue *ptr,
rvalue *index);
rvalue *
convert_vector (location *loc,
rvalue *vector,
type *type);
void
set_str_option (enum gcc_jit_str_option opt,
const char *value);

View file

@ -1341,6 +1341,23 @@ recording::context::new_array_access (recording::location *loc,
return result;
}
/* Create a recording::convert_vector instance and add it to this context's list
of mementos.
Implements the post-error-checking part of
gcc_jit_context_convert_vector. */
recording::rvalue *
recording::context::new_convert_vector (recording::location *loc,
recording::rvalue *vector,
recording::type *type)
{
// TODO: instead have an "internal function" memento?
recording::rvalue *result = new convert_vector (this, loc, vector, type);
record (result);
return result;
}
/* Create a recording::case_ instance and add it to this context's list
of mementos.
@ -6572,6 +6589,61 @@ recording::array_access::write_reproducer (reproducer &r)
r.get_identifier_as_rvalue (m_index));
}
/* The implementation of class gcc::jit::recording::convert_vector. */
/* Implementation of pure virtual hook recording::memento::replay_into
for recording::convert_vector. */
void
recording::convert_vector::replay_into (replayer *r)
{
set_playback_obj (
r->convert_vector (playback_location (r, m_loc),
m_vector->playback_rvalue (),
m_type->playback_type ()));
}
/* Implementation of pure virtual hook recording::rvalue::visit_children
for recording::convert_vector. */
void
recording::convert_vector::visit_children (rvalue_visitor *v)
{
v->visit (m_vector);
}
/* Implementation of recording::memento::make_debug_string for
array accesses. */
recording::string *
recording::convert_vector::make_debug_string ()
{
enum precedence prec = get_precedence ();
return string::from_printf (m_ctxt,
"(%s)%s",
m_type->get_debug_string (),
m_vector->get_debug_string_parens (prec));
}
/* Implementation of recording::memento::write_reproducer for
convert_vector. */
void
recording::convert_vector::write_reproducer (reproducer &r)
{
const char *id = r.make_identifier (this, "lvalue");
r.write (" gcc_jit_rvalue *%s = \n"
" gcc_jit_context_convert_vector (%s, /* gcc_jit_context *ctxt */\n"
" %s, /*gcc_jit_location *loc */\n"
" %s, /* gcc_jit_rvalue *vector */\n"
" %s); /* gcc_jit_type *type */\n",
id,
r.get_identifier (get_context ()),
r.get_identifier (m_loc),
r.get_identifier_as_rvalue (m_vector),
r.get_identifier_as_type (m_type));
}
/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
/* Implementation of pure virtual hook recording::memento::replay_into

View file

@ -230,6 +230,11 @@ public:
rvalue *ptr,
rvalue *index);
rvalue *
new_convert_vector (location *loc,
rvalue *vector,
type *type);
case_ *
new_case (rvalue *min_value,
rvalue *max_value,
@ -2004,6 +2009,35 @@ private:
rvalue *m_index;
};
class convert_vector : public rvalue
{
public:
convert_vector (context *ctxt,
location *loc,
rvalue *vector,
type *type)
: rvalue (ctxt, loc, type),
m_vector (vector),
m_type (type)
{}
void replay_into (replayer *r) final override;
void visit_children (rvalue_visitor *v) 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_POSTFIX;
}
private:
rvalue *m_vector;
type *m_type;
};
class access_field_of_lvalue : public lvalue
{
public:

View file

@ -2556,6 +2556,42 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
return (gcc_jit_lvalue *)ctxt->new_array_access (loc, ptr, index);
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
gcc::jit::recording::context::new_convert_vector method in
jit-recording.cc. */
gcc_jit_rvalue *
gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_rvalue *vector,
gcc_jit_type *type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (vector, ctxt, loc, "NULL vector");
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
gcc::jit::recording::vector_type *value_vec_type
= vector->get_type ()->dyn_cast_vector_type ();
RETURN_NULL_IF_FAIL_PRINTF1 (value_vec_type, ctxt, loc,
"%s is not a value of a vector type",
vector->get_debug_string ());
gcc::jit::recording::vector_type *as_vec_type
= type->dyn_cast_vector_type ();
RETURN_NULL_IF_FAIL_PRINTF1 (as_vec_type, ctxt, loc,
"%s is not a vector type",
type->get_debug_string ());
RETURN_NULL_IF_FAIL_PRINTF2 (
as_vec_type->get_num_units () == value_vec_type->get_num_units (), ctxt,
loc, "%s should contain the same number of elements as %s",
vector->get_debug_string (), type->get_debug_string ());
return (gcc_jit_rvalue *)ctxt->new_convert_vector (loc, vector, type);
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the

View file

@ -1338,6 +1338,16 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_rvalue *ptr,
gcc_jit_rvalue *index);
#define LIBGCCJIT_HAVE_gcc_jit_context_convert_vector
/* Given a vector rvalue, cast it to the type ``type``, doing an element-wise
conversion. */
extern gcc_jit_rvalue *
gcc_jit_context_convert_vector (gcc_jit_context *ctxt,
gcc_jit_location *loc,
gcc_jit_rvalue *vector,
gcc_jit_type *type);
/* Field access is provided separately for both lvalues and rvalues. */
/* Accessing a field of an lvalue of struct type, analogous to:

View file

@ -299,3 +299,8 @@ LIBGCCJIT_ABI_29 {
global:
gcc_jit_global_set_readonly;
} LIBGCCJIT_ABI_28;
LIBGCCJIT_ABI_30 {
global:
gcc_jit_context_convert_vector;
} LIBGCCJIT_ABI_29;

View file

@ -148,6 +148,13 @@
/* test-const-attribute.c: This can't be in the testcases array as it needs
the `-O3` flag. */
/* test-convert-vector.c */
#define create_code create_code_convert_vector
#define verify_code verify_code_convert_vector
#include "test-convert-vector.c"
#undef create_code
#undef verify_code
/* test-debug-strings.c */
#define create_code create_code_debug_strings
#define verify_code verify_code_debug_strings
@ -504,6 +511,9 @@ const struct testcase testcases[] = {
{"constants",
create_code_constants,
verify_code_constants},
{"convert_vector",
create_code_convert_vector,
verify_code_convert_vector},
{"debug_strings",
create_code_debug_strings,
verify_code_debug_strings},

View file

@ -0,0 +1,60 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "libgccjit.h"
#include "harness.h"
void
create_code (gcc_jit_context *ctxt, void *user_data)
{
/* Let's try to inject the equivalent of:
int __attribute__ ((__vector_size__ (8))) convert_vec(double __attribute__ ((__vector_size__ (16))) double_vec)
{
return __builtin_convertvector (double_vec, int __attribute__ ((__vector_size__ (8))));
}
*/
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
gcc_jit_type *int_vector_type =
gcc_jit_type_get_vector (int_type, 2);
gcc_jit_type *double_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
gcc_jit_type *double_vector_type =
gcc_jit_type_get_vector (double_type, 2);
/* Build the convert_vec. */
gcc_jit_param *param =
gcc_jit_context_new_param (ctxt, NULL, double_vector_type, "double_vec");
gcc_jit_function *convert_vec =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
int_vector_type,
"convert_vec",
1, &param,
0);
gcc_jit_block *block = gcc_jit_function_new_block (convert_vec, NULL);
gcc_jit_lvalue *var = gcc_jit_function_new_local (convert_vec, NULL, double_vector_type, "mem_vec");
gcc_jit_block_add_assignment (block, NULL, var, gcc_jit_param_as_rvalue (param));
gcc_jit_block_end_with_return (block,
NULL,
gcc_jit_context_convert_vector (ctxt, NULL, gcc_jit_lvalue_as_rvalue (var), int_vector_type));
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
CHECK_NON_NULL (result);
typedef int __attribute__ ((__vector_size__ (8))) (*convert_vec)(double __attribute__ ((__vector_size__ (16))) double_vec);
double __attribute__ ((__vector_size__ (16))) double_vec = { 3.2, 7.9 };
convert_vec func = (convert_vec)gcc_jit_result_get_code (result, "convert_vec");
int __attribute__ ((__vector_size__ (8))) res = func (double_vec);
int __attribute__ ((__vector_size__ (8))) expected = { 3, 7 };
CHECK_VECTOR_VALUE (2, res, expected);
}