LCOV - code coverage report
Current view: top level - gcc - optabs-libfuncs.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 78.5 % 433 340
Test Date: 2026-09-19 16:22:48 Functions: 74.4 % 43 32
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     33559262 : libfunc_hasher::hash (libfunc_entry *e)
      54              : {
      55     33559262 :   return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
      56              : }
      57              : 
      58              : /* Used for libfunc_hash.  */
      59              : 
      60              : bool
      61     27259854 : libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
      62              : {
      63     27259854 :   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        42242 : convert_optab_libfunc (convert_optab optab, machine_mode mode1,
      71              :                        machine_mode mode2)
      72              : {
      73        42242 :   struct libfunc_entry e;
      74        42242 :   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        42242 :   if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
      80              :     return NULL_RTX;
      81              : 
      82        42242 :   e.op = optab;
      83        42242 :   e.mode1 = mode1;
      84        42242 :   e.mode2 = mode2;
      85        42242 :   slot = libfunc_hash->find_slot (&e, NO_INSERT);
      86        42242 :   if (!slot)
      87              :     {
      88         3406 :       const struct convert_optab_libcall_d *d
      89         3406 :         = &convlib_def[optab - FIRST_CONV_OPTAB];
      90              : 
      91         3406 :       if (d->libcall_gen == NULL)
      92              :         return NULL;
      93              : 
      94         3406 :       d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
      95         3406 :       slot = libfunc_hash->find_slot (&e, NO_INSERT);
      96         3406 :       if (!slot)
      97              :         return NULL;
      98              :     }
      99        42242 :   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      2523900 : optab_libfunc (optab optab, machine_mode mode)
     107              : {
     108      2523900 :   struct libfunc_entry e;
     109      2523900 :   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      2523900 :   if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
     115              :     return NULL_RTX;
     116              : 
     117      1852403 :   e.op = optab;
     118      1852403 :   e.mode1 = mode;
     119      1852403 :   e.mode2 = VOIDmode;
     120      1852403 :   slot = libfunc_hash->find_slot (&e, NO_INSERT);
     121      1852403 :   if (!slot)
     122              :     {
     123      1688097 :       const struct optab_libcall_d *d
     124      1688097 :         = &normlib_def[optab - FIRST_NORM_OPTAB];
     125              : 
     126      1688097 :       if (d->libcall_gen == NULL)
     127              :         return NULL;
     128              : 
     129      1352147 :       d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
     130      1352147 :       slot = libfunc_hash->find_slot (&e, NO_INSERT);
     131      1352147 :       if (!slot)
     132              :         return NULL;
     133              :     }
     134       182306 :   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        17916 : gen_libfunc (optab optable, const char *opname, int suffix,
     152              :              machine_mode mode)
     153              : {
     154        17916 :   unsigned opname_len = strlen (opname);
     155        17916 :   const char *mname = GET_MODE_NAME (mode);
     156        17916 :   unsigned mname_len = strlen (mname);
     157        17916 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     158        17916 :   int len = prefix_len + opname_len + mname_len + 1 + 1;
     159        17916 :   char *libfunc_name = XALLOCAVEC (char, len);
     160        17916 :   char *p;
     161        17916 :   const char *q;
     162              : 
     163        17916 :   p = libfunc_name;
     164        17916 :   *p++ = '_';
     165        17916 :   *p++ = '_';
     166        17916 :   if (targetm.libfunc_gnu_prefix)
     167              :     {
     168            0 :       *p++ = 'g';
     169            0 :       *p++ = 'n';
     170            0 :       *p++ = 'u';
     171            0 :       *p++ = '_';
     172              :     }
     173        84307 :   for (q = opname; *q;)
     174        66391 :     *p++ = *q++;
     175        53748 :   for (q = mname; *q; q++)
     176        35832 :     *p++ = TOLOWER (*q);
     177        17916 :   *p++ = suffix;
     178        17916 :   *p = '\0';
     179              : 
     180        17916 :   set_optab_libfunc (optable, mode,
     181        17916 :                      ggc_alloc_string (libfunc_name, p - libfunc_name));
     182        17916 : }
     183              : 
     184              : /* Like gen_libfunc, but verify that integer operation is involved.  */
     185              : 
     186              : void
     187      1345086 : gen_int_libfunc (optab optable, const char *opname, char suffix,
     188              :                  machine_mode mode)
     189              : {
     190      1345086 :   int maxsize = 2 * BITS_PER_WORD;
     191      1345086 :   int minsize = BITS_PER_WORD;
     192      1345086 :   scalar_int_mode int_mode;
     193              : 
     194      1345086 :   if (!is_int_mode (mode, &int_mode))
     195      1345086 :     return;
     196        41461 :   if (maxsize < LONG_LONG_TYPE_SIZE)
     197              :     maxsize = LONG_LONG_TYPE_SIZE;
     198        41461 :   if (minsize > INT_TYPE_SIZE
     199        80690 :       && (trapv_binoptab_p (optable)
     200        39229 :           || trapv_unoptab_p (optable)))
     201              :     minsize = INT_TYPE_SIZE;
     202        55087 :   if (GET_MODE_BITSIZE (int_mode) < minsize
     203        55087 :       || GET_MODE_BITSIZE (int_mode) > maxsize)
     204              :     return;
     205        12506 :   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         5410 : gen_fp_libfunc (optab optable, const char *opname, char suffix,
     212              :                 machine_mode mode)
     213              : {
     214         5410 :   char *dec_opname;
     215              : 
     216         5410 :   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
     217         3707 :     gen_libfunc (optable, opname, suffix, mode);
     218         5410 :   if (DECIMAL_FLOAT_MODE_P (mode))
     219              :     {
     220         1703 :       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         1703 :       memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
     224         1703 :       strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
     225         1703 :       gen_libfunc (optable, dec_opname, suffix, mode);
     226              :     }
     227         5410 : }
     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         9986 : gen_int_fp_libfunc (optab optable, const char *name, char suffix,
     268              :                     machine_mode mode)
     269              : {
     270         9986 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     271           27 :     gen_fp_libfunc (optable, name, suffix, mode);
     272         9986 :   if (INTEGRAL_MODE_P (mode))
     273         9943 :     gen_int_libfunc (optable, name, suffix, mode);
     274         9986 : }
     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          125 : gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
     281              :                      machine_mode mode)
     282              : {
     283          125 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     284            0 :     gen_fp_libfunc (optable, name, suffix, mode);
     285          125 :   if (GET_MODE_CLASS (mode) == MODE_INT)
     286              :     {
     287          125 :       int len = strlen (name);
     288          125 :       char *v_name = XALLOCAVEC (char, len + 2);
     289          125 :       strcpy (v_name, name);
     290          125 :       v_name[len] = 'v';
     291          125 :       v_name[len + 1] = 0;
     292          125 :       gen_int_libfunc (optable, v_name, suffix, mode);
     293              :     }
     294          125 : }
     295              : 
     296              : /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
     297              :    involved.  */
     298              : 
     299              : void
     300       912698 : gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
     301              :                           machine_mode mode)
     302              : {
     303       912698 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     304         1753 :     gen_fp_libfunc (optable, name, suffix, mode);
     305       912698 :   if (INTEGRAL_MODE_P (mode))
     306       909676 :     gen_int_libfunc (optable, name, suffix, mode);
     307       912698 :   if (ALL_FIXED_POINT_MODE_P (mode))
     308            0 :     gen_fixed_libfunc (optable, name, suffix, mode);
     309       912698 : }
     310              : 
     311              : /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
     312              :    involved.  */
     313              : 
     314              : void
     315        46526 : gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
     316              :                                  machine_mode mode)
     317              : {
     318        46526 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     319          357 :     gen_fp_libfunc (optable, name, suffix, mode);
     320        46526 :   if (INTEGRAL_MODE_P (mode))
     321        46153 :     gen_int_libfunc (optable, name, suffix, mode);
     322        46526 :   if (SIGNED_FIXED_POINT_MODE_P (mode))
     323            0 :     gen_signed_fixed_libfunc (optable, name, suffix, mode);
     324        46526 : }
     325              : 
     326              : /* Like gen_libfunc, but verify that INT or FIXED operation is
     327              :    involved.  */
     328              : 
     329              : void
     330       271220 : gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
     331              :                        machine_mode mode)
     332              : {
     333       271220 :   if (INTEGRAL_MODE_P (mode))
     334       271220 :     gen_int_libfunc (optable, name, suffix, mode);
     335       271220 :   if (ALL_FIXED_POINT_MODE_P (mode))
     336            0 :     gen_fixed_libfunc (optable, name, suffix, mode);
     337       271220 : }
     338              : 
     339              : /* Like gen_libfunc, but verify that INT or signed FIXED operation is
     340              :    involved.  */
     341              : 
     342              : void
     343          480 : gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
     344              :                               machine_mode mode)
     345              : {
     346          480 :   if (INTEGRAL_MODE_P (mode))
     347          256 :     gen_int_libfunc (optable, name, suffix, mode);
     348          480 :   if (SIGNED_FIXED_POINT_MODE_P (mode))
     349            0 :     gen_signed_fixed_libfunc (optable, name, suffix, mode);
     350          480 : }
     351              : 
     352              : /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
     353              :    involved.  */
     354              : 
     355              : void
     356        36984 : gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
     357              :                                 machine_mode mode)
     358              : {
     359        36984 :   if (INTEGRAL_MODE_P (mode))
     360        36942 :     gen_int_libfunc (optable, name, suffix, mode);
     361        36984 :   if (UNSIGNED_FIXED_POINT_MODE_P (mode))
     362            0 :     gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
     363        36984 : }
     364              : 
     365              : /* Helper function for gen_interclass_conv_libfunc and gen_bitint_fp_libfunc.
     366              :    Return name for interclass conversion function.  */
     367              : 
     368              : static const char *
     369         2214 : gen_interclass_conv_libfunc_name (const char *opname, bool decimal_p,
     370              :                                   const char *tname, const char *fname)
     371              : {
     372         2214 :   size_t opname_len = strlen (opname);
     373         2214 :   size_t mname_len = 0;
     374              : 
     375         2214 :   const char *q;
     376         2214 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     377         2214 :   char *libfunc_name, *suffix;
     378         2214 :   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
     379         2214 :   char *p;
     380              : 
     381              :   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
     382              :      depends on which underlying decimal floating point format is used.  */
     383         2214 :   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
     384              : 
     385         2214 :   mname_len = strlen (tname) + strlen (fname);
     386              : 
     387         2214 :   nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
     388         2214 :   nondec_name[0] = '_';
     389         2214 :   nondec_name[1] = '_';
     390         2214 :   if (targetm.libfunc_gnu_prefix)
     391              :     {
     392            0 :       nondec_name[2] = 'g';
     393            0 :       nondec_name[3] = 'n';
     394            0 :       nondec_name[4] = 'u';
     395            0 :       nondec_name[5] = '_';
     396              :     }
     397              : 
     398         2214 :   memcpy (&nondec_name[prefix_len], opname, opname_len);
     399         2214 :   nondec_suffix = nondec_name + opname_len + prefix_len;
     400              : 
     401         2214 :   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
     402         2214 :   dec_name[0] = '_';
     403         2214 :   dec_name[1] = '_';
     404         2214 :   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
     405         2214 :   memcpy (&dec_name[2+dec_len], opname, opname_len);
     406         2214 :   dec_suffix = dec_name + dec_len + opname_len + 2;
     407              : 
     408         2214 :   if (decimal_p)
     409              :     {
     410              :       libfunc_name = dec_name;
     411              :       suffix = dec_suffix;
     412              :     }
     413              :   else
     414              :     {
     415         1139 :       libfunc_name = nondec_name;
     416         1139 :       suffix = nondec_suffix;
     417              :     }
     418              : 
     419         2214 :   p = suffix;
     420         6818 :   for (q = fname; *q; p++, q++)
     421         4604 :     *p = TOLOWER (*q);
     422         6802 :   for (q = tname; *q; p++, q++)
     423         4588 :     *p = TOLOWER (*q);
     424              : 
     425         2214 :   *p = '\0';
     426              : 
     427         2214 :   return ggc_alloc_string (libfunc_name, p - libfunc_name);
     428              : }
     429              : 
     430              : /* Initialize the libfunc fields of an entire group of entries of an
     431              :    inter-mode-class conversion optab.  The string formation rules are
     432              :    similar to the ones for init_libfuncs, above, but instead of having
     433              :    a mode name and an operand count these functions have two mode names
     434              :    and no operand count.  */
     435              : 
     436              : void
     437         2130 : gen_interclass_conv_libfunc (convert_optab tab,
     438              :                              const char *opname,
     439              :                              machine_mode tmode,
     440              :                              machine_mode fmode)
     441              : {
     442         2130 :   const char *name
     443         2130 :     = gen_interclass_conv_libfunc_name (opname,
     444         2130 :                                         DECIMAL_FLOAT_MODE_P (fmode)
     445         1594 :                                         || DECIMAL_FLOAT_MODE_P (tmode),
     446         2130 :                                         GET_MODE_NAME (tmode),
     447         2130 :                                         GET_MODE_NAME (fmode));
     448         2130 :   set_conv_libfunc (tab, tmode, fmode, name);
     449         2130 : }
     450              : 
     451              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     452              :    int->fp conversion.  */
     453              : 
     454              : void
     455          757 : gen_int_to_fp_conv_libfunc (convert_optab tab,
     456              :                             const char *opname,
     457              :                             machine_mode tmode,
     458              :                             machine_mode fmode)
     459              : {
     460          757 :   if (GET_MODE_CLASS (fmode) != MODE_INT)
     461              :     return;
     462          757 :   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
     463              :     return;
     464          757 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     465              : }
     466              : 
     467              : /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
     468              :    naming scheme.  */
     469              : 
     470              : void
     471          277 : gen_ufloat_conv_libfunc (convert_optab tab,
     472              :                          const char *opname ATTRIBUTE_UNUSED,
     473              :                          machine_mode tmode,
     474              :                          machine_mode fmode)
     475              : {
     476          277 :   if (DECIMAL_FLOAT_MODE_P (tmode))
     477           70 :     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
     478              :   else
     479          207 :     gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
     480          277 : }
     481              : 
     482              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     483              :    fp->int conversion.  */
     484              : 
     485              : void
     486            0 : gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
     487              :                                        const char *opname,
     488              :                                        machine_mode tmode,
     489              :                                        machine_mode fmode)
     490              : {
     491            0 :   if (GET_MODE_CLASS (fmode) != MODE_INT)
     492              :     return;
     493            0 :   if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
     494              :     return;
     495            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     496              : }
     497              : 
     498              : /* Same as gen_interclass_conv_libfunc but verify that we are producing
     499              :    fp->int conversion with no decimal floating point involved.  */
     500              : 
     501              : void
     502          744 : gen_fp_to_int_conv_libfunc (convert_optab tab,
     503              :                             const char *opname,
     504              :                             machine_mode tmode,
     505              :                             machine_mode fmode)
     506              : {
     507          744 :   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
     508              :     return;
     509          744 :   if (GET_MODE_CLASS (tmode) != MODE_INT)
     510              :     return;
     511          744 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     512              : }
     513              : 
     514              : /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
     515              :    The string formation rules are
     516              :    similar to the ones for init_libfunc, above.  */
     517              : 
     518              : void
     519         1276 : gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
     520              :                              machine_mode tmode, machine_mode fmode)
     521              : {
     522         1276 :   size_t opname_len = strlen (opname);
     523         1276 :   size_t mname_len = 0;
     524              : 
     525         1276 :   const char *fname, *tname;
     526         1276 :   const char *q;
     527         1276 :   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
     528         1276 :   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
     529         1276 :   char *libfunc_name, *suffix;
     530         1276 :   char *p;
     531              : 
     532              :   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
     533              :      depends on which underlying decimal floating point format is used.  */
     534         1276 :   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
     535              : 
     536         1276 :   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
     537              : 
     538         1276 :   nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
     539         1276 :   nondec_name[0] = '_';
     540         1276 :   nondec_name[1] = '_';
     541         1276 :   if (targetm.libfunc_gnu_prefix)
     542              :     {
     543            0 :       nondec_name[2] = 'g';
     544            0 :       nondec_name[3] = 'n';
     545            0 :       nondec_name[4] = 'u';
     546            0 :       nondec_name[5] = '_';
     547              :     }
     548         1276 :   memcpy (&nondec_name[prefix_len], opname, opname_len);
     549         1276 :   nondec_suffix = nondec_name + opname_len + prefix_len;
     550              : 
     551         1276 :   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
     552         1276 :   dec_name[0] = '_';
     553         1276 :   dec_name[1] = '_';
     554         1276 :   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
     555         1276 :   memcpy (&dec_name[2 + dec_len], opname, opname_len);
     556         1276 :   dec_suffix = dec_name + dec_len + opname_len + 2;
     557              : 
     558         1276 :   fname = GET_MODE_NAME (fmode);
     559         1276 :   tname = GET_MODE_NAME (tmode);
     560              : 
     561         1276 :   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
     562              :     {
     563              :       libfunc_name = dec_name;
     564              :       suffix = dec_suffix;
     565              :     }
     566              :   else
     567              :     {
     568         1276 :       libfunc_name = nondec_name;
     569         1276 :       suffix = nondec_suffix;
     570              :     }
     571              : 
     572         1276 :   p = suffix;
     573         3828 :   for (q = fname; *q; p++, q++)
     574         2552 :     *p = TOLOWER (*q);
     575         3828 :   for (q = tname; *q; p++, q++)
     576         2552 :     *p = TOLOWER (*q);
     577              : 
     578         1276 :   *p++ = '2';
     579         1276 :   *p = '\0';
     580              : 
     581         1276 :   set_conv_libfunc (tab, tmode, fmode,
     582         1276 :                     ggc_alloc_string (libfunc_name, p - libfunc_name));
     583         1276 : }
     584              : 
     585              : /* Pick proper libcall for trunc_optab.  We need to chose if we do
     586              :    truncation or extension and interclass or intraclass.  */
     587              : 
     588              : void
     589          867 : gen_trunc_conv_libfunc (convert_optab tab,
     590              :                         const char *opname,
     591              :                         machine_mode tmode,
     592              :                         machine_mode fmode)
     593              : {
     594          867 :   scalar_float_mode float_tmode, float_fmode;
     595          867 :   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
     596         1734 :       || !is_a <scalar_float_mode> (tmode, &float_tmode)
     597          867 :       || float_tmode == float_fmode)
     598              :     return;
     599              : 
     600          867 :   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
     601          329 :     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     602              : 
     603          867 :   if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode)
     604           87 :       && (REAL_MODE_FORMAT (float_tmode) != &arm_bfloat_half_format
     605            1 :           || REAL_MODE_FORMAT (float_fmode) != &ieee_half_format)
     606          953 :       && (REAL_MODE_FORMAT (float_tmode) != &ieee_quad_format
     607            0 :           || REAL_MODE_FORMAT (float_fmode) != &ibm_extended_format))
     608              :     return;
     609              : 
     610          781 :   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
     611          538 :     gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     612              : }
     613              : 
     614              : /* Pick proper libcall for extend_optab.  We need to chose if we do
     615              :    truncation or extension and interclass or intraclass.  */
     616              : 
     617              : void
     618         1038 : gen_extend_conv_libfunc (convert_optab tab,
     619              :                          const char *opname ATTRIBUTE_UNUSED,
     620              :                          machine_mode tmode,
     621              :                          machine_mode fmode)
     622              : {
     623         1038 :   scalar_float_mode float_tmode, float_fmode;
     624         1038 :   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
     625         2076 :       || !is_a <scalar_float_mode> (tmode, &float_tmode)
     626         1038 :       || float_tmode == float_fmode)
     627              :     return;
     628              : 
     629         1038 :   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
     630          300 :     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
     631              : 
     632         1038 :   if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
     633              :     return;
     634              : 
     635         1038 :   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
     636          738 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     637              : }
     638              : 
     639              : /* Pick proper libcall for fract_optab.  We need to chose if we do
     640              :    interclass or intraclass.  */
     641              : 
     642              : void
     643            0 : gen_fract_conv_libfunc (convert_optab tab,
     644              :                         const char *opname,
     645              :                         machine_mode tmode,
     646              :                         machine_mode fmode)
     647              : {
     648            0 :   if (tmode == fmode)
     649              :     return;
     650            0 :   if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
     651              :     return;
     652              : 
     653            0 :   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
     654            0 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     655              :   else
     656            0 :     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     657              : }
     658              : 
     659              : /* Pick proper libcall for fractuns_optab.  */
     660              : 
     661              : void
     662            0 : gen_fractuns_conv_libfunc (convert_optab tab,
     663              :                            const char *opname,
     664              :                            machine_mode tmode,
     665              :                            machine_mode fmode)
     666              : {
     667            0 :   if (tmode == fmode)
     668              :     return;
     669              :   /* One mode must be a fixed-point mode, and the other must be an integer
     670              :      mode.  */
     671            0 :   if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
     672            0 :         || (ALL_FIXED_POINT_MODE_P (fmode)
     673            0 :             && GET_MODE_CLASS (tmode) == MODE_INT)))
     674              :     return;
     675              : 
     676            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     677              : }
     678              : 
     679              : /* Pick proper libcall for satfract_optab.  We need to chose if we do
     680              :    interclass or intraclass.  */
     681              : 
     682              : void
     683            0 : gen_satfract_conv_libfunc (convert_optab tab,
     684              :                            const char *opname,
     685              :                            machine_mode tmode,
     686              :                            machine_mode fmode)
     687              : {
     688            0 :   if (tmode == fmode)
     689              :     return;
     690              :   /* TMODE must be a fixed-point mode.  */
     691            0 :   if (!ALL_FIXED_POINT_MODE_P (tmode))
     692              :     return;
     693              : 
     694            0 :   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
     695            0 :     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
     696              :   else
     697            0 :     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     698              : }
     699              : 
     700              : /* Pick proper libcall for satfractuns_optab.  */
     701              : 
     702              : void
     703            0 : gen_satfractuns_conv_libfunc (convert_optab tab,
     704              :                               const char *opname,
     705              :                               machine_mode tmode,
     706              :                               machine_mode fmode)
     707              : {
     708            0 :   if (tmode == fmode)
     709              :     return;
     710              :   /* TMODE must be a fixed-point mode, and FMODE must be an integer mode.  */
     711            0 :   if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
     712              :     return;
     713              : 
     714            0 :   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
     715              : }
     716              : 
     717              : /* Pick proper libcall for bitinttofp_optab and bitintfromfp_optab.  */
     718              : 
     719              : void
     720           84 : gen_bitint_fp_libfunc (optab optable, const char *opname, char suffix,
     721              :                        machine_mode mode)
     722              : {
     723           84 :   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     724              :     {
     725           84 :       const char *name;
     726           84 :       if (suffix == '0')
     727           44 :         name = gen_interclass_conv_libfunc_name (opname,
     728              :                                                  DECIMAL_FLOAT_MODE_P (mode),
     729           44 :                                                  GET_MODE_NAME (mode),
     730              :                                                  "bitint");
     731              :       else
     732           40 :         name = gen_interclass_conv_libfunc_name (opname,
     733              :                                                  DECIMAL_FLOAT_MODE_P (mode),
     734              :                                                  "bitint",
     735           40 :                                                  GET_MODE_NAME (mode));
     736           84 :       set_optab_libfunc (optable, mode, name);
     737              :     }
     738           84 : }
     739              : 
     740              : /* Hashtable callbacks for libfunc_decls.  */
     741              : 
     742              : struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
     743              : {
     744              :   static hashval_t
     745      4275737 :   hash (tree entry)
     746              :   {
     747      4275737 :     return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
     748              :   }
     749              : 
     750              :   static bool
     751      8599425 :   equal (tree decl, tree name)
     752              :   {
     753      8599425 :     return DECL_NAME (decl) == name;
     754              :   }
     755              : };
     756              : 
     757              : /* A table of previously-created libfuncs, hashed by name.  */
     758              : static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
     759              : 
     760              : /* Build a decl for a libfunc named NAME with visibility VIS.  */
     761              : 
     762              : tree
     763      2312093 : build_libfunc_function_visibility (const char *name, symbol_visibility vis)
     764              : {
     765              :   /* ??? We don't have any type information; pretend this is "int foo ()".  */
     766      2312093 :   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
     767              :                           get_identifier (name),
     768              :                           build_function_type (integer_type_node, NULL_TREE));
     769      2312093 :   DECL_EXTERNAL (decl) = 1;
     770      2312093 :   TREE_PUBLIC (decl) = 1;
     771      2312093 :   DECL_ARTIFICIAL (decl) = 1;
     772      2312093 :   DECL_VISIBILITY (decl) = vis;
     773      2312093 :   DECL_VISIBILITY_SPECIFIED (decl) = 1;
     774      2312093 :   gcc_assert (DECL_ASSEMBLER_NAME (decl));
     775              : 
     776      2312093 :   return decl;
     777              : }
     778              : 
     779              : /* Build a decl for a libfunc named NAME.  */
     780              : 
     781              : tree
     782            0 : build_libfunc_function (const char *name)
     783              : {
     784            0 :   return build_libfunc_function_visibility (name, VISIBILITY_DEFAULT);
     785              : }
     786              : 
     787              : /* Return a libfunc for NAME, creating one if we don't already have one.
     788              :    The decl is given visibility VIS.  The returned rtx is a SYMBOL_REF.  */
     789              : 
     790              : rtx
     791      6336886 : init_one_libfunc_visibility (const char *name, symbol_visibility vis)
     792              : {
     793      6336886 :   tree id, decl;
     794      6336886 :   hashval_t hash;
     795              : 
     796      6336886 :   if (libfunc_decls == NULL)
     797       286955 :     libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
     798              : 
     799              :   /* See if we have already created a libfunc decl for this function.  */
     800      6336886 :   id = get_identifier (name);
     801      6336886 :   hash = IDENTIFIER_HASH_VALUE (id);
     802      6336886 :   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
     803      6336886 :   decl = *slot;
     804      6336886 :   if (decl == NULL)
     805              :     {
     806              :       /* Create a new decl, so that it can be passed to
     807              :          targetm.encode_section_info.  */
     808      2312093 :       decl = build_libfunc_function_visibility (name, vis);
     809      2312093 :       *slot = decl;
     810              :     }
     811      6336886 :   return XEXP (DECL_RTL (decl), 0);
     812              : }
     813              : 
     814              : rtx
     815      6336886 : init_one_libfunc (const char *name)
     816              : {
     817      6336886 :   return init_one_libfunc_visibility (name, VISIBILITY_DEFAULT);
     818              : }
     819              : 
     820              : /* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
     821              : 
     822              : rtx
     823            1 : set_user_assembler_libfunc (const char *name, const char *asmspec)
     824              : {
     825            1 :   tree id, decl;
     826            1 :   hashval_t hash;
     827              : 
     828            1 :   id = get_identifier (name);
     829            1 :   hash = IDENTIFIER_HASH_VALUE (id);
     830            1 :   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
     831            1 :   gcc_assert (slot);
     832            1 :   decl = (tree) *slot;
     833            1 :   set_user_assembler_name (decl, asmspec);
     834            1 :   return XEXP (DECL_RTL (decl), 0);
     835              : }
     836              : 
     837              : /* Call this to reset the function entry for one optab (OPTABLE) in mode
     838              :    MODE to NAME, which should be either 0 or a string constant.  */
     839              : 
     840              : void
     841      4747717 : set_optab_libfunc (optab op, machine_mode mode, const char *name)
     842              : {
     843      4747717 :   rtx val;
     844      4747717 :   struct libfunc_entry e;
     845      4747717 :   struct libfunc_entry **slot;
     846              : 
     847      4747717 :   e.op = op;
     848      4747717 :   e.mode1 = mode;
     849      4747717 :   e.mode2 = VOIDmode;
     850              : 
     851      4747717 :   if (name)
     852      4747717 :     val = init_one_libfunc (name);
     853              :   else
     854              :     val = 0;
     855      4747717 :   slot = libfunc_hash->find_slot (&e, INSERT);
     856      4747717 :   if (*slot == NULL)
     857      4747716 :     *slot = ggc_alloc<libfunc_entry> ();
     858      4747717 :   (*slot)->op = op;
     859      4747717 :   (*slot)->mode1 = mode;
     860      4747717 :   (*slot)->mode2 = VOIDmode;
     861      4747717 :   (*slot)->libfunc = val;
     862      4747717 : }
     863              : 
     864              : /* Call this to reset the function entry for one conversion optab
     865              :    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
     866              :    either 0 or a string constant.  */
     867              : 
     868              : void
     869         3406 : set_conv_libfunc (convert_optab optab, machine_mode tmode,
     870              :                   machine_mode fmode, const char *name)
     871              : {
     872         3406 :   rtx val;
     873         3406 :   struct libfunc_entry e;
     874         3406 :   struct libfunc_entry **slot;
     875              : 
     876         3406 :   e.op = optab;
     877         3406 :   e.mode1 = tmode;
     878         3406 :   e.mode2 = fmode;
     879              : 
     880         3406 :   if (name)
     881         3406 :     val = init_one_libfunc (name);
     882              :   else
     883              :     val = 0;
     884         3406 :   slot = libfunc_hash->find_slot (&e, INSERT);
     885         3406 :   if (*slot == NULL)
     886         3406 :     *slot = ggc_alloc<libfunc_entry> ();
     887         3406 :   (*slot)->op = optab;
     888         3406 :   (*slot)->mode1 = tmode;
     889         3406 :   (*slot)->mode2 = fmode;
     890         3406 :   (*slot)->libfunc = val;
     891         3406 : }
     892              : 
     893              : /* Call this to initialize the contents of the optabs
     894              :    appropriately for the current target machine.  */
     895              : 
     896              : void
     897       790793 : init_optabs (void)
     898              : {
     899       790793 :   if (libfunc_hash)
     900            0 :     libfunc_hash->empty ();
     901              :   else
     902       790793 :     libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
     903              : 
     904              :   /* Fill in the optabs with the insns we support.  */
     905       790793 :   init_all_optabs (this_fn_optabs);
     906              : 
     907              :   /* The ffs function operates on `int'.  Fall back on it if we do not
     908              :      have a libgcc2 function for that width.  */
     909       790793 :   if (INT_TYPE_SIZE < BITS_PER_WORD)
     910              :     {
     911       775751 :       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
     912       775751 :       set_optab_libfunc (ffs_optab, mode, "ffs");
     913              :     }
     914              : 
     915              :   /* Explicitly initialize the bswap libfuncs since we need them to be
     916              :      valid for things other than word_mode.  */
     917       790793 :   if (targetm.libfunc_gnu_prefix)
     918              :     {
     919            0 :       set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
     920            0 :       set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
     921              :     }
     922              :   else
     923              :     {
     924       790793 :       set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
     925       790793 :       set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
     926              :     }
     927              : 
     928              :   /* Use cabs for double complex abs, since systems generally have cabs.
     929              :      Don't define any libcall for float complex, so that cabs will be used.  */
     930       790793 :   if (complex_double_type_node)
     931       790793 :     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
     932              :                        "cabs");
     933              : 
     934       790793 :   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
     935       790793 :   unwind_sjlj_unregister_libfunc
     936       790793 :     = init_one_libfunc ("_Unwind_SjLj_Unregister");
     937              : 
     938              :   /* Allow the target to add more libcalls or rename some, etc.  */
     939       790793 :   targetm.init_libfuncs ();
     940       790793 : }
     941              : 
     942              : /* A helper function for init_sync_libfuncs.  Using the basename BASE,
     943              :    install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
     944              : 
     945              : static void
     946            0 : init_sync_libfuncs_1 (optab tab, const char *base, int max)
     947              : {
     948            0 :   machine_mode mode;
     949            0 :   char buf[64];
     950            0 :   size_t len = strlen (base);
     951            0 :   int i;
     952              : 
     953            0 :   gcc_assert (max <= 8);
     954            0 :   gcc_assert (len + 3 < sizeof (buf));
     955              : 
     956            0 :   memcpy (buf, base, len);
     957            0 :   buf[len] = '_';
     958            0 :   buf[len + 1] = '0';
     959            0 :   buf[len + 2] = '\0';
     960              : 
     961            0 :   mode = QImode;
     962            0 :   for (i = 1; i <= max; i *= 2)
     963              :     {
     964            0 :       if (i > 1)
     965            0 :         mode = GET_MODE_2XWIDER_MODE (mode).require ();
     966            0 :       buf[len + 1] = '0' + i;
     967            0 :       set_optab_libfunc (tab, mode, buf);
     968              :     }
     969            0 : }
     970              : 
     971              : void
     972            0 : init_sync_libfuncs (int max)
     973              : {
     974            0 :   if (!flag_sync_libcalls)
     975              :     return;
     976              : 
     977            0 :   init_sync_libfuncs_1 (sync_compare_and_swap_optab,
     978              :                         "__sync_val_compare_and_swap", max);
     979            0 :   init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
     980              :                         "__sync_lock_test_and_set", max);
     981              : 
     982            0 :   init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
     983            0 :   init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
     984            0 :   init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
     985            0 :   init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
     986            0 :   init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
     987            0 :   init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
     988              : 
     989            0 :   init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
     990            0 :   init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
     991            0 :   init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
     992            0 :   init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
     993            0 :   init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
     994            0 :   init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
     995              : }
     996              : 
     997              : #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.