--------------------
``LIBGCCJIT_ABI_30`` covers the addition of
:func:`gcc_jit_context_convert_vector`
+=======
+
+.. _LIBGCCJIT_ABI_31:
+
+``LIBGCCJIT_ABI_31``
+--------------------
+``LIBGCCJIT_ABI_31`` covers the addition of functions to manipulate vectors:
+
+ * :func:`gcc_jit_context_new_rvalue_vector_perm`
+ * :func:`gcc_jit_context_new_vector_access`
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
+.. function:: gcc_jit_rvalue * \
+ gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt, \
+ gcc_jit_location *loc, \
+ gcc_jit_rvalue *elements1, \
+ gcc_jit_rvalue *elements2, \
+ gcc_jit_rvalue *mask);
+
+ Build a permutation of two vectors.
+
+ "elements1" and "elements2" should have the same type.
+ The length of "mask" and "elements1" should be the same.
+ The element type of "mask" should be integral.
+ The size of the element type of "mask" and "elements1" should be the same.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_31`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+ Analogous to:
+
+ .. code-block:: c
+
+ __builtin_shuffle (elements1, elements2, mask)
+
+ in C.
+
Unary Operations
****************
PTR[INDEX]
in C (or, indeed, to ``PTR + INDEX``).
+
+.. function:: gcc_jit_lvalue *\
+ gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_rvalue *vector,\
+ gcc_jit_rvalue *index)
+
+ Given an rvalue of vector type ``T __attribute__ ((__vector_size__ (SIZE)))``,
+ get the element `T` at the given index.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_31`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+ Analogous to:
+
+ .. code-block:: c
+
+ VECTOR[INDEX]
+
+ in C.
return new rvalue (this, t_ctor);
}
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ vector perm. */
+
+playback::rvalue *
+playback::context::new_rvalue_vector_perm (location *loc,
+ rvalue* elements1,
+ rvalue* elements2,
+ rvalue* mask)
+{
+ tree t_elements1 = elements1->as_tree ();
+ tree t_elements2 = elements2->as_tree ();
+ tree t_mask = mask->as_tree ();
+
+ tree t_vector_perm = build3 (VEC_PERM_EXPR, TREE_TYPE (t_elements1),
+ t_elements1, t_elements2, t_mask);
+ if (loc)
+ set_tree_location (t_vector_perm, loc);
+ return new rvalue (this, t_vector_perm);
+}
+
/* Coerce a tree expression into a boolean tree expression. */
tree
return new rvalue (this, t_result);
}
+/* The following functions come from c-common.h. */
+/* Like c_mark_addressable but don't check register qualifier. */
+void
+common_mark_addressable_vec (tree t)
+{
+ while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR)
+ {
+ t = TREE_OPERAND (t, 0);
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != COMPOUND_LITERAL_EXPR
+ && TREE_CODE (t) != TARGET_EXPR)
+ return;
+ if (!VAR_P (t) || !DECL_HARD_REGISTER (t))
+ TREE_ADDRESSABLE (t) = 1;
+ if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+ TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
+ else if (TREE_CODE (t) == TARGET_EXPR)
+ TREE_ADDRESSABLE (TARGET_EXPR_SLOT (t)) = 1;
+}
+
+/* Return true if TYPE is a vector type that should be subject to the GNU
+ vector extensions (as opposed to a vector type that is used only for
+ the purposes of defining target-specific built-in functions). */
+
+inline bool
+gnu_vector_type_p (const_tree type)
+{
+ return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
+}
+
+/* Return nonzero if REF is an lvalue valid for this language.
+ Lvalues can be assigned, unless their type has TYPE_READONLY.
+ Lvalues can have their address taken, unless they have C_DECL_REGISTER. */
+
+bool
+lvalue_p (const_tree ref)
+{
+ const enum tree_code code = TREE_CODE (ref);
+
+ switch (code)
+ {
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case COMPONENT_REF:
+ return lvalue_p (TREE_OPERAND (ref, 0));
+
+ case C_MAYBE_CONST_EXPR:
+ return lvalue_p (TREE_OPERAND (ref, 1));
+
+ case COMPOUND_LITERAL_EXPR:
+ case STRING_CST:
+ return true;
+
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ /* MEM_REFs can appear from -fgimple parsing or folding, so allow them
+ here as well. */
+ case INDIRECT_REF:
+ case ARRAY_REF:
+ case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case ERROR_MARK:
+ return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
+
+ case BIND_EXPR:
+ return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
+
+ default:
+ return false;
+ }
+}
+
+bool
+convert_vector_to_array_for_subscript (tree *vecp)
+{
+ bool ret = false;
+ if (gnu_vector_type_p (TREE_TYPE (*vecp)))
+ {
+ tree type = TREE_TYPE (*vecp);
+
+ ret = !lvalue_p (*vecp);
+
+ /* We are building an ARRAY_REF so mark the vector as addressable
+ to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P
+ for function parameters. */
+ /* NOTE: that was the missing piece for making vector access work with
+ optimizations enabled. */
+ common_mark_addressable_vec (*vecp);
+
+ *vecp = build1 (VIEW_CONVERT_EXPR,
+ build_array_type_nelts (TREE_TYPE (type),
+ TYPE_VECTOR_SUBPARTS (type)),
+ *vecp);
+ }
+ return ret;
+}
+
+/* Construct a playback::lvalue instance (wrapping a tree) for a
+ vector access. */
+
+playback::lvalue *
+playback::context::
+new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index)
+{
+ gcc_assert (vector);
+ gcc_assert (index);
+
+ /* For comparison, see:
+ c/c-typeck.cc: build_array_ref
+ */
+
+ tree t_vector = vector->as_tree ();
+ bool non_lvalue = convert_vector_to_array_for_subscript (&t_vector);
+ tree type = TREE_TYPE (TREE_TYPE (t_vector));
+ tree t_result = build4 (ARRAY_REF, type, t_vector, index->as_tree (),
+ NULL_TREE, NULL_TREE);
+ if (non_lvalue)
+ t_result = non_lvalue (t_result);
+
+ if (loc)
+ set_tree_location (t_result, loc);
+ return new lvalue (this, t_result);
+}
+
/* Construct a tree for a field access. */
tree
type *type,
const auto_vec<rvalue *> &elements);
+ rvalue *
+ new_rvalue_vector_perm (location *loc,
+ rvalue* elements1,
+ rvalue* elements2,
+ rvalue* mask);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
convert_vector (location *loc,
rvalue *vector,
type *type);
+ lvalue *
+ new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index);
void
set_str_option (enum gcc_jit_str_option opt,
return result;
}
+recording::rvalue *
+recording::context::new_rvalue_vector_perm (location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask)
+{
+ recording::rvalue *result
+ = new memento_of_new_rvalue_vector_perm (this, loc, elements1, elements2,
+ mask);
+ record (result);
+ return result;
+}
+
recording::rvalue *
recording::context::new_ctor (recording::location *loc,
recording::type *type,
return result;
}
+/* Create a recording::vector_access instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_vector_access. */
+
+recording::lvalue *
+recording::context::new_vector_access (recording::location *loc,
+ recording::rvalue *vector,
+ recording::rvalue *index)
+{
+ recording::lvalue *result = new vector_access (this, loc, vector, index);
+ record (result);
+ return result;
+}
+
/* Create a recording::case_ instance and add it to this context's list
of mementos.
elements_id);
}
+/* The implementation of class
+ gcc::jit::recording::memento_of_new_rvalue_vector_perm. */
+
+/* The constructor for
+ gcc::jit::recording::memento_of_new_rvalue_vector_perm. */
+
+recording::memento_of_new_rvalue_vector_perm::
+memento_of_new_rvalue_vector_perm (context *ctxt,
+ location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask)
+: rvalue (ctxt, loc, elements1->get_type ()),
+ m_elements1 (elements1),
+ m_elements2 (elements2),
+ m_mask (mask)
+{
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_vector_perm. */
+
+void
+recording::memento_of_new_rvalue_vector_perm::replay_into (replayer *r)
+{
+ playback::rvalue *playback_elements1 = m_elements1->playback_rvalue ();
+ playback::rvalue *playback_elements2 = m_elements2->playback_rvalue ();
+ playback::rvalue *playback_mask = m_mask->playback_rvalue ();
+
+ set_playback_obj (r->new_rvalue_vector_perm (playback_location (r, m_loc),
+ playback_elements1,
+ playback_elements2,
+ playback_mask));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::memento_of_new_rvalue_from_vector. */
+
+ void
+recording::memento_of_new_rvalue_vector_perm::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_elements1);
+ v->visit (m_elements2);
+ v->visit (m_mask);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ vectors. */
+
+ recording::string *
+recording::memento_of_new_rvalue_vector_perm::make_debug_string ()
+{
+ /* Now build a string. */
+ string *result = string::from_printf (m_ctxt,
+ "shufflevector (%s, %s, %s)",
+ m_elements1->get_debug_string (),
+ m_elements2->get_debug_string (),
+ m_mask->get_debug_string ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vectors. */
+
+ void
+recording::memento_of_new_rvalue_vector_perm::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "vector");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_rvalue_vector_perm (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue **elements1*/\n"
+ " %s, /* gcc_jit_rvalue **elements2*/\n"
+ " %s); /* gcc_jit_rvalue **mask*/\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_elements1),
+ r.get_identifier_as_rvalue (m_elements2),
+ r.get_identifier_as_rvalue (m_mask));
+}
+
void
recording::ctor::visit_children (rvalue_visitor *v)
{
v->visit (m_vector);
}
+/* The implementation of class gcc::jit::recording::vector_access. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::vector_access. */
+
+void
+recording::vector_access::replay_into (replayer *r)
+{
+ set_playback_obj (
+ r->new_vector_access (playback_location (r, m_loc),
+ m_vector->playback_rvalue (),
+ m_index->playback_rvalue ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::vector_access. */
+
+void
+recording::vector_access::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_vector);
+ v->visit (m_index);
+}
+
/* Implementation of recording::memento::make_debug_string for
array accesses. */
r.get_identifier_as_type (m_type));
}
+recording::string *
+recording::vector_access::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "%s[%s]",
+ m_vector->get_debug_string_parens (prec),
+ m_index->get_debug_string_parens (prec));
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vector_access. */
+
+void
+recording::vector_access::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "lvalue");
+ r.write (" gcc_jit_lvalue *%s = \n"
+ " gcc_jit_context_new_vector_access (%s, /* gcc_jit_context *ctxt */\n"
+ " %s, /*gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *vector */\n"
+ " %s); /* gcc_jit_rvalue *index */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_vector),
+ r.get_identifier_as_rvalue (m_index));
+}
+
/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
/* Implementation of pure virtual hook recording::memento::replay_into
vector_type *type,
rvalue **elements);
+ rvalue *
+ new_rvalue_vector_perm (location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
rvalue *vector,
type *type);
+ lvalue *
+ new_vector_access (location *loc,
+ rvalue *vector,
+ rvalue *index);
+
case_ *
new_case (rvalue *min_value,
rvalue *max_value,
return m_other_type->dyn_cast_array_type ();
}
+ vector_type *dyn_cast_vector_type () final override {
+ return m_other_type->dyn_cast_vector_type ();
+ }
+
private:
string * make_debug_string () final override;
void write_reproducer (reproducer &r) final override;
auto_vec<rvalue *> m_elements;
};
+class memento_of_new_rvalue_vector_perm : public rvalue
+{
+public:
+ memento_of_new_rvalue_vector_perm (context *ctxt,
+ location *loc,
+ rvalue *elements1,
+ rvalue *elements2,
+ rvalue *mask);
+
+ 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:
+ rvalue *m_elements1;
+ rvalue *m_elements2;
+ rvalue *m_mask;
+};
+
class ctor : public rvalue
{
public:
type *m_type;
};
+class vector_access : public lvalue
+{
+public:
+ vector_access (context *ctxt,
+ location *loc,
+ rvalue *vector,
+ rvalue *index)
+ : lvalue (ctxt, loc, vector->get_type ()->dyn_cast_vector_type ()
+ ->get_element_type ()),
+ m_vector (vector),
+ m_index (index)
+ {}
+
+ 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;
+ rvalue *m_index;
+};
+
class access_field_of_lvalue : public lvalue
{
public:
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ gcc::jit::recording::vector_type *vector_type = type->dyn_cast_vector_type ();
+ RETURN_NULL_IF_FAIL (vector_type == NULL, ctxt, loc,
+ "cannot cast vector types");
RETURN_NULL_IF_FAIL_PRINTF3 (
is_valid_cast (rvalue->get_type (), type),
ctxt, loc,
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
+ gcc::jit::recording::context::new_vector_access method in
+ jit-recording.cc. */
+
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_rvalue *index)
+{
+ 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 (index, ctxt, loc, "NULL index");
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ vector->get_type ()->dyn_cast_vector_type (),
+ ctxt, loc,
+ "vector: %s (type: %s) is not a vector",
+ vector->get_debug_string (),
+ vector->get_type ()->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ index->get_type ()->is_numeric (),
+ ctxt, loc,
+ "index: %s (type: %s) is not of numeric type",
+ index->get_debug_string (),
+ index->get_type ()->get_debug_string ());
+
+ return (gcc_jit_lvalue *)ctxt->new_vector_access (loc, vector, index);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
(gcc::jit::recording::rvalue **)elements);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_rvalue_vector_perm method, in
+ jit-recording.cc. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *elements1,
+ gcc_jit_rvalue *elements2,
+ gcc_jit_rvalue *mask)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL ctxt");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ RETURN_NULL_IF_FAIL (elements1, ctxt, loc, "NULL elements1");
+ RETURN_NULL_IF_FAIL (elements2, ctxt, loc, "NULL elements2");
+ RETURN_NULL_IF_FAIL (mask, ctxt, loc, "NULL mask");
+
+ /* LOC can be NULL. */
+
+ gcc::jit::recording::type *elements1_type = elements1->get_type ();
+ gcc::jit::recording::type *elements2_type = elements2->get_type ();
+ RETURN_NULL_IF_FAIL_PRINTF4 (
+ compatible_types (elements1->get_type ()->unqualified (),
+ elements2->get_type ()->unqualified ()),
+ ctxt, loc,
+ "mismatching types for vector perm:"
+ " elements1: %s (type: %s) elements2: %s (type: %s)",
+ elements1->get_debug_string (),
+ elements1_type->get_debug_string (),
+ elements2->get_debug_string (),
+ elements2_type->get_debug_string ());
+
+ gcc::jit::recording::type *mask_type = mask->get_type ();
+ gcc::jit::recording::vector_type *mask_vector_type =
+ mask_type->dyn_cast_vector_type ();
+ gcc::jit::recording::vector_type *elements1_vector_type =
+ elements1_type->dyn_cast_vector_type ();
+
+ size_t mask_len = mask_vector_type->get_num_units ();
+ size_t elements1_len = elements1_vector_type->get_num_units ();
+
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ mask_len == elements1_len,
+ ctxt, loc,
+ "mismatching length for mask:"
+ " elements1 length: %ld mask length: %ld",
+ mask_len,
+ elements1_len);
+
+ gcc::jit::recording::type *mask_element_type =
+ mask_vector_type->get_element_type ();
+
+ RETURN_NULL_IF_FAIL (
+ mask_element_type->is_int (),
+ ctxt, loc,
+ "elements of mask must be of an integer type");
+
+ gcc::jit::recording::type *elements1_element_type =
+ elements1_vector_type->get_element_type ();
+ size_t mask_element_size = mask_element_type->get_size ();
+ size_t elements1_element_size = elements1_element_type->get_size ();
+
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ mask_element_size == elements1_element_size,
+ ctxt, loc,
+ "mismatching size for mask element type:"
+ " elements1 element type: %ld mask element type: %ld",
+ mask_element_size,
+ elements1_element_size);
+
+ return (gcc_jit_rvalue *)ctxt->new_rvalue_vector_perm (loc, elements1,
+ elements2, mask);
+}
+
/* A mutex around the cached state in parse_basever.
Ideally this would be within parse_basever, but the mutex is only needed
by libgccjit. */
gcc_jit_rvalue *vector,
gcc_jit_type *type);
+/* Build a permutation vector rvalue from an 3 arrays of elements.
+
+ "vec_type" should be a vector type, created using gcc_jit_type_get_vector.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_31; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+*/
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_vector_perm (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *elements1,
+ gcc_jit_rvalue *elements2,
+ gcc_jit_rvalue *mask);
+
+#define LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+
+/* Get the element at INDEX in VECTOR.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_31; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_VECTOR_OPERATIONS
+*/
+extern gcc_jit_lvalue *
+gcc_jit_context_new_vector_access (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *vector,
+ gcc_jit_rvalue *index);
+
/* Field access is provided separately for both lvalues and rvalues. */
/* Accessing a field of an lvalue of struct type, analogous to:
global:
gcc_jit_context_convert_vector;
} LIBGCCJIT_ABI_29;
+
+LIBGCCJIT_ABI_31 {
+ global:
+ gcc_jit_context_new_vector_access;
+ gcc_jit_context_new_rvalue_vector_perm;
+} LIBGCCJIT_ABI_30;
/* test-weak-attribute.c: This can't be in the testcases array as it
doesn't have a verify_code implementation. */
+/* test-vector-perm.c */
+#define create_code create_code_vector_perm
+#define verify_code verify_code_vector_perm
+#include "test-vector-perm.c"
+#undef create_code
+#undef verify_code
+
/* Now expose the individual testcases as instances of this struct. */
struct testcase
verify_code_version},
{"volatile",
create_code_volatile,
- verify_code_volatile}
+ verify_code_volatile},
+ {"vector_perm",
+ create_code_vector_perm,
+ verify_code_vector_perm},
};
const int num_testcases = (sizeof (testcases) / sizeof (testcases[0]));
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+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 *v4si =
+ gcc_jit_type_get_vector (int_type, 4);
+
+ gcc_jit_function *func_vector =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "vector",
+ 0, NULL,
+ 0);
+
+ gcc_jit_rvalue *elements[4]
+ = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 4),
+ };
+
+ gcc_jit_rvalue *vector
+ = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements);
+
+ gcc_jit_rvalue *index
+ = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2);
+
+ gcc_jit_block *block_a = gcc_jit_function_new_block (func_vector, NULL);
+ gcc_jit_lvalue *value
+ = gcc_jit_context_new_vector_access (ctxt, NULL, vector, index);
+ gcc_jit_block_end_with_return (block_a, NULL, gcc_jit_lvalue_as_rvalue (value));
+
+ gcc_jit_function *func_vector_perm =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ v4si,
+ "vector_perm",
+ 0, NULL,
+ 0);
+
+ gcc_jit_rvalue *elements2[4]
+ = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 5),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 6),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 8),
+ };
+
+ gcc_jit_rvalue *vector2
+ = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, elements2);
+
+ gcc_jit_rvalue *mask_values[4]
+ = { gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 7),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 3),
+ gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0),
+ };
+
+ gcc_jit_rvalue *mask
+ = gcc_jit_context_new_rvalue_from_vector (ctxt, NULL, v4si, 4, mask_values);
+
+ gcc_jit_block *block_b = gcc_jit_function_new_block (func_vector_perm, NULL);
+ gcc_jit_rvalue *result = gcc_jit_context_new_rvalue_vector_perm (ctxt, NULL, vector, vector2, mask);
+ gcc_jit_block_end_with_return (block_b, NULL, result);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_NON_NULL (result);
+
+ typedef int (*vector) ();
+ vector fn = (vector)gcc_jit_result_get_code (result, "vector");
+ CHECK_NON_NULL (fn);
+
+ int vector_access = fn ();
+ CHECK_VALUE (vector_access, 3);
+
+ typedef v4si (*vector_perm) ();
+ vector_perm perm_fn = (vector_perm)gcc_jit_result_get_code (result, "vector_perm");
+ CHECK_NON_NULL (perm_fn);
+
+ v4si vector_perm_res = perm_fn ();
+ v4si expected_vec = { 8, 3, 4, 1 };
+ CHECK_VECTOR_VALUE (4, vector_perm_res, expected_vec);
+}