LCOV - code coverage report
Current view: top level - gcc - optabs-libfuncs.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 77.9 % 421 328
Test Date: 2026-02-28 14:20:25 Functions: 73.2 % 41 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Mapping from optabs to underlying library functions
       2              :    Copyright (C) 1987-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "target.h"
      25              : #include "insn-codes.h"
      26              : #include "optabs-libfuncs.h"
      27              : #include "libfuncs.h"
      28              : #include "optabs-query.h"
      29              : #include "tree.h"
      30              : #include "stringpool.h"
      31              : #include "varasm.h"
      32              : #include "stor-layout.h"
      33              : #include "rtl.h"
      34              : 
      35              : struct target_libfuncs default_target_libfuncs;
      36              : #if SWITCHABLE_TARGET
      37              : struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
      38              : #endif
      39              : 
      40              : #define libfunc_hash \
      41              :   (this_target_libfuncs->x_libfunc_hash)
      42              : 
      43              : /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
      44              : #if ENABLE_DECIMAL_BID_FORMAT
      45              : #define DECIMAL_PREFIX "bid_"
      46              : #else
      47              : #define DECIMAL_PREFIX "dpd_"
      48              : #endif
      49              : 
      50              : /* Used for libfunc_hash.  */
      51              : 
      52              : hashval_t
      53     31315223 : libfunc_hasher::hash (libfunc_entry *e)
      54              : {
      55     31315223 :   return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
      56              : }
      57              : 
      58              : /* Used for libfunc_hash.  */
      59              : 
      60              : bool
      61     26824435 : libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
      62              : {
      63     26824435 :   return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
      64              : }
      65              : 
      66              : /* Return libfunc corresponding operation defined by OPTAB converting
      67              :    from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
      68              :    if no libfunc is available.  */
      69              : rtx
      70        36610 : convert_optab_libfunc (convert_optab optab, machine_mode mode1,
      71              :                        machine_mode mode2)
      72              : {
      73        36610 :   struct libfunc_entry e;
      74        36610 :   struct libfunc_entry **slot;
      75              : 
      76              :   /* ??? This ought to be an assert, but not all of the places
      77              :      that we expand optabs know about the optabs that got moved
      78              :      to being direct.  */
      79        36610 :   if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
      80              :     return NULL_RTX;
      81              : 
      82        36610 :   e.op = optab;
      83        36610 :   e.mode1 = mode1;
      84        36610 :   e.mode2 = mode2;
      85        36610 :   slot = libfunc_hash->find_slot (&e, NO_INSERT);
      86        36610 :   if (!slot)
      87              :     {
      88         3231 :       const struct convert_optab_libcall_d *d
      89         3231 :         = &convlib_def[optab - FIRST_CONV_OPTAB];
      90              : 
      91         3231 :       if (d->libcall_gen == NULL)
      92              :         return NULL;
      93              : 
      94         3231 :       d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
      95         3231 :       slot = libfunc_hash->find_slot (&e, NO_INSERT);
      96         3231 :       if (!slot)
      97              :         return NULL;
      98              :     }
      99        36610 :   return (*slot)->libfunc;
     100              : }
     101              : 
     102              : /* Return libfunc corresponding operation defined by OPTAB in MODE.
     103              :    Trigger lazy initialization if needed, return NULL if no libfunc is
     104              :    available.  */
     105              : rtx
     106      2154139 : optab_libfunc (optab optab, machine_mode mode)
     107              : {
     108      2154139 :   struct libfunc_entry e;
     109      2154139 :   struct libfunc_entry **slot;
     110              : 
     111              :   /* ??? This ought to be an assert, but not all of the places
     112              :      that we expand optabs know about the optabs that got moved
     113              :      to being direct.  */
     114      2154139 :   if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
     115              :     return NULL_RTX;
     116              : 
     117      1668810 :   e.op = optab;
     118      1668810 :   e.mode1 = mode;
     119      1668810 :   e.mode2 = VOIDmode;
     120      1668810 :   slot = libfunc_hash->find_slot (&e, NO_INSERT);
     121      1668810 :   if (!slot)
     122              :     {
     123      1521378 :       const struct optab_libcall_d *d
     124      1521378 :         = &normlib_def[optab - FIRST_NORM_OPTAB];
     125              : 
     126      1521378 :       if (d->libcall_gen == NULL)
     127              :         return NULL;
     128              : 
     129      1220255 :       d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
     130      1220255 :       slot = libfunc_hash->find_slot (&e, NO_INSERT);
     131      1220255 :       if (!slot)
     132              :         return NULL;
     133              :     }
     134       164902 :   return (*slot)->libfunc;
     135              : }
     136              : 
     137              : /* Initialize the libfunc fields of an entire group of entries in some
     138              :    optab.  Each entry is set equal to a string consisting of a leading
     139              :    pair of underscores followed by a generic operation name followed by
     140              :    a mode name (downshifted to lowercase) followed by a single character
     141              :    representing the number of operands for the given operation (which is
     142              :    usually one of the characters '2', '3', or '4').
     143              : 
     144              :    OPTABLE is the table in which libfunc fields are to be initialized.
     145              :    OPNAME is the generic (string) name of the operation.
     146              :    SUFFIX is the character which specifies the number of operands for
     147              :      the given generic operation.
     148              :    MODE is the mode to generate for.  */
     149              : 
     150              : static void
     151        17470 : gen_libfunc (optab optable, const char *opname, int suffix,
     152              :              machine_mode mode)
     153              : {
     154        17470 :   unsigned opname_len = strlen (opname);
     155        17470 :   const char *mname = GET_MODE_NAME (mode);
     156        17470 :   unsigned mname_len = strlen (mname);
     157        17470 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     158        17470 :   int len = prefix_len + opname_len + mname_len + 1 + 1;
     159        17470 :   char *libfunc_name = XALLOCAVEC (char, len);
     160        17470 :   char *p;
     161        17470 :   const char *q;
     162              : 
     163        17470 :   p = libfunc_name;
     164        17470 :   *p++ = '_';
     165        17470 :   *p++ = '_';
     166        17470 :   if (targetm.libfunc_gnu_prefix)
     167              :     {
     168            0 :       *p++ = 'g';
     169            0 :       *p++ = 'n';
     170            0 :       *p++ = 'u';
     171            0 :       *p++ = '_';
     172              :     }
     173        82472 :   for (q = opname; *q;)
     174        65002 :     *p++ = *q++;
     175        52410 :   for (q = mname; *q; q++)
     176        34940 :     *p++ = TOLOWER (*q);
     177        17470 :   *p++ = suffix;
     178        17470 :   *p = '\0';
     179              : 
     180        17470 :   set_optab_libfunc (optable, mode,
     181        17470 :                      ggc_alloc_string (libfunc_name, p - libfunc_name));
     182        17470 : }
     183              : 
     184              : /* Like gen_libfunc, but verify that integer operation is involved.  */
     185              : 
     186              : void
     187      1213449 : gen_int_libfunc (optab optable, const char *opname, char suffix,
     188              :                  machine_mode mode)
     189              : {
     190      1213449 :   int maxsize = 2 * BITS_PER_WORD;
     191      1213449 :   int minsize = BITS_PER_WORD;
     192      1213449 :   scalar_int_mode int_mode;
     193              : 
     194      1213449 :   if (!is_int_mode (mode, &int_mode))
     195      1213449 :     return;
     196        39041 :   if (maxsize < LONG_LONG_TYPE_SIZE)
     197              :     maxsize = LONG_LONG_TYPE_SIZE;
     198        39041 :   if (minsize > INT_TYPE_SIZE
     199        76987 :       && (trapv_binoptab_p (optable)
     200        37946 :           || trapv_unoptab_p (optable)))
     201              :     minsize = INT_TYPE_SIZE;
     202        39041 :   if (GET_MODE_BITSIZE (int_mode) < minsize
     203        51102 :       || GET_MODE_BITSIZE (int_mode) > maxsize)
     204              :     return;
     205        12061 :   gen_libfunc (optable, opname, suffix, int_mode);
     206              : }
     207              : 
     208              : /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
     209              : 
     210              : void
     211         5409 : gen_fp_libfunc (optab optable, const char *opname, char suffix,
     212              :                 machine_mode mode)
     213              : {
     214         5409 :   char *dec_opname;
     215              : 
     216         5409 :   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
     217         3704 :     gen_libfunc (optable, opname, suffix, mode);
     218         5409 :   if (DECIMAL_FLOAT_MODE_P (mode))
     219              :     {
     220         1705 :       dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
     221              :       /* For BID support, change the name to have either a bid_ or dpd_ prefix
     222              :          depending on the low level floating format used.  */
     223         1705 :       memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
     224         1705 :       strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
     225         1705 :       gen_libfunc (optable, dec_opname, suffix, mode);
     226              :     }
     227         5409 : }
     228              : 
     229              : /* Like gen_libfunc, but verify that fixed-point operation is involved.  */
     230              : 
     231              : void
     232            0 : gen_fixed_libfunc (optab optable, const char *opname, char suffix,
     233              :                    machine_mode mode)
     234              : {
     235            0 :   if (!ALL_FIXED_POINT_MODE_P (mode))
     236              :     return;
     237            0 :   gen_libfunc (optable, opname, suffix, mode);
     238              : }
     239              : 
     240              : /* Like gen_libfunc, but verify that signed fixed-point operation is
     241              :    involved.  */
     242              : 
     243              : void
     244            0 : gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
     245              :                           machine_mode mode)
     246              : {
     247            0 :   if (!SIGNED_FIXED_POINT_MODE_P (mode))
     248              :     return;
     249            0 :   gen_libfunc (optable, opname, suffix, mode);
     250              : }
     251              : 
     252              : /* Like gen_libfunc, but verify that unsigned fixed-point operation is
     253              :    involved.  */
     254              : 
     255              : void
     256            0 : gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
     257              :                             machine_mode mode)
     258              : {
     259            0 :   if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
     260              :     return;
     261            0 :   gen_libfunc (optable, opname, suffix, mode);
     262              : }
     263              : 
     264              : /* Like gen_libfunc, but verify that FP or INT operation is involved.  */
     265              : 
     266              : void
     267         9360 : gen_int_fp_libfunc (optab optable, const char *name, char suffix,
     268              :                     machine_mode mode)
     269              : {
     270         9360 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     271           27 :     gen_fp_libfunc (optable, name, suffix, mode);
     272         9360 :   if (INTEGRAL_MODE_P (mode))
     273         9333 :     gen_int_libfunc (optable, name, suffix, mode);
     274         9360 : }
     275              : 
     276              : /* Like gen_libfunc, but verify that FP or INT operation is involved
     277              :    and add 'v' suffix for integer operation.  */
     278              : 
     279              : void
     280          117 : gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
     281              :                      machine_mode mode)
     282              : {
     283          117 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     284            0 :     gen_fp_libfunc (optable, name, suffix, mode);
     285          117 :   if (GET_MODE_CLASS (mode) == MODE_INT)
     286              :     {
     287          117 :       int len = strlen (name);
     288          117 :       char *v_name = XALLOCAVEC (char, len + 2);
     289          117 :       strcpy (v_name, name);
     290          117 :       v_name[len] = 'v';
     291          117 :       v_name[len + 1] = 0;
     292          117 :       gen_int_libfunc (optable, v_name, suffix, mode);
     293              :     }
     294          117 : }
     295              : 
     296              : /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
     297              :    involved.  */
     298              : 
     299              : void
     300       824765 : gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
     301              :                           machine_mode mode)
     302              : {
     303       824765 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     304         1737 :     gen_fp_libfunc (optable, name, suffix, mode);
     305       824765 :   if (INTEGRAL_MODE_P (mode))
     306       821798 :     gen_int_libfunc (optable, name, suffix, mode);
     307       824765 :   if (ALL_FIXED_POINT_MODE_P (mode))
     308            0 :     gen_fixed_libfunc (optable, name, suffix, mode);
     309       824765 : }
     310              : 
     311              : /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
     312              :    involved.  */
     313              : 
     314              : void
     315        37728 : gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
     316              :                                  machine_mode mode)
     317              : {
     318        37728 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     319          351 :     gen_fp_libfunc (optable, name, suffix, mode);
     320        37728 :   if (INTEGRAL_MODE_P (mode))
     321        37369 :     gen_int_libfunc (optable, name, suffix, mode);
     322        37728 :   if (SIGNED_FIXED_POINT_MODE_P (mode))
     323            0 :     gen_signed_fixed_libfunc (optable, name, suffix, mode);
     324        37728 : }
     325              : 
     326              : /* Like gen_libfunc, but verify that INT or FIXED operation is
     327              :    involved.  */
     328              : 
     329              : void
     330       246601 : gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
     331              :                        machine_mode mode)
     332              : {
     333       246601 :   if (INTEGRAL_MODE_P (mode))
     334       246601 :     gen_int_libfunc (optable, name, suffix, mode);
     335       246601 :   if (ALL_FIXED_POINT_MODE_P (mode))
     336            0 :     gen_fixed_libfunc (optable, name, suffix, mode);
     337       246601 : }
     338              : 
     339              : /* Like gen_libfunc, but verify that INT or signed FIXED operation is
     340              :    involved.  */
     341              : 
     342              : void
     343          352 : gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
     344              :                               machine_mode mode)
     345              : {
     346          352 :   if (INTEGRAL_MODE_P (mode))
     347          220 :     gen_int_libfunc (optable, name, suffix, mode);
     348          352 :   if (SIGNED_FIXED_POINT_MODE_P (mode))
     349            0 :     gen_signed_fixed_libfunc (optable, name, suffix, mode);
     350          352 : }
     351              : 
     352              : /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
     353              :    involved.  */
     354              : 
     355              : void
     356        36978 : gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
     357              :                                 machine_mode mode)
     358              : {
     359        36978 :   if (INTEGRAL_MODE_P (mode))
     360        36951 :     gen_int_libfunc (optable, name, suffix, mode);
     361        36978 :   if (UNSIGNED_FIXED_POINT_MODE_P (mode))
     362            0 :     gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
     363        36978 : }
     364              : 
     365              : /* Initialize the libfunc fields of an entire group of entries of an
     366              :    inter-mode-class conversion optab.  The string formation rules are
     367              :    similar to the ones for init_libfuncs, above, but instead of having
     368              :    a mode name and an operand count these functions have two mode names
     369              :    and no operand count.  */
     370              : 
     371              : void
     372         2090 : gen_interclass_conv_libfunc (convert_optab tab,
     373              :                              const char *opname,
     374              :                              machine_mode tmode,
     375              :                              machine_mode fmode)
     376              : {
     377         2090 :   size_t opname_len = strlen (opname);
     378         2090 :   size_t mname_len = 0;
     379              : 
     380         2090 :   const char *fname, *tname;
     381         2090 :   const char *q;
     382         2090 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     383         2090 :   char *libfunc_name, *suffix;
     384         2090 :   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
     385         2090 :   char *p;
     386              : 
     387              :   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
     388              :      depends on which underlying decimal floating point format is used.  */
     389         2090 :   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
     390              : 
     391         2090 :   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
     392              : 
     393         2090 :   nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
     394         2090 :   nondec_name[0] = '_';
     395         2090 :   nondec_name[1] = '_';
     396         2090 :   if (targetm.libfunc_gnu_prefix)
     397              :     {
     398            0 :       nondec_name[2] = 'g';
     399            0 :       nondec_name[3] = 'n';
     400            0 :       nondec_name[4] = 'u';
     401            0 :       nondec_name[5] = '_';
     402              :     }
     403              : 
     404         2090 :   memcpy (&nondec_name[prefix_len], opname, opname_len);
     405         2090 :   nondec_suffix = nondec_name + opname_len + prefix_len;
     406              : 
     407         2090 :   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
     408         2090 :   dec_name[0] = '_';
     409         2090 :   dec_name[1] = '_';
     410         2090 :   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
     411         2090 :   memcpy (&dec_name[2+dec_len], opname, opname_len);
     412         2090 :   dec_suffix = dec_name + dec_len + opname_len + 2;
     413              : 
     414         2090 :   fname = GET_MODE_NAME (fmode);
     415         2090 :   tname = GET_MODE_NAME (tmode);
     416              : 
     417         2090 :   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
     418              :     {
     419              :       libfunc_name = dec_name;
     420              :       suffix = dec_suffix;
     421              :     }
     422              :   else
     423              :     {
     424         2090 :       libfunc_name = nondec_name;
     425         2090 :       suffix = nondec_suffix;
     426              :     }
     427              : 
     428         2090 :   p = suffix;
     429         6270 :   for (q = fname; *q; p++, q++)
     430         4180 :     *p = TOLOWER (*q);
     431         6270 :   for (q = tname; *q; p++, q++)
     432         4180 :     *p = TOLOWER (*q);
     433              : 
     434         2090 :   *p = '\0';
     435              : 
     436         2090 :   set_conv_libfunc (tab, tmode, fmode,
     437         2090 :                     ggc_alloc_string (libfunc_name, p - libfunc_name));
     438         2090 : }
     439              : 
     440              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     441              :    int->fp conversion.  */
     442              : 
     443              : void
     444          739 : gen_int_to_fp_conv_libfunc (convert_optab tab,
     445              :                             const char *opname,
     446              :                             machine_mode tmode,
     447              :                             machine_mode fmode)
     448              : {
     449          739 :   if (GET_MODE_CLASS (fmode) != MODE_INT)
     450              :     return;
     451          739 :   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
     452              :     return;
     453          739 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     454              : }
     455              : 
     456              : /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
     457              :    naming scheme.  */
     458              : 
     459              : void
     460          266 : gen_ufloat_conv_libfunc (convert_optab tab,
     461              :                          const char *opname ATTRIBUTE_UNUSED,
     462              :                          machine_mode tmode,
     463              :                          machine_mode fmode)
     464              : {
     465          266 :   if (DECIMAL_FLOAT_MODE_P (tmode))
     466           79 :     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
     467              :   else
     468          187 :     gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
     469          266 : }
     470              : 
     471              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     472              :    fp->int conversion.  */
     473              : 
     474              : void
     475            0 : gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
     476              :                                        const char *opname,
     477              :                                        machine_mode tmode,
     478              :                                        machine_mode fmode)
     479              : {
     480            0 :   if (GET_MODE_CLASS (fmode) != MODE_INT)
     481              :     return;
     482            0 :   if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
     483              :     return;
     484            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     485              : }
     486              : 
     487              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     488              :    fp->int conversion with no decimal floating point involved.  */
     489              : 
     490              : void
     491          722 : gen_fp_to_int_conv_libfunc (convert_optab tab,
     492              :                             const char *opname,
     493              :                             machine_mode tmode,
     494              :                             machine_mode fmode)
     495              : {
     496          722 :   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
     497              :     return;
     498          722 :   if (GET_MODE_CLASS (tmode) != MODE_INT)
     499              :     return;
     500          722 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     501              : }
     502              : 
     503              : /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
     504              :    The string formation rules are
     505              :    similar to the ones for init_libfunc, above.  */
     506              : 
     507              : void
     508         1141 : gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
     509              :                              machine_mode tmode, machine_mode fmode)
     510              : {
     511         1141 :   size_t opname_len = strlen (opname);
     512         1141 :   size_t mname_len = 0;
     513              : 
     514         1141 :   const char *fname, *tname;
     515         1141 :   const char *q;
     516         1141 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     517         1141 :   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
     518         1141 :   char *libfunc_name, *suffix;
     519         1141 :   char *p;
     520              : 
     521              :   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
     522              :      depends on which underlying decimal floating point format is used.  */
     523         1141 :   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
     524              : 
     525         1141 :   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
     526              : 
     527         1141 :   nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
     528         1141 :   nondec_name[0] = '_';
     529         1141 :   nondec_name[1] = '_';
     530         1141 :   if (targetm.libfunc_gnu_prefix)
     531              :     {
     532            0 :       nondec_name[2] = 'g';
     533            0 :       nondec_name[3] = 'n';
     534            0 :       nondec_name[4] = 'u';
     535            0 :       nondec_name[5] = '_';
     536              :     }
     537         1141 :   memcpy (&nondec_name[prefix_len], opname, opname_len);
     538         1141 :   nondec_suffix = nondec_name + opname_len + prefix_len;
     539              : 
     540         1141 :   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
     541         1141 :   dec_name[0] = '_';
     542         1141 :   dec_name[1] = '_';
     543         1141 :   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
     544         1141 :   memcpy (&dec_name[2 + dec_len], opname, opname_len);
     545         1141 :   dec_suffix = dec_name + dec_len + opname_len + 2;
     546              : 
     547         1141 :   fname = GET_MODE_NAME (fmode);
     548         1141 :   tname = GET_MODE_NAME (tmode);
     549              : 
     550         1141 :   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
     551              :     {
     552              :       libfunc_name = dec_name;
     553              :       suffix = dec_suffix;
     554              :     }
     555              :   else
     556              :     {
     557         1141 :       libfunc_name = nondec_name;
     558         1141 :       suffix = nondec_suffix;
     559              :     }
     560              : 
     561         1141 :   p = suffix;
     562         3423 :   for (q = fname; *q; p++, q++)
     563         2282 :     *p = TOLOWER (*q);
     564         3423 :   for (q = tname; *q; p++, q++)
     565         2282 :     *p = TOLOWER (*q);
     566              : 
     567         1141 :   *p++ = '2';
     568         1141 :   *p = '\0';
     569              : 
     570         1141 :   set_conv_libfunc (tab, tmode, fmode,
     571         1141 :                     ggc_alloc_string (libfunc_name, p - libfunc_name));
     572         1141 : }
     573              : 
     574              : /* Pick proper libcall for trunc_optab.  We need to chose if we do
     575              :    truncation or extension and interclass or intraclass.  */
     576              : 
     577              : void
     578          810 : gen_trunc_conv_libfunc (convert_optab tab,
     579              :                         const char *opname,
     580              :                         machine_mode tmode,
     581              :                         machine_mode fmode)
     582              : {
     583          810 :   scalar_float_mode float_tmode, float_fmode;
     584          810 :   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
     585         1620 :       || !is_a <scalar_float_mode> (tmode, &float_tmode)
     586          810 :       || float_tmode == float_fmode)
     587          810 :     return;
     588              : 
     589          810 :   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
     590          329 :     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     591              : 
     592          810 :   if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode)
     593           87 :       && (REAL_MODE_FORMAT (float_tmode) != &arm_bfloat_half_format
     594            1 :           || REAL_MODE_FORMAT (float_fmode) != &ieee_half_format)
     595           86 :       && (REAL_MODE_FORMAT (float_tmode) != &ieee_quad_format
     596            0 :           || REAL_MODE_FORMAT (float_fmode) != &ibm_extended_format))
     597              :     return;
     598              : 
     599          724 :   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
     600          481 :     gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     601              : }
     602              : 
     603              : /* Pick proper libcall for extend_optab.  We need to chose if we do
     604              :    truncation or extension and interclass or intraclass.  */
     605              : 
     606              : void
     607          960 : gen_extend_conv_libfunc (convert_optab tab,
     608              :                          const char *opname ATTRIBUTE_UNUSED,
     609              :                          machine_mode tmode,
     610              :                          machine_mode fmode)
     611              : {
     612          960 :   scalar_float_mode float_tmode, float_fmode;
     613          960 :   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
     614         1920 :       || !is_a <scalar_float_mode> (tmode, &float_tmode)
     615          960 :       || float_tmode == float_fmode)
     616          960 :     return;
     617              : 
     618          960 :   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
     619          300 :     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     620              : 
     621          960 :   if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
     622              :     return;
     623              : 
     624          960 :   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
     625          660 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     626              : }
     627              : 
     628              : /* Pick proper libcall for fract_optab.  We need to chose if we do
     629              :    interclass or intraclass.  */
     630              : 
     631              : void
     632            0 : gen_fract_conv_libfunc (convert_optab tab,
     633              :                         const char *opname,
     634              :                         machine_mode tmode,
     635              :                         machine_mode fmode)
     636              : {
     637            0 :   if (tmode == fmode)
     638              :     return;
     639            0 :   if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
     640              :     return;
     641              : 
     642            0 :   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
     643            0 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     644              :   else
     645            0 :     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     646              : }
     647              : 
     648              : /* Pick proper libcall for fractuns_optab.  */
     649              : 
     650              : void
     651            0 : gen_fractuns_conv_libfunc (convert_optab tab,
     652              :                            const char *opname,
     653              :                            machine_mode tmode,
     654              :                            machine_mode fmode)
     655              : {
     656            0 :   if (tmode == fmode)
     657              :     return;
     658              :   /* One mode must be a fixed-point mode, and the other must be an integer
     659              :      mode.  */
     660            0 :   if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
     661            0 :         || (ALL_FIXED_POINT_MODE_P (fmode)
     662            0 :             && GET_MODE_CLASS (tmode) == MODE_INT)))
     663              :     return;
     664              : 
     665            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     666              : }
     667              : 
     668              : /* Pick proper libcall for satfract_optab.  We need to chose if we do
     669              :    interclass or intraclass.  */
     670              : 
     671              : void
     672            0 : gen_satfract_conv_libfunc (convert_optab tab,
     673              :                            const char *opname,
     674              :                            machine_mode tmode,
     675              :                            machine_mode fmode)
     676              : {
     677            0 :   if (tmode == fmode)
     678              :     return;
     679              :   /* TMODE must be a fixed-point mode.  */
     680            0 :   if (!ALL_FIXED_POINT_MODE_P (tmode))
     681              :     return;
     682              : 
     683            0 :   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
     684            0 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     685              :   else
     686            0 :     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     687              : }
     688              : 
     689              : /* Pick proper libcall for satfractuns_optab.  */
     690              : 
     691              : void
     692            0 : gen_satfractuns_conv_libfunc (convert_optab tab,
     693              :                               const char *opname,
     694              :                               machine_mode tmode,
     695              :                               machine_mode fmode)
     696              : {
     697            0 :   if (tmode == fmode)
     698              :     return;
     699              :   /* TMODE must be a fixed-point mode, and FMODE must be an integer mode.  */
     700            0 :   if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
     701              :     return;
     702              : 
     703            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     704              : }
     705              : 
     706              : /* Hashtable callbacks for libfunc_decls.  */
     707              : 
     708              : struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
     709              : {
     710              :   static hashval_t
     711      4202485 :   hash (tree entry)
     712              :   {
     713      4202485 :     return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
     714              :   }
     715              : 
     716              :   static bool
     717      8452877 :   equal (tree decl, tree name)
     718              :   {
     719      8452877 :     return DECL_NAME (decl) == name;
     720              :   }
     721              : };
     722              : 
     723              : /* A table of previously-created libfuncs, hashed by name.  */
     724              : static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
     725              : 
     726              : /* Build a decl for a libfunc named NAME with visibility VIS.  */
     727              : 
     728              : tree
     729      2244787 : build_libfunc_function_visibility (const char *name, symbol_visibility vis)
     730              : {
     731              :   /* ??? We don't have any type information; pretend this is "int foo ()".  */
     732      2244787 :   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
     733              :                           get_identifier (name),
     734              :                           build_function_type (integer_type_node, NULL_TREE));
     735      2244787 :   DECL_EXTERNAL (decl) = 1;
     736      2244787 :   TREE_PUBLIC (decl) = 1;
     737      2244787 :   DECL_ARTIFICIAL (decl) = 1;
     738      2244787 :   DECL_VISIBILITY (decl) = vis;
     739      2244787 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
     740      2244787 :   gcc_assert (DECL_ASSEMBLER_NAME (decl));
     741              : 
     742      2244787 :   return decl;
     743              : }
     744              : 
     745              : /* Build a decl for a libfunc named NAME.  */
     746              : 
     747              : tree
     748            0 : build_libfunc_function (const char *name)
     749              : {
     750            0 :   return build_libfunc_function_visibility (name, VISIBILITY_DEFAULT);
     751              : }
     752              : 
     753              : /* Return a libfunc for NAME, creating one if we don't already have one.
     754              :    The decl is given visibility VIS.  The returned rtx is a SYMBOL_REF.  */
     755              : 
     756              : rtx
     757      6204748 : init_one_libfunc_visibility (const char *name, symbol_visibility vis)
     758              : {
     759      6204748 :   tree id, decl;
     760      6204748 :   hashval_t hash;
     761              : 
     762      6204748 :   if (libfunc_decls == NULL)
     763       278638 :     libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
     764              : 
     765              :   /* See if we have already created a libfunc decl for this function.  */
     766      6204748 :   id = get_identifier (name);
     767      6204748 :   hash = IDENTIFIER_HASH_VALUE (id);
     768      6204748 :   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
     769      6204748 :   decl = *slot;
     770      6204748 :   if (decl == NULL)
     771              :     {
     772              :       /* Create a new decl, so that it can be passed to
     773              :          targetm.encode_section_info.  */
     774      2244787 :       decl = build_libfunc_function_visibility (name, vis);
     775      2244787 :       *slot = decl;
     776              :     }
     777      6204748 :   return XEXP (DECL_RTL (decl), 0);
     778              : }
     779              : 
     780              : rtx
     781      6204748 : init_one_libfunc (const char *name)
     782              : {
     783      6204748 :   return init_one_libfunc_visibility (name, VISIBILITY_DEFAULT);
     784              : }
     785              : 
     786              : /* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
     787              : 
     788              : rtx
     789            1 : set_user_assembler_libfunc (const char *name, const char *asmspec)
     790              : {
     791            1 :   tree id, decl;
     792            1 :   hashval_t hash;
     793              : 
     794            1 :   id = get_identifier (name);
     795            1 :   hash = IDENTIFIER_HASH_VALUE (id);
     796            1 :   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
     797            1 :   gcc_assert (slot);
     798            1 :   decl = (tree) *slot;
     799            1 :   set_user_assembler_name (decl, asmspec);
     800            1 :   return XEXP (DECL_RTL (decl), 0);
     801              : }
     802              : 
     803              : /* Call this to reset the function entry for one optab (OPTABLE) in mode
     804              :    MODE to NAME, which should be either 0 or a string constant.  */
     805              : 
     806              : void
     807      4648587 : set_optab_libfunc (optab op, machine_mode mode, const char *name)
     808              : {
     809      4648587 :   rtx val;
     810      4648587 :   struct libfunc_entry e;
     811      4648587 :   struct libfunc_entry **slot;
     812              : 
     813      4648587 :   e.op = op;
     814      4648587 :   e.mode1 = mode;
     815      4648587 :   e.mode2 = VOIDmode;
     816              : 
     817      4648587 :   if (name)
     818      4648587 :     val = init_one_libfunc (name);
     819              :   else
     820              :     val = 0;
     821      4648587 :   slot = libfunc_hash->find_slot (&e, INSERT);
     822      4648587 :   if (*slot == NULL)
     823      4648586 :     *slot = ggc_alloc<libfunc_entry> ();
     824      4648587 :   (*slot)->op = op;
     825      4648587 :   (*slot)->mode1 = mode;
     826      4648587 :   (*slot)->mode2 = VOIDmode;
     827      4648587 :   (*slot)->libfunc = val;
     828      4648587 : }
     829              : 
     830              : /* Call this to reset the function entry for one conversion optab
     831              :    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
     832              :    either 0 or a string constant.  */
     833              : 
     834              : void
     835         3231 : set_conv_libfunc (convert_optab optab, machine_mode tmode,
     836              :                   machine_mode fmode, const char *name)
     837              : {
     838         3231 :   rtx val;
     839         3231 :   struct libfunc_entry e;
     840         3231 :   struct libfunc_entry **slot;
     841              : 
     842         3231 :   e.op = optab;
     843         3231 :   e.mode1 = tmode;
     844         3231 :   e.mode2 = fmode;
     845              : 
     846         3231 :   if (name)
     847         3231 :     val = init_one_libfunc (name);
     848              :   else
     849              :     val = 0;
     850         3231 :   slot = libfunc_hash->find_slot (&e, INSERT);
     851         3231 :   if (*slot == NULL)
     852         3231 :     *slot = ggc_alloc<libfunc_entry> ();
     853         3231 :   (*slot)->op = optab;
     854         3231 :   (*slot)->mode1 = tmode;
     855         3231 :   (*slot)->mode2 = fmode;
     856         3231 :   (*slot)->libfunc = val;
     857         3231 : }
     858              : 
     859              : /* Call this to initialize the contents of the optabs
     860              :    appropriately for the current target machine.  */
     861              : 
     862              : void
     863       774345 : init_optabs (void)
     864              : {
     865       774345 :   if (libfunc_hash)
     866            0 :     libfunc_hash->empty ();
     867              :   else
     868       774345 :     libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
     869              : 
     870              :   /* Fill in the optabs with the insns we support.  */
     871       774345 :   init_all_optabs (this_fn_optabs);
     872              : 
     873              :   /* The ffs function operates on `int'.  Fall back on it if we do not
     874              :      have a libgcc2 function for that width.  */
     875       774345 :   if (INT_TYPE_SIZE < BITS_PER_WORD)
     876              :     {
     877       759391 :       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
     878       759391 :       set_optab_libfunc (ffs_optab, mode, "ffs");
     879              :     }
     880              : 
     881              :   /* Explicitly initialize the bswap libfuncs since we need them to be
     882              :      valid for things other than word_mode.  */
     883       774345 :   if (targetm.libfunc_gnu_prefix)
     884              :     {
     885            0 :       set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
     886            0 :       set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
     887              :     }
     888              :   else
     889              :     {
     890       774345 :       set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
     891       774345 :       set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
     892              :     }
     893              : 
     894              :   /* Use cabs for double complex abs, since systems generally have cabs.
     895              :      Don't define any libcall for float complex, so that cabs will be used.  */
     896       774345 :   if (complex_double_type_node)
     897       774345 :     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
     898              :                        "cabs");
     899              : 
     900       774345 :   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
     901       774345 :   unwind_sjlj_unregister_libfunc
     902       774345 :     = init_one_libfunc ("_Unwind_SjLj_Unregister");
     903              : 
     904              :   /* Allow the target to add more libcalls or rename some, etc.  */
     905       774345 :   targetm.init_libfuncs ();
     906       774345 : }
     907              : 
     908              : /* A helper function for init_sync_libfuncs.  Using the basename BASE,
     909              :    install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
     910              : 
     911              : static void
     912            0 : init_sync_libfuncs_1 (optab tab, const char *base, int max)
     913              : {
     914            0 :   machine_mode mode;
     915            0 :   char buf[64];
     916            0 :   size_t len = strlen (base);
     917            0 :   int i;
     918              : 
     919            0 :   gcc_assert (max <= 8);
     920            0 :   gcc_assert (len + 3 < sizeof (buf));
     921              : 
     922            0 :   memcpy (buf, base, len);
     923            0 :   buf[len] = '_';
     924            0 :   buf[len + 1] = '0';
     925            0 :   buf[len + 2] = '\0';
     926              : 
     927            0 :   mode = QImode;
     928            0 :   for (i = 1; i <= max; i *= 2)
     929              :     {
     930            0 :       if (i > 1)
     931            0 :         mode = GET_MODE_2XWIDER_MODE (mode).require ();
     932            0 :       buf[len + 1] = '0' + i;
     933            0 :       set_optab_libfunc (tab, mode, buf);
     934              :     }
     935            0 : }
     936              : 
     937              : void
     938            0 : init_sync_libfuncs (int max)
     939              : {
     940            0 :   if (!flag_sync_libcalls)
     941              :     return;
     942              : 
     943            0 :   init_sync_libfuncs_1 (sync_compare_and_swap_optab,
     944              :                         "__sync_val_compare_and_swap", max);
     945            0 :   init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
     946              :                         "__sync_lock_test_and_set", max);
     947              : 
     948            0 :   init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
     949            0 :   init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
     950            0 :   init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
     951            0 :   init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
     952            0 :   init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
     953            0 :   init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
     954              : 
     955            0 :   init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
     956            0 :   init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
     957            0 :   init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
     958            0 :   init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
     959            0 :   init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
     960            0 :   init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
     961              : }
     962              : 
     963              : #include "gt-optabs-libfuncs.h"
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.