From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 76707 invoked by alias); 4 Oct 2017 13:45:27 -0000 Mailing-List: contact jit-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Subscribe: Sender: jit-owner@gcc.gnu.org Received: (qmail 76487 invoked by uid 89); 4 Oct 2017 13:45:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.2 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=covers, Operations, unions, playback X-Spam-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 04 Oct 2017 13:45:14 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6E977267D5; Wed, 4 Oct 2017 13:45:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6E977267D5 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from c64.redhat.com (ovpn-112-12.phx2.redhat.com [10.3.112.12]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED3DB5C8B9; Wed, 4 Oct 2017 13:45:11 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org, jit@gcc.gnu.org Cc: Michael Cree , David Malcolm Subject: [committed] jit: implement gcc_jit_context_new_rvalue_from_vector Date: Sun, 01 Jan 2017 00:00:00 -0000 Message-Id: <1507124739-8398-1-git-send-email-dmalcolm@redhat.com> In-Reply-To: <20170917100539.4d4rn3fdsk6uk4xh@tower> References: <20170917100539.4d4rn3fdsk6uk4xh@tower> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 04 Oct 2017 13:45:13 +0000 (UTC) X-IsSubscribed: yes X-SW-Source: 2017-q4/txt/msg00000.txt.bz2 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 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 &elements) +{ + vec *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 &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 &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 &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_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 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 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 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 (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 +#include +#include + +#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 +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 +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 +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 +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 +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 (ctxt, result, "jit_v4si_add", check_add); + verify_vec_code (ctxt, result, "jit_v4si_sub", check_sub); + verify_vec_code (ctxt, result, "jit_v4si_mult", check_mult); + verify_vec_code (ctxt, result, "jit_v4si_div", check_div); + + verify_vec_code (ctxt, result, "jit_v4ui_add", check_add); + verify_vec_code (ctxt, result, "jit_v4ui_sub", check_sub); + verify_vec_code (ctxt, result, "jit_v4ui_mult", check_mult); + verify_vec_code (ctxt, result, "jit_v4ui_div", check_div); + + verify_vec_code (ctxt, result, "jit_v4f_add", check_add); + verify_vec_code (ctxt, result, "jit_v4f_sub", check_sub); + verify_vec_code (ctxt, result, "jit_v4f_mult", check_mult); + verify_vec_code (ctxt, result, "jit_v4f_div", check_div); +} -- 1.8.5.3