From ca4b3606c853b3425cf4ef9e88fbd5939f0e8f7c Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 14 May 2022 17:24:29 -0400 Subject: [PATCH] libgccjit: Add convert vector gcc/jit/ChangeLog: * docs/topics/compatibility.rst (LIBGCCJIT_ABI_26): 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. --- gcc/jit/docs/topics/compatibility.rst | 7 ++ gcc/jit/docs/topics/expressions.rst | 18 +++++ gcc/jit/jit-playback.cc | 31 +++++++++ gcc/jit/jit-playback.h | 5 ++ gcc/jit/jit-recording.cc | 72 ++++++++++++++++++++ gcc/jit/jit-recording.h | 34 +++++++++ gcc/jit/libgccjit.cc | 36 ++++++++++ gcc/jit/libgccjit.h | 8 +++ gcc/jit/libgccjit.map | 5 ++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++ gcc/testsuite/jit.dg/test-convert-vector.c | 56 +++++++++++++++ 11 files changed, 282 insertions(+) create mode 100644 gcc/testsuite/jit.dg/test-convert-vector.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index ebede440ee4..33eb1a0bc06 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -378,3 +378,10 @@ alignment of a variable: -------------------- ``LIBGCCJIT_ABI_25`` covers the addition of :func:`gcc_jit_type_get_restrict` + +.. _LIBGCCJIT_ABI_26: + +``LIBGCCJIT_ABI_26`` +-------------------- +``LIBGCCJIT_ABI_26`` covers the addition of +:func:`gcc_jit_context_convert_vector` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index 42cfee36302..a75e69bf1f4 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -699,6 +699,24 @@ 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``. + + 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_26`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_convert_vector + Lvalues ------- diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index dddd537f3b1..48901d71418 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -1527,6 +1527,37 @@ 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 (); + + /* It seems IFN_VEC_CONVERT only work on registers, not on memory. */ + if (TREE_CODE (t_vector) == VAR_DECL) + DECL_REGISTER (t_vector) = 1; + 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 diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index b0166f8f6ce..59ffd739875 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -191,6 +191,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); diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 9b5b8005ebe..a0ce834a610 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -1309,6 +1309,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. @@ -6307,6 +6324,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 diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 4a8082991fb..7650e2a8241 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -215,6 +215,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, @@ -1907,6 +1912,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: diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 0451b4df7f9..517ef46628c 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -2503,6 +2503,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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 749f6c24177..00beab8f397 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1301,6 +1301,14 @@ 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 + +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: diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 8b90a0e2ff3..e95d7be5d09 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -276,3 +276,8 @@ LIBGCCJIT_ABI_25 { global: gcc_jit_type_get_restrict; } LIBGCCJIT_ABI_24; + +LIBGCCJIT_ABI_26 { + global: + gcc_jit_context_convert_vector; +} LIBGCCJIT_ABI_25; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index e762563f9bd..528e5b4f921 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -126,6 +126,13 @@ #undef create_code #undef verify_code +/* 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 @@ -437,6 +444,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}, diff --git a/gcc/testsuite/jit.dg/test-convert-vector.c b/gcc/testsuite/jit.dg/test-convert-vector.c new file mode 100644 index 00000000000..b9bf648cd9a --- /dev/null +++ b/gcc/testsuite/jit.dg/test-convert-vector.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +#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, ¶m, + 0); + gcc_jit_block *block = gcc_jit_function_new_block (convert_vec, NULL); + gcc_jit_block_end_with_return (block, + NULL, + gcc_jit_context_convert_vector (ctxt, NULL, gcc_jit_param_as_rvalue (param), 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); +} -- 2.43.0