From patchwork Mon Jan 17 22:18:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoni Boucher X-Patchwork-Id: 50123 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E7D2B385802F for ; Mon, 17 Jan 2022 22:18:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E7D2B385802F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1642457919; bh=LaA3wxcgNSVYpN96UiVVkNmP+CfvmV70Esmo/c9llPc=; h=Subject:To:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=SRzAhXDuEJVcVHwstPYqbyzbdT+kucGpdHtDr/U8bXHY/1htkQKAfrBHfFMyay5eX GnmdVsBlWK7NikNGzPQRJw9AzoMxOhqNTjtnJ/mtmAtVTv7vz3tSJsCPmMlASzIVOV CmPuMosc7hh/BXCOrQXJj7p4gt4SDmW6Tip+CBc0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from sender4-pp-o91.zoho.com (sender4-pp-o91.zoho.com [136.143.188.91]) by sourceware.org (Postfix) with ESMTPS id 891E43858D3C; Mon, 17 Jan 2022 22:18:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 891E43858D3C ARC-Seal: i=1; a=rsa-sha256; t=1642457885; cv=none; d=zohomail.com; s=zohoarc; b=mE3oIAzTgU8X8/n2l2isgsu5vqy4mMQEoSltBKHckCeMAGzxBttXKXtZ7gXg4o1A15fR84CeexJES+KyWvZl5y333P/XDTfwaWlj+m4wNVi83UEZYa41JI1wzPxF3cSRpQYi45saZi0wD+HceKjsSTrT7v79ISUPE5X0fQABZi4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642457885; h=Content-Type:Date:From:MIME-Version:Message-ID:Subject:To; bh=LaA3wxcgNSVYpN96UiVVkNmP+CfvmV70Esmo/c9llPc=; b=B0+MMI1dY5gLPMXr67tUft3CveFU/zob8Qrog10pF/VvEq3uTdVe2FGzjh8wUJV88+HHSzI/tExMahadTLJvBElHkAksFsI1xfh4h5IDbzbBA+Bvvyhm/v/+9+q/vwudN6QEFDwbuJ3l6cVYn0rt3UAkNh8F+f30LqHTHcnpAak= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=zoho.com; spf=pass smtp.mailfrom=bouanto@zoho.com; dmarc=pass header.from= Received: from [192.168.1.174] (38.87.11.6 [38.87.11.6]) by mx.zohomail.com with SMTPS id 1642457882982915.8716720902992; Mon, 17 Jan 2022 14:18:02 -0800 (PST) Message-ID: <13bdd05cfd7006a332ec785ab371356f0354db4d.camel@zoho.com> Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071] To: gcc-patches@gcc.gnu.org, jit@gcc.gnu.org Date: Mon, 17 Jan 2022 17:18:01 -0500 User-Agent: Evolution 3.42.3 MIME-Version: 1.0 X-Zoho-Virus-Status: 1 X-ZohoMailClient: External X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Antoni Boucher via Gcc-patches From: Antoni Boucher Reply-To: Antoni Boucher Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi. This patch add support for bitcasts in libgccjit. It passes the JIT tests, but since I added a function in tree.c, I wonder if I should run the whole testsuite. David, you can now disregard my question in my email about 128-bit integers regarding my issue with initialize_sizetypes being called multiple times because this patch fix this issue. I turns out there was a cache of types that needed to be cleared when you initialize the JIT. The check for sizes is pending, because it requires the updates to get_size I made in my patch for 128-bit integers. Thanks for the review! From 35e113b51c416af0c13bc7eb160ff6c0cbcff813 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 9 Jun 2021 18:29:14 -0400 Subject: [PATCH] libgccjit: Add support for bitcasts [PR104071] 2022-01-17 Antoni Boucher gcc/jit/ PR target/104071 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_20): New ABI tag. * docs/topics/expressions.rst: Add documentation for the function gcc_jit_context_new_bitcast. * dummy-frontend.c: clear the cache of non-standard integer types to avoid having issues with some optimizations of bitcast where the SSA_NAME will have a size of a cached integer type that should have been invalidated, causing a comparison of integer constant to fail. * jit-playback.c: New function (new_bitcast). * jit-playback.h: New function (new_bitcast). * jit-recording.c: New functions (new_bitcast, bitcast::replay_into, bitcast::visit_children, bitcast::make_debug_string, bitcast::write_reproducer). * jit-recording.h: New calss (bitcast) and new function (new_bitcast, bitcast::replay_into, bitcast::visit_children, bitcast::make_debug_string, bitcast::write_reproducer, bitcast::get_precedence). * libgccjit.c: New function (gcc_jit_context_new_bitcast) * libgccjit.h: New function (gcc_jit_context_new_bitcast) * libgccjit.map (LIBGCCJIT_ABI_20): New ABI tag. gcc/testsuite/ PR target/104071 * jit.dg/all-non-failing-tests.h: Add new test-bitcast. * jit.dg/test-bitcast.c: New test. gcc/ PR target/104071 * tree.c: New function (clear_nonstandard_integer_type_cache). * tree.h: New function (clear_nonstandard_integer_type_cache). --- gcc/jit/docs/topics/compatibility.rst | 9 +++ gcc/jit/docs/topics/expressions.rst | 10 +++ gcc/jit/dummy-frontend.c | 2 + gcc/jit/jit-playback.c | 13 ++++ gcc/jit/jit-playback.h | 5 ++ gcc/jit/jit-recording.c | 66 ++++++++++++++++++++ gcc/jit/jit-recording.h | 32 ++++++++++ gcc/jit/libgccjit.c | 28 +++++++++ gcc/jit/libgccjit.h | 9 +++ gcc/jit/libgccjit.map | 6 ++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++ gcc/testsuite/jit.dg/test-bitcast.c | 60 ++++++++++++++++++ gcc/tree.c | 8 +++ gcc/tree.h | 1 + 14 files changed, 259 insertions(+) create mode 100644 gcc/testsuite/jit.dg/test-bitcast.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 16cebe31a10..b5a6b704dda 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -302,3 +302,12 @@ thread-local storage model of a variable: section of a variable: * :func:`gcc_jit_lvalue_set_link_section` + +.. _LIBGCCJIT_ABI_20: + +``LIBGCCJIT_ABI_20`` +----------------------- +``LIBGCCJIT_ABI_20`` covers the addition of an API entrypoint to bitcast a +value from one type to another: + + * :func:`gcc_jit_context_new_bitcast` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index 791a20398ca..6e0b5db777b 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -649,6 +649,16 @@ Type-coercion * int <-> bool * P* <-> Q*, for pointer types P and Q +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *rvalue,\ + gcc_jit_type *type) + + Given an rvalue of T, bitcast it to another type. + + The type of rvalue must be the same size as the size of ``type``. + Lvalues ------- diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c index 84ff359bfe3..c3da97642e3 100644 --- a/gcc/jit/dummy-frontend.c +++ b/gcc/jit/dummy-frontend.c @@ -592,6 +592,8 @@ jit_langhook_init (void) global_dc->begin_diagnostic = jit_begin_diagnostic; global_dc->end_diagnostic = jit_end_diagnostic; + clear_nonstandard_integer_type_cache (); + build_common_tree_nodes (false); /* I don't know why this has to be done explicitly. */ diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 1d64caf4e20..4ad2f6ce41d 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -1390,6 +1390,19 @@ new_cast (playback::location *loc, return new rvalue (this, t_cast); } +playback::rvalue * +playback::context:: +new_bitcast (location *loc, + rvalue *expr, + type *type_) +{ + tree t_bitcast = build1 (VIEW_CONVERT_EXPR, + type_->as_tree (), expr->as_tree ()); + if (loc) + set_tree_location (t_bitcast, loc); + return new rvalue (this, t_bitcast); +} + /* Construct a playback::lvalue instance (wrapping a tree) for an array access. */ diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index c93d7055d43..5b107be9d69 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -180,6 +180,11 @@ public: rvalue *expr, type *type_); + rvalue * + new_bitcast (location *loc, + rvalue *expr, + type *type_); + lvalue * new_array_access (location *loc, rvalue *ptr, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index ee8934131d1..ae3381b586d 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -1242,6 +1242,22 @@ recording::context::new_cast (recording::location *loc, return result; } +/* Create a recording::bitcast instance and add it to this context's list + of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_bitcast. */ + +recording::rvalue * +recording::context::new_bitcast (location *loc, + rvalue *expr, + type *type_) +{ + recording::rvalue *result = new bitcast (this, loc, expr, type_); + record (result); + return result; +} + /* Create a recording::call instance and add it to this context's list of mementos. @@ -5740,6 +5756,56 @@ recording::cast::write_reproducer (reproducer &r) r.get_identifier_as_type (get_type ())); } +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::bitcast. */ + +void +recording::bitcast::replay_into (replayer *r) +{ + set_playback_obj (r->new_bitcast (playback_location (r, m_loc), + m_rvalue->playback_rvalue (), + get_type ()->playback_type ())); +} + +/* Implementation of pure virtual hook recording::rvalue::visit_children + for recording::bitcast. */ +void +recording::bitcast::visit_children (rvalue_visitor *v) +{ + v->visit (m_rvalue); +} + +/* Implementation of recording::memento::make_debug_string for + casts. */ + +recording::string * +recording::bitcast::make_debug_string () +{ + enum precedence prec = get_precedence (); + return string::from_printf (m_ctxt, + "bitcast(%s, %s)", + m_rvalue->get_debug_string_parens (prec), + get_type ()->get_debug_string ()); +} + +/* Implementation of recording::memento::write_reproducer for casts. */ + +void +recording::bitcast::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "rvalue"); + r.write (" gcc_jit_rvalue *%s =\n" + " gcc_jit_context_new_bitcast (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_rvalue *rvalue */\n" + " %s); /* gcc_jit_type *type */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_rvalue (m_rvalue), + r.get_identifier_as_type (get_type ())); +} + /* The implementation of class gcc::jit::recording::base_call. */ /* The constructor for gcc::jit::recording::base_call. */ diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index b663d0f21f5..713aac36ebe 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -205,6 +205,11 @@ public: rvalue *expr, type *type_); + rvalue * + new_bitcast (location *loc, + rvalue *expr, + type *type_); + lvalue * new_array_access (location *loc, rvalue *ptr, @@ -1691,6 +1696,33 @@ private: rvalue *m_rvalue; }; +class bitcast : public rvalue +{ +public: + bitcast (context *ctxt, + location *loc, + rvalue *a, + type *type_) + : rvalue (ctxt, loc, type_), + m_rvalue (a) + {} + + 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_CAST; + } + +private: + rvalue *m_rvalue; +}; + class base_call : public rvalue { public: diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 03704ef10b8..cd8516d1c4d 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -2405,6 +2405,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt, return static_cast (ctxt->new_cast (loc, rvalue, type)); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::new_bitcast method in jit-recording.c. */ + +gcc_jit_rvalue * +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *rvalue, + 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 (rvalue, ctxt, loc, "NULL rvalue"); + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); + // TODO: check the sizes. + /*RETURN_NULL_IF_FAIL_PRINTF3 ( + is_valid_cast (rvalue->get_type (), type), + ctxt, loc, + "cannot cast %s from type: %s to type: %s", + rvalue->get_debug_string (), + rvalue->get_type ()->get_debug_string (), + type->get_debug_string ());*/ + + return static_cast (ctxt->new_bitcast (loc, rvalue, 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 2a5ffacb1fe..de4f9daaebc 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1206,6 +1206,15 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt, gcc_jit_rvalue *rvalue, gcc_jit_type *type); +/* Reinterpret a value as another type. + + The types must be of the same size. */ +extern gcc_jit_rvalue * +gcc_jit_context_new_bitcast (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_rvalue *rvalue, + gcc_jit_type *type); + extern gcc_jit_lvalue * gcc_jit_context_new_array_access (gcc_jit_context *ctxt, gcc_jit_location *loc, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index f373fd39ac7..7b6f415ac82 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -238,8 +238,14 @@ LIBGCCJIT_ABI_18 { } LIBGCCJIT_ABI_17; LIBGCCJIT_ABI_19 { + global: gcc_jit_context_new_array_constructor; gcc_jit_context_new_struct_constructor; gcc_jit_context_new_union_constructor; gcc_jit_global_set_initializer_rvalue; } LIBGCCJIT_ABI_18; + +LIBGCCJIT_ABI_20 { + global: + gcc_jit_context_new_bitcast; +} LIBGCCJIT_ABI_19; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 29afe064db6..656351edce1 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -77,6 +77,13 @@ /* test-builtin-unreachable.c: We don't add this one, since it touches the optimization level of the context as a whole. */ +/* test-bitcast.c */ +#define create_code create_code_bitcast +#define verify_code verify_code_bitcast +#include "test-bitcast.c" +#undef create_code +#undef verify_code + /* test-calling-external-function.c */ #define create_code create_code_calling_external_function #define verify_code verify_code_calling_external_function @@ -400,6 +407,9 @@ const struct testcase testcases[] = { {"builtin-memcpy", create_code_builtin_memcpy, verify_code_builtin_memcpy}, + {"bitcast", + create_code_bitcast, + verify_code_bitcast}, {"calling_external_function", create_code_calling_external_function, verify_code_calling_external_function}, diff --git a/gcc/testsuite/jit.dg/test-bitcast.c b/gcc/testsuite/jit.dg/test-bitcast.c new file mode 100644 index 00000000000..2d70622051a --- /dev/null +++ b/gcc/testsuite/jit.dg/test-bitcast.c @@ -0,0 +1,60 @@ +#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 +my_bitcast (double x) +{ + return bitcast(x, int); +} + */ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *double_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); + + gcc_jit_param *x = + gcc_jit_context_new_param ( + ctxt, + NULL, + double_type, "x"); + gcc_jit_param *params[1] = {x}; + gcc_jit_function *func = + gcc_jit_context_new_function (ctxt, + NULL, + GCC_JIT_FUNCTION_EXPORTED, + int_type, + "my_bitcast", + 1, params, 0); + + gcc_jit_block *initial = + gcc_jit_function_new_block (func, "initial"); + + gcc_jit_block_end_with_return(initial, NULL, + gcc_jit_context_new_bitcast(ctxt, + NULL, + gcc_jit_param_as_rvalue(x), + int_type + )); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef int (*my_bitcast_fn_type) (double); + CHECK_NON_NULL (result); + my_bitcast_fn_type my_bitcast = + (my_bitcast_fn_type)gcc_jit_result_get_code (result, "my_bitcast"); + CHECK_NON_NULL (my_bitcast); + int val = my_bitcast (-5.1298714); + note ("my_bitcast returned: %d", val); + CHECK_VALUE (val, 35569201); +} diff --git a/gcc/tree.c b/gcc/tree.c index d98b77db50b..e4bf4e84675 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6963,6 +6963,14 @@ build_reference_type (tree to_type) (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64) static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2]; +void clear_nonstandard_integer_type_cache (void) +{ + for (size_t i = 0 ; i < 2 * MAX_INT_CACHED_PREC + 2 ; i++) + { + nonstandard_integer_type_cache[i] = NULL; + } +} + /* Builds a signed or unsigned integer type of precision PRECISION. Used for C bitfields whose precision does not match that of built-in target types. */ diff --git a/gcc/tree.h b/gcc/tree.h index 318019c4dc5..640b492802c 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5385,6 +5385,7 @@ extern bool real_minus_onep (const_tree); extern void init_ttree (void); extern void build_common_tree_nodes (bool); extern void build_common_builtin_nodes (void); +extern void clear_nonstandard_integer_type_cache (void); extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int); extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT); extern tree build_range_type (tree, tree, tree); -- 2.26.2.7.g19db9cfb68.dirty