https://gcc.gnu.org/g:536163c3f51c679c7ac64333480501a0a89a3d76
commit r16-4546-g536163c3f51c679c7ac64333480501a0a89a3d76 Author: Antoni Boucher <[email protected]> Date: Fri Sep 19 08:44:04 2025 -0400 libgccjit: Add _Float16, _Float32, _Float64 and __float128 support for jit gcc/ChangeLog: * config/i386/i386-jit.cc: Mark new float types as supported. gcc/jit/ChangeLog: * docs/topics/types.rst: Document new types. * dummy-frontend.cc: Support new types in tree_type_to_jit_type. * jit-common.h: Update NUM_GCC_JIT_TYPES. * jit-playback.cc: Support new types in get_tree_node_for_type. * jit-recording.cc: Support new types. * libgccjit.h (gcc_jit_types): Add new types. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: Mention new test. * jit.dg/test-sized-float.c: New test. Diff: --- gcc/config/i386/i386-jit.cc | 12 ++ gcc/jit/docs/topics/types.rst | 8 ++ gcc/jit/dummy-frontend.cc | 26 ++++- gcc/jit/jit-common.h | 2 +- gcc/jit/jit-playback.cc | 33 ++++++ gcc/jit/jit-recording.cc | 43 ++++++- gcc/jit/libgccjit.h | 4 + gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 ++ gcc/testsuite/jit.dg/test-sized-float.c | 167 +++++++++++++++++++++++++++ 9 files changed, 296 insertions(+), 9 deletions(-) diff --git a/gcc/config/i386/i386-jit.cc b/gcc/config/i386/i386-jit.cc index c1e2929a4735..73ca5905c18b 100644 --- a/gcc/config/i386/i386-jit.cc +++ b/gcc/config/i386/i386-jit.cc @@ -65,6 +65,18 @@ ix86_jit_register_target_info (void) jit_target_add_supported_target_dependent_type (GCC_JIT_TYPE_INT128_T); } + if (float16_type_node != NULL && TYPE_PRECISION (float16_type_node) == 16) + jit_target_add_supported_target_dependent_type (GCC_JIT_TYPE_FLOAT16); + + if (float32_type_node != NULL && TYPE_PRECISION (float32_type_node) == 32) + jit_target_add_supported_target_dependent_type (GCC_JIT_TYPE_FLOAT32); + + if (float64_type_node != NULL && TYPE_PRECISION (float64_type_node) == 64) + jit_target_add_supported_target_dependent_type (GCC_JIT_TYPE_FLOAT64); + + if (float128_type_node != NULL && TYPE_PRECISION (float128_type_node) == 128) + jit_target_add_supported_target_dependent_type (GCC_JIT_TYPE_FLOAT128); + #define ADD_TARGET_INFO jit_add_target_info #include "i386-rust-and-jit.inc" #undef ADD_TARGET_INFO diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index 92830652913e..ae4d7d4e2853 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -119,6 +119,14 @@ Standard types - * - :c:data:`GCC_JIT_TYPE_LONG_DOUBLE` - + * - :c:data:`GCC_JIT_TYPE_FLOAT16` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT32` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT64` + - + * - :c:data:`GCC_JIT_TYPE_FLOAT128` + - * - :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` - C type: ``(const char *)`` * - :c:data:`GCC_JIT_TYPE_SIZE_T` diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index faf9d036350f..0668d67099f5 100644 --- a/gcc/jit/dummy-frontend.cc +++ b/gcc/jit/dummy-frontend.cc @@ -1195,12 +1195,6 @@ recording::type* tree_type_to_jit_type (tree type) // FIXME: wrong type. return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); - /* TODO: Remove when we add support for sized floating-point types. */ - for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) - if (type == FLOATN_NX_TYPE_NODE (i)) - // FIXME: wrong type. - return new recording::memento_of_get_type (&target_builtins_ctxt, - GCC_JIT_TYPE_VOID); if (type == void_type_node) return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_VOID); @@ -1266,6 +1260,26 @@ recording::type* tree_type_to_jit_type (tree type) else if (type == bfloat16_type_node) return new recording::memento_of_get_type (&target_builtins_ctxt, GCC_JIT_TYPE_BFLOAT16); + else if (type == float16_type_node) + { + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_FLOAT16); + } + else if (type == float32_type_node) + { + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_FLOAT32); + } + else if (type == float64_type_node) + { + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_FLOAT64); + } + else if (type == float128_type_node) + { + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_FLOAT128); + } else if (type == dfloat128_type_node) // FIXME: wrong type. return new recording::memento_of_get_type (&target_builtins_ctxt, diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index 8c07f557d0cb..e32bd881b828 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see #endif #endif -const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_BFLOAT16 + 1; +const int NUM_GCC_JIT_TYPES = GCC_JIT_TYPE_FLOAT128 + 1; /* This comment is included by the docs. diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index d5145d0e7cd1..00d5e7290ede 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -295,6 +295,39 @@ get_tree_node_for_type (enum gcc_jit_types type_) return double_type_node; case GCC_JIT_TYPE_LONG_DOUBLE: return long_double_type_node; + case GCC_JIT_TYPE_FLOAT16: + if (float16_type_node == NULL || TYPE_PRECISION (float16_type_node) != 16) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); + return NULL; + } + return float16_type_node; + case GCC_JIT_TYPE_FLOAT32: + if (float32_type_node == NULL || TYPE_PRECISION (float32_type_node) != 32) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); + return NULL; + } + return float32_type_node; + case GCC_JIT_TYPE_FLOAT64: + if (float64_type_node == NULL || TYPE_PRECISION (float64_type_node) != 64) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); + return NULL; + } + return float64_type_node; + case GCC_JIT_TYPE_FLOAT128: + if (float128_type_node == NULL + || TYPE_PRECISION (float128_type_node) != 128) + { + add_error (NULL, "gcc_jit_types value unsupported on this target: %i", + type_); + return NULL; + } + return float128_type_node; case GCC_JIT_TYPE_SIZE_T: return size_type_node; diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 754ccb2b1c63..6816a71dcd81 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -2662,6 +2662,18 @@ recording::memento_of_get_type::get_size () m = targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE); size = GET_MODE_PRECISION (m).to_constant (); break; + case GCC_JIT_TYPE_FLOAT16: + size = 16; + break; + case GCC_JIT_TYPE_FLOAT32: + size = 32; + break; + case GCC_JIT_TYPE_FLOAT64: + size = 64; + break; + case GCC_JIT_TYPE_FLOAT128: + size = 128; + break; case GCC_JIT_TYPE_SIZE_T: size = MAX_BITS_PER_WORD; break; @@ -2718,6 +2730,10 @@ recording::memento_of_get_type::dereference () case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: case GCC_JIT_TYPE_COMPLEX_FLOAT: case GCC_JIT_TYPE_COMPLEX_DOUBLE: case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: @@ -2783,6 +2799,10 @@ recording::memento_of_get_type::is_int () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return false; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2842,6 +2862,10 @@ recording::memento_of_get_type::is_signed () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2902,6 +2926,10 @@ recording::memento_of_get_type::is_float () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return true; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -2966,6 +2994,10 @@ recording::memento_of_get_type::is_bool () const case GCC_JIT_TYPE_BFLOAT16: case GCC_JIT_TYPE_DOUBLE: case GCC_JIT_TYPE_LONG_DOUBLE: + case GCC_JIT_TYPE_FLOAT16: + case GCC_JIT_TYPE_FLOAT32: + case GCC_JIT_TYPE_FLOAT64: + case GCC_JIT_TYPE_FLOAT128: return false; case GCC_JIT_TYPE_CONST_CHAR_PTR: @@ -3043,8 +3075,11 @@ static const char * const get_type_strings[] = { "__int32_t", /* GCC_JIT_TYPE_INT32_T */ "__int64_t", /* GCC_JIT_TYPE_INT64_T */ "__int128_t", /* GCC_JIT_TYPE_INT128_T */ - - "bfloat16", /* GCC_JIT_TYPE_BFLOAT16 */ + "bfloat16", /* GCC_JIT_TYPE_BFLOAT16 */ + "_Float16", /* GCC_JIT_TYPE_FLOAT16 */ + "_Float32", /* GCC_JIT_TYPE_FLOAT32 */ + "_Float64", /* GCC_JIT_TYPE_FLOAT64 */ + "__float128", /* GCC_JIT_TYPE_FLOAT128 */ }; /* Implementation of recording::memento::make_debug_string for @@ -3091,6 +3126,10 @@ static const char * const get_type_enum_strings[] = { "GCC_JIT_TYPE_INT64_T", "GCC_JIT_TYPE_INT128_T", "GCC_JIT_TYPE_BFLOAT16", + "GCC_JIT_TYPE_FLOAT16", + "GCC_JIT_TYPE_FLOAT32", + "GCC_JIT_TYPE_FLOAT64", + "GCC_JIT_TYPE_FLOAT128", }; void diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index f71ed630589a..1cc5e6a9946c 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -619,6 +619,10 @@ enum gcc_jit_types GCC_JIT_TYPE_INT128_T, GCC_JIT_TYPE_BFLOAT16, + GCC_JIT_TYPE_FLOAT16, + GCC_JIT_TYPE_FLOAT32, + GCC_JIT_TYPE_FLOAT64, + GCC_JIT_TYPE_FLOAT128, }; extern gcc_jit_type * diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index dc98ad24526c..fe9ad1da3f4d 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -404,6 +404,13 @@ #undef create_code #undef verify_code +/* test-sized-float.c */ +#define create_code create_code_sized_float +#define verify_code verify_code_sized_float +#include "test-sized-float.c" +#undef create_code +#undef verify_code + /* test-target-builtins.c: This can't be in the testcases array as it is target-specific. */ @@ -638,6 +645,9 @@ const struct testcase testcases[] = { {"sizeof", create_code_sizeof, verify_code_sizeof}, + {"sized-float", + create_code_sized_float, + verify_code_sized_float}, {"string_literal", create_code_string_literal, verify_code_string_literal}, diff --git a/gcc/testsuite/jit.dg/test-sized-float.c b/gcc/testsuite/jit.dg/test-sized-float.c new file mode 100644 index 000000000000..fc90f14e6454 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-sized-float.c @@ -0,0 +1,167 @@ +#include <stdio.h> +#include <stddef.h> +#include <stdbool.h> + +#include "libgccjit.h" + +#include "harness.h" + +struct float_zoo +{ + _Float16 m_float16; + _Float32 m_float32; + _Float64 m_float64; + __float128 m_float128; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + void + test_caller (struct float_zoo *z) + { + for each fields "m_field": + z->m_field = ...some data; + } + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + +#define CREATE_FIELD(TYPE, NAME) \ + gcc_jit_context_new_field ( \ + ctxt, NULL, \ + gcc_jit_context_get_type (ctxt, TYPE), \ + NAME) + + gcc_jit_context *info_ctxt = gcc_jit_context_acquire (); + gcc_jit_target_info *target_info = gcc_jit_context_get_target_info (info_ctxt); + + enum gcc_jit_types float_type1 = GCC_JIT_TYPE_FLOAT; + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT16)) + float_type1 = GCC_JIT_TYPE_FLOAT16; + + enum gcc_jit_types float_type2 = GCC_JIT_TYPE_FLOAT; + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT32)) + float_type2 = GCC_JIT_TYPE_FLOAT32; + + enum gcc_jit_types float_type3 = GCC_JIT_TYPE_FLOAT; + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT64)) + float_type3 = GCC_JIT_TYPE_FLOAT64; + + enum gcc_jit_types float_type4 = GCC_JIT_TYPE_FLOAT; + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT128)) + float_type4 = GCC_JIT_TYPE_FLOAT128; + + gcc_jit_field *field_m_float16 = CREATE_FIELD(float_type1, "m_float16"); + gcc_jit_field *field_m_float32 = CREATE_FIELD(float_type2, "m_float32"); + gcc_jit_field *field_m_float64 = CREATE_FIELD(float_type3, "m_float64"); + gcc_jit_field *field_m_float128 = CREATE_FIELD(float_type4, "m_float128"); + +#undef CREATE_FIELD + + gcc_jit_field *zoo_fields[] = { + field_m_float16, + field_m_float32, + field_m_float64, + field_m_float128, + }; + + gcc_jit_type *zoo_type = + gcc_jit_struct_as_type ( + gcc_jit_context_new_struct_type ( + ctxt, + NULL, + "float_zoo", + sizeof (zoo_fields) / sizeof (zoo_fields[0]), + zoo_fields)); + + gcc_jit_type *zoo_ptr_type = + gcc_jit_type_get_pointer (zoo_type); + + /* Build the test_fn. */ + gcc_jit_param *param_z = + gcc_jit_context_new_param (ctxt, NULL, zoo_ptr_type, "z"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_float_types", + 1, ¶m_z, + 0); + gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); + + /* Write to the various fields of param "z". */ +#define ASSIGN(FIELD, EXPR) \ + gcc_jit_block_add_assignment ( \ + block, NULL, \ + gcc_jit_rvalue_dereference_field ( \ + gcc_jit_param_as_rvalue (param_z), \ + NULL, \ + (FIELD)), \ + (EXPR)); + + ASSIGN(field_m_float16, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, float_type1), + 3.141)) + ASSIGN(field_m_float32, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, float_type2), + 3.141)) + ASSIGN(field_m_float64, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, float_type3), + 3.141)) + ASSIGN(field_m_float128, + gcc_jit_context_new_rvalue_from_double ( + ctxt, + gcc_jit_context_get_type (ctxt, float_type4), + 3.141)) + +#undef ASSIGN + + gcc_jit_block_end_with_void_return (block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef void (*fn_type) (struct float_zoo *); + CHECK_NON_NULL (result); + + fn_type test_float_types = + (fn_type)gcc_jit_result_get_code (result, "test_float_types"); + CHECK_NON_NULL (test_float_types); + + struct float_zoo z; + memset (&z, 0xf0, sizeof (z)); + + /* Call the JIT-generated function. */ + test_float_types (&z); + + /* Verify that it correctly wrote to the various fields. */ + gcc_jit_context *info_ctxt = gcc_jit_context_acquire (); + gcc_jit_target_info *target_info = gcc_jit_context_get_target_info (info_ctxt); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT16)) + CHECK_VALUE (z.m_float16, (_Float16)3.141); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT32)) + CHECK_VALUE (z.m_float32, (_Float32)3.141); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT64)) + CHECK_VALUE (z.m_float64, (_Float64)3.141); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT128)) + CHECK_VALUE (z.m_float128, (__float128)3.141); + + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT16)) + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT16)), sizeof (_Float16)); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT32)) + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT32)), sizeof (_Float32)); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT64)) + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT64)), sizeof (_Float64)); + if (gcc_jit_target_info_supports_target_dependent_type (target_info, GCC_JIT_TYPE_FLOAT128)) + CHECK_VALUE (gcc_jit_type_get_size (gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT128)), sizeof (__float128)); +}
