LCOV - code coverage report
Current view: top level - gcc/config/i386 - i386-features.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 1247 1346 92.6 %
Date: 2020-03-28 11:57:23 Functions: 63 65 96.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Copyright (C) 1988-2020 Free Software Foundation, Inc.
       2                 :            : 
       3                 :            : This file is part of GCC.
       4                 :            : 
       5                 :            : GCC is free software; you can redistribute it and/or modify
       6                 :            : it under the terms of the GNU General Public License as published by
       7                 :            : the Free Software Foundation; either version 3, or (at your option)
       8                 :            : any later version.
       9                 :            : 
      10                 :            : GCC is distributed in the hope that it will be useful,
      11                 :            : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :            : GNU General Public License for more details.
      14                 :            : 
      15                 :            : You should have received a copy of the GNU General Public License
      16                 :            : along with GCC; see the file COPYING3.  If not see
      17                 :            : <http://www.gnu.org/licenses/>.  */
      18                 :            : 
      19                 :            : #define IN_TARGET_CODE 1
      20                 :            : 
      21                 :            : #include "config.h"
      22                 :            : #include "system.h"
      23                 :            : #include "coretypes.h"
      24                 :            : #include "backend.h"
      25                 :            : #include "rtl.h"
      26                 :            : #include "tree.h"
      27                 :            : #include "memmodel.h"
      28                 :            : #include "gimple.h"
      29                 :            : #include "cfghooks.h"
      30                 :            : #include "cfgloop.h"
      31                 :            : #include "df.h"
      32                 :            : #include "tm_p.h"
      33                 :            : #include "stringpool.h"
      34                 :            : #include "expmed.h"
      35                 :            : #include "optabs.h"
      36                 :            : #include "regs.h"
      37                 :            : #include "emit-rtl.h"
      38                 :            : #include "recog.h"
      39                 :            : #include "cgraph.h"
      40                 :            : #include "diagnostic.h"
      41                 :            : #include "cfgbuild.h"
      42                 :            : #include "alias.h"
      43                 :            : #include "fold-const.h"
      44                 :            : #include "attribs.h"
      45                 :            : #include "calls.h"
      46                 :            : #include "stor-layout.h"
      47                 :            : #include "varasm.h"
      48                 :            : #include "output.h"
      49                 :            : #include "insn-attr.h"
      50                 :            : #include "flags.h"
      51                 :            : #include "except.h"
      52                 :            : #include "explow.h"
      53                 :            : #include "expr.h"
      54                 :            : #include "cfgrtl.h"
      55                 :            : #include "common/common-target.h"
      56                 :            : #include "langhooks.h"
      57                 :            : #include "reload.h"
      58                 :            : #include "gimplify.h"
      59                 :            : #include "dwarf2.h"
      60                 :            : #include "tm-constrs.h"
      61                 :            : #include "cselib.h"
      62                 :            : #include "sched-int.h"
      63                 :            : #include "opts.h"
      64                 :            : #include "tree-pass.h"
      65                 :            : #include "context.h"
      66                 :            : #include "pass_manager.h"
      67                 :            : #include "target-globals.h"
      68                 :            : #include "gimple-iterator.h"
      69                 :            : #include "tree-vectorizer.h"
      70                 :            : #include "shrink-wrap.h"
      71                 :            : #include "builtins.h"
      72                 :            : #include "rtl-iter.h"
      73                 :            : #include "tree-iterator.h"
      74                 :            : #include "dbgcnt.h"
      75                 :            : #include "case-cfn-macros.h"
      76                 :            : #include "dojump.h"
      77                 :            : #include "fold-const-call.h"
      78                 :            : #include "tree-vrp.h"
      79                 :            : #include "tree-ssanames.h"
      80                 :            : #include "selftest.h"
      81                 :            : #include "selftest-rtl.h"
      82                 :            : #include "print-rtl.h"
      83                 :            : #include "intl.h"
      84                 :            : #include "ifcvt.h"
      85                 :            : #include "symbol-summary.h"
      86                 :            : #include "ipa-prop.h"
      87                 :            : #include "ipa-fnsummary.h"
      88                 :            : #include "wide-int-bitmask.h"
      89                 :            : #include "tree-vector-builder.h"
      90                 :            : #include "debug.h"
      91                 :            : #include "dwarf2out.h"
      92                 :            : #include "i386-builtins.h"
      93                 :            : #include "i386-features.h"
      94                 :            : 
      95                 :            : const char * const xlogue_layout::STUB_BASE_NAMES[XLOGUE_STUB_COUNT] = {
      96                 :            :   "savms64",
      97                 :            :   "resms64",
      98                 :            :   "resms64x",
      99                 :            :   "savms64f",
     100                 :            :   "resms64f",
     101                 :            :   "resms64fx"
     102                 :            : };
     103                 :            : 
     104                 :            : const unsigned xlogue_layout::REG_ORDER[xlogue_layout::MAX_REGS] = {
     105                 :            : /* The below offset values are where each register is stored for the layout
     106                 :            :    relative to incoming stack pointer.  The value of each m_regs[].offset will
     107                 :            :    be relative to the incoming base pointer (rax or rsi) used by the stub.
     108                 :            : 
     109                 :            :     s_instances:   0            1               2               3
     110                 :            :     Offset:                                     realigned or    aligned + 8
     111                 :            :     Register       aligned      aligned + 8     aligned w/HFP   w/HFP   */
     112                 :            :     XMM15_REG,  /* 0x10         0x18            0x10            0x18    */
     113                 :            :     XMM14_REG,  /* 0x20         0x28            0x20            0x28    */
     114                 :            :     XMM13_REG,  /* 0x30         0x38            0x30            0x38    */
     115                 :            :     XMM12_REG,  /* 0x40         0x48            0x40            0x48    */
     116                 :            :     XMM11_REG,  /* 0x50         0x58            0x50            0x58    */
     117                 :            :     XMM10_REG,  /* 0x60         0x68            0x60            0x68    */
     118                 :            :     XMM9_REG,   /* 0x70         0x78            0x70            0x78    */
     119                 :            :     XMM8_REG,   /* 0x80         0x88            0x80            0x88    */
     120                 :            :     XMM7_REG,   /* 0x90         0x98            0x90            0x98    */
     121                 :            :     XMM6_REG,   /* 0xa0         0xa8            0xa0            0xa8    */
     122                 :            :     SI_REG,     /* 0xa8         0xb0            0xa8            0xb0    */
     123                 :            :     DI_REG,     /* 0xb0         0xb8            0xb0            0xb8    */
     124                 :            :     BX_REG,     /* 0xb8         0xc0            0xb8            0xc0    */
     125                 :            :     BP_REG,     /* 0xc0         0xc8            N/A             N/A     */
     126                 :            :     R12_REG,    /* 0xc8         0xd0            0xc0            0xc8    */
     127                 :            :     R13_REG,    /* 0xd0         0xd8            0xc8            0xd0    */
     128                 :            :     R14_REG,    /* 0xd8         0xe0            0xd0            0xd8    */
     129                 :            :     R15_REG,    /* 0xe0         0xe8            0xd8            0xe0    */
     130                 :            : };
     131                 :            : 
     132                 :            : /* Instantiate static const values.  */
     133                 :            : const HOST_WIDE_INT xlogue_layout::STUB_INDEX_OFFSET;
     134                 :            : const unsigned xlogue_layout::MIN_REGS;
     135                 :            : const unsigned xlogue_layout::MAX_REGS;
     136                 :            : const unsigned xlogue_layout::MAX_EXTRA_REGS;
     137                 :            : const unsigned xlogue_layout::VARIANT_COUNT;
     138                 :            : const unsigned xlogue_layout::STUB_NAME_MAX_LEN;
     139                 :            : 
     140                 :            : /* Initialize xlogue_layout::s_stub_names to zero.  */
     141                 :            : char xlogue_layout::s_stub_names[2][XLOGUE_STUB_COUNT][VARIANT_COUNT]
     142                 :            :                                 [STUB_NAME_MAX_LEN];
     143                 :            : 
     144                 :            : /* Instantiates all xlogue_layout instances.  */
     145                 :            : const xlogue_layout xlogue_layout::s_instances[XLOGUE_SET_COUNT] = {
     146                 :            :   xlogue_layout (0, false),
     147                 :            :   xlogue_layout (8, false),
     148                 :            :   xlogue_layout (0, true),
     149                 :            :   xlogue_layout (8, true)
     150                 :            : };
     151                 :            : 
     152                 :            : /* Return an appropriate const instance of xlogue_layout based upon values
     153                 :            :    in cfun->machine and crtl.  */
     154                 :            : const class xlogue_layout &
     155                 :      56936 : xlogue_layout::get_instance ()
     156                 :            : {
     157                 :      56936 :   enum xlogue_stub_sets stub_set;
     158                 :      56936 :   bool aligned_plus_8 = cfun->machine->call_ms2sysv_pad_in;
     159                 :            : 
     160                 :      56936 :   if (stack_realign_fp)
     161                 :            :     stub_set = XLOGUE_SET_HFP_ALIGNED_OR_REALIGN;
     162                 :      46680 :   else if (frame_pointer_needed)
     163                 :      36040 :     stub_set = aligned_plus_8
     164                 :      36040 :               ? XLOGUE_SET_HFP_ALIGNED_PLUS_8
     165                 :            :               : XLOGUE_SET_HFP_ALIGNED_OR_REALIGN;
     166                 :            :   else
     167                 :      10640 :     stub_set = aligned_plus_8 ? XLOGUE_SET_ALIGNED_PLUS_8 : XLOGUE_SET_ALIGNED;
     168                 :            : 
     169                 :      56936 :   return s_instances[stub_set];
     170                 :            : }
     171                 :            : 
     172                 :            : /* Determine how many clobbered registers can be saved by the stub.
     173                 :            :    Returns the count of registers the stub will save and restore.  */
     174                 :            : unsigned
     175                 :      42270 : xlogue_layout::count_stub_managed_regs ()
     176                 :            : {
     177                 :      42270 :   bool hfp = frame_pointer_needed || stack_realign_fp;
     178                 :      42270 :   unsigned i, count;
     179                 :      42270 :   unsigned regno;
     180                 :            : 
     181                 :     125360 :   for (count = i = MIN_REGS; i < MAX_REGS; ++i)
     182                 :            :     {
     183                 :     123650 :       regno = REG_ORDER[i];
     184                 :     123650 :       if (regno == BP_REG && hfp)
     185                 :      24640 :         continue;
     186                 :      99010 :       if (!ix86_save_reg (regno, false, false))
     187                 :            :         break;
     188                 :      58450 :       ++count;
     189                 :            :     }
     190                 :      42270 :   return count;
     191                 :            : }
     192                 :            : 
     193                 :            : /* Determine if register REGNO is a stub managed register given the
     194                 :            :    total COUNT of stub managed registers.  */
     195                 :            : bool
     196                 :    2220610 : xlogue_layout::is_stub_managed_reg (unsigned regno, unsigned count)
     197                 :            : {
     198                 :    2220610 :   bool hfp = frame_pointer_needed || stack_realign_fp;
     199                 :    2220610 :   unsigned i;
     200                 :            : 
     201                 :   28172100 :   for (i = 0; i < count; ++i)
     202                 :            :     {
     203                 :   26555200 :       gcc_assert (i < MAX_REGS);
     204                 :   26555200 :       if (REG_ORDER[i] == BP_REG && hfp)
     205                 :     466560 :         ++count;
     206                 :   26088600 :       else if (REG_ORDER[i] == regno)
     207                 :            :         return true;
     208                 :            :     }
     209                 :            :   return false;
     210                 :            : }
     211                 :            : 
     212                 :            : /* Constructor for xlogue_layout.  */
     213                 :     799108 : xlogue_layout::xlogue_layout (HOST_WIDE_INT stack_align_off_in, bool hfp)
     214                 :     799108 :   : m_hfp (hfp) , m_nregs (hfp ? 17 : 18),
     215                 :     799108 :     m_stack_align_off_in (stack_align_off_in)
     216                 :            : {
     217                 :     799108 :   HOST_WIDE_INT offset = stack_align_off_in;
     218                 :     799108 :   unsigned i, j;
     219                 :            : 
     220                 :   15183100 :   for (i = j = 0; i < MAX_REGS; ++i)
     221                 :            :     {
     222                 :   14383900 :       unsigned regno = REG_ORDER[i];
     223                 :            : 
     224                 :   14383900 :       if (regno == BP_REG && hfp)
     225                 :     399554 :         continue;
     226                 :   13984400 :       if (SSE_REGNO_P (regno))
     227                 :            :         {
     228                 :    7991080 :           offset += 16;
     229                 :            :           /* Verify that SSE regs are always aligned.  */
     230                 :    7991080 :           gcc_assert (!((stack_align_off_in + offset) & 15));
     231                 :            :         }
     232                 :            :       else
     233                 :    5993310 :         offset += 8;
     234                 :            : 
     235                 :   13984400 :       m_regs[j].regno    = regno;
     236                 :   13984400 :       m_regs[j++].offset = offset - STUB_INDEX_OFFSET;
     237                 :            :     }
     238                 :     799108 :   gcc_assert (j == m_nregs);
     239                 :     799108 : }
     240                 :            : 
     241                 :            : const char *
     242                 :      14666 : xlogue_layout::get_stub_name (enum xlogue_stub stub,
     243                 :            :                               unsigned n_extra_regs)
     244                 :            : {
     245                 :      14666 :   const int have_avx = TARGET_AVX;
     246                 :      14666 :   char *name = s_stub_names[!!have_avx][stub][n_extra_regs];
     247                 :            : 
     248                 :            :   /* Lazy init */
     249                 :      14666 :   if (!*name)
     250                 :            :     {
     251                 :        362 :       int res = snprintf (name, STUB_NAME_MAX_LEN, "__%s_%s_%u",
     252                 :            :                           (have_avx ? "avx" : "sse"),
     253                 :        181 :                           STUB_BASE_NAMES[stub],
     254                 :            :                           MIN_REGS + n_extra_regs);
     255                 :        181 :       gcc_checking_assert (res < (int)STUB_NAME_MAX_LEN);
     256                 :            :     }
     257                 :            : 
     258                 :      14666 :   return name;
     259                 :            : }
     260                 :            : 
     261                 :            : /* Return rtx of a symbol ref for the entry point (based upon
     262                 :            :    cfun->machine->call_ms2sysv_extra_regs) of the specified stub.  */
     263                 :            : rtx
     264                 :      14666 : xlogue_layout::get_stub_rtx (enum xlogue_stub stub)
     265                 :            : {
     266                 :      14666 :   const unsigned n_extra_regs = cfun->machine->call_ms2sysv_extra_regs;
     267                 :      14666 :   gcc_checking_assert (n_extra_regs <= MAX_EXTRA_REGS);
     268                 :      14666 :   gcc_assert (stub < XLOGUE_STUB_COUNT);
     269                 :      14666 :   gcc_assert (crtl->stack_realign_finalized);
     270                 :            : 
     271                 :      14666 :   return gen_rtx_SYMBOL_REF (Pmode, get_stub_name (stub, n_extra_regs));
     272                 :            : }
     273                 :            : 
     274                 :            : unsigned scalar_chain::max_id = 0;
     275                 :            : 
     276                 :            : namespace {
     277                 :            : 
     278                 :            : /* Initialize new chain.  */
     279                 :            : 
     280                 :    4806270 : scalar_chain::scalar_chain (enum machine_mode smode_, enum machine_mode vmode_)
     281                 :            : {
     282                 :    4806270 :   smode = smode_;
     283                 :    4806270 :   vmode = vmode_;
     284                 :            : 
     285                 :    4806270 :   chain_id = ++max_id;
     286                 :            : 
     287                 :    4806270 :    if (dump_file)
     288                 :        121 :     fprintf (dump_file, "Created a new instruction chain #%d\n", chain_id);
     289                 :            : 
     290                 :    4806270 :   bitmap_obstack_initialize (NULL);
     291                 :    4806270 :   insns = BITMAP_ALLOC (NULL);
     292                 :    4806270 :   defs = BITMAP_ALLOC (NULL);
     293                 :    4806270 :   defs_conv = BITMAP_ALLOC (NULL);
     294                 :    4806270 :   queue = NULL;
     295                 :    4806270 : }
     296                 :            : 
     297                 :            : /* Free chain's data.  */
     298                 :            : 
     299                 :    9612540 : scalar_chain::~scalar_chain ()
     300                 :            : {
     301                 :    4806270 :   BITMAP_FREE (insns);
     302                 :    4806270 :   BITMAP_FREE (defs);
     303                 :    4806270 :   BITMAP_FREE (defs_conv);
     304                 :    4806270 :   bitmap_obstack_release (NULL);
     305                 :    4806270 : }
     306                 :            : 
     307                 :            : /* Add instruction into chains' queue.  */
     308                 :            : 
     309                 :            : void
     310                 :   18277000 : scalar_chain::add_to_queue (unsigned insn_uid)
     311                 :            : {
     312                 :   18277000 :   if (bitmap_bit_p (insns, insn_uid)
     313                 :   18277000 :       || bitmap_bit_p (queue, insn_uid))
     314                 :   13941600 :     return;
     315                 :            : 
     316                 :    4335370 :   if (dump_file)
     317                 :        225 :     fprintf (dump_file, "  Adding insn %d into chain's #%d queue\n",
     318                 :            :              insn_uid, chain_id);
     319                 :    4335370 :   bitmap_set_bit (queue, insn_uid);
     320                 :            : }
     321                 :            : 
     322                 :    4511080 : general_scalar_chain::general_scalar_chain (enum machine_mode smode_,
     323                 :    4511080 :                                             enum machine_mode vmode_)
     324                 :    4511080 :      : scalar_chain (smode_, vmode_)
     325                 :            : {
     326                 :    4511080 :   insns_conv = BITMAP_ALLOC (NULL);
     327                 :    4511080 :   n_sse_to_integer = 0;
     328                 :    4511080 :   n_integer_to_sse = 0;
     329                 :    4511080 : }
     330                 :            : 
     331                 :    9022160 : general_scalar_chain::~general_scalar_chain ()
     332                 :            : {
     333                 :    4511080 :   BITMAP_FREE (insns_conv);
     334                 :    9022160 : }
     335                 :            : 
     336                 :            : /* For DImode conversion, mark register defined by DEF as requiring
     337                 :            :    conversion.  */
     338                 :            : 
     339                 :            : void
     340                 :   14085700 : general_scalar_chain::mark_dual_mode_def (df_ref def)
     341                 :            : {
     342                 :   14085700 :   gcc_assert (DF_REF_REG_DEF_P (def));
     343                 :            : 
     344                 :            :   /* Record the def/insn pair so we can later efficiently iterate over
     345                 :            :      the defs to convert on insns not in the chain.  */
     346                 :   14085700 :   bool reg_new = bitmap_set_bit (defs_conv, DF_REF_REGNO (def));
     347                 :   14085700 :   if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def)))
     348                 :            :     {
     349                 :    2058040 :       if (!bitmap_set_bit (insns_conv, DF_REF_INSN_UID (def))
     350                 :    2058040 :           && !reg_new)
     351                 :            :         return;
     352                 :    1957800 :       n_integer_to_sse++;
     353                 :            :     }
     354                 :            :   else
     355                 :            :     {
     356                 :   12027700 :       if (!reg_new)
     357                 :            :         return;
     358                 :    4302140 :       n_sse_to_integer++;
     359                 :            :     }
     360                 :            :  
     361                 :    6259940 :   if (dump_file)
     362                 :        564 :     fprintf (dump_file,
     363                 :            :              "  Mark r%d def in insn %d as requiring both modes in chain #%d\n",
     364                 :        282 :              DF_REF_REGNO (def), DF_REF_INSN_UID (def), chain_id);
     365                 :            : }
     366                 :            : 
     367                 :            : /* For TImode conversion, it is unused.  */
     368                 :            : 
     369                 :            : void
     370                 :          0 : timode_scalar_chain::mark_dual_mode_def (df_ref)
     371                 :            : {
     372                 :          0 :   gcc_unreachable ();
     373                 :            : }
     374                 :            : 
     375                 :            : /* Check REF's chain to add new insns into a queue
     376                 :            :    and find registers requiring conversion.  */
     377                 :            : 
     378                 :            : void
     379                 :   13011200 : scalar_chain::analyze_register_chain (bitmap candidates, df_ref ref)
     380                 :            : {
     381                 :   13011200 :   df_link *chain;
     382                 :            : 
     383                 :   13011200 :   gcc_assert (bitmap_bit_p (insns, DF_REF_INSN_UID (ref))
     384                 :            :               || bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)));
     385                 :   13011200 :   add_to_queue (DF_REF_INSN_UID (ref));
     386                 :            : 
     387                 :   42941500 :   for (chain = DF_REF_CHAIN (ref); chain; chain = chain->next)
     388                 :            :     {
     389                 :   29930400 :       unsigned uid = DF_REF_INSN_UID (chain->ref);
     390                 :            : 
     391                 :   29930400 :       if (!NONDEBUG_INSN_P (DF_REF_INSN (chain->ref)))
     392                 :    4589020 :         continue;
     393                 :            : 
     394                 :   25341300 :       if (!DF_REF_REG_MEM_P (chain->ref))
     395                 :            :         {
     396                 :   20295900 :           if (bitmap_bit_p (insns, uid))
     397                 :    5989830 :             continue;
     398                 :            : 
     399                 :   14306100 :           if (bitmap_bit_p (candidates, uid))
     400                 :            :             {
     401                 :    5265800 :               add_to_queue (uid);
     402                 :    5265800 :               continue;
     403                 :            :             }
     404                 :            :         }
     405                 :            : 
     406                 :   14085700 :       if (DF_REF_REG_DEF_P (chain->ref))
     407                 :            :         {
     408                 :    2058040 :           if (dump_file)
     409                 :         98 :             fprintf (dump_file, "  r%d def in insn %d isn't convertible\n",
     410                 :            :                      DF_REF_REGNO (chain->ref), uid);
     411                 :    2058040 :           mark_dual_mode_def (chain->ref);
     412                 :            :         }
     413                 :            :       else
     414                 :            :         {
     415                 :   12027700 :           if (dump_file)
     416                 :        724 :             fprintf (dump_file, "  r%d use in insn %d isn't convertible\n",
     417                 :            :                      DF_REF_REGNO (chain->ref), uid);
     418                 :   12027700 :           mark_dual_mode_def (ref);
     419                 :            :         }
     420                 :            :     }
     421                 :   13011200 : }
     422                 :            : 
     423                 :            : /* Add instruction into a chain.  */
     424                 :            : 
     425                 :            : void
     426                 :    9141640 : scalar_chain::add_insn (bitmap candidates, unsigned int insn_uid)
     427                 :            : {
     428                 :    9141640 :   if (bitmap_bit_p (insns, insn_uid))
     429                 :            :     return;
     430                 :            : 
     431                 :    9141640 :   if (dump_file)
     432                 :        346 :     fprintf (dump_file, "  Adding insn %d to chain #%d\n", insn_uid, chain_id);
     433                 :            : 
     434                 :    9141640 :   bitmap_set_bit (insns, insn_uid);
     435                 :            : 
     436                 :    9141640 :   rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
     437                 :    9141640 :   rtx def_set = single_set (insn);
     438                 :    9141640 :   if (def_set && REG_P (SET_DEST (def_set))
     439                 :   16100900 :       && !HARD_REGISTER_P (SET_DEST (def_set)))
     440                 :    6959230 :     bitmap_set_bit (defs, REGNO (SET_DEST (def_set)));
     441                 :            : 
     442                 :            :   /* ???  The following is quadratic since analyze_register_chain
     443                 :            :      iterates over all refs to look for dual-mode regs.  Instead this
     444                 :            :      should be done separately for all regs mentioned in the chain once.  */
     445                 :    9141640 :   df_ref ref;
     446                 :   17998200 :   for (ref = DF_INSN_UID_DEFS (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
     447                 :    8856560 :     if (!HARD_REGISTER_P (DF_REF_REG (ref)))
     448                 :    6959230 :       analyze_register_chain (candidates, ref);
     449                 :   20133800 :   for (ref = DF_INSN_UID_USES (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref))
     450                 :   10992100 :     if (!DF_REF_REG_MEM_P (ref))
     451                 :    6051950 :       analyze_register_chain (candidates, ref);
     452                 :            : }
     453                 :            : 
     454                 :            : /* Build new chain starting from insn INSN_UID recursively
     455                 :            :    adding all dependent uses and definitions.  */
     456                 :            : 
     457                 :            : void
     458                 :    4806270 : scalar_chain::build (bitmap candidates, unsigned insn_uid)
     459                 :            : {
     460                 :    4806270 :   queue = BITMAP_ALLOC (NULL);
     461                 :    4806270 :   bitmap_set_bit (queue, insn_uid);
     462                 :            : 
     463                 :    4806270 :   if (dump_file)
     464                 :        121 :     fprintf (dump_file, "Building chain #%d...\n", chain_id);
     465                 :            : 
     466                 :   13947900 :   while (!bitmap_empty_p (queue))
     467                 :            :     {
     468                 :    9141640 :       insn_uid = bitmap_first_set_bit (queue);
     469                 :    9141640 :       bitmap_clear_bit (queue, insn_uid);
     470                 :    9141640 :       bitmap_clear_bit (candidates, insn_uid);
     471                 :    9141640 :       add_insn (candidates, insn_uid);
     472                 :            :     }
     473                 :            : 
     474                 :    4806270 :   if (dump_file)
     475                 :            :     {
     476                 :        121 :       fprintf (dump_file, "Collected chain #%d...\n", chain_id);
     477                 :        121 :       fprintf (dump_file, "  insns: ");
     478                 :        121 :       dump_bitmap (dump_file, insns);
     479                 :        121 :       if (!bitmap_empty_p (defs_conv))
     480                 :            :         {
     481                 :        121 :           bitmap_iterator bi;
     482                 :        121 :           unsigned id;
     483                 :        121 :           const char *comma = "";
     484                 :        121 :           fprintf (dump_file, "  defs to convert: ");
     485                 :        395 :           EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
     486                 :            :             {
     487                 :        274 :               fprintf (dump_file, "%sr%d", comma, id);
     488                 :        274 :               comma = ", ";
     489                 :            :             }
     490                 :        121 :           fprintf (dump_file, "\n");
     491                 :            :         }
     492                 :            :     }
     493                 :            : 
     494                 :    4806270 :   BITMAP_FREE (queue);
     495                 :    4806270 : }
     496                 :            : 
     497                 :            : /* Return a cost of building a vector costant
     498                 :            :    instead of using a scalar one.  */
     499                 :            : 
     500                 :            : int
     501                 :    1719340 : general_scalar_chain::vector_const_cost (rtx exp)
     502                 :            : {
     503                 :    1719340 :   gcc_assert (CONST_INT_P (exp));
     504                 :            : 
     505                 :    1719340 :   if (standard_sse_constant_p (exp, vmode))
     506                 :     477296 :     return ix86_cost->sse_op;
     507                 :            :   /* We have separate costs for SImode and DImode, use SImode costs
     508                 :            :      for smaller modes.  */
     509                 :    1701800 :   return ix86_cost->sse_load[smode == DImode ? 1 : 0];
     510                 :            : }
     511                 :            : 
     512                 :            : /* Compute a gain for chain conversion.  */
     513                 :            : 
     514                 :            : int
     515                 :    4511080 : general_scalar_chain::compute_convert_gain ()
     516                 :            : {
     517                 :    4511080 :   bitmap_iterator bi;
     518                 :    4511080 :   unsigned insn_uid;
     519                 :    4511080 :   int gain = 0;
     520                 :    4511080 :   int cost = 0;
     521                 :            : 
     522                 :    4511080 :   if (dump_file)
     523                 :        121 :     fprintf (dump_file, "Computing gain for chain #%d...\n", chain_id);
     524                 :            : 
     525                 :            :   /* SSE costs distinguish between SImode and DImode loads/stores, for
     526                 :            :      int costs factor in the number of GPRs involved.  When supporting
     527                 :            :      smaller modes than SImode the int load/store costs need to be
     528                 :            :      adjusted as well.  */
     529                 :    4511080 :   unsigned sse_cost_idx = smode == DImode ? 1 : 0;
     530                 :    4511080 :   unsigned m = smode == DImode ? (TARGET_64BIT ? 1 : 2) : 1;
     531                 :            : 
     532                 :   13097100 :   EXECUTE_IF_SET_IN_BITMAP (insns, 0, insn_uid, bi)
     533                 :            :     {
     534                 :    8586040 :       rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
     535                 :    8586040 :       rtx def_set = single_set (insn);
     536                 :    8586040 :       rtx src = SET_SRC (def_set);
     537                 :    8586040 :       rtx dst = SET_DEST (def_set);
     538                 :    8586040 :       int igain = 0;
     539                 :            : 
     540                 :    8586040 :       if (REG_P (src) && REG_P (dst))
     541                 :    1461950 :         igain += 2 * m - ix86_cost->xmm_move;
     542                 :    7124090 :       else if (REG_P (src) && MEM_P (dst))
     543                 :    1837260 :         igain
     544                 :    1837260 :           += m * ix86_cost->int_store[2] - ix86_cost->sse_store[sse_cost_idx];
     545                 :    5286830 :       else if (MEM_P (src) && REG_P (dst))
     546                 :    2604690 :         igain += m * ix86_cost->int_load[2] - ix86_cost->sse_load[sse_cost_idx];
     547                 :    2682140 :       else if (GET_CODE (src) == ASHIFT
     548                 :    2682140 :                || GET_CODE (src) == ASHIFTRT
     549                 :    2526340 :                || GET_CODE (src) == LSHIFTRT)
     550                 :            :         {
     551                 :     240015 :           if (m == 2)
     552                 :            :             {
     553                 :       8241 :               if (INTVAL (XEXP (src, 1)) >= 32)
     554                 :       5786 :                 igain += ix86_cost->add;
     555                 :            :               else
     556                 :       2455 :                 igain += ix86_cost->shift_const;
     557                 :            :             }
     558                 :            : 
     559                 :     240015 :           igain += ix86_cost->shift_const - ix86_cost->sse_op;
     560                 :            : 
     561                 :     240015 :           if (CONST_INT_P (XEXP (src, 0)))
     562                 :          0 :             igain -= vector_const_cost (XEXP (src, 0));
     563                 :            :         }
     564                 :    2442130 :       else if (GET_CODE (src) == PLUS
     565                 :            :                || GET_CODE (src) == MINUS
     566                 :    2442130 :                || GET_CODE (src) == IOR
     567                 :     920374 :                || GET_CODE (src) == XOR
     568                 :     874461 :                || GET_CODE (src) == AND)
     569                 :            :         {
     570                 :    1664140 :           igain += m * ix86_cost->add - ix86_cost->sse_op;
     571                 :            :           /* Additional gain for andnot for targets without BMI.  */
     572                 :    1664140 :           if (GET_CODE (XEXP (src, 0)) == NOT
     573                 :        182 :               && !TARGET_BMI)
     574                 :        164 :             igain += m * ix86_cost->add;
     575                 :            : 
     576                 :    1664140 :           if (CONST_INT_P (XEXP (src, 0)))
     577                 :          0 :             igain -= vector_const_cost (XEXP (src, 0));
     578                 :    1664140 :           if (CONST_INT_P (XEXP (src, 1)))
     579                 :     978537 :             igain -= vector_const_cost (XEXP (src, 1));
     580                 :            :         }
     581                 :     777983 :       else if (GET_CODE (src) == NEG
     582                 :     777983 :                || GET_CODE (src) == NOT)
     583                 :      36020 :         igain += m * ix86_cost->add - ix86_cost->sse_op - COSTS_N_INSNS (1);
     584                 :     741963 :       else if (GET_CODE (src) == SMAX
     585                 :            :                || GET_CODE (src) == SMIN
     586                 :     741963 :                || GET_CODE (src) == UMAX
     587                 :     740909 :                || GET_CODE (src) == UMIN)
     588                 :            :         {
     589                 :            :           /* We do not have any conditional move cost, estimate it as a
     590                 :            :              reg-reg move.  Comparisons are costed as adds.  */
     591                 :       1164 :           igain += m * (COSTS_N_INSNS (2) + ix86_cost->add);
     592                 :            :           /* Integer SSE ops are all costed the same.  */
     593                 :       1164 :           igain -= ix86_cost->sse_op;
     594                 :            :         }
     595                 :     740799 :       else if (GET_CODE (src) == COMPARE)
     596                 :            :         {
     597                 :            :           /* Assume comparison cost is the same.  */
     598                 :            :         }
     599                 :     740799 :       else if (CONST_INT_P (src))
     600                 :            :         {
     601                 :     740799 :           if (REG_P (dst))
     602                 :            :             /* DImode can be immediate for TARGET_64BIT and SImode always.  */
     603                 :     740799 :             igain += m * COSTS_N_INSNS (1);
     604                 :          0 :           else if (MEM_P (dst))
     605                 :          0 :             igain += (m * ix86_cost->int_store[2]
     606                 :          0 :                      - ix86_cost->sse_store[sse_cost_idx]);
     607                 :     740799 :           igain -= vector_const_cost (src);
     608                 :            :         }
     609                 :            :       else
     610                 :          0 :         gcc_unreachable ();
     611                 :            : 
     612                 :    8586040 :       if (igain != 0 && dump_file)
     613                 :            :         {
     614                 :        109 :           fprintf (dump_file, "  Instruction gain %d for ", igain);
     615                 :        109 :           dump_insn_slim (dump_file, insn);
     616                 :            :         }
     617                 :    8586040 :       gain += igain;
     618                 :            :     }
     619                 :            : 
     620                 :    4511080 :   if (dump_file)
     621                 :        121 :     fprintf (dump_file, "  Instruction conversion gain: %d\n", gain);
     622                 :            : 
     623                 :            :   /* Cost the integer to sse and sse to integer moves.  */
     624                 :    4511080 :   cost += n_sse_to_integer * ix86_cost->sse_to_integer;
     625                 :            :   /* ???  integer_to_sse but we only have that in the RA cost table.
     626                 :            :      Assume sse_to_integer/integer_to_sse are the same which they
     627                 :            :      are at the moment.  */
     628                 :    4511080 :   cost += n_integer_to_sse * ix86_cost->sse_to_integer;
     629                 :            : 
     630                 :    4511080 :   if (dump_file)
     631                 :        121 :     fprintf (dump_file, "  Registers conversion cost: %d\n", cost);
     632                 :            : 
     633                 :    4511080 :   gain -= cost;
     634                 :            : 
     635                 :    4511080 :   if (dump_file)
     636                 :        121 :     fprintf (dump_file, "  Total gain: %d\n", gain);
     637                 :            : 
     638                 :    4511080 :   return gain;
     639                 :            : }
     640                 :            : 
     641                 :            : /* Insert generated conversion instruction sequence INSNS
     642                 :            :    after instruction AFTER.  New BB may be required in case
     643                 :            :    instruction has EH region attached.  */
     644                 :            : 
     645                 :            : void
     646                 :      51870 : scalar_chain::emit_conversion_insns (rtx insns, rtx_insn *after)
     647                 :            : {
     648                 :      51870 :   if (!control_flow_insn_p (after))
     649                 :            :     {
     650                 :      51831 :       emit_insn_after (insns, after);
     651                 :      51831 :       return;
     652                 :            :     }
     653                 :            : 
     654                 :         39 :   basic_block bb = BLOCK_FOR_INSN (after);
     655                 :         39 :   edge e = find_fallthru_edge (bb->succs);
     656                 :         39 :   gcc_assert (e);
     657                 :            : 
     658                 :         39 :   basic_block new_bb = split_edge (e);
     659                 :         39 :   emit_insn_after (insns, BB_HEAD (new_bb));
     660                 :            : }
     661                 :            : 
     662                 :            : } // anon namespace
     663                 :            : 
     664                 :            : /* Generate the canonical SET_SRC to move GPR to a VMODE vector register,
     665                 :            :    zeroing the upper parts.  */
     666                 :            : 
     667                 :            : static rtx
     668                 :      53229 : gen_gpr_to_xmm_move_src (enum machine_mode vmode, rtx gpr)
     669                 :            : {
     670                 :     106458 :   switch (GET_MODE_NUNITS (vmode))
     671                 :            :     {
     672                 :          0 :     case 1:
     673                 :            :       /* We are not using this case currently.  */
     674                 :          0 :       gcc_unreachable ();
     675                 :      53103 :     case 2:
     676                 :     106206 :       return gen_rtx_VEC_CONCAT (vmode, gpr,
     677                 :            :                                  CONST0_RTX (GET_MODE_INNER (vmode)));
     678                 :        126 :     default:
     679                 :        126 :       return gen_rtx_VEC_MERGE (vmode, gen_rtx_VEC_DUPLICATE (vmode, gpr),
     680                 :            :                                 CONST0_RTX (vmode), GEN_INT (HOST_WIDE_INT_1U));
     681                 :            :     }
     682                 :            : }
     683                 :            : 
     684                 :            : /* Make vector copies for all register REGNO definitions
     685                 :            :    and replace its uses in a chain.  */
     686                 :            : 
     687                 :            : void
     688                 :       2310 : general_scalar_chain::make_vector_copies (rtx_insn *insn, rtx reg)
     689                 :            : {
     690                 :       2310 :   rtx vreg = *defs_map.get (reg);
     691                 :            : 
     692                 :       2310 :   start_sequence ();
     693                 :       2310 :   if (!TARGET_INTER_UNIT_MOVES_TO_VEC)
     694                 :            :     {
     695                 :          0 :       rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
     696                 :          0 :       if (smode == DImode && !TARGET_64BIT)
     697                 :            :         {
     698                 :          0 :           emit_move_insn (adjust_address (tmp, SImode, 0),
     699                 :          0 :                           gen_rtx_SUBREG (SImode, reg, 0));
     700                 :          0 :           emit_move_insn (adjust_address (tmp, SImode, 4),
     701                 :          0 :                           gen_rtx_SUBREG (SImode, reg, 4));
     702                 :            :         }
     703                 :            :       else
     704                 :          0 :         emit_move_insn (copy_rtx (tmp), reg);
     705                 :          0 :       emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
     706                 :            :                               gen_gpr_to_xmm_move_src (vmode, tmp)));
     707                 :            :     }
     708                 :       2310 :   else if (!TARGET_64BIT && smode == DImode)
     709                 :            :     {
     710                 :       2306 :       if (TARGET_SSE4_1)
     711                 :            :         {
     712                 :        432 :           emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
     713                 :            :                                       CONST0_RTX (V4SImode),
     714                 :        432 :                                       gen_rtx_SUBREG (SImode, reg, 0)));
     715                 :        432 :           emit_insn (gen_sse4_1_pinsrd (gen_rtx_SUBREG (V4SImode, vreg, 0),
     716                 :        432 :                                         gen_rtx_SUBREG (V4SImode, vreg, 0),
     717                 :        432 :                                         gen_rtx_SUBREG (SImode, reg, 4),
     718                 :            :                                         GEN_INT (2)));
     719                 :            :         }
     720                 :            :       else
     721                 :            :         {
     722                 :       1874 :           rtx tmp = gen_reg_rtx (DImode);
     723                 :       1874 :           emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, vreg, 0),
     724                 :            :                                       CONST0_RTX (V4SImode),
     725                 :       1874 :                                       gen_rtx_SUBREG (SImode, reg, 0)));
     726                 :       1874 :           emit_insn (gen_sse2_loadld (gen_rtx_SUBREG (V4SImode, tmp, 0),
     727                 :            :                                       CONST0_RTX (V4SImode),
     728                 :       1874 :                                       gen_rtx_SUBREG (SImode, reg, 4)));
     729                 :       1874 :           emit_insn (gen_vec_interleave_lowv4si
     730                 :       1874 :                      (gen_rtx_SUBREG (V4SImode, vreg, 0),
     731                 :       1874 :                       gen_rtx_SUBREG (V4SImode, vreg, 0),
     732                 :       1874 :                       gen_rtx_SUBREG (V4SImode, tmp, 0)));
     733                 :            :         }
     734                 :            :     }
     735                 :            :   else
     736                 :          4 :     emit_insn (gen_rtx_SET (gen_rtx_SUBREG (vmode, vreg, 0),
     737                 :            :                             gen_gpr_to_xmm_move_src (vmode, reg)));
     738                 :       2310 :   rtx_insn *seq = get_insns ();
     739                 :       2310 :   end_sequence ();
     740                 :       2310 :   emit_conversion_insns (seq, insn);
     741                 :            : 
     742                 :       2310 :   if (dump_file)
     743                 :          0 :     fprintf (dump_file,
     744                 :            :              "  Copied r%d to a vector register r%d for insn %d\n",
     745                 :          0 :              REGNO (reg), REGNO (vreg), INSN_UID (insn));
     746                 :       2310 : }
     747                 :            : 
     748                 :            : /* Copy the definition SRC of INSN inside the chain to DST for
     749                 :            :    scalar uses outside of the chain.  */
     750                 :            : 
     751                 :            : void
     752                 :       7117 : general_scalar_chain::convert_reg (rtx_insn *insn, rtx dst, rtx src)
     753                 :            : {
     754                 :       7117 :   start_sequence ();
     755                 :       7117 :   if (!TARGET_INTER_UNIT_MOVES_FROM_VEC)
     756                 :            :     {
     757                 :          0 :       rtx tmp = assign_386_stack_local (smode, SLOT_STV_TEMP);
     758                 :          0 :       emit_move_insn (tmp, src);
     759                 :          0 :       if (!TARGET_64BIT && smode == DImode)
     760                 :            :         {
     761                 :          0 :           emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
     762                 :          0 :                           adjust_address (tmp, SImode, 0));
     763                 :          0 :           emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
     764                 :          0 :                           adjust_address (tmp, SImode, 4));
     765                 :            :         }
     766                 :            :       else
     767                 :          0 :         emit_move_insn (dst, copy_rtx (tmp));
     768                 :            :     }
     769                 :       7117 :   else if (!TARGET_64BIT && smode == DImode)
     770                 :            :     {
     771                 :       7086 :       if (TARGET_SSE4_1)
     772                 :            :         {
     773                 :          0 :           rtx tmp = gen_rtx_PARALLEL (VOIDmode,
     774                 :            :                                       gen_rtvec (1, const0_rtx));
     775                 :          0 :           emit_insn
     776                 :          0 :               (gen_rtx_SET
     777                 :            :                (gen_rtx_SUBREG (SImode, dst, 0),
     778                 :            :                 gen_rtx_VEC_SELECT (SImode,
     779                 :            :                                     gen_rtx_SUBREG (V4SImode, src, 0),
     780                 :            :                                     tmp)));
     781                 :            : 
     782                 :          0 :           tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, const1_rtx));
     783                 :          0 :           emit_insn
     784                 :          0 :               (gen_rtx_SET
     785                 :            :                (gen_rtx_SUBREG (SImode, dst, 4),
     786                 :            :                 gen_rtx_VEC_SELECT (SImode,
     787                 :            :                                     gen_rtx_SUBREG (V4SImode, src, 0),
     788                 :            :                                     tmp)));
     789                 :            :         }
     790                 :            :       else
     791                 :            :         {
     792                 :       7086 :           rtx vcopy = gen_reg_rtx (V2DImode);
     793                 :       7086 :           emit_move_insn (vcopy, gen_rtx_SUBREG (V2DImode, src, 0));
     794                 :       7086 :           emit_move_insn (gen_rtx_SUBREG (SImode, dst, 0),
     795                 :       7086 :                           gen_rtx_SUBREG (SImode, vcopy, 0));
     796                 :       7086 :           emit_move_insn (vcopy,
     797                 :            :                           gen_rtx_LSHIFTRT (V2DImode,
     798                 :            :                                             vcopy, GEN_INT (32)));
     799                 :       7086 :           emit_move_insn (gen_rtx_SUBREG (SImode, dst, 4),
     800                 :       7086 :                           gen_rtx_SUBREG (SImode, vcopy, 0));
     801                 :            :         }
     802                 :            :     }
     803                 :            :   else
     804                 :         31 :     emit_move_insn (dst, src);
     805                 :            : 
     806                 :       7117 :   rtx_insn *seq = get_insns ();
     807                 :       7117 :   end_sequence ();
     808                 :       7117 :   emit_conversion_insns (seq, insn);
     809                 :            : 
     810                 :       7117 :   if (dump_file)
     811                 :          0 :     fprintf (dump_file,
     812                 :            :              "  Copied r%d to a scalar register r%d for insn %d\n",
     813                 :          0 :              REGNO (src), REGNO (dst), INSN_UID (insn));
     814                 :       7117 : }
     815                 :            : 
     816                 :            : /* Convert operand OP in INSN.  We should handle
     817                 :            :    memory operands and uninitialized registers.
     818                 :            :    All other register uses are converted during
     819                 :            :    registers conversion.  */
     820                 :            : 
     821                 :            : void
     822                 :      68639 : general_scalar_chain::convert_op (rtx *op, rtx_insn *insn)
     823                 :            : {
     824                 :      68639 :   *op = copy_rtx_if_shared (*op);
     825                 :            : 
     826                 :      68639 :   if (GET_CODE (*op) == NOT)
     827                 :            :     {
     828                 :        128 :       convert_op (&XEXP (*op, 0), insn);
     829                 :        128 :       PUT_MODE (*op, vmode);
     830                 :            :     }
     831                 :      68511 :   else if (MEM_P (*op))
     832                 :            :     {
     833                 :      53225 :       rtx tmp = gen_reg_rtx (GET_MODE (*op));
     834                 :            : 
     835                 :            :       /* Handle movabs.  */
     836                 :      53225 :       if (!memory_operand (*op, GET_MODE (*op)))
     837                 :            :         {
     838                 :          0 :           rtx tmp2 = gen_reg_rtx (GET_MODE (*op));
     839                 :            : 
     840                 :          0 :           emit_insn_before (gen_rtx_SET (tmp2, *op), insn);
     841                 :          0 :           *op = tmp2;
     842                 :            :         }
     843                 :            : 
     844                 :      53225 :       emit_insn_before (gen_rtx_SET (gen_rtx_SUBREG (vmode, tmp, 0),
     845                 :            :                                      gen_gpr_to_xmm_move_src (vmode, *op)),
     846                 :            :                         insn);
     847                 :      53225 :       *op = gen_rtx_SUBREG (vmode, tmp, 0);
     848                 :            : 
     849                 :      53225 :       if (dump_file)
     850                 :          0 :         fprintf (dump_file, "  Preloading operand for insn %d into r%d\n",
     851                 :          0 :                  INSN_UID (insn), REGNO (tmp));
     852                 :            :     }
     853                 :      15286 :   else if (REG_P (*op))
     854                 :            :     {
     855                 :      12510 :       *op = gen_rtx_SUBREG (vmode, *op, 0);
     856                 :            :     }
     857                 :       2776 :   else if (CONST_INT_P (*op))
     858                 :            :     {
     859                 :       2776 :       rtx vec_cst;
     860                 :       2776 :       rtx tmp = gen_rtx_SUBREG (vmode, gen_reg_rtx (smode), 0);
     861                 :            : 
     862                 :            :       /* Prefer all ones vector in case of -1.  */
     863                 :       2776 :       if (constm1_operand (*op, GET_MODE (*op)))
     864                 :        245 :         vec_cst = CONSTM1_RTX (vmode);
     865                 :            :       else
     866                 :            :         {
     867                 :       2531 :           unsigned n = GET_MODE_NUNITS (vmode);
     868                 :       2531 :           rtx *v = XALLOCAVEC (rtx, n);
     869                 :       2531 :           v[0] = *op;
     870                 :       5382 :           for (unsigned i = 1; i < n; ++i)
     871                 :       2851 :             v[i] = const0_rtx;
     872                 :       2531 :           vec_cst = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (n, v));
     873                 :            :         }
     874                 :            : 
     875                 :       2776 :       if (!standard_sse_constant_p (vec_cst, vmode))
     876                 :            :         {
     877                 :       1690 :           start_sequence ();
     878                 :       1690 :           vec_cst = validize_mem (force_const_mem (vmode, vec_cst));
     879                 :       1690 :           rtx_insn *seq = get_insns ();
     880                 :       1690 :           end_sequence ();
     881                 :       1690 :           emit_insn_before (seq, insn);
     882                 :            :         }
     883                 :            : 
     884                 :       2776 :       emit_insn_before (gen_move_insn (copy_rtx (tmp), vec_cst), insn);
     885                 :       2776 :       *op = tmp;
     886                 :            :     }
     887                 :            :   else
     888                 :            :     {
     889                 :          0 :       gcc_assert (SUBREG_P (*op));
     890                 :          0 :       gcc_assert (GET_MODE (*op) == vmode);
     891                 :            :     }
     892                 :      68639 : }
     893                 :            : 
     894                 :            : /* Convert INSN to vector mode.  */
     895                 :            : 
     896                 :            : void
     897                 :     106050 : general_scalar_chain::convert_insn (rtx_insn *insn)
     898                 :            : {
     899                 :            :   /* Generate copies for out-of-chain uses of defs and adjust debug uses.  */
     900                 :     175681 :   for (df_ref ref = DF_INSN_DEFS (insn); ref; ref = DF_REF_NEXT_LOC (ref))
     901                 :      69631 :     if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
     902                 :            :       {
     903                 :       7733 :         df_link *use;
     904                 :      15426 :         for (use = DF_REF_CHAIN (ref); use; use = use->next)
     905                 :      14810 :           if (NONDEBUG_INSN_P (DF_REF_INSN (use->ref))
     906                 :      14810 :               && (DF_REF_REG_MEM_P (use->ref)
     907                 :      12951 :                   || !bitmap_bit_p (insns, DF_REF_INSN_UID (use->ref))))
     908                 :            :             break;
     909                 :       7733 :         if (use)
     910                 :      14234 :           convert_reg (insn, DF_REF_REG (ref),
     911                 :      14234 :                        *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]));
     912                 :        616 :         else if (MAY_HAVE_DEBUG_BIND_INSNS)
     913                 :            :           {
     914                 :            :             /* If we generated a scalar copy we can leave debug-insns
     915                 :            :                as-is, if not, we have to adjust them.  */
     916                 :       1232 :             auto_vec<rtx_insn *, 5> to_reset_debug_insns;
     917                 :       2342 :             for (use = DF_REF_CHAIN (ref); use; use = use->next)
     918                 :       1726 :               if (DEBUG_INSN_P (DF_REF_INSN (use->ref)))
     919                 :            :                 {
     920                 :        607 :                   rtx_insn *debug_insn = DF_REF_INSN (use->ref);
     921                 :            :                   /* If there's a reaching definition outside of the
     922                 :            :                      chain we have to reset.  */
     923                 :        607 :                   df_link *def;
     924                 :       1902 :                   for (def = DF_REF_CHAIN (use->ref); def; def = def->next)
     925                 :       1437 :                     if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def->ref)))
     926                 :            :                       break;
     927                 :        607 :                   if (def)
     928                 :        142 :                     to_reset_debug_insns.safe_push (debug_insn);
     929                 :            :                   else
     930                 :            :                     {
     931                 :         40 :                       *DF_REF_REAL_LOC (use->ref)
     932                 :        930 :                         = *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]);
     933                 :        465 :                       df_insn_rescan (debug_insn);
     934                 :            :                     }
     935                 :            :                 }
     936                 :            :             /* Have to do the reset outside of the DF_CHAIN walk to not
     937                 :            :                disrupt it.  */
     938                 :        758 :             while (!to_reset_debug_insns.is_empty ())
     939                 :            :               {
     940                 :        142 :                 rtx_insn *debug_insn = to_reset_debug_insns.pop ();
     941                 :        142 :                 INSN_VAR_LOCATION_LOC (debug_insn) = gen_rtx_UNKNOWN_VAR_LOC ();
     942                 :        142 :                 df_insn_rescan_debug_internal (debug_insn);
     943                 :            :               }
     944                 :            :           }
     945                 :            :       }
     946                 :            : 
     947                 :            :   /* Replace uses in this insn with the defs we use in the chain.  */
     948                 :     262759 :   for (df_ref ref = DF_INSN_USES (insn); ref; ref = DF_REF_NEXT_LOC (ref))
     949                 :     156709 :     if (!DF_REF_REG_MEM_P (ref))
     950                 :     214022 :       if (rtx *vreg = defs_map.get (regno_reg_rtx[DF_REF_REGNO (ref)]))
     951                 :            :         {
     952                 :            :           /* Also update a corresponding REG_DEAD note.  */
     953                 :       8481 :           rtx note = find_reg_note (insn, REG_DEAD, DF_REF_REG (ref));
     954                 :       8481 :           if (note)
     955                 :       4803 :             XEXP (note, 0) = *vreg;
     956                 :       8481 :           *DF_REF_REAL_LOC (ref) = *vreg;
     957                 :            :         }
     958                 :            : 
     959                 :     106050 :   rtx def_set = single_set (insn);
     960                 :     106050 :   rtx src = SET_SRC (def_set);
     961                 :     106050 :   rtx dst = SET_DEST (def_set);
     962                 :     106050 :   rtx subreg;
     963                 :            : 
     964                 :     106050 :   if (MEM_P (dst) && !REG_P (src))
     965                 :            :     {
     966                 :            :       /* There are no scalar integer instructions and therefore
     967                 :            :          temporary register usage is required.  */
     968                 :        138 :       rtx tmp = gen_reg_rtx (smode);
     969                 :        138 :       emit_conversion_insns (gen_move_insn (dst, tmp), insn);
     970                 :        138 :       dst = gen_rtx_SUBREG (vmode, tmp, 0);
     971                 :            :     }
     972                 :     105912 :   else if (REG_P (dst))
     973                 :            :     {
     974                 :            :       /* Replace the definition with a SUBREG to the definition we
     975                 :            :          use inside the chain.  */
     976                 :      61109 :       rtx *vdef = defs_map.get (dst);
     977                 :       7733 :       if (vdef)
     978                 :       7733 :         dst = *vdef;
     979                 :      61109 :       dst = gen_rtx_SUBREG (vmode, dst, 0);
     980                 :            :       /* IRA doesn't like to have REG_EQUAL/EQUIV notes when the SET_DEST
     981                 :            :          is a non-REG_P.  So kill those off.  */
     982                 :      61109 :       rtx note = find_reg_equal_equiv_note (insn);
     983                 :      61109 :       if (note)
     984                 :       2472 :         remove_note (insn, note);
     985                 :            :     }
     986                 :            : 
     987                 :     106050 :   switch (GET_CODE (src))
     988                 :            :     {
     989                 :       1205 :     case ASHIFT:
     990                 :       1205 :     case ASHIFTRT:
     991                 :       1205 :     case LSHIFTRT:
     992                 :       1205 :       convert_op (&XEXP (src, 0), insn);
     993                 :       1205 :       PUT_MODE (src, vmode);
     994                 :            :       break;
     995                 :            : 
     996                 :       7264 :     case PLUS:
     997                 :       7264 :     case MINUS:
     998                 :       7264 :     case IOR:
     999                 :       7264 :     case XOR:
    1000                 :       7264 :     case AND:
    1001                 :       7264 :     case SMAX:
    1002                 :       7264 :     case SMIN:
    1003                 :       7264 :     case UMAX:
    1004                 :       7264 :     case UMIN:
    1005                 :       7264 :       convert_op (&XEXP (src, 0), insn);
    1006                 :       7264 :       convert_op (&XEXP (src, 1), insn);
    1007                 :       7264 :       PUT_MODE (src, vmode);
    1008                 :            :       break;
    1009                 :            : 
    1010                 :         54 :     case NEG:
    1011                 :         54 :       src = XEXP (src, 0);
    1012                 :         54 :       convert_op (&src, insn);
    1013                 :         54 :       subreg = gen_reg_rtx (vmode);
    1014                 :         54 :       emit_insn_before (gen_move_insn (subreg, CONST0_RTX (vmode)), insn);
    1015                 :         54 :       src = gen_rtx_MINUS (vmode, subreg, src);
    1016                 :         54 :       break;
    1017                 :            : 
    1018                 :         96 :     case NOT:
    1019                 :         96 :       src = XEXP (src, 0);
    1020                 :         96 :       convert_op (&src, insn);
    1021                 :         96 :       subreg = gen_reg_rtx (vmode);
    1022                 :         96 :       emit_insn_before (gen_move_insn (subreg, CONSTM1_RTX (vmode)), insn);
    1023                 :         96 :       src = gen_rtx_XOR (vmode, src, subreg);
    1024                 :         96 :       break;
    1025                 :            : 
    1026                 :      50297 :     case MEM:
    1027                 :      50297 :       if (!REG_P (dst))
    1028                 :      50297 :         convert_op (&src, insn);
    1029                 :            :       break;
    1030                 :            : 
    1031                 :      45768 :     case REG:
    1032                 :      45768 :       if (!MEM_P (dst))
    1033                 :        965 :         convert_op (&src, insn);
    1034                 :            :       break;
    1035                 :            : 
    1036                 :          0 :     case SUBREG:
    1037                 :          0 :       gcc_assert (GET_MODE (src) == vmode);
    1038                 :            :       break;
    1039                 :            : 
    1040                 :          0 :     case COMPARE:
    1041                 :          0 :       src = SUBREG_REG (XEXP (XEXP (src, 0), 0));
    1042                 :            : 
    1043                 :          0 :       gcc_assert (REG_P (src) && GET_MODE (src) == DImode);
    1044                 :          0 :       subreg = gen_rtx_SUBREG (V2DImode, src, 0);
    1045                 :          0 :       emit_insn_before (gen_vec_interleave_lowv2di (copy_rtx_if_shared (subreg),
    1046                 :            :                                                     copy_rtx_if_shared (subreg),
    1047                 :            :                                                     copy_rtx_if_shared (subreg)),
    1048                 :            :                         insn);
    1049                 :          0 :       dst = gen_rtx_REG (CCmode, FLAGS_REG);
    1050                 :          0 :       src = gen_rtx_UNSPEC (CCmode, gen_rtvec (2, copy_rtx_if_shared (subreg),
    1051                 :            :                                                copy_rtx_if_shared (subreg)),
    1052                 :            :                             UNSPEC_PTEST);
    1053                 :          0 :       break;
    1054                 :            : 
    1055                 :       1366 :     case CONST_INT:
    1056                 :       1366 :       convert_op (&src, insn);
    1057                 :       1366 :       break;
    1058                 :            : 
    1059                 :          0 :     default:
    1060                 :          0 :       gcc_unreachable ();
    1061                 :            :     }
    1062                 :            : 
    1063                 :     106050 :   SET_SRC (def_set) = src;
    1064                 :     106050 :   SET_DEST (def_set) = dst;
    1065                 :            : 
    1066                 :            :   /* Drop possible dead definitions.  */
    1067                 :     106050 :   PATTERN (insn) = def_set;
    1068                 :            : 
    1069                 :     106050 :   INSN_CODE (insn) = -1;
    1070                 :     106050 :   int patt = recog_memoized (insn);
    1071                 :     106050 :   if  (patt == -1)
    1072                 :          0 :     fatal_insn_not_found (insn);
    1073                 :     106050 :   df_insn_rescan (insn);
    1074                 :     106050 : }
    1075                 :            : 
    1076                 :            : /* Fix uses of converted REG in debug insns.  */
    1077                 :            : 
    1078                 :            : void
    1079                 :     253411 : timode_scalar_chain::fix_debug_reg_uses (rtx reg)
    1080                 :            : {
    1081                 :     253411 :   if (!flag_var_tracking)
    1082                 :            :     return;
    1083                 :            : 
    1084                 :     230244 :   df_ref ref, next;
    1085                 :     465881 :   for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref; ref = next)
    1086                 :            :     {
    1087                 :     235637 :       rtx_insn *insn = DF_REF_INSN (ref);
    1088                 :            :       /* Make sure the next ref is for a different instruction,
    1089                 :            :          so that we're not affected by the rescan.  */
    1090                 :     235637 :       next = DF_REF_NEXT_REG (ref);
    1091                 :     235637 :       while (next && DF_REF_INSN (next) == insn)
    1092                 :          0 :         next = DF_REF_NEXT_REG (next);
    1093                 :            : 
    1094                 :     235637 :       if (DEBUG_INSN_P (insn))
    1095                 :            :         {
    1096                 :            :           /* It may be a debug insn with a TImode variable in
    1097                 :            :              register.  */
    1098                 :            :           bool changed = false;
    1099                 :         62 :           for (; ref != next; ref = DF_REF_NEXT_REG (ref))
    1100                 :            :             {
    1101                 :         31 :               rtx *loc = DF_REF_LOC (ref);
    1102                 :         31 :               if (REG_P (*loc) && GET_MODE (*loc) == V1TImode)
    1103                 :            :                 {
    1104                 :         31 :                   *loc = gen_rtx_SUBREG (TImode, *loc, 0);
    1105                 :         31 :                   changed = true;
    1106                 :            :                 }
    1107                 :            :             }
    1108                 :         31 :           if (changed)
    1109                 :         31 :             df_insn_rescan (insn);
    1110                 :            :         }
    1111                 :            :     }
    1112                 :            : }
    1113                 :            : 
    1114                 :            : /* Convert INSN from TImode to V1T1mode.  */
    1115                 :            : 
    1116                 :            : void
    1117                 :     555601 : timode_scalar_chain::convert_insn (rtx_insn *insn)
    1118                 :            : {
    1119                 :     555601 :   rtx def_set = single_set (insn);
    1120                 :     555601 :   rtx src = SET_SRC (def_set);
    1121                 :     555601 :   rtx dst = SET_DEST (def_set);
    1122                 :            : 
    1123                 :     555601 :   switch (GET_CODE (dst))
    1124                 :            :     {
    1125                 :     253411 :     case REG:
    1126                 :     253411 :       {
    1127                 :     253411 :         rtx tmp = find_reg_equal_equiv_note (insn);
    1128                 :     253411 :         if (tmp)
    1129                 :        108 :           PUT_MODE (XEXP (tmp, 0), V1TImode);
    1130                 :     253411 :         PUT_MODE (dst, V1TImode);
    1131                 :     253411 :         fix_debug_reg_uses (dst);
    1132                 :            :       }
    1133                 :     253411 :       break;
    1134                 :     302190 :     case MEM:
    1135                 :     302190 :       PUT_MODE (dst, V1TImode);
    1136                 :            :       break;
    1137                 :            : 
    1138                 :          0 :     default:
    1139                 :          0 :       gcc_unreachable ();
    1140                 :            :     }
    1141                 :            : 
    1142                 :     555601 :   switch (GET_CODE (src))
    1143                 :            :     {
    1144                 :     259885 :     case REG:
    1145                 :     259885 :       PUT_MODE (src, V1TImode);
    1146                 :            :       /* Call fix_debug_reg_uses only if SRC is never defined.  */
    1147                 :     259885 :       if (!DF_REG_DEF_CHAIN (REGNO (src)))
    1148                 :          0 :         fix_debug_reg_uses (src);
    1149                 :            :       break;
    1150                 :            : 
    1151                 :     253411 :     case MEM:
    1152                 :     253411 :       PUT_MODE (src, V1TImode);
    1153                 :            :       break;
    1154                 :            : 
    1155                 :      15924 :     case CONST_WIDE_INT:
    1156                 :      15924 :       if (NONDEBUG_INSN_P (insn))
    1157                 :            :         {
    1158                 :            :           /* Since there are no instructions to store 128-bit constant,
    1159                 :            :              temporary register usage is required.  */
    1160                 :      15924 :           rtx tmp = gen_reg_rtx (V1TImode);
    1161                 :      15924 :           start_sequence ();
    1162                 :      15924 :           src = gen_rtx_CONST_VECTOR (V1TImode, gen_rtvec (1, src));
    1163                 :      15924 :           src = validize_mem (force_const_mem (V1TImode, src));
    1164                 :      15924 :           rtx_insn *seq = get_insns ();
    1165                 :      15924 :           end_sequence ();
    1166                 :      15924 :           if (seq)
    1167                 :          1 :             emit_insn_before (seq, insn);
    1168                 :      15924 :           emit_conversion_insns (gen_rtx_SET (dst, tmp), insn);
    1169                 :      15924 :           dst = tmp;
    1170                 :            :         }
    1171                 :            :       break;
    1172                 :            : 
    1173                 :      26381 :     case CONST_INT:
    1174                 :      26381 :       switch (standard_sse_constant_p (src, TImode))
    1175                 :            :         {
    1176                 :      25695 :         case 1:
    1177                 :      25695 :           src = CONST0_RTX (GET_MODE (dst));
    1178                 :      25695 :           break;
    1179                 :        686 :         case 2:
    1180                 :        686 :           src = CONSTM1_RTX (GET_MODE (dst));
    1181                 :        686 :           break;
    1182                 :          0 :         default:
    1183                 :          0 :           gcc_unreachable ();
    1184                 :            :         }
    1185                 :      26381 :       if (NONDEBUG_INSN_P (insn))
    1186                 :            :         {
    1187                 :      26381 :           rtx tmp = gen_reg_rtx (V1TImode);
    1188                 :            :           /* Since there are no instructions to store standard SSE
    1189                 :            :              constant, temporary register usage is required.  */
    1190                 :      26381 :           emit_conversion_insns (gen_rtx_SET (dst, tmp), insn);
    1191                 :      26381 :           dst = tmp;
    1192                 :            :         }
    1193                 :            :       break;
    1194                 :            : 
    1195                 :          0 :     default:
    1196                 :          0 :       gcc_unreachable ();
    1197                 :            :     }
    1198                 :            : 
    1199                 :     555601 :   SET_SRC (def_set) = src;
    1200                 :     555601 :   SET_DEST (def_set) = dst;
    1201                 :            : 
    1202                 :            :   /* Drop possible dead definitions.  */
    1203                 :     555601 :   PATTERN (insn) = def_set;
    1204                 :            : 
    1205                 :     555601 :   INSN_CODE (insn) = -1;
    1206                 :     555601 :   recog_memoized (insn);
    1207                 :     555601 :   df_insn_rescan (insn);
    1208                 :     555601 : }
    1209                 :            : 
    1210                 :            : /* Generate copies from defs used by the chain but not defined therein.
    1211                 :            :    Also populates defs_map which is used later by convert_insn.  */
    1212                 :            : 
    1213                 :            : void
    1214                 :      49919 : general_scalar_chain::convert_registers ()
    1215                 :            : {
    1216                 :      49919 :   bitmap_iterator bi;
    1217                 :      49919 :   unsigned id;
    1218                 :      57958 :   EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, id, bi)
    1219                 :            :     {
    1220                 :       8039 :       rtx chain_reg = gen_reg_rtx (smode);
    1221                 :       8039 :       defs_map.put (regno_reg_rtx[id], chain_reg);
    1222                 :            :     }
    1223                 :      52229 :   EXECUTE_IF_SET_IN_BITMAP (insns_conv, 0, id, bi)
    1224                 :       6069 :     for (df_ref ref = DF_INSN_UID_DEFS (id); ref; ref = DF_REF_NEXT_LOC (ref))
    1225                 :       3759 :       if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref)))
    1226                 :       2310 :         make_vector_copies (DF_REF_INSN (ref), DF_REF_REAL_REG (ref));
    1227                 :      49919 : }
    1228                 :            : 
    1229                 :            : /* Convert whole chain creating required register
    1230                 :            :    conversions and copies.  */
    1231                 :            : 
    1232                 :            : int
    1233                 :     345108 : scalar_chain::convert ()
    1234                 :            : {
    1235                 :     345108 :   bitmap_iterator bi;
    1236                 :     345108 :   unsigned id;
    1237                 :     345108 :   int converted_insns = 0;
    1238                 :            : 
    1239                 :     345108 :   if (!dbg_cnt (stv_conversion))
    1240                 :            :     return 0;
    1241                 :            : 
    1242                 :     345108 :   if (dump_file)
    1243                 :          0 :     fprintf (dump_file, "Converting chain #%d...\n", chain_id);
    1244                 :            : 
    1245                 :     345108 :   convert_registers ();
    1246                 :            : 
    1247                 :    1006760 :   EXECUTE_IF_SET_IN_BITMAP (insns, 0, id, bi)
    1248                 :            :     {
    1249                 :     661651 :       convert_insn (DF_INSN_UID_GET (id)->insn);
    1250                 :     661651 :       converted_insns++;
    1251                 :            :     }
    1252                 :            : 
    1253                 :            :   return converted_insns;
    1254                 :            : }
    1255                 :            : 
    1256                 :            : /* Return 1 if INSN uses or defines a hard register.
    1257                 :            :    Hard register uses in a memory address are ignored.
    1258                 :            :    Clobbers and flags definitions are ignored.  */
    1259                 :            : 
    1260                 :            : static bool
    1261                 :   86098000 : has_non_address_hard_reg (rtx_insn *insn)
    1262                 :            : {
    1263                 :   86098000 :   df_ref ref;
    1264                 :  137568000 :   FOR_EACH_INSN_DEF (ref, insn)
    1265                 :   75881000 :     if (HARD_REGISTER_P (DF_REF_REAL_REG (ref))
    1266                 :   41656200 :         && !DF_REF_FLAGS_IS_SET (ref, DF_REF_MUST_CLOBBER)
    1267                 :  108841000 :         && DF_REF_REGNO (ref) != FLAGS_REG)
    1268                 :            :       return true;
    1269                 :            : 
    1270                 :  117602000 :   FOR_EACH_INSN_USE (ref, insn)
    1271                 :   72156100 :     if (!DF_REF_REG_MEM_P (ref) && HARD_REGISTER_P (DF_REF_REAL_REG (ref)))
    1272                 :            :       return true;
    1273                 :            : 
    1274                 :            :   return false;
    1275                 :            : }
    1276                 :            : 
    1277                 :            : /* Check if comparison INSN may be transformed
    1278                 :            :    into vector comparison.  Currently we transform
    1279                 :            :    zero checks only which look like:
    1280                 :            : 
    1281                 :            :    (set (reg:CCZ 17 flags)
    1282                 :            :         (compare:CCZ (ior:SI (subreg:SI (reg:DI x) 4)
    1283                 :            :                              (subreg:SI (reg:DI x) 0))
    1284                 :            :                      (const_int 0 [0])))  */
    1285                 :            : 
    1286                 :            : static bool
    1287                 :    5561930 : convertible_comparison_p (rtx_insn *insn, enum machine_mode mode)
    1288                 :            : {
    1289                 :            :   /* ??? Currently convertible for double-word DImode chain only.  */
    1290                 :    5561930 :   if (TARGET_64BIT || mode != DImode)
    1291                 :            :     return false;
    1292                 :            : 
    1293                 :     536222 :   if (!TARGET_SSE4_1)
    1294                 :            :     return false;
    1295                 :            : 
    1296                 :      22723 :   rtx def_set = single_set (insn);
    1297                 :            : 
    1298                 :      22723 :   gcc_assert (def_set);
    1299                 :            : 
    1300                 :      22723 :   rtx src = SET_SRC (def_set);
    1301                 :      22723 :   rtx dst = SET_DEST (def_set);
    1302                 :            : 
    1303                 :      22723 :   gcc_assert (GET_CODE (src) == COMPARE);
    1304                 :            : 
    1305                 :      22723 :   if (GET_CODE (dst) != REG
    1306                 :      22723 :       || REGNO (dst) != FLAGS_REG
    1307                 :      45446 :       || GET_MODE (dst) != CCZmode)
    1308                 :            :     return false;
    1309                 :            : 
    1310                 :      13545 :   rtx op1 = XEXP (src, 0);
    1311                 :      13545 :   rtx op2 = XEXP (src, 1);
    1312                 :            : 
    1313                 :      13545 :   if (op2 != CONST0_RTX (GET_MODE (op2)))
    1314                 :            :     return false;
    1315                 :            : 
    1316                 :       2267 :   if (GET_CODE (op1) != IOR)
    1317                 :            :     return false;
    1318                 :            : 
    1319                 :        130 :   op2 = XEXP (op1, 1);
    1320                 :        130 :   op1 = XEXP (op1, 0);
    1321                 :            : 
    1322                 :        130 :   if (!SUBREG_P (op1)
    1323                 :          0 :       || !SUBREG_P (op2)
    1324                 :          0 :       || GET_MODE (op1) != SImode
    1325                 :          0 :       || GET_MODE (op2) != SImode
    1326                 :        130 :       || ((SUBREG_BYTE (op1) != 0
    1327                 :          0 :            || SUBREG_BYTE (op2) != GET_MODE_SIZE (SImode))
    1328                 :          0 :           && (SUBREG_BYTE (op2) != 0
    1329                 :          0 :               || SUBREG_BYTE (op1) != GET_MODE_SIZE (SImode))))
    1330                 :        130 :     return false;
    1331                 :            : 
    1332                 :          0 :   op1 = SUBREG_REG (op1);
    1333                 :          0 :   op2 = SUBREG_REG (op2);
    1334                 :            : 
    1335                 :          0 :   if (op1 != op2
    1336                 :            :       || !REG_P (op1)
    1337                 :          0 :       || GET_MODE (op1) != DImode)
    1338                 :          0 :     return false;
    1339                 :            : 
    1340                 :            :   return true;
    1341                 :            : }
    1342                 :            : 
    1343                 :            : /* The general version of scalar_to_vector_candidate_p.  */
    1344                 :            : 
    1345                 :            : static bool
    1346                 :  145681000 : general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode)
    1347                 :            : {
    1348                 :  145681000 :   rtx def_set = single_set (insn);
    1349                 :            : 
    1350                 :  145681000 :   if (!def_set)
    1351                 :            :     return false;
    1352                 :            : 
    1353                 :   61174900 :   if (has_non_address_hard_reg (insn))
    1354                 :            :     return false;
    1355                 :            : 
    1356                 :   31606100 :   rtx src = SET_SRC (def_set);
    1357                 :   31606100 :   rtx dst = SET_DEST (def_set);
    1358                 :            : 
    1359                 :   31606100 :   if (GET_CODE (src) == COMPARE)
    1360                 :    5561930 :     return convertible_comparison_p (insn, mode);
    1361                 :            : 
    1362                 :            :   /* We are interested in "mode" only.  */
    1363                 :   26044200 :   if ((GET_MODE (src) != mode
    1364                 :   16613300 :        && !CONST_INT_P (src))
    1365                 :   13431700 :       || GET_MODE (dst) != mode)
    1366                 :            :     return false;
    1367                 :            : 
    1368                 :   11309500 :   if (!REG_P (dst) && !MEM_P (dst))
    1369                 :            :     return false;
    1370                 :            : 
    1371                 :   11113600 :   switch (GET_CODE (src))
    1372                 :            :     {
    1373                 :      59354 :     case ASHIFTRT:
    1374                 :      59354 :       if (!TARGET_AVX512VL)
    1375                 :            :         return false;
    1376                 :            :       /* FALLTHRU */
    1377                 :            : 
    1378                 :     267820 :     case ASHIFT:
    1379                 :     267820 :     case LSHIFTRT:
    1380                 :     267820 :       if (!CONST_INT_P (XEXP (src, 1))
    1381                 :     513248 :           || !IN_RANGE (INTVAL (XEXP (src, 1)), 0, GET_MODE_BITSIZE (mode)-1))
    1382                 :      22423 :         return false;
    1383                 :            :       break;
    1384                 :            : 
    1385                 :       1168 :     case SMAX:
    1386                 :       1168 :     case SMIN:
    1387                 :       1168 :     case UMAX:
    1388                 :       1168 :     case UMIN:
    1389                 :       1168 :       if ((mode == DImode && !TARGET_AVX512VL)
    1390                 :       1168 :           || (mode == SImode && !TARGET_SSE4_1))
    1391                 :            :         return false;
    1392                 :            :       /* Fallthru.  */
    1393                 :            : 
    1394                 :    1912800 :     case PLUS:
    1395                 :    1912800 :     case MINUS:
    1396                 :    1912800 :     case IOR:
    1397                 :    1912800 :     case XOR:
    1398                 :    1912800 :     case AND:
    1399                 :    1912800 :       if (!REG_P (XEXP (src, 1))
    1400                 :    1912800 :           && !MEM_P (XEXP (src, 1))
    1401                 :    1119510 :           && !CONST_INT_P (XEXP (src, 1)))
    1402                 :            :         return false;
    1403                 :            : 
    1404                 :    1845170 :       if (GET_MODE (XEXP (src, 1)) != mode
    1405                 :    1051880 :           && !CONST_INT_P (XEXP (src, 1)))
    1406                 :            :         return false;
    1407                 :            :       break;
    1408                 :            : 
    1409                 :            :     case NEG:
    1410                 :            :     case NOT:
    1411                 :            :       break;
    1412                 :            : 
    1413                 :            :     case REG:
    1414                 :            :       return true;
    1415                 :            : 
    1416                 :    4439710 :     case MEM:
    1417                 :    4439710 :     case CONST_INT:
    1418                 :    4439710 :       return REG_P (dst);
    1419                 :            : 
    1420                 :    1096710 :     default:
    1421                 :    1096710 :       return false;
    1422                 :            :     }
    1423                 :            : 
    1424                 :    2128840 :   if (!REG_P (XEXP (src, 0))
    1425                 :    2128840 :       && !MEM_P (XEXP (src, 0))
    1426                 :     187678 :       && !CONST_INT_P (XEXP (src, 0))
    1427                 :            :       /* Check for andnot case.  */
    1428                 :     187678 :       && (GET_CODE (src) != AND
    1429                 :      14369 :           || GET_CODE (XEXP (src, 0)) != NOT
    1430                 :        186 :           || !REG_P (XEXP (XEXP (src, 0), 0))))
    1431                 :            :       return false;
    1432                 :            : 
    1433                 :    1941340 :   if (GET_MODE (XEXP (src, 0)) != mode
    1434                 :          0 :       && !CONST_INT_P (XEXP (src, 0)))
    1435                 :          0 :     return false;
    1436                 :            : 
    1437                 :            :   return true;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : /* The TImode version of scalar_to_vector_candidate_p.  */
    1441                 :            : 
    1442                 :            : static bool
    1443                 :   59266600 : timode_scalar_to_vector_candidate_p (rtx_insn *insn)
    1444                 :            : {
    1445                 :   59266600 :   rtx def_set = single_set (insn);
    1446                 :            : 
    1447                 :   59266600 :   if (!def_set)
    1448                 :            :     return false;
    1449                 :            : 
    1450                 :   24923000 :   if (has_non_address_hard_reg (insn))
    1451                 :            :     return false;
    1452                 :            : 
    1453                 :   13840300 :   rtx src = SET_SRC (def_set);
    1454                 :   13840300 :   rtx dst = SET_DEST (def_set);
    1455                 :            : 
    1456                 :            :   /* Only TImode load and store are allowed.  */
    1457                 :   13840300 :   if (GET_MODE (dst) != TImode)
    1458                 :            :     return false;
    1459                 :            : 
    1460                 :     627126 :   if (MEM_P (dst))
    1461                 :            :     {
    1462                 :            :       /* Check for store.  Memory must be aligned or unaligned store
    1463                 :            :          is optimal.  Only support store from register, standard SSE
    1464                 :            :          constant or CONST_WIDE_INT generated from piecewise store.
    1465                 :            : 
    1466                 :            :          ??? Verify performance impact before enabling CONST_INT for
    1467                 :            :          __int128 store.  */
    1468                 :     323442 :       if (misaligned_operand (dst, TImode)
    1469                 :     323442 :           && !TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
    1470                 :            :         return false;
    1471                 :            : 
    1472                 :     323437 :       switch (GET_CODE (src))
    1473                 :            :         {
    1474                 :            :         default:
    1475                 :            :           return false;
    1476                 :            : 
    1477                 :     296000 :         case REG:
    1478                 :     296000 :         case CONST_WIDE_INT:
    1479                 :     296000 :           return true;
    1480                 :            : 
    1481                 :      26858 :         case CONST_INT:
    1482                 :      26858 :           return standard_sse_constant_p (src, TImode);
    1483                 :            :         }
    1484                 :            :     }
    1485                 :     303684 :   else if (MEM_P (src))
    1486                 :            :     {
    1487                 :            :       /* Check for load.  Memory must be aligned or unaligned load is
    1488                 :            :          optimal.  */
    1489                 :     271637 :       return (REG_P (dst)
    1490                 :     271637 :               && (!misaligned_operand (src, TImode)
    1491                 :     244208 :                   || TARGET_SSE_UNALIGNED_LOAD_OPTIMAL));
    1492                 :            :     }
    1493                 :            : 
    1494                 :            :   return false;
    1495                 :            : }
    1496                 :            : 
    1497                 :            : /* For a register REGNO, scan instructions for its defs and uses.
    1498                 :            :    Put REGNO in REGS if a def or use isn't in CANDIDATES.  */
    1499                 :            : 
    1500                 :            : static void
    1501                 :     543408 : timode_check_non_convertible_regs (bitmap candidates, bitmap regs,
    1502                 :            :                                    unsigned int regno)
    1503                 :            : {
    1504                 :     543408 :   for (df_ref def = DF_REG_DEF_CHAIN (regno);
    1505                 :    1085820 :        def;
    1506                 :     542412 :        def = DF_REF_NEXT_REG (def))
    1507                 :            :     {
    1508                 :     555961 :       if (!bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
    1509                 :            :         {
    1510                 :      13549 :           if (dump_file)
    1511                 :          0 :             fprintf (dump_file,
    1512                 :            :                      "r%d has non convertible def in insn %d\n",
    1513                 :          0 :                      regno, DF_REF_INSN_UID (def));
    1514                 :            : 
    1515                 :      13549 :           bitmap_set_bit (regs, regno);
    1516                 :      13549 :           break;
    1517                 :            :         }
    1518                 :            :     }
    1519                 :            : 
    1520                 :     543408 :   for (df_ref ref = DF_REG_USE_CHAIN (regno);
    1521                 :    1280910 :        ref;
    1522                 :     737499 :        ref = DF_REF_NEXT_REG (ref))
    1523                 :            :     {
    1524                 :            :       /* Debug instructions are skipped.  */
    1525                 :     755726 :       if (NONDEBUG_INSN_P (DF_REF_INSN (ref))
    1526                 :     755726 :           && !bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
    1527                 :            :         {
    1528                 :      18227 :           if (dump_file)
    1529                 :          0 :             fprintf (dump_file,
    1530                 :            :                      "r%d has non convertible use in insn %d\n",
    1531                 :          0 :                      regno, DF_REF_INSN_UID (ref));
    1532                 :            : 
    1533                 :      18227 :           bitmap_set_bit (regs, regno);
    1534                 :      18227 :           break;
    1535                 :            :         }
    1536                 :            :     }
    1537                 :     543408 : }
    1538                 :            : 
    1539                 :            : /* The TImode version of remove_non_convertible_regs.  */
    1540                 :            : 
    1541                 :            : static void
    1542                 :     545646 : timode_remove_non_convertible_regs (bitmap candidates)
    1543                 :            : {
    1544                 :     545646 :   bitmap_iterator bi;
    1545                 :     545646 :   unsigned id;
    1546                 :     545646 :   bitmap regs = BITMAP_ALLOC (NULL);
    1547                 :            : 
    1548                 :    1139090 :   EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
    1549                 :            :     {
    1550                 :     593447 :       rtx def_set = single_set (DF_INSN_UID_GET (id)->insn);
    1551                 :     593447 :       rtx dest = SET_DEST (def_set);
    1552                 :     593447 :       rtx src = SET_SRC (def_set);
    1553                 :            : 
    1554                 :     643486 :       if ((!REG_P (dest)
    1555                 :     271066 :            || bitmap_bit_p (regs, REGNO (dest))
    1556                 :     270481 :            || HARD_REGISTER_P (dest))
    1557                 :     594032 :           && (!REG_P (src)
    1558                 :     280076 :               || bitmap_bit_p (regs, REGNO (src))
    1559                 :     272927 :               || HARD_REGISTER_P (src)))
    1560                 :      50039 :         continue;
    1561                 :            : 
    1562                 :     543408 :       if (REG_P (dest))
    1563                 :     270481 :         timode_check_non_convertible_regs (candidates, regs,
    1564                 :            :                                            REGNO (dest));
    1565                 :            : 
    1566                 :     543408 :       if (REG_P (src))
    1567                 :     272927 :         timode_check_non_convertible_regs (candidates, regs,
    1568                 :            :                                            REGNO (src));
    1569                 :            :     }
    1570                 :            : 
    1571                 :     575758 :   EXECUTE_IF_SET_IN_BITMAP (regs, 0, id, bi)
    1572                 :            :     {
    1573                 :      30112 :       for (df_ref def = DF_REG_DEF_CHAIN (id);
    1574                 :      62461 :            def;
    1575                 :      32349 :            def = DF_REF_NEXT_REG (def))
    1576                 :      32349 :         if (bitmap_bit_p (candidates, DF_REF_INSN_UID (def)))
    1577                 :            :           {
    1578                 :      17655 :             if (dump_file)
    1579                 :          0 :               fprintf (dump_file, "Removing insn %d from candidates list\n",
    1580                 :          0 :                        DF_REF_INSN_UID (def));
    1581                 :            : 
    1582                 :      17655 :             bitmap_clear_bit (candidates, DF_REF_INSN_UID (def));
    1583                 :            :           }
    1584                 :            : 
    1585                 :      30112 :       for (df_ref ref = DF_REG_USE_CHAIN (id);
    1586                 :      81164 :            ref;
    1587                 :      51052 :            ref = DF_REF_NEXT_REG (ref))
    1588                 :      51052 :         if (bitmap_bit_p (candidates, DF_REF_INSN_UID (ref)))
    1589                 :            :           {
    1590                 :      20191 :             if (dump_file)
    1591                 :          0 :               fprintf (dump_file, "Removing insn %d from candidates list\n",
    1592                 :          0 :                        DF_REF_INSN_UID (ref));
    1593                 :            : 
    1594                 :      20191 :             bitmap_clear_bit (candidates, DF_REF_INSN_UID (ref));
    1595                 :            :           }
    1596                 :            :     }
    1597                 :            : 
    1598                 :     545646 :   BITMAP_FREE (regs);
    1599                 :     545646 : }
    1600                 :            : 
    1601                 :            : /* Main STV pass function.  Find and convert scalar
    1602                 :            :    instructions into vector mode when profitable.  */
    1603                 :            : 
    1604                 :            : static unsigned int
    1605                 :    1183810 : convert_scalars_to_vector (bool timode_p)
    1606                 :            : {
    1607                 :    1183810 :   basic_block bb;
    1608                 :    1183810 :   int converted_insns = 0;
    1609                 :            : 
    1610                 :    1183810 :   bitmap_obstack_initialize (NULL);
    1611                 :    1183810 :   const machine_mode cand_mode[3] = { SImode, DImode, TImode };
    1612                 :    1183810 :   const machine_mode cand_vmode[3] = { V4SImode, V2DImode, V1TImode };
    1613                 :    3551420 :   bitmap_head candidates[3];  /* { SImode, DImode, TImode } */
    1614                 :    4735230 :   for (unsigned i = 0; i < 3; ++i)
    1615                 :    3551420 :     bitmap_initialize (&candidates[i], &bitmap_default_obstack);
    1616                 :            : 
    1617                 :    1183810 :   calculate_dominance_info (CDI_DOMINATORS);
    1618                 :    1183810 :   df_set_flags (DF_DEFER_INSN_RESCAN);
    1619                 :    1183810 :   df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
    1620                 :    1183810 :   df_analyze ();
    1621                 :            : 
    1622                 :            :   /* Find all instructions we want to convert into vector mode.  */
    1623                 :    1183810 :   if (dump_file)
    1624                 :         44 :     fprintf (dump_file, "Searching for mode conversion candidates...\n");
    1625                 :            : 
    1626                 :   12449400 :   FOR_EACH_BB_FN (bb, cfun)
    1627                 :            :     {
    1628                 :   11265600 :       rtx_insn *insn;
    1629                 :  278633000 :       FOR_BB_INSNS (bb, insn)
    1630                 :  133684000 :         if (timode_p
    1631                 :  133684000 :             && timode_scalar_to_vector_candidate_p (insn))
    1632                 :            :           {
    1633                 :     593447 :             if (dump_file)
    1634                 :          0 :               fprintf (dump_file, "  insn %d is marked as a TImode candidate\n",
    1635                 :          0 :                        INSN_UID (insn));
    1636                 :            : 
    1637                 :     593447 :             bitmap_set_bit (&candidates[2], INSN_UID (insn));
    1638                 :            :           }
    1639                 :  133090000 :         else if (!timode_p)
    1640                 :            :           {
    1641                 :            :             /* Check {SI,DI}mode.  */
    1642                 :  211512000 :             for (unsigned i = 0; i <= 1; ++i)
    1643                 :  145681000 :               if (general_scalar_to_vector_candidate_p (insn, cand_mode[i]))
    1644                 :            :                 {
    1645                 :    8586040 :                   if (dump_file)
    1646                 :        346 :                     fprintf (dump_file, "  insn %d is marked as a %s candidate\n",
    1647                 :        346 :                              INSN_UID (insn), i == 0 ? "SImode" : "DImode");
    1648                 :            : 
    1649                 :    8586040 :                   bitmap_set_bit (&candidates[i], INSN_UID (insn));
    1650                 :    8586040 :                   break;
    1651                 :            :                 }
    1652                 :            :           }
    1653                 :            :     }
    1654                 :            : 
    1655                 :    1183810 :   if (timode_p)
    1656                 :     545646 :     timode_remove_non_convertible_regs (&candidates[2]);
    1657                 :            : 
    1658                 :    3578320 :   for (unsigned i = 0; i <= 2; ++i)
    1659                 :    2880720 :     if (!bitmap_empty_p (&candidates[i]))
    1660                 :            :       break;
    1661                 :    2394510 :     else if (i == 2 && dump_file)
    1662                 :         23 :       fprintf (dump_file, "There are no candidates for optimization.\n");
    1663                 :            : 
    1664                 :    4735230 :   for (unsigned i = 0; i <= 2; ++i)
    1665                 :    8357690 :     while (!bitmap_empty_p (&candidates[i]))
    1666                 :            :       {
    1667                 :    4806270 :         unsigned uid = bitmap_first_set_bit (&candidates[i]);
    1668                 :    4806270 :         scalar_chain *chain;
    1669                 :            : 
    1670                 :    4806270 :         if (cand_mode[i] == TImode)
    1671                 :     295189 :           chain = new timode_scalar_chain;
    1672                 :            :         else
    1673                 :    4511080 :           chain = new general_scalar_chain (cand_mode[i], cand_vmode[i]);
    1674                 :            : 
    1675                 :            :         /* Find instructions chain we want to convert to vector mode.
    1676                 :            :            Check all uses and definitions to estimate all required
    1677                 :            :            conversions.  */
    1678                 :    4806270 :         chain->build (&candidates[i], uid);
    1679                 :            : 
    1680                 :    4806270 :         if (chain->compute_convert_gain () > 0)
    1681                 :     345108 :           converted_insns += chain->convert ();
    1682                 :            :         else
    1683                 :    4461160 :           if (dump_file)
    1684                 :        121 :             fprintf (dump_file, "Chain #%d conversion is not profitable\n",
    1685                 :            :                      chain->chain_id);
    1686                 :            : 
    1687                 :    4806270 :         delete chain;
    1688                 :            :       }
    1689                 :            : 
    1690                 :    1183810 :   if (dump_file)
    1691                 :         44 :     fprintf (dump_file, "Total insns converted: %d\n", converted_insns);
    1692                 :            : 
    1693                 :    4735230 :   for (unsigned i = 0; i <= 2; ++i)
    1694                 :    3551420 :     bitmap_release (&candidates[i]);
    1695                 :    1183810 :   bitmap_obstack_release (NULL);
    1696                 :    1183810 :   df_process_deferred_rescans ();
    1697                 :            : 
    1698                 :            :   /* Conversion means we may have 128bit register spills/fills
    1699                 :            :      which require aligned stack.  */
    1700                 :    1183810 :   if (converted_insns)
    1701                 :            :     {
    1702                 :      63502 :       if (crtl->stack_alignment_needed < 128)
    1703                 :       2097 :         crtl->stack_alignment_needed = 128;
    1704                 :      63502 :       if (crtl->stack_alignment_estimated < 128)
    1705                 :        252 :         crtl->stack_alignment_estimated = 128;
    1706                 :            : 
    1707                 :      63502 :       crtl->stack_realign_needed
    1708                 :      63502 :         = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
    1709                 :      63502 :       crtl->stack_realign_tried = crtl->stack_realign_needed;
    1710                 :            : 
    1711                 :      63502 :       crtl->stack_realign_processed = true;
    1712                 :            : 
    1713                 :      63502 :       if (!crtl->drap_reg)
    1714                 :            :         {
    1715                 :      63241 :           rtx drap_rtx = targetm.calls.get_drap_rtx ();
    1716                 :            : 
    1717                 :            :           /* stack_realign_drap and drap_rtx must match.  */
    1718                 :     126482 :           gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL));
    1719                 :            : 
    1720                 :            :           /* Do nothing if NULL is returned,
    1721                 :            :              which means DRAP is not needed.  */
    1722                 :      63241 :           if (drap_rtx != NULL)
    1723                 :            :             {
    1724                 :          0 :               crtl->args.internal_arg_pointer = drap_rtx;
    1725                 :            : 
    1726                 :            :               /* Call fixup_tail_calls to clean up
    1727                 :            :                  REG_EQUIV note if DRAP is needed. */
    1728                 :          0 :               fixup_tail_calls ();
    1729                 :            :             }
    1730                 :            :         }
    1731                 :            : 
    1732                 :            :       /* Fix up DECL_RTL/DECL_INCOMING_RTL of arguments.  */
    1733                 :      63502 :       if (TARGET_64BIT)
    1734                 :     123960 :         for (tree parm = DECL_ARGUMENTS (current_function_decl);
    1735                 :     123960 :              parm; parm = DECL_CHAIN (parm))
    1736                 :            :           {
    1737                 :      77918 :             if (TYPE_MODE (TREE_TYPE (parm)) != TImode)
    1738                 :      67065 :               continue;
    1739                 :      10853 :             if (DECL_RTL_SET_P (parm)
    1740                 :      21706 :                 && GET_MODE (DECL_RTL (parm)) == V1TImode)
    1741                 :            :               {
    1742                 :        108 :                 rtx r = DECL_RTL (parm);
    1743                 :        108 :                 if (REG_P (r))
    1744                 :        108 :                   SET_DECL_RTL (parm, gen_rtx_SUBREG (TImode, r, 0));
    1745                 :            :               }
    1746                 :      10853 :             if (DECL_INCOMING_RTL (parm)
    1747                 :      10853 :                 && GET_MODE (DECL_INCOMING_RTL (parm)) == V1TImode)
    1748                 :            :               {
    1749                 :          0 :                 rtx r = DECL_INCOMING_RTL (parm);
    1750                 :          0 :                 if (REG_P (r))
    1751                 :          0 :                   DECL_INCOMING_RTL (parm) = gen_rtx_SUBREG (TImode, r, 0);
    1752                 :            :               }
    1753                 :            :           }
    1754                 :            :     }
    1755                 :            : 
    1756                 :    1183810 :   return 0;
    1757                 :            : }
    1758                 :            : 
    1759                 :            : /* Modify the vzeroupper pattern in INSN so that it describes the effect
    1760                 :            :    that the instruction has on the SSE registers.  LIVE_REGS are the set
    1761                 :            :    of registers that are live across the instruction.
    1762                 :            : 
    1763                 :            :    For a live register R we use:
    1764                 :            : 
    1765                 :            :      (set (reg:V2DF R) (reg:V2DF R))
    1766                 :            : 
    1767                 :            :    which preserves the low 128 bits but clobbers the upper bits.  */
    1768                 :            : 
    1769                 :            : static void
    1770                 :       5974 : ix86_add_reg_usage_to_vzeroupper (rtx_insn *insn, bitmap live_regs)
    1771                 :            : {
    1772                 :       5974 :   rtx pattern = PATTERN (insn);
    1773                 :       5974 :   unsigned int nregs = TARGET_64BIT ? 16 : 8;
    1774                 :       5974 :   unsigned int npats = nregs;
    1775                 :     100518 :   for (unsigned int i = 0; i < nregs; ++i)
    1776                 :            :     {
    1777                 :      94544 :       unsigned int regno = GET_SSE_REGNO (i);
    1778                 :      94544 :       if (!bitmap_bit_p (live_regs, regno))
    1779                 :      94270 :         npats--;
    1780                 :            :     }
    1781                 :       5974 :   if (npats == 0)
    1782                 :            :     return;
    1783                 :        232 :   rtvec vec = rtvec_alloc (npats + 1);
    1784                 :        232 :   RTVEC_ELT (vec, 0) = XVECEXP (pattern, 0, 0);
    1785                 :       3944 :   for (unsigned int i = 0, j = 0; i < nregs; ++i)
    1786                 :            :     {
    1787                 :       3712 :       unsigned int regno = GET_SSE_REGNO (i);
    1788                 :       3712 :       if (!bitmap_bit_p (live_regs, regno))
    1789                 :       3438 :         continue;
    1790                 :        274 :       rtx reg = gen_rtx_REG (V2DImode, regno);
    1791                 :        274 :       ++j;
    1792                 :        274 :       RTVEC_ELT (vec, j) = gen_rtx_SET (reg, reg);
    1793                 :            :     }
    1794                 :        232 :   XVEC (pattern, 0) = vec;
    1795                 :        232 :   INSN_CODE (insn) = -1;
    1796                 :        232 :   df_insn_rescan (insn);
    1797                 :            : }
    1798                 :            : 
    1799                 :            : /* Walk the vzeroupper instructions in the function and annotate them
    1800                 :            :    with the effect that they have on the SSE registers.  */
    1801                 :            : 
    1802                 :            : static void
    1803                 :      50894 : ix86_add_reg_usage_to_vzerouppers (void)
    1804                 :            : {
    1805                 :      50894 :   basic_block bb;
    1806                 :      50894 :   rtx_insn *insn;
    1807                 :      50894 :   auto_bitmap live_regs;
    1808                 :            : 
    1809                 :      50894 :   df_analyze ();
    1810                 :     287417 :   FOR_EACH_BB_FN (bb, cfun)
    1811                 :            :     {
    1812                 :     236523 :       bitmap_copy (live_regs, df_get_live_out (bb));
    1813                 :     236523 :       df_simulate_initialize_backwards (bb, live_regs);
    1814                 :    6162880 :       FOR_BB_INSNS_REVERSE (bb, insn)
    1815                 :            :         {
    1816                 :    2963180 :           if (!NONDEBUG_INSN_P (insn))
    1817                 :    1381040 :             continue;
    1818                 :    1582140 :           if (vzeroupper_pattern (PATTERN (insn), VOIDmode))
    1819                 :       5974 :             ix86_add_reg_usage_to_vzeroupper (insn, live_regs);
    1820                 :    1582140 :           df_simulate_one_insn_backwards (bb, insn, live_regs);
    1821                 :            :         }
    1822                 :            :     }
    1823                 :      50894 : }
    1824                 :            : 
    1825                 :            : static unsigned int
    1826                 :      50894 : rest_of_handle_insert_vzeroupper (void)
    1827                 :            : {
    1828                 :      50894 :   int i;
    1829                 :            : 
    1830                 :            :   /* vzeroupper instructions are inserted immediately after reload to
    1831                 :            :      account for possible spills from 256bit or 512bit registers.  The pass
    1832                 :            :      reuses mode switching infrastructure by re-running mode insertion
    1833                 :            :      pass, so disable entities that have already been processed.  */
    1834                 :     356258 :   for (i = 0; i < MAX_386_ENTITIES; i++)
    1835                 :     305364 :     ix86_optimize_mode_switching[i] = 0;
    1836                 :            : 
    1837                 :      50894 :   ix86_optimize_mode_switching[AVX_U128] = 1;
    1838                 :            : 
    1839                 :            :   /* Call optimize_mode_switching.  */
    1840                 :      50894 :   g->get_passes ()->execute_pass_mode_switching ();
    1841                 :      50894 :   ix86_add_reg_usage_to_vzerouppers ();
    1842                 :      50894 :   return 0;
    1843                 :            : }
    1844                 :            : 
    1845                 :            : namespace {
    1846                 :            : 
    1847                 :            : const pass_data pass_data_insert_vzeroupper =
    1848                 :            : {
    1849                 :            :   RTL_PASS, /* type */
    1850                 :            :   "vzeroupper", /* name */
    1851                 :            :   OPTGROUP_NONE, /* optinfo_flags */
    1852                 :            :   TV_MACH_DEP, /* tv_id */
    1853                 :            :   0, /* properties_required */
    1854                 :            :   0, /* properties_provided */
    1855                 :            :   0, /* properties_destroyed */
    1856                 :            :   0, /* todo_flags_start */
    1857                 :            :   TODO_df_finish, /* todo_flags_finish */
    1858                 :            : };
    1859                 :            : 
    1860                 :            : class pass_insert_vzeroupper : public rtl_opt_pass
    1861                 :            : {
    1862                 :            : public:
    1863                 :     200540 :   pass_insert_vzeroupper(gcc::context *ctxt)
    1864                 :     401080 :     : rtl_opt_pass(pass_data_insert_vzeroupper, ctxt)
    1865                 :            :   {}
    1866                 :            : 
    1867                 :            :   /* opt_pass methods: */
    1868                 :     942964 :   virtual bool gate (function *)
    1869                 :            :     {
    1870                 :     942964 :       return TARGET_AVX
    1871                 :      73456 :              && TARGET_VZEROUPPER && flag_expensive_optimizations
    1872                 :     994195 :              && !optimize_size;
    1873                 :            :     }
    1874                 :            : 
    1875                 :      50894 :   virtual unsigned int execute (function *)
    1876                 :            :     {
    1877                 :      50894 :       return rest_of_handle_insert_vzeroupper ();
    1878                 :            :     }
    1879                 :            : 
    1880                 :            : }; // class pass_insert_vzeroupper
    1881                 :            : 
    1882                 :            : const pass_data pass_data_stv =
    1883                 :            : {
    1884                 :            :   RTL_PASS, /* type */
    1885                 :            :   "stv", /* name */
    1886                 :            :   OPTGROUP_NONE, /* optinfo_flags */
    1887                 :            :   TV_MACH_DEP, /* tv_id */
    1888                 :            :   0, /* properties_required */
    1889                 :            :   0, /* properties_provided */
    1890                 :            :   0, /* properties_destroyed */
    1891                 :            :   0, /* todo_flags_start */
    1892                 :            :   TODO_df_finish, /* todo_flags_finish */
    1893                 :            : };
    1894                 :            : 
    1895                 :            : class pass_stv : public rtl_opt_pass
    1896                 :            : {
    1897                 :            : public:
    1898                 :     401080 :   pass_stv (gcc::context *ctxt)
    1899                 :     401080 :     : rtl_opt_pass (pass_data_stv, ctxt),
    1900                 :     802160 :       timode_p (false)
    1901                 :            :   {}
    1902                 :            : 
    1903                 :            :   /* opt_pass methods: */
    1904                 :    1885930 :   virtual bool gate (function *)
    1905                 :            :     {
    1906                 :     942964 :       return ((!timode_p || TARGET_64BIT)
    1907                 :    2733800 :               && TARGET_STV && TARGET_SSE2 && optimize > 1);
    1908                 :            :     }
    1909                 :            : 
    1910                 :    1183810 :   virtual unsigned int execute (function *)
    1911                 :            :     {
    1912                 :    1183810 :       return convert_scalars_to_vector (timode_p);
    1913                 :            :     }
    1914                 :            : 
    1915                 :     200540 :   opt_pass *clone ()
    1916                 :            :     {
    1917                 :     200540 :       return new pass_stv (m_ctxt);
    1918                 :            :     }
    1919                 :            : 
    1920                 :     401080 :   void set_pass_param (unsigned int n, bool param)
    1921                 :            :     {
    1922                 :     401080 :       gcc_assert (n == 0);
    1923                 :     401080 :       timode_p = param;
    1924                 :     401080 :     }
    1925                 :            : 
    1926                 :            : private:
    1927                 :            :   bool timode_p;
    1928                 :            : }; // class pass_stv
    1929                 :            : 
    1930                 :            : } // anon namespace
    1931                 :            : 
    1932                 :            : rtl_opt_pass *
    1933                 :     200540 : make_pass_insert_vzeroupper (gcc::context *ctxt)
    1934                 :            : {
    1935                 :     200540 :   return new pass_insert_vzeroupper (ctxt);
    1936                 :            : }
    1937                 :            : 
    1938                 :            : rtl_opt_pass *
    1939                 :     200540 : make_pass_stv (gcc::context *ctxt)
    1940                 :            : {
    1941                 :     200540 :   return new pass_stv (ctxt);
    1942                 :            : }
    1943                 :            : 
    1944                 :            : /* Inserting ENDBRANCH instructions.  */
    1945                 :            : 
    1946                 :            : static unsigned int
    1947                 :        234 : rest_of_insert_endbranch (void)
    1948                 :            : {
    1949                 :        234 :   timevar_push (TV_MACH_DEP);
    1950                 :            : 
    1951                 :        234 :   rtx cet_eb;
    1952                 :        234 :   rtx_insn *insn;
    1953                 :        234 :   basic_block bb;
    1954                 :            : 
    1955                 :            :   /* Currently emit EB if it's a tracking function, i.e. 'nocf_check' is
    1956                 :            :      absent among function attributes.  Later an optimization will be
    1957                 :            :      introduced to make analysis if an address of a static function is
    1958                 :            :      taken.  A static function whose address is not taken will get a
    1959                 :            :      nocf_check attribute.  This will allow to reduce the number of EB.  */
    1960                 :            : 
    1961                 :        468 :   if (!lookup_attribute ("nocf_check",
    1962                 :        234 :                          TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
    1963                 :        226 :       && (!flag_manual_endbr
    1964                 :          3 :           || lookup_attribute ("cf_check",
    1965                 :          3 :                                DECL_ATTRIBUTES (cfun->decl)))
    1966                 :        459 :       && !cgraph_node::get (cfun->decl)->only_called_directly_p ())
    1967                 :            :     {
    1968                 :            :       /* Queue ENDBR insertion to x86_function_profiler.  */
    1969                 :        206 :       if (crtl->profile && flag_fentry)
    1970                 :          3 :         cfun->machine->endbr_queued_at_entrance = true;
    1971                 :            :       else
    1972                 :            :         {
    1973                 :        203 :           cet_eb = gen_nop_endbr ();
    1974                 :            : 
    1975                 :        203 :           bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
    1976                 :        203 :           insn = BB_HEAD (bb);
    1977                 :        203 :           emit_insn_before (cet_eb, insn);
    1978                 :            :         }
    1979                 :            :     }
    1980                 :            : 
    1981                 :        234 :   bb = 0;
    1982                 :       1074 :   FOR_EACH_BB_FN (bb, cfun)
    1983                 :            :     {
    1984                 :       7633 :       for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
    1985                 :       6793 :            insn = NEXT_INSN (insn))
    1986                 :            :         {
    1987                 :       6793 :           if (CALL_P (insn))
    1988                 :            :             {
    1989                 :        407 :               bool need_endbr;
    1990                 :        407 :               need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
    1991                 :        407 :               if (!need_endbr && !SIBLING_CALL_P (insn))
    1992                 :            :                 {
    1993                 :        381 :                   rtx call = get_call_rtx_from (insn);
    1994                 :        381 :                   rtx fnaddr = XEXP (call, 0);
    1995                 :        381 :                   tree fndecl = NULL_TREE;
    1996                 :            : 
    1997                 :            :                   /* Also generate ENDBRANCH for non-tail call which
    1998                 :            :                      may return via indirect branch.  */
    1999                 :        381 :                   if (GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
    2000                 :        356 :                     fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
    2001                 :        356 :                   if (fndecl == NULL_TREE)
    2002                 :         67 :                     fndecl = MEM_EXPR (fnaddr);
    2003                 :        381 :                   if (fndecl
    2004                 :        360 :                       && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
    2005                 :        387 :                       && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
    2006                 :            :                     fndecl = NULL_TREE;
    2007                 :        747 :                   if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
    2008                 :            :                     {
    2009                 :        357 :                       tree fntype = TREE_TYPE (fndecl);
    2010                 :        714 :                       if (lookup_attribute ("indirect_return",
    2011                 :        357 :                                             TYPE_ATTRIBUTES (fntype)))
    2012                 :            :                         need_endbr = true;
    2013                 :            :                     }
    2014                 :            :                 }
    2015                 :        401 :               if (!need_endbr)
    2016                 :        397 :                 continue;
    2017                 :            :               /* Generate ENDBRANCH after CALL, which can return more than
    2018                 :            :                  twice, setjmp-like functions.  */
    2019                 :            : 
    2020                 :         10 :               cet_eb = gen_nop_endbr ();
    2021                 :         10 :               emit_insn_after_setloc (cet_eb, insn, INSN_LOCATION (insn));
    2022                 :         10 :               continue;
    2023                 :            :             }
    2024                 :            : 
    2025                 :       6386 :           if (JUMP_P (insn) && flag_cet_switch)
    2026                 :            :             {
    2027                 :          9 :               rtx target = JUMP_LABEL (insn);
    2028                 :          9 :               if (target == NULL_RTX || ANY_RETURN_P (target))
    2029                 :          5 :                 continue;
    2030                 :            : 
    2031                 :            :               /* Check the jump is a switch table.  */
    2032                 :          4 :               rtx_insn *label = as_a<rtx_insn *> (target);
    2033                 :          4 :               rtx_insn *table = next_insn (label);
    2034                 :          4 :               if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
    2035                 :          2 :                 continue;
    2036                 :            : 
    2037                 :            :               /* For the indirect jump find out all places it jumps and insert
    2038                 :            :                  ENDBRANCH there.  It should be done under a special flag to
    2039                 :            :                  control ENDBRANCH generation for switch stmts.  */
    2040                 :          2 :               edge_iterator ei;
    2041                 :          2 :               edge e;
    2042                 :          2 :               basic_block dest_blk;
    2043                 :            : 
    2044                 :         24 :               FOR_EACH_EDGE (e, ei, bb->succs)
    2045                 :            :                 {
    2046                 :         22 :                   rtx_insn *insn;
    2047                 :            : 
    2048                 :         22 :                   dest_blk = e->dest;
    2049                 :         22 :                   insn = BB_HEAD (dest_blk);
    2050                 :         22 :                   gcc_assert (LABEL_P (insn));
    2051                 :         22 :                   cet_eb = gen_nop_endbr ();
    2052                 :         22 :                   emit_insn_after (cet_eb, insn);
    2053                 :            :                 }
    2054                 :          2 :               continue;
    2055                 :            :             }
    2056                 :            : 
    2057                 :       6377 :           if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
    2058                 :            :             {
    2059                 :         63 :               cet_eb = gen_nop_endbr ();
    2060                 :         63 :               emit_insn_after (cet_eb, insn);
    2061                 :         63 :               continue;
    2062                 :            :             }
    2063                 :            :         }
    2064                 :            :     }
    2065                 :            : 
    2066                 :        234 :   timevar_pop (TV_MACH_DEP);
    2067                 :        234 :   return 0;
    2068                 :            : }
    2069                 :            : 
    2070                 :            : namespace {
    2071                 :            : 
    2072                 :            : const pass_data pass_data_insert_endbranch =
    2073                 :            : {
    2074                 :            :   RTL_PASS, /* type.  */
    2075                 :            :   "cet", /* name.  */
    2076                 :            :   OPTGROUP_NONE, /* optinfo_flags.  */
    2077                 :            :   TV_MACH_DEP, /* tv_id.  */
    2078                 :            :   0, /* properties_required.  */
    2079                 :            :   0, /* properties_provided.  */
    2080                 :            :   0, /* properties_destroyed.  */
    2081                 :            :   0, /* todo_flags_start.  */
    2082                 :            :   0, /* todo_flags_finish.  */
    2083                 :            : };
    2084                 :            : 
    2085                 :            : class pass_insert_endbranch : public rtl_opt_pass
    2086                 :            : {
    2087                 :            : public:
    2088                 :     200540 :   pass_insert_endbranch (gcc::context *ctxt)
    2089                 :     401080 :     : rtl_opt_pass (pass_data_insert_endbranch, ctxt)
    2090                 :            :   {}
    2091                 :            : 
    2092                 :            :   /* opt_pass methods: */
    2093                 :     942964 :   virtual bool gate (function *)
    2094                 :            :     {
    2095                 :     942964 :       return ((flag_cf_protection & CF_BRANCH));
    2096                 :            :     }
    2097                 :            : 
    2098                 :        234 :   virtual unsigned int execute (function *)
    2099                 :            :     {
    2100                 :        234 :       return rest_of_insert_endbranch ();
    2101                 :            :     }
    2102                 :            : 
    2103                 :            : }; // class pass_insert_endbranch
    2104                 :            : 
    2105                 :            : } // anon namespace
    2106                 :            : 
    2107                 :            : rtl_opt_pass *
    2108                 :     200540 : make_pass_insert_endbranch (gcc::context *ctxt)
    2109                 :            : {
    2110                 :     200540 :   return new pass_insert_endbranch (ctxt);
    2111                 :            : }
    2112                 :            : 
    2113                 :            : /* At entry of the nearest common dominator for basic blocks with
    2114                 :            :    conversions, generate a single
    2115                 :            :         vxorps %xmmN, %xmmN, %xmmN
    2116                 :            :    for all
    2117                 :            :         vcvtss2sd  op, %xmmN, %xmmX
    2118                 :            :         vcvtsd2ss  op, %xmmN, %xmmX
    2119                 :            :         vcvtsi2ss  op, %xmmN, %xmmX
    2120                 :            :         vcvtsi2sd  op, %xmmN, %xmmX
    2121                 :            : 
    2122                 :            :    NB: We want to generate only a single vxorps to cover the whole
    2123                 :            :    function.  The LCM algorithm isn't appropriate here since it may
    2124                 :            :    place a vxorps inside the loop.  */
    2125                 :            : 
    2126                 :            : static unsigned int
    2127                 :      19085 : remove_partial_avx_dependency (void)
    2128                 :            : {
    2129                 :      19085 :   timevar_push (TV_MACH_DEP);
    2130                 :            : 
    2131                 :      19085 :   bitmap_obstack_initialize (NULL);
    2132                 :      19085 :   bitmap convert_bbs = BITMAP_ALLOC (NULL);
    2133                 :            : 
    2134                 :      19085 :   basic_block bb;
    2135                 :      19085 :   rtx_insn *insn, *set_insn;
    2136                 :      19085 :   rtx set;
    2137                 :      19085 :   rtx v4sf_const0 = NULL_RTX;
    2138                 :            : 
    2139                 :      19085 :   auto_vec<rtx_insn *> control_flow_insns;
    2140                 :            : 
    2141                 :     210398 :   FOR_EACH_BB_FN (bb, cfun)
    2142                 :            :     {
    2143                 :    4822450 :       FOR_BB_INSNS (bb, insn)
    2144                 :            :         {
    2145                 :    2315570 :           if (!NONDEBUG_INSN_P (insn))
    2146                 :     986728 :             continue;
    2147                 :            : 
    2148                 :    1328840 :           set = single_set (insn);
    2149                 :    1328840 :           if (!set)
    2150                 :      40283 :             continue;
    2151                 :            : 
    2152                 :    1288560 :           if (get_attr_avx_partial_xmm_update (insn)
    2153                 :            :               != AVX_PARTIAL_XMM_UPDATE_TRUE)
    2154                 :    1285770 :             continue;
    2155                 :            : 
    2156                 :       2789 :           if (!v4sf_const0)
    2157                 :            :             {
    2158                 :       1043 :               calculate_dominance_info (CDI_DOMINATORS);
    2159                 :       1043 :               df_set_flags (DF_DEFER_INSN_RESCAN);
    2160                 :       1043 :               df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
    2161                 :       1043 :               df_md_add_problem ();
    2162                 :       1043 :               df_analyze ();
    2163                 :       1043 :               v4sf_const0 = gen_reg_rtx (V4SFmode);
    2164                 :            :             }
    2165                 :            : 
    2166                 :            :           /* Convert PARTIAL_XMM_UPDATE_TRUE insns, DF -> SF, SF -> DF,
    2167                 :            :              SI -> SF, SI -> DF, DI -> SF, DI -> DF, to vec_dup and
    2168                 :            :              vec_merge with subreg.  */
    2169                 :       2789 :           rtx src = SET_SRC (set);
    2170                 :       2789 :           rtx dest = SET_DEST (set);
    2171                 :       2789 :           machine_mode dest_mode = GET_MODE (dest);
    2172                 :            : 
    2173                 :       2789 :           rtx zero;
    2174                 :       2789 :           machine_mode dest_vecmode;
    2175                 :       2789 :           if (dest_mode == E_SFmode)
    2176                 :            :             {
    2177                 :            :               dest_vecmode = V4SFmode;
    2178                 :            :               zero = v4sf_const0;
    2179                 :            :             }
    2180                 :            :           else
    2181                 :            :             {
    2182                 :       1147 :               dest_vecmode = V2DFmode;
    2183                 :       1147 :               zero = gen_rtx_SUBREG (V2DFmode, v4sf_const0, 0);
    2184                 :            :             }
    2185                 :            : 
    2186                 :            :           /* Change source to vector mode.  */
    2187                 :       2789 :           src = gen_rtx_VEC_DUPLICATE (dest_vecmode, src);
    2188                 :       2789 :           src = gen_rtx_VEC_MERGE (dest_vecmode, src, zero,
    2189                 :            :                                    GEN_INT (HOST_WIDE_INT_1U));
    2190                 :            :           /* Change destination to vector mode.  */
    2191                 :       2789 :           rtx vec = gen_reg_rtx (dest_vecmode);
    2192                 :            :           /* Generate an XMM vector SET.  */
    2193                 :       2789 :           set = gen_rtx_SET (vec, src);
    2194                 :       2789 :           set_insn = emit_insn_before (set, insn);
    2195                 :       2789 :           df_insn_rescan (set_insn);
    2196                 :            : 
    2197                 :       2789 :           if (cfun->can_throw_non_call_exceptions)
    2198                 :            :             {
    2199                 :            :               /* Handle REG_EH_REGION note.  */
    2200                 :          3 :               rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
    2201                 :          3 :               if (note)
    2202                 :            :                 {
    2203                 :          3 :                   control_flow_insns.safe_push (set_insn);
    2204                 :          3 :                   add_reg_note (set_insn, REG_EH_REGION, XEXP (note, 0));
    2205                 :            :                 }
    2206                 :            :             }
    2207                 :            : 
    2208                 :       2789 :           src = gen_rtx_SUBREG (dest_mode, vec, 0);
    2209                 :       2789 :           set = gen_rtx_SET (dest, src);
    2210                 :            : 
    2211                 :            :           /* Drop possible dead definitions.  */
    2212                 :       2789 :           PATTERN (insn) = set;
    2213                 :            : 
    2214                 :       2789 :           INSN_CODE (insn) = -1;
    2215                 :       2789 :           recog_memoized (insn);
    2216                 :       2789 :           df_insn_rescan (insn);
    2217                 :       2789 :           bitmap_set_bit (convert_bbs, bb->index);
    2218                 :            :         }
    2219                 :            :     }
    2220                 :            : 
    2221                 :      19085 :   if (v4sf_const0)
    2222                 :            :     {
    2223                 :            :       /* (Re-)discover loops so that bb->loop_father can be used in the
    2224                 :            :          analysis below.  */
    2225                 :       1043 :       loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
    2226                 :            : 
    2227                 :            :       /* Generate a vxorps at entry of the nearest dominator for basic
    2228                 :            :          blocks with conversions, which is in the fake loop that
    2229                 :            :          contains the whole function, so that there is only a single
    2230                 :            :          vxorps in the whole function.   */
    2231                 :       1043 :       bb = nearest_common_dominator_for_set (CDI_DOMINATORS,
    2232                 :            :                                              convert_bbs);
    2233                 :       1741 :       while (bb->loop_father->latch
    2234                 :       1741 :              != EXIT_BLOCK_PTR_FOR_FN (cfun))
    2235                 :        698 :         bb = get_immediate_dominator (CDI_DOMINATORS,
    2236                 :            :                                       bb->loop_father->header);
    2237                 :            : 
    2238                 :       1043 :       set = gen_rtx_SET (v4sf_const0, CONST0_RTX (V4SFmode));
    2239                 :            : 
    2240                 :       1043 :       insn = BB_HEAD (bb);
    2241                 :       2819 :       while (insn && !NONDEBUG_INSN_P (insn))
    2242                 :            :         {
    2243                 :       1777 :           if (insn == BB_END (bb))
    2244                 :            :             {
    2245                 :            :               insn = NULL;
    2246                 :            :               break;
    2247                 :            :             }
    2248                 :       1776 :           insn = NEXT_INSN (insn);
    2249                 :            :         }
    2250                 :       1043 :       if (insn == BB_HEAD (bb))
    2251                 :          0 :         set_insn = emit_insn_before (set, insn);
    2252                 :            :       else
    2253                 :       2086 :         set_insn = emit_insn_after (set,
    2254                 :       1043 :                                     insn ? PREV_INSN (insn) : BB_END (bb));
    2255                 :       1043 :       df_insn_rescan (set_insn);
    2256                 :       1043 :       df_process_deferred_rescans ();
    2257                 :       1043 :       loop_optimizer_finalize ();
    2258                 :            : 
    2259                 :       1043 :       if (!control_flow_insns.is_empty ())
    2260                 :            :         {
    2261                 :          3 :           free_dominance_info (CDI_DOMINATORS);
    2262                 :            : 
    2263                 :          3 :           unsigned int i;
    2264                 :          6 :           FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
    2265                 :          3 :             if (control_flow_insn_p (insn))
    2266                 :            :               {
    2267                 :            :                 /* Split the block after insn.  There will be a fallthru
    2268                 :            :                    edge, which is OK so we keep it.  We have to create
    2269                 :            :                    the exception edges ourselves.  */
    2270                 :          3 :                 bb = BLOCK_FOR_INSN (insn);
    2271                 :          3 :                 split_block (bb, insn);
    2272                 :          3 :                 rtl_make_eh_edge (NULL, bb, BB_END (bb));
    2273                 :            :               }
    2274                 :            :         }
    2275                 :            :     }
    2276                 :            : 
    2277                 :      19085 :   bitmap_obstack_release (NULL);
    2278                 :      19085 :   BITMAP_FREE (convert_bbs);
    2279                 :            : 
    2280                 :      19085 :   timevar_pop (TV_MACH_DEP);
    2281                 :      19085 :   return 0;
    2282                 :            : }
    2283                 :            : 
    2284                 :            : namespace {
    2285                 :            : 
    2286                 :            : const pass_data pass_data_remove_partial_avx_dependency =
    2287                 :            : {
    2288                 :            :   RTL_PASS, /* type */
    2289                 :            :   "rpad", /* name */
    2290                 :            :   OPTGROUP_NONE, /* optinfo_flags */
    2291                 :            :   TV_MACH_DEP, /* tv_id */
    2292                 :            :   0, /* properties_required */
    2293                 :            :   0, /* properties_provided */
    2294                 :            :   0, /* properties_destroyed */
    2295                 :            :   0, /* todo_flags_start */
    2296                 :            :   TODO_df_finish, /* todo_flags_finish */
    2297                 :            : };
    2298                 :            : 
    2299                 :            : class pass_remove_partial_avx_dependency : public rtl_opt_pass
    2300                 :            : {
    2301                 :            : public:
    2302                 :     200540 :   pass_remove_partial_avx_dependency (gcc::context *ctxt)
    2303                 :     401080 :     : rtl_opt_pass (pass_data_remove_partial_avx_dependency, ctxt)
    2304                 :            :   {}
    2305                 :            : 
    2306                 :            :   /* opt_pass methods: */
    2307                 :     942964 :   virtual bool gate (function *)
    2308                 :            :     {
    2309                 :     942964 :       return (TARGET_AVX
    2310                 :      73456 :               && TARGET_SSE_PARTIAL_REG_DEPENDENCY
    2311                 :      22647 :               && TARGET_SSE_MATH
    2312                 :      22567 :               && optimize
    2313                 :     962388 :               && optimize_function_for_speed_p (cfun));
    2314                 :            :     }
    2315                 :            : 
    2316                 :      19085 :   virtual unsigned int execute (function *)
    2317                 :            :     {
    2318                 :      19085 :       return remove_partial_avx_dependency ();
    2319                 :            :     }
    2320                 :            : }; // class pass_rpad
    2321                 :            : 
    2322                 :            : } // anon namespace
    2323                 :            : 
    2324                 :            : rtl_opt_pass *
    2325                 :     200540 : make_pass_remove_partial_avx_dependency (gcc::context *ctxt)
    2326                 :            : {
    2327                 :     200540 :   return new pass_remove_partial_avx_dependency (ctxt);
    2328                 :            : }
    2329                 :            : 
    2330                 :            : /* This compares the priority of target features in function DECL1
    2331                 :            :    and DECL2.  It returns positive value if DECL1 is higher priority,
    2332                 :            :    negative value if DECL2 is higher priority and 0 if they are the
    2333                 :            :    same.  */
    2334                 :            : 
    2335                 :            : int
    2336                 :        935 : ix86_compare_version_priority (tree decl1, tree decl2)
    2337                 :            : {
    2338                 :        935 :   unsigned int priority1 = get_builtin_code_for_version (decl1, NULL);
    2339                 :        935 :   unsigned int priority2 = get_builtin_code_for_version (decl2, NULL);
    2340                 :            : 
    2341                 :        935 :   return (int)priority1 - (int)priority2;
    2342                 :            : }
    2343                 :            : 
    2344                 :            : /* V1 and V2 point to function versions with different priorities
    2345                 :            :    based on the target ISA.  This function compares their priorities.  */
    2346                 :            :  
    2347                 :            : static int
    2348                 :       6046 : feature_compare (const void *v1, const void *v2)
    2349                 :            : {
    2350                 :       6046 :   typedef struct _function_version_info
    2351                 :            :     {
    2352                 :            :       tree version_decl;
    2353                 :            :       tree predicate_chain;
    2354                 :            :       unsigned int dispatch_priority;
    2355                 :            :     } function_version_info;
    2356                 :            : 
    2357                 :       6046 :   const function_version_info c1 = *(const function_version_info *)v1;
    2358                 :       6046 :   const function_version_info c2 = *(const function_version_info *)v2;
    2359                 :       6046 :   return (c2.dispatch_priority - c1.dispatch_priority);
    2360                 :            : }
    2361                 :            : 
    2362                 :            : /* This adds a condition to the basic_block NEW_BB in function FUNCTION_DECL
    2363                 :            :    to return a pointer to VERSION_DECL if the outcome of the expression
    2364                 :            :    formed by PREDICATE_CHAIN is true.  This function will be called during
    2365                 :            :    version dispatch to decide which function version to execute.  It returns
    2366                 :            :    the basic block at the end, to which more conditions can be added.  */
    2367                 :            : 
    2368                 :            : static basic_block
    2369                 :        722 : add_condition_to_bb (tree function_decl, tree version_decl,
    2370                 :            :                      tree predicate_chain, basic_block new_bb)
    2371                 :            : {
    2372                 :        722 :   gimple *return_stmt;
    2373                 :        722 :   tree convert_expr, result_var;
    2374                 :        722 :   gimple *convert_stmt;
    2375                 :        722 :   gimple *call_cond_stmt;
    2376                 :        722 :   gimple *if_else_stmt;
    2377                 :            : 
    2378                 :        722 :   basic_block bb1, bb2, bb3;
    2379                 :        722 :   edge e12, e23;
    2380                 :            : 
    2381                 :        722 :   tree cond_var, and_expr_var = NULL_TREE;
    2382                 :        722 :   gimple_seq gseq;
    2383                 :            : 
    2384                 :        722 :   tree predicate_decl, predicate_arg;
    2385                 :            : 
    2386                 :        722 :   push_cfun (DECL_STRUCT_FUNCTION (function_decl));
    2387                 :            : 
    2388                 :        722 :   gcc_assert (new_bb != NULL);
    2389                 :        722 :   gseq = bb_seq (new_bb);
    2390                 :            : 
    2391                 :            : 
    2392                 :        722 :   convert_expr = build1 (CONVERT_EXPR, ptr_type_node,
    2393                 :            :                          build_fold_addr_expr (version_decl));
    2394                 :        722 :   result_var = create_tmp_var (ptr_type_node);
    2395                 :        722 :   convert_stmt = gimple_build_assign (result_var, convert_expr); 
    2396                 :        722 :   return_stmt = gimple_build_return (result_var);
    2397                 :            : 
    2398                 :        722 :   if (predicate_chain == NULL_TREE)
    2399                 :            :     {
    2400                 :        162 :       gimple_seq_add_stmt (&gseq, convert_stmt);
    2401                 :        162 :       gimple_seq_add_stmt (&gseq, return_stmt);
    2402                 :        162 :       set_bb_seq (new_bb, gseq);
    2403                 :        162 :       gimple_set_bb (convert_stmt, new_bb);
    2404                 :        162 :       gimple_set_bb (return_stmt, new_bb);
    2405                 :        162 :       pop_cfun ();
    2406                 :        162 :       return new_bb;
    2407                 :            :     }
    2408                 :            : 
    2409                 :       1168 :   while (predicate_chain != NULL)
    2410                 :            :     {
    2411                 :        608 :       cond_var = create_tmp_var (integer_type_node);
    2412                 :        608 :       predicate_decl = TREE_PURPOSE (predicate_chain);
    2413                 :        608 :       predicate_arg = TREE_VALUE (predicate_chain);
    2414                 :        608 :       call_cond_stmt = gimple_build_call (predicate_decl, 1, predicate_arg);
    2415                 :        608 :       gimple_call_set_lhs (call_cond_stmt, cond_var);
    2416                 :            : 
    2417                 :        608 :       gimple_set_block (call_cond_stmt, DECL_INITIAL (function_decl));
    2418                 :        608 :       gimple_set_bb (call_cond_stmt, new_bb);
    2419                 :        608 :       gimple_seq_add_stmt (&gseq, call_cond_stmt);
    2420                 :            : 
    2421                 :        608 :       predicate_chain = TREE_CHAIN (predicate_chain);
    2422                 :            :       
    2423                 :        608 :       if (and_expr_var == NULL)
    2424                 :            :         and_expr_var = cond_var;
    2425                 :            :       else
    2426                 :            :         {
    2427                 :         48 :           gimple *assign_stmt;
    2428                 :            :           /* Use MIN_EXPR to check if any integer is zero?.
    2429                 :            :              and_expr_var = min_expr <cond_var, and_expr_var>  */
    2430                 :         48 :           assign_stmt = gimple_build_assign (and_expr_var,
    2431                 :            :                           build2 (MIN_EXPR, integer_type_node,
    2432                 :            :                                   cond_var, and_expr_var));
    2433                 :            : 
    2434                 :         48 :           gimple_set_block (assign_stmt, DECL_INITIAL (function_decl));
    2435                 :         48 :           gimple_set_bb (assign_stmt, new_bb);
    2436                 :         48 :           gimple_seq_add_stmt (&gseq, assign_stmt);
    2437                 :            :         }
    2438                 :            :     }
    2439                 :            : 
    2440                 :        560 :   if_else_stmt = gimple_build_cond (GT_EXPR, and_expr_var,
    2441                 :            :                                     integer_zero_node,
    2442                 :            :                                     NULL_TREE, NULL_TREE);
    2443                 :        560 :   gimple_set_block (if_else_stmt, DECL_INITIAL (function_decl));
    2444                 :        560 :   gimple_set_bb (if_else_stmt, new_bb);
    2445                 :        560 :   gimple_seq_add_stmt (&gseq, if_else_stmt);
    2446                 :            : 
    2447                 :        560 :   gimple_seq_add_stmt (&gseq, convert_stmt);
    2448                 :        560 :   gimple_seq_add_stmt (&gseq, return_stmt);
    2449                 :        560 :   set_bb_seq (new_bb, gseq);
    2450                 :            : 
    2451                 :        560 :   bb1 = new_bb;
    2452                 :        560 :   e12 = split_block (bb1, if_else_stmt);
    2453                 :        560 :   bb2 = e12->dest;
    2454                 :        560 :   e12->flags &= ~EDGE_FALLTHRU;
    2455                 :        560 :   e12->flags |= EDGE_TRUE_VALUE;
    2456                 :            : 
    2457                 :        560 :   e23 = split_block (bb2, return_stmt);
    2458                 :            : 
    2459                 :        560 :   gimple_set_bb (convert_stmt, bb2);
    2460                 :        560 :   gimple_set_bb (return_stmt, bb2);
    2461                 :            : 
    2462                 :        560 :   bb3 = e23->dest;
    2463                 :        560 :   make_edge (bb1, bb3, EDGE_FALSE_VALUE); 
    2464                 :            : 
    2465                 :        560 :   remove_edge (e23);
    2466                 :        560 :   make_edge (bb2, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
    2467                 :            : 
    2468                 :        560 :   pop_cfun ();
    2469                 :            : 
    2470                 :        560 :   return bb3;
    2471                 :            : }
    2472                 :            : 
    2473                 :            : /* This function generates the dispatch function for
    2474                 :            :    multi-versioned functions.  DISPATCH_DECL is the function which will
    2475                 :            :    contain the dispatch logic.  FNDECLS are the function choices for
    2476                 :            :    dispatch, and is a tree chain.  EMPTY_BB is the basic block pointer
    2477                 :            :    in DISPATCH_DECL in which the dispatch code is generated.  */
    2478                 :            : 
    2479                 :            : static int
    2480                 :        162 : dispatch_function_versions (tree dispatch_decl,
    2481                 :            :                             void *fndecls_p,
    2482                 :            :                             basic_block *empty_bb)
    2483                 :            : {
    2484                 :        162 :   tree default_decl;
    2485                 :        162 :   gimple *ifunc_cpu_init_stmt;
    2486                 :        162 :   gimple_seq gseq;
    2487                 :        162 :   int ix;
    2488                 :        162 :   tree ele;
    2489                 :        162 :   vec<tree> *fndecls;
    2490                 :        162 :   unsigned int num_versions = 0;
    2491                 :        162 :   unsigned int actual_versions = 0;
    2492                 :        162 :   unsigned int i;
    2493                 :            : 
    2494                 :        162 :   struct _function_version_info
    2495                 :            :     {
    2496                 :            :       tree version_decl;
    2497                 :            :       tree predicate_chain;
    2498                 :            :       unsigned int dispatch_priority;
    2499                 :            :     }*function_version_info;
    2500                 :            : 
    2501                 :        162 :   gcc_assert (dispatch_decl != NULL
    2502                 :            :               && fndecls_p != NULL
    2503                 :            :               && empty_bb != NULL);
    2504                 :            : 
    2505                 :            :   /*fndecls_p is actually a vector.  */
    2506                 :        162 :   fndecls = static_cast<vec<tree> *> (fndecls_p);
    2507                 :            : 
    2508                 :            :   /* At least one more version other than the default.  */
    2509                 :        162 :   num_versions = fndecls->length ();
    2510                 :        162 :   gcc_assert (num_versions >= 2);
    2511                 :            : 
    2512                 :        162 :   function_version_info = (struct _function_version_info *)
    2513                 :        162 :     XNEWVEC (struct _function_version_info, (num_versions - 1));
    2514                 :            : 
    2515                 :            :   /* The first version in the vector is the default decl.  */
    2516                 :        162 :   default_decl = (*fndecls)[0];
    2517                 :            : 
    2518                 :        162 :   push_cfun (DECL_STRUCT_FUNCTION (dispatch_decl));
    2519                 :            : 
    2520                 :        162 :   gseq = bb_seq (*empty_bb);
    2521                 :            :   /* Function version dispatch is via IFUNC.  IFUNC resolvers fire before
    2522                 :            :      constructors, so explicity call __builtin_cpu_init here.  */
    2523                 :        162 :   ifunc_cpu_init_stmt
    2524                 :        162 :     = gimple_build_call_vec (get_ix86_builtin (IX86_BUILTIN_CPU_INIT), vNULL);
    2525                 :        162 :   gimple_seq_add_stmt (&gseq, ifunc_cpu_init_stmt);
    2526                 :        162 :   gimple_set_bb (ifunc_cpu_init_stmt, *empty_bb);
    2527                 :        162 :   set_bb_seq (*empty_bb, gseq);
    2528                 :            : 
    2529                 :        162 :   pop_cfun ();
    2530                 :            : 
    2531                 :            : 
    2532                 :        938 :   for (ix = 1; fndecls->iterate (ix, &ele); ++ix)
    2533                 :            :     {
    2534                 :        776 :       tree version_decl = ele;
    2535                 :        776 :       tree predicate_chain = NULL_TREE;
    2536                 :        776 :       unsigned int priority;
    2537                 :            :       /* Get attribute string, parse it and find the right predicate decl.
    2538                 :            :          The predicate function could be a lengthy combination of many
    2539                 :            :          features, like arch-type and various isa-variants.  */
    2540                 :        776 :       priority = get_builtin_code_for_version (version_decl,
    2541                 :            :                                                &predicate_chain);
    2542                 :            : 
    2543                 :        776 :       if (predicate_chain == NULL_TREE)
    2544                 :        216 :         continue;
    2545                 :            : 
    2546                 :        560 :       function_version_info [actual_versions].version_decl = version_decl;
    2547                 :        560 :       function_version_info [actual_versions].predicate_chain
    2548                 :        560 :          = predicate_chain;
    2549                 :        560 :       function_version_info [actual_versions].dispatch_priority = priority;
    2550                 :        560 :       actual_versions++;
    2551                 :            :     }
    2552                 :            : 
    2553                 :            :   /* Sort the versions according to descending order of dispatch priority.  The
    2554                 :            :      priority is based on the ISA.  This is not a perfect solution.  There
    2555                 :            :      could still be ambiguity.  If more than one function version is suitable
    2556                 :            :      to execute,  which one should be dispatched?  In future, allow the user
    2557                 :            :      to specify a dispatch  priority next to the version.  */
    2558                 :        162 :   qsort (function_version_info, actual_versions,
    2559                 :            :          sizeof (struct _function_version_info), feature_compare);
    2560                 :            : 
    2561                 :        722 :   for  (i = 0; i < actual_versions; ++i)
    2562                 :        560 :     *empty_bb = add_condition_to_bb (dispatch_decl,
    2563                 :            :                                      function_version_info[i].version_decl,
    2564                 :        560 :                                      function_version_info[i].predicate_chain,
    2565                 :            :                                      *empty_bb);
    2566                 :            : 
    2567                 :            :   /* dispatch default version at the end.  */
    2568                 :        162 :   *empty_bb = add_condition_to_bb (dispatch_decl, default_decl,
    2569                 :            :                                    NULL, *empty_bb);
    2570                 :            : 
    2571                 :        162 :   free (function_version_info);
    2572                 :        162 :   return 0;
    2573                 :            : }
    2574                 :            : 
    2575                 :            : /* This function changes the assembler name for functions that are
    2576                 :            :    versions.  If DECL is a function version and has a "target"
    2577                 :            :    attribute, it appends the attribute string to its assembler name.  */
    2578                 :            : 
    2579                 :            : static tree
    2580                 :        868 : ix86_mangle_function_version_assembler_name (tree decl, tree id)
    2581                 :            : {
    2582                 :        868 :   tree version_attr;
    2583                 :        868 :   const char *orig_name, *version_string;
    2584                 :        868 :   char *attr_str, *assembler_name;
    2585                 :            : 
    2586                 :        868 :   if (DECL_DECLARED_INLINE_P (decl)
    2587                 :         72 :       && lookup_attribute ("gnu_inline",
    2588                 :        940 :                            DECL_ATTRIBUTES (decl)))
    2589                 :          0 :     error_at (DECL_SOURCE_LOCATION (decl),
    2590                 :            :               "function versions cannot be marked as %<gnu_inline%>,"
    2591                 :            :               " bodies have to be generated");
    2592                 :            : 
    2593                 :        868 :   if (DECL_VIRTUAL_P (decl)
    2594                 :       1736 :       || DECL_VINDEX (decl))
    2595                 :          0 :     sorry ("virtual function multiversioning not supported");
    2596                 :            : 
    2597                 :        868 :   version_attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
    2598                 :            : 
    2599                 :            :   /* target attribute string cannot be NULL.  */
    2600                 :        868 :   gcc_assert (version_attr != NULL_TREE);
    2601                 :            : 
    2602                 :        868 :   orig_name = IDENTIFIER_POINTER (id);
    2603                 :        868 :   version_string
    2604                 :        868 :     = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr)));
    2605                 :            : 
    2606                 :        868 :   if (strcmp (version_string, "default") == 0)
    2607                 :            :     return id;
    2608                 :            : 
    2609                 :        728 :   attr_str = sorted_attr_string (TREE_VALUE (version_attr));
    2610                 :        728 :   assembler_name = XNEWVEC (char, strlen (orig_name) + strlen (attr_str) + 2);
    2611                 :            : 
    2612                 :        728 :   sprintf (assembler_name, "%s.%s", orig_name, attr_str);
    2613                 :            : 
    2614                 :            :   /* Allow assembler name to be modified if already set.  */
    2615                 :        728 :   if (DECL_ASSEMBLER_NAME_SET_P (decl))
    2616                 :         16 :     SET_DECL_RTL (decl, NULL);
    2617                 :            : 
    2618                 :        728 :   tree ret = get_identifier (assembler_name);
    2619                 :        728 :   XDELETEVEC (attr_str);
    2620                 :        728 :   XDELETEVEC (assembler_name);
    2621                 :        728 :   return ret;
    2622                 :            : }
    2623                 :            : 
    2624                 :            : tree 
    2625                 :  167583000 : ix86_mangle_decl_assembler_name (tree decl, tree id)
    2626                 :            : {
    2627                 :            :   /* For function version, add the target suffix to the assembler name.  */
    2628                 :  167583000 :   if (TREE_CODE (decl) == FUNCTION_DECL
    2629                 :  167583000 :       && DECL_FUNCTION_VERSIONED (decl))
    2630                 :        868 :     id = ix86_mangle_function_version_assembler_name (decl, id);
    2631                 :            : #ifdef SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME
    2632                 :            :   id = SUBTARGET_MANGLE_DECL_ASSEMBLER_NAME (decl, id);
    2633                 :            : #endif
    2634                 :            : 
    2635                 :  167583000 :   return id;
    2636                 :            : }
    2637                 :            : 
    2638                 :            : /* Make a dispatcher declaration for the multi-versioned function DECL.
    2639                 :            :    Calls to DECL function will be replaced with calls to the dispatcher
    2640                 :            :    by the front-end.  Returns the decl of the dispatcher function.  */
    2641                 :            : 
    2642                 :            : tree
    2643                 :        314 : ix86_get_function_versions_dispatcher (void *decl)
    2644                 :            : {
    2645                 :        314 :   tree fn = (tree) decl;
    2646                 :        314 :   struct cgraph_node *node = NULL;
    2647                 :        314 :   struct cgraph_node *default_node = NULL;
    2648                 :        314 :   struct cgraph_function_version_info *node_v = NULL;
    2649                 :        314 :   struct cgraph_function_version_info *first_v = NULL;
    2650                 :            : 
    2651                 :        314 :   tree dispatch_decl = NULL;
    2652                 :            : 
    2653                 :        314 :   struct cgraph_function_version_info *default_version_info = NULL;
    2654                 :            :  
    2655                 :        628 :   gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));
    2656                 :            : 
    2657                 :        314 :   node = cgraph_node::get (fn);
    2658                 :        314 :   gcc_assert (node != NULL);
    2659                 :            : 
    2660                 :        314 :   node_v = node->function_version ();
    2661                 :        314 :   gcc_assert (node_v != NULL);
    2662                 :            :  
    2663                 :        314 :   if (node_v->dispatcher_resolver != NULL)
    2664                 :            :     return node_v->dispatcher_resolver;
    2665                 :            : 
    2666                 :            :   /* Find the default version and make it the first node.  */
    2667                 :            :   first_v = node_v;
    2668                 :            :   /* Go to the beginning of the chain.  */
    2669                 :        394 :   while (first_v->prev != NULL)
    2670                 :            :     first_v = first_v->prev;
    2671                 :            :   default_version_info = first_v;
    2672                 :        262 :   while (default_version_info != NULL)
    2673                 :            :     {
    2674                 :        254 :       if (is_function_default_version
    2675                 :        254 :             (default_version_info->this_node->decl))
    2676                 :            :         break;
    2677                 :         92 :       default_version_info = default_version_info->next;
    2678                 :            :     }
    2679                 :            : 
    2680                 :            :   /* If there is no default node, just return NULL.  */
    2681                 :        170 :   if (default_version_info == NULL)
    2682                 :            :     return NULL;
    2683                 :            : 
    2684                 :            :   /* Make default info the first node.  */
    2685                 :        162 :   if (first_v != default_version_info)
    2686                 :            :     {
    2687                 :         16 :       default_version_info->prev->next = default_version_info->next;
    2688                 :         16 :       if (default_version_info->next)
    2689                 :          0 :         default_version_info->next->prev = default_version_info->prev;
    2690                 :         16 :       first_v->prev = default_version_info;
    2691                 :         16 :       default_version_info->next = first_v;
    2692                 :         16 :       default_version_info->prev = NULL;
    2693                 :            :     }
    2694                 :            : 
    2695                 :        162 :   default_node = default_version_info->this_node;
    2696                 :            : 
    2697                 :            : #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
    2698                 :        162 :   if (targetm.has_ifunc_p ())
    2699                 :            :     {
    2700                 :        162 :       struct cgraph_function_version_info *it_v = NULL;
    2701                 :        162 :       struct cgraph_node *dispatcher_node = NULL;
    2702                 :        162 :       struct cgraph_function_version_info *dispatcher_version_info = NULL;
    2703                 :            : 
    2704                 :            :       /* Right now, the dispatching is done via ifunc.  */
    2705                 :        162 :       dispatch_decl = make_dispatcher_decl (default_node->decl);
    2706                 :            : 
    2707                 :        162 :       dispatcher_node = cgraph_node::get_create (dispatch_decl);
    2708                 :        162 :       gcc_assert (dispatcher_node != NULL);
    2709                 :        162 :       dispatcher_node->dispatcher_function = 1;
    2710                 :        162 :       dispatcher_version_info
    2711                 :        162 :         = dispatcher_node->insert_new_function_version ();
    2712                 :        162 :       dispatcher_version_info->next = default_version_info;
    2713                 :        162 :       dispatcher_node->definition = 1;
    2714                 :            : 
    2715                 :            :       /* Set the dispatcher for all the versions.  */
    2716                 :        162 :       it_v = default_version_info;
    2717                 :       1100 :       while (it_v != NULL)
    2718                 :            :         {
    2719                 :        938 :           it_v->dispatcher_resolver = dispatch_decl;
    2720                 :        938 :           it_v = it_v->next;
    2721                 :            :         }
    2722                 :            :     }
    2723                 :            :   else
    2724                 :            : #endif
    2725                 :            :     {
    2726                 :          0 :       error_at (DECL_SOURCE_LOCATION (default_node->decl),
    2727                 :            :                 "multiversioning needs %<ifunc%> which is not supported "
    2728                 :            :                 "on this target");
    2729                 :            :     }
    2730                 :            : 
    2731                 :            :   return dispatch_decl;
    2732                 :            : }
    2733                 :            : 
    2734                 :            : /* Make the resolver function decl to dispatch the versions of
    2735                 :            :    a multi-versioned function,  DEFAULT_DECL.  IFUNC_ALIAS_DECL is
    2736                 :            :    ifunc alias that will point to the created resolver.  Create an
    2737                 :            :    empty basic block in the resolver and store the pointer in
    2738                 :            :    EMPTY_BB.  Return the decl of the resolver function.  */
    2739                 :            : 
    2740                 :            : static tree
    2741                 :        162 : make_resolver_func (const tree default_decl,
    2742                 :            :                     const tree ifunc_alias_decl,
    2743                 :            :                     basic_block *empty_bb)
    2744                 :            : {
    2745                 :        162 :   tree decl, type, t;
    2746                 :            : 
    2747                 :            :   /* Create resolver function name based on default_decl.  */
    2748                 :        162 :   tree decl_name = clone_function_name (default_decl, "resolver");
    2749                 :        162 :   const char *resolver_name = IDENTIFIER_POINTER (decl_name);
    2750                 :            : 
    2751                 :            :   /* The resolver function should return a (void *). */
    2752                 :        162 :   type = build_function_type_list (ptr_type_node, NULL_TREE);
    2753                 :            : 
    2754                 :        162 :   decl = build_fn_decl (resolver_name, type);
    2755                 :        162 :   SET_DECL_ASSEMBLER_NAME (decl, decl_name);
    2756                 :            : 
    2757                 :        162 :   DECL_NAME (decl) = decl_name;
    2758                 :        162 :   TREE_USED (decl) = 1;
    2759                 :        162 :   DECL_ARTIFICIAL (decl) = 1;
    2760                 :        162 :   DECL_IGNORED_P (decl) = 1;
    2761                 :        162 :   TREE_PUBLIC (decl) = 0;
    2762                 :        162 :   DECL_UNINLINABLE (decl) = 1;
    2763                 :            : 
    2764                 :            :   /* Resolver is not external, body is generated.  */
    2765                 :        162 :   DECL_EXTERNAL (decl) = 0;
    2766                 :        162 :   DECL_EXTERNAL (ifunc_alias_decl) = 0;
    2767                 :            : 
    2768                 :        162 :   DECL_CONTEXT (decl) = NULL_TREE;
    2769                 :        162 :   DECL_INITIAL (decl) = make_node (BLOCK);
    2770                 :        162 :   DECL_STATIC_CONSTRUCTOR (decl) = 0;
    2771                 :            : 
    2772                 :        162 :   if (DECL_COMDAT_GROUP (default_decl)
    2773                 :        162 :       || TREE_PUBLIC (default_decl))
    2774                 :            :     {
    2775                 :            :       /* In this case, each translation unit with a call to this
    2776                 :            :          versioned function will put out a resolver.  Ensure it
    2777                 :            :          is comdat to keep just one copy.  */
    2778                 :        139 :       DECL_COMDAT (decl) = 1;
    2779                 :        139 :       make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
    2780                 :            :     }
    2781                 :            :   else
    2782                 :         23 :     TREE_PUBLIC (ifunc_alias_decl) = 0;
    2783                 :            : 
    2784                 :            :   /* Build result decl and add to function_decl. */
    2785                 :        162 :   t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node);
    2786                 :        162 :   DECL_CONTEXT (t) = decl;
    2787                 :        162 :   DECL_ARTIFICIAL (t) = 1;
    2788                 :        162 :   DECL_IGNORED_P (t) = 1;
    2789                 :        162 :   DECL_RESULT (decl) = t;
    2790                 :            : 
    2791                 :        162 :   gimplify_function_tree (decl);
    2792                 :        162 :   push_cfun (DECL_STRUCT_FUNCTION (decl));
    2793                 :        162 :   *empty_bb = init_lowered_empty_function (decl, false,
    2794                 :            :                                            profile_count::uninitialized ());
    2795                 :            : 
    2796                 :        162 :   cgraph_node::add_new_function (decl, true);
    2797                 :        162 :   symtab->call_cgraph_insertion_hooks (cgraph_node::get_create (decl));
    2798                 :            : 
    2799                 :        162 :   pop_cfun ();
    2800                 :            : 
    2801                 :        162 :   gcc_assert (ifunc_alias_decl != NULL);
    2802                 :            :   /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name.  */
    2803                 :        162 :   DECL_ATTRIBUTES (ifunc_alias_decl)
    2804                 :        324 :     = make_attribute ("ifunc", resolver_name,
    2805                 :        162 :                       DECL_ATTRIBUTES (ifunc_alias_decl));
    2806                 :            : 
    2807                 :            :   /* Create the alias for dispatch to resolver here.  */
    2808                 :        162 :   cgraph_node::create_same_body_alias (ifunc_alias_decl, decl);
    2809                 :        162 :   return decl;
    2810                 :            : }
    2811                 :            : 
    2812                 :            : /* Generate the dispatching code body to dispatch multi-versioned function
    2813                 :            :    DECL.  The target hook is called to process the "target" attributes and
    2814                 :            :    provide the code to dispatch the right function at run-time.  NODE points
    2815                 :            :    to the dispatcher decl whose body will be created.  */
    2816                 :            : 
    2817                 :            : tree 
    2818                 :        162 : ix86_generate_version_dispatcher_body (void *node_p)
    2819                 :            : {
    2820                 :        162 :   tree resolver_decl;
    2821                 :        162 :   basic_block empty_bb;
    2822                 :        162 :   tree default_ver_decl;
    2823                 :        162 :   struct cgraph_node *versn;
    2824                 :        162 :   struct cgraph_node *node;
    2825                 :            : 
    2826                 :        162 :   struct cgraph_function_version_info *node_version_info = NULL;
    2827                 :        162 :   struct cgraph_function_version_info *versn_info = NULL;
    2828                 :            : 
    2829                 :        162 :   node = (cgraph_node *)node_p;
    2830                 :            : 
    2831                 :        162 :   node_version_info = node->function_version ();
    2832                 :        162 :   gcc_assert (node->dispatcher_function
    2833                 :            :               && node_version_info != NULL);
    2834                 :            : 
    2835                 :        162 :   if (node_version_info->dispatcher_resolver)
    2836                 :            :     return node_version_info->dispatcher_resolver;
    2837                 :            : 
    2838                 :            :   /* The first version in the chain corresponds to the default version.  */
    2839                 :        162 :   default_ver_decl = node_version_info->next->this_node->decl;
    2840                 :            : 
    2841                 :            :   /* node is going to be an alias, so remove the finalized bit.  */
    2842                 :        162 :   node->definition = false;
    2843                 :            : 
    2844                 :        162 :   resolver_decl = make_resolver_func (default_ver_decl,
    2845                 :            :                                       node->decl, &empty_bb);
    2846                 :            : 
    2847                 :        162 :   node_version_info->dispatcher_resolver = resolver_decl;
    2848                 :            : 
    2849                 :        162 :   push_cfun (DECL_STRUCT_FUNCTION (resolver_decl));
    2850                 :            : 
    2851                 :        162 :   auto_vec<tree, 2> fn_ver_vec;
    2852                 :            : 
    2853                 :       1100 :   for (versn_info = node_version_info->next; versn_info;
    2854                 :        938 :        versn_info = versn_info->next)
    2855                 :            :     {
    2856                 :        938 :       versn = versn_info->this_node;
    2857                 :            :       /* Check for virtual functions here again, as by this time it should
    2858                 :            :          have been determined if this function needs a vtable index or
    2859                 :            :          not.  This happens for methods in derived classes that override
    2860                 :            :          virtual methods in base classes but are not explicitly marked as
    2861                 :            :          virtual.  */
    2862                 :        938 :       if (DECL_VINDEX (versn->decl))
    2863                 :          0 :         sorry ("virtual function multiversioning not supported");
    2864                 :            : 
    2865                 :        938 :       fn_ver_vec.safe_push (versn->decl);
    2866                 :            :     }
    2867                 :            : 
    2868                 :        162 :   dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
    2869                 :        162 :   cgraph_edge::rebuild_edges ();
    2870                 :        162 :   pop_cfun ();
    2871                 :        162 :   return resolver_decl;
    2872                 :            : }
    2873                 :            : 
    2874                 :            : 

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.