https://gcc.gnu.org/g:17b02d8f2b385cbe0f72a5ed0acf34818934b79e
commit r17-3969-g17b02d8f2b385cbe0f72a5ed0acf34818934b79e Author: Jakub Jelinek <[email protected]> Date: Mon Sep 7 08:46:52 2026 +0200 Use optabs-libfuncs.cc infrastructure for __floatbitint<mode> and __fix<mode>bitint calls rs6000.cc likes to rename some of the libfuncs for certain names and uses set_conv_libfunc/set_optab_libfunc overrides for that. Unfortunately the large/huge _BitInt <-> binary/decimal floating point ifns build the libcall names by hand and so it isn't possible to override them (and for pru/c6x which don't support _BitInt yet doesn't add the __gnu prefix either). The following patch adds libcall only optabs for this so that they can be overridden and also can be cached, if one has more than one conversion from/to _BitInt to certain floating point mode, the name/rtx won't be constructed each time again. Tested additionally on _Float128 a; long double b; _BitInt(176) c; _Decimal128 d; void foo () { a = c; } void bar () { b = c; } void baz () { c = a; } void qux () { c = b; } void corge () { d = c; } void garply () { c = d; } on x86_64-linux (I've verified it emits exactly the same names as before) and with an incremental patch on powerpc64le-linux (where it fixed problems on that testcase). 2026-09-07 Jakub Jelinek <[email protected]> * optabs.def (bitinttofp_optab, bitintfromfp_optab): New optabs. * optabs-libfuncs.h (gen_bitint_fp_libfunc): Declare. * optabs-libfuncs.cc (gen_interclass_conv_libfunc): Move most of the function into ... (gen_interclass_conv_libfunc_name_name): New helper function. (gen_bitint_fp_libfunc): New function. * internal-fn.cc (expand_FLOATTOBITINT): Use optab_libfunc (bitintfromfp_optab, mode) instead of constructing libcall name manually. (expand_BITINTTOFLOAT): Similarly with optab_libfunc (bitinttofp_optab, mode). Reviewed-by: Richard Biener <[email protected]> Diff: --- gcc/internal-fn.cc | 54 ++------------------------------------ gcc/optabs-libfuncs.cc | 70 +++++++++++++++++++++++++++++++++++++------------- gcc/optabs-libfuncs.h | 1 + gcc/optabs.def | 3 +++ 4 files changed, 58 insertions(+), 70 deletions(-) diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 0138c6f7ef01..c57b594ac591 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -5722,32 +5722,7 @@ expand_FLOATTOBITINT (internal_fn, gcall *stmt) rtx arg0 = expand_normal (gimple_call_arg (stmt, 0)); rtx arg1 = expand_normal (gimple_call_arg (stmt, 1)); rtx arg2 = expand_normal (gimple_call_arg (stmt, 2)); - const char *mname = GET_MODE_NAME (mode); - unsigned mname_len = strlen (mname); - int len = 12 + mname_len; - if (DECIMAL_FLOAT_MODE_P (mode)) - len += 4; - char *libfunc_name = XALLOCAVEC (char, len); - char *p = libfunc_name; - const char *q; - if (DECIMAL_FLOAT_MODE_P (mode)) - { -#if ENABLE_DECIMAL_BID_FORMAT - memcpy (p, "__bid_fix", 9); -#else - memcpy (p, "__dpd_fix", 9); -#endif - p += 9; - } - else - { - memcpy (p, "__fix", 5); - p += 5; - } - for (q = mname; *q; q++) - *p++ = TOLOWER (*q); - memcpy (p, "bitint", 7); - rtx fun = init_one_libfunc (libfunc_name); + rtx fun = optab_libfunc (bitintfromfp_optab, mode); emit_library_call (fun, LCT_NORMAL, VOIDmode, arg0, ptr_mode, arg1, SImode, arg2, mode); } @@ -5761,32 +5736,7 @@ expand_BITINTTOFLOAT (internal_fn, gcall *stmt) machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); rtx arg0 = expand_normal (gimple_call_arg (stmt, 0)); rtx arg1 = expand_normal (gimple_call_arg (stmt, 1)); - const char *mname = GET_MODE_NAME (mode); - unsigned mname_len = strlen (mname); - int len = 14 + mname_len; - if (DECIMAL_FLOAT_MODE_P (mode)) - len += 4; - char *libfunc_name = XALLOCAVEC (char, len); - char *p = libfunc_name; - const char *q; - if (DECIMAL_FLOAT_MODE_P (mode)) - { -#if ENABLE_DECIMAL_BID_FORMAT - memcpy (p, "__bid_floatbitint", 17); -#else - memcpy (p, "__dpd_floatbitint", 17); -#endif - p += 17; - } - else - { - memcpy (p, "__floatbitint", 13); - p += 13; - } - for (q = mname; *q; q++) - *p++ = TOLOWER (*q); - *p = '\0'; - rtx fun = init_one_libfunc (libfunc_name); + rtx fun = optab_libfunc (bitinttofp_optab, mode); rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); rtx val = emit_library_call_value (fun, target, LCT_PURE, mode, arg0, ptr_mode, arg1, SImode); diff --git a/gcc/optabs-libfuncs.cc b/gcc/optabs-libfuncs.cc index 1b201e915afa..1866b7f3acf2 100644 --- a/gcc/optabs-libfuncs.cc +++ b/gcc/optabs-libfuncs.cc @@ -362,22 +362,16 @@ gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix, gen_unsigned_fixed_libfunc (optable, name, suffix, mode); } -/* Initialize the libfunc fields of an entire group of entries of an - inter-mode-class conversion optab. The string formation rules are - similar to the ones for init_libfuncs, above, but instead of having - a mode name and an operand count these functions have two mode names - and no operand count. */ +/* Helper function for gen_interclass_conv_libfunc and gen_bitint_fp_libfunc. + Return name for interclass conversion function. */ -void -gen_interclass_conv_libfunc (convert_optab tab, - const char *opname, - machine_mode tmode, - machine_mode fmode) +static const char * +gen_interclass_conv_libfunc_name (const char *opname, bool decimal_p, + const char *tname, const char *fname) { size_t opname_len = strlen (opname); size_t mname_len = 0; - const char *fname, *tname; const char *q; int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2; char *libfunc_name, *suffix; @@ -388,7 +382,7 @@ gen_interclass_conv_libfunc (convert_optab tab, depends on which underlying decimal floating point format is used. */ const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1; - mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode)); + mname_len = strlen (tname) + strlen (fname); nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1); nondec_name[0] = '_'; @@ -411,10 +405,7 @@ gen_interclass_conv_libfunc (convert_optab tab, memcpy (&dec_name[2+dec_len], opname, opname_len); dec_suffix = dec_name + dec_len + opname_len + 2; - fname = GET_MODE_NAME (fmode); - tname = GET_MODE_NAME (tmode); - - if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode)) + if (decimal_p) { libfunc_name = dec_name; suffix = dec_suffix; @@ -433,8 +424,28 @@ gen_interclass_conv_libfunc (convert_optab tab, *p = '\0'; - set_conv_libfunc (tab, tmode, fmode, - ggc_alloc_string (libfunc_name, p - libfunc_name)); + return ggc_alloc_string (libfunc_name, p - libfunc_name); +} + +/* Initialize the libfunc fields of an entire group of entries of an + inter-mode-class conversion optab. The string formation rules are + similar to the ones for init_libfuncs, above, but instead of having + a mode name and an operand count these functions have two mode names + and no operand count. */ + +void +gen_interclass_conv_libfunc (convert_optab tab, + const char *opname, + machine_mode tmode, + machine_mode fmode) +{ + const char *name + = gen_interclass_conv_libfunc_name (opname, + DECIMAL_FLOAT_MODE_P (fmode) + || DECIMAL_FLOAT_MODE_P (tmode), + GET_MODE_NAME (tmode), + GET_MODE_NAME (fmode)); + set_conv_libfunc (tab, tmode, fmode, name); } /* Same as gen_interclass_conv_libfunc but verify that we are producing @@ -703,6 +714,29 @@ gen_satfractuns_conv_libfunc (convert_optab tab, gen_interclass_conv_libfunc (tab, opname, tmode, fmode); } +/* Pick proper libcall for bitinttofp_optab and bitintfromfp_optab. */ + +void +gen_bitint_fp_libfunc (optab optable, const char *opname, char suffix, + machine_mode mode) +{ + if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT) + { + const char *name; + if (suffix == '0') + name = gen_interclass_conv_libfunc_name (opname, + DECIMAL_FLOAT_MODE_P (mode), + GET_MODE_NAME (mode), + "bitint"); + else + name = gen_interclass_conv_libfunc_name (opname, + DECIMAL_FLOAT_MODE_P (mode), + "bitint", + GET_MODE_NAME (mode)); + set_optab_libfunc (optable, mode, name); + } +} + /* Hashtable callbacks for libfunc_decls. */ struct libfunc_decl_hasher : ggc_ptr_hash<tree_node> diff --git a/gcc/optabs-libfuncs.h b/gcc/optabs-libfuncs.h index 8ce6fdcad13a..3fd5244a89a1 100644 --- a/gcc/optabs-libfuncs.h +++ b/gcc/optabs-libfuncs.h @@ -37,6 +37,7 @@ void gen_int_fp_signed_fixed_libfunc (optab, const char *, char, machine_mode); void gen_int_fixed_libfunc (optab, const char *, char, machine_mode); void gen_int_signed_fixed_libfunc (optab, const char *, char, machine_mode); void gen_int_unsigned_fixed_libfunc (optab, const char *, char, machine_mode); +void gen_bitint_fp_libfunc (optab, const char *, char, machine_mode); void gen_interclass_conv_libfunc (convert_optab, const char *, machine_mode, machine_mode); diff --git a/gcc/optabs.def b/gcc/optabs.def index 327e3efaf8a9..37738f396ddf 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -207,6 +207,9 @@ OPTAB_NL(unord_optab, NULL, UNORDERED, "unord", '2', gen_fp_libfunc) OPTAB_NL(powi_optab, NULL, UNKNOWN, "powi", '2', gen_fp_libfunc) +OPTAB_NL(bitinttofp_optab, NULL, UNKNOWN, "float", '0', gen_bitint_fp_libfunc) +OPTAB_NL(bitintfromfp_optab, NULL, UNKNOWN, "fix", '1', gen_bitint_fp_libfunc) + /* These are all initialized individually, on a per-host basis. */ OPTAB_NC(sqrt_optab, "sqrt$a2", SQRT) OPTAB_NC(sync_old_add_optab, "sync_old_add$I$a", UNKNOWN)
