LCOV - code coverage report
Current view: top level - gcc - sel-sched-ir.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 2312 2680 86.3 %
Date: 2020-04-04 11:58:09 Functions: 227 269 84.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Instruction scheduling pass.  Selective scheduler and pipeliner.
       2                 :            :    Copyright (C) 2006-2020 Free Software Foundation, Inc.
       3                 :            : 
       4                 :            : This file is part of GCC.
       5                 :            : 
       6                 :            : GCC is free software; you can redistribute it and/or modify it under
       7                 :            : the terms of the GNU General Public License as published by the Free
       8                 :            : Software Foundation; either version 3, or (at your option) any later
       9                 :            : version.
      10                 :            : 
      11                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :            : for more details.
      15                 :            : 
      16                 :            : You should have received a copy of the GNU General Public License
      17                 :            : along with GCC; see the file COPYING3.  If not see
      18                 :            : <http://www.gnu.org/licenses/>.  */
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : #include "system.h"
      22                 :            : #include "coretypes.h"
      23                 :            : #include "backend.h"
      24                 :            : #include "cfghooks.h"
      25                 :            : #include "tree.h"
      26                 :            : #include "rtl.h"
      27                 :            : #include "df.h"
      28                 :            : #include "memmodel.h"
      29                 :            : #include "tm_p.h"
      30                 :            : #include "cfgrtl.h"
      31                 :            : #include "cfganal.h"
      32                 :            : #include "cfgbuild.h"
      33                 :            : #include "insn-config.h"
      34                 :            : #include "insn-attr.h"
      35                 :            : #include "recog.h"
      36                 :            : #include "target.h"
      37                 :            : #include "sched-int.h"
      38                 :            : #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
      39                 :            : 
      40                 :            : #ifdef INSN_SCHEDULING
      41                 :            : #include "regset.h"
      42                 :            : #include "cfgloop.h"
      43                 :            : #include "sel-sched-ir.h"
      44                 :            : /* We don't have to use it except for sel_print_insn.  */
      45                 :            : #include "sel-sched-dump.h"
      46                 :            : 
      47                 :            : /* A vector holding bb info for whole scheduling pass.  */
      48                 :            : vec<sel_global_bb_info_def> sel_global_bb_info;
      49                 :            : 
      50                 :            : /* A vector holding bb info.  */
      51                 :            : vec<sel_region_bb_info_def> sel_region_bb_info;
      52                 :            : 
      53                 :            : /* A pool for allocating all lists.  */
      54                 :            : object_allocator<_list_node> sched_lists_pool ("sel-sched-lists");
      55                 :            : 
      56                 :            : /* This contains information about successors for compute_av_set.  */
      57                 :            : struct succs_info current_succs;
      58                 :            : 
      59                 :            : /* Data structure to describe interaction with the generic scheduler utils.  */
      60                 :            : static struct common_sched_info_def sel_common_sched_info;
      61                 :            : 
      62                 :            : /* The loop nest being pipelined.  */
      63                 :            : class loop *current_loop_nest;
      64                 :            : 
      65                 :            : /* LOOP_NESTS is a vector containing the corresponding loop nest for
      66                 :            :    each region.  */
      67                 :            : static vec<loop_p> loop_nests;
      68                 :            : 
      69                 :            : /* Saves blocks already in loop regions, indexed by bb->index.  */
      70                 :            : static sbitmap bbs_in_loop_rgns = NULL;
      71                 :            : 
      72                 :            : /* CFG hooks that are saved before changing create_basic_block hook.  */
      73                 :            : static struct cfg_hooks orig_cfg_hooks;
      74                 :            : 
      75                 :            : 
      76                 :            : /* Array containing reverse topological index of function basic blocks,
      77                 :            :    indexed by BB->INDEX.  */
      78                 :            : static int *rev_top_order_index = NULL;
      79                 :            : 
      80                 :            : /* Length of the above array.  */
      81                 :            : static int rev_top_order_index_len = -1;
      82                 :            : 
      83                 :            : /* A regset pool structure.  */
      84                 :            : static struct
      85                 :            : {
      86                 :            :   /* The stack to which regsets are returned.  */
      87                 :            :   regset *v;
      88                 :            : 
      89                 :            :   /* Its pointer.  */
      90                 :            :   int n;
      91                 :            : 
      92                 :            :   /* Its size.  */
      93                 :            :   int s;
      94                 :            : 
      95                 :            :   /* In VV we save all generated regsets so that, when destructing the
      96                 :            :      pool, we can compare it with V and check that every regset was returned
      97                 :            :      back to pool.  */
      98                 :            :   regset *vv;
      99                 :            : 
     100                 :            :   /* The pointer of VV stack.  */
     101                 :            :   int nn;
     102                 :            : 
     103                 :            :   /* Its size.  */
     104                 :            :   int ss;
     105                 :            : 
     106                 :            :   /* The difference between allocated and returned regsets.  */
     107                 :            :   int diff;
     108                 :            : } regset_pool = { NULL, 0, 0, NULL, 0, 0, 0 };
     109                 :            : 
     110                 :            : /* This represents the nop pool.  */
     111                 :            : static struct
     112                 :            : {
     113                 :            :   /* The vector which holds previously emitted nops.  */
     114                 :            :   insn_t *v;
     115                 :            : 
     116                 :            :   /* Its pointer.  */
     117                 :            :   int n;
     118                 :            : 
     119                 :            :   /* Its size.  */
     120                 :            :   int s;
     121                 :            : } nop_pool = { NULL, 0, 0 };
     122                 :            : 
     123                 :            : /* The pool for basic block notes.  */
     124                 :            : static vec<rtx_note *> bb_note_pool;
     125                 :            : 
     126                 :            : /* A NOP pattern used to emit placeholder insns.  */
     127                 :            : rtx nop_pattern = NULL_RTX;
     128                 :            : /* A special instruction that resides in EXIT_BLOCK.
     129                 :            :    EXIT_INSN is successor of the insns that lead to EXIT_BLOCK.  */
     130                 :            : rtx_insn *exit_insn = NULL;
     131                 :            : 
     132                 :            : /* TRUE if while scheduling current region, which is loop, its preheader
     133                 :            :    was removed.  */
     134                 :            : bool preheader_removed = false;
     135                 :            : 
     136                 :            : 
     137                 :            : /* Forward static declarations.  */
     138                 :            : static void fence_clear (fence_t);
     139                 :            : 
     140                 :            : static void deps_init_id (idata_t, insn_t, bool);
     141                 :            : static void init_id_from_df (idata_t, insn_t, bool);
     142                 :            : static expr_t set_insn_init (expr_t, vinsn_t, int);
     143                 :            : 
     144                 :            : static void cfg_preds (basic_block, insn_t **, int *);
     145                 :            : static void prepare_insn_expr (insn_t, int);
     146                 :            : static void free_history_vect (vec<expr_history_def> &);
     147                 :            : 
     148                 :            : static void move_bb_info (basic_block, basic_block);
     149                 :            : static void remove_empty_bb (basic_block, bool);
     150                 :            : static void sel_merge_blocks (basic_block, basic_block);
     151                 :            : static void sel_remove_loop_preheader (void);
     152                 :            : static bool bb_has_removable_jump_to_p (basic_block, basic_block);
     153                 :            : 
     154                 :            : static bool insn_is_the_only_one_in_bb_p (insn_t);
     155                 :            : static void create_initial_data_sets (basic_block);
     156                 :            : 
     157                 :            : static void free_av_set (basic_block);
     158                 :            : static void invalidate_av_set (basic_block);
     159                 :            : static void extend_insn_data (void);
     160                 :            : static void sel_init_new_insn (insn_t, int, int = -1);
     161                 :            : static void finish_insns (void);
     162                 :            : 
     163                 :            : /* Various list functions.  */
     164                 :            : 
     165                 :            : /* Copy an instruction list L.  */
     166                 :            : ilist_t
     167                 :       4433 : ilist_copy (ilist_t l)
     168                 :            : {
     169                 :       4433 :   ilist_t head = NULL, *tailp = &head;
     170                 :            : 
     171                 :      17185 :   while (l)
     172                 :            :     {
     173                 :      12752 :       ilist_add (tailp, ILIST_INSN (l));
     174                 :      12752 :       tailp = &ILIST_NEXT (*tailp);
     175                 :      12752 :       l = ILIST_NEXT (l);
     176                 :            :     }
     177                 :            : 
     178                 :       4433 :   return head;
     179                 :            : }
     180                 :            : 
     181                 :            : /* Invert an instruction list L.  */
     182                 :            : ilist_t
     183                 :          0 : ilist_invert (ilist_t l)
     184                 :            : {
     185                 :          0 :   ilist_t res = NULL;
     186                 :            : 
     187                 :          0 :   while (l)
     188                 :            :     {
     189                 :          0 :       ilist_add (&res, ILIST_INSN (l));
     190                 :          0 :       l = ILIST_NEXT (l);
     191                 :            :     }
     192                 :            : 
     193                 :          0 :   return res;
     194                 :            : }
     195                 :            : 
     196                 :            : /* Add a new boundary to the LP list with parameters TO, PTR, and DC.  */
     197                 :            : void
     198                 :       6344 : blist_add (blist_t *lp, insn_t to, ilist_t ptr, deps_t dc)
     199                 :            : {
     200                 :       6344 :   bnd_t bnd;
     201                 :            : 
     202                 :       6344 :   _list_add (lp);
     203                 :       6344 :   bnd = BLIST_BND (*lp);
     204                 :            : 
     205                 :       6344 :   BND_TO (bnd) = to;
     206                 :       6344 :   BND_PTR (bnd) = ptr;
     207                 :       6344 :   BND_AV (bnd) = NULL;
     208                 :       6344 :   BND_AV1 (bnd) = NULL;
     209                 :       6344 :   BND_DC (bnd) = dc;
     210                 :       6344 : }
     211                 :            : 
     212                 :            : /* Remove the list note pointed to by LP.  */
     213                 :            : void
     214                 :       6344 : blist_remove (blist_t *lp)
     215                 :            : {
     216                 :       6344 :   bnd_t b = BLIST_BND (*lp);
     217                 :            : 
     218                 :       6344 :   av_set_clear (&BND_AV (b));
     219                 :       6344 :   av_set_clear (&BND_AV1 (b));
     220                 :       6344 :   ilist_clear (&BND_PTR (b));
     221                 :            : 
     222                 :       6344 :   _list_remove (lp);
     223                 :       6344 : }
     224                 :            : 
     225                 :            : /* Init a fence tail L.  */
     226                 :            : void
     227                 :       1719 : flist_tail_init (flist_tail_t l)
     228                 :            : {
     229                 :       1719 :   FLIST_TAIL_HEAD (l) = NULL;
     230                 :       1719 :   FLIST_TAIL_TAILP (l) = &FLIST_TAIL_HEAD (l);
     231                 :       1719 : }
     232                 :            : 
     233                 :            : /* Try to find fence corresponding to INSN in L.  */
     234                 :            : fence_t
     235                 :      73719 : flist_lookup (flist_t l, insn_t insn)
     236                 :            : {
     237                 :     173823 :   while (l)
     238                 :            :     {
     239                 :     100119 :       if (FENCE_INSN (FLIST_FENCE (l)) == insn)
     240                 :         15 :         return FLIST_FENCE (l);
     241                 :            : 
     242                 :     100104 :       l = FLIST_NEXT (l);
     243                 :            :     }
     244                 :            : 
     245                 :            :   return NULL;
     246                 :            : }
     247                 :            : 
     248                 :            : /* Init the fields of F before running fill_insns.  */
     249                 :            : static void
     250                 :       1911 : init_fence_for_scheduling (fence_t f)
     251                 :            : {
     252                 :       1911 :   FENCE_BNDS (f) = NULL;
     253                 :       1911 :   FENCE_PROCESSED_P (f) = false;
     254                 :       1911 :   FENCE_SCHEDULED_P (f) = false;
     255                 :        839 : }
     256                 :            : 
     257                 :            : /* Add new fence consisting of INSN and STATE to the list pointed to by LP.  */
     258                 :            : static void
     259                 :       1072 : flist_add (flist_t *lp, insn_t insn, state_t state, deps_t dc, void *tc,
     260                 :            :            insn_t last_scheduled_insn, vec<rtx_insn *, va_gc> *executing_insns,
     261                 :            :            int *ready_ticks, int ready_ticks_size, insn_t sched_next,
     262                 :            :            int cycle, int cycle_issued_insns, int issue_more,
     263                 :            :            bool starts_cycle_p, bool after_stall_p)
     264                 :            : {
     265                 :       1072 :   fence_t f;
     266                 :            : 
     267                 :       1072 :   _list_add (lp);
     268                 :       1072 :   f = FLIST_FENCE (*lp);
     269                 :            : 
     270                 :       1072 :   FENCE_INSN (f) = insn;
     271                 :            : 
     272                 :       1072 :   gcc_assert (state != NULL);
     273                 :       1072 :   FENCE_STATE (f) = state;
     274                 :            : 
     275                 :       1072 :   FENCE_CYCLE (f) = cycle;
     276                 :       1072 :   FENCE_ISSUED_INSNS (f) = cycle_issued_insns;
     277                 :       1072 :   FENCE_STARTS_CYCLE_P (f) = starts_cycle_p;
     278                 :       1072 :   FENCE_AFTER_STALL_P (f) = after_stall_p;
     279                 :            : 
     280                 :       1072 :   gcc_assert (dc != NULL);
     281                 :       1072 :   FENCE_DC (f) = dc;
     282                 :            : 
     283                 :       1072 :   gcc_assert (tc != NULL || targetm.sched.alloc_sched_context == NULL);
     284                 :       1072 :   FENCE_TC (f) = tc;
     285                 :            : 
     286                 :       1072 :   FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn;
     287                 :       1072 :   FENCE_ISSUE_MORE (f) = issue_more;
     288                 :       1072 :   FENCE_EXECUTING_INSNS (f) = executing_insns;
     289                 :       1072 :   FENCE_READY_TICKS (f) = ready_ticks;
     290                 :       1072 :   FENCE_READY_TICKS_SIZE (f) = ready_ticks_size;
     291                 :       1072 :   FENCE_SCHED_NEXT (f) = sched_next;
     292                 :            : 
     293                 :       1072 :   init_fence_for_scheduling (f);
     294                 :       1072 : }
     295                 :            : 
     296                 :            : /* Remove the head node of the list pointed to by LP.  */
     297                 :            : static void
     298                 :       1911 : flist_remove (flist_t *lp)
     299                 :            : {
     300                 :       1911 :   if (FENCE_INSN (FLIST_FENCE (*lp)))
     301                 :       1071 :     fence_clear (FLIST_FENCE (*lp));
     302                 :       1911 :   _list_remove (lp);
     303                 :       1911 : }
     304                 :            : 
     305                 :            : /* Clear the fence list pointed to by LP.  */
     306                 :            : void
     307                 :       1694 : flist_clear (flist_t *lp)
     308                 :            : {
     309                 :       3605 :   while (*lp)
     310                 :       1911 :     flist_remove (lp);
     311                 :       1694 : }
     312                 :            : 
     313                 :            : /* Add ORIGINAL_INSN the def list DL honoring CROSSED_CALL_ABIS.  */
     314                 :            : void
     315                 :       4662 : def_list_add (def_list_t *dl, insn_t original_insn,
     316                 :            :               unsigned int crossed_call_abis)
     317                 :            : {
     318                 :       4662 :   def_t d;
     319                 :            : 
     320                 :       4662 :   _list_add (dl);
     321                 :       4662 :   d = DEF_LIST_DEF (*dl);
     322                 :            : 
     323                 :       4662 :   d->orig_insn = original_insn;
     324                 :       4662 :   d->crossed_call_abis = crossed_call_abis;
     325                 :       4662 : }
     326                 :            : 
     327                 :            : 
     328                 :            : /* Functions to work with target contexts.  */
     329                 :            : 
     330                 :            : /* Bulk target context.  It is convenient for debugging purposes to ensure
     331                 :            :    that there are no uninitialized (null) target contexts.  */
     332                 :            : static tc_t bulk_tc = (tc_t) 1;
     333                 :            : 
     334                 :            : /* Target hooks wrappers.  In the future we can provide some default
     335                 :            :    implementations for them.  */
     336                 :            : 
     337                 :            : /* Allocate a store for the target context.  */
     338                 :            : static tc_t
     339                 :       1276 : alloc_target_context (void)
     340                 :            : {
     341                 :       1276 :   return (targetm.sched.alloc_sched_context
     342                 :       1276 :           ? targetm.sched.alloc_sched_context () : bulk_tc);
     343                 :            : }
     344                 :            : 
     345                 :            : /* Init target context TC.
     346                 :            :    If CLEAN_P is true, then make TC as it is beginning of the scheduler.
     347                 :            :    Overwise, copy current backend context to TC.  */
     348                 :            : static void
     349                 :       3193 : init_target_context (tc_t tc, bool clean_p)
     350                 :            : {
     351                 :          0 :   if (targetm.sched.init_sched_context)
     352                 :          0 :     targetm.sched.init_sched_context (tc, clean_p);
     353                 :          0 : }
     354                 :            : 
     355                 :            : /* Allocate and initialize a target context.  Meaning of CLEAN_P is the same as
     356                 :            :    int init_target_context ().  */
     357                 :            : tc_t
     358                 :       1078 : create_target_context (bool clean_p)
     359                 :            : {
     360                 :       1078 :   tc_t tc = alloc_target_context ();
     361                 :            : 
     362                 :       1078 :   init_target_context (tc, clean_p);
     363                 :       1078 :   return tc;
     364                 :            : }
     365                 :            : 
     366                 :            : /* Copy TC to the current backend context.  */
     367                 :            : void
     368                 :       2307 : set_target_context (tc_t tc)
     369                 :            : {
     370                 :       2307 :   if (targetm.sched.set_sched_context)
     371                 :          0 :     targetm.sched.set_sched_context (tc);
     372                 :       2307 : }
     373                 :            : 
     374                 :            : /* TC is about to be destroyed.  Free any internal data.  */
     375                 :            : static void
     376                 :       3193 : clear_target_context (tc_t tc)
     377                 :            : {
     378                 :          0 :   if (targetm.sched.clear_sched_context)
     379                 :          0 :     targetm.sched.clear_sched_context (tc);
     380                 :          0 : }
     381                 :            : 
     382                 :            : /*  Clear and free it.  */
     383                 :            : static void
     384                 :       1276 : delete_target_context (tc_t tc)
     385                 :            : {
     386                 :          0 :   clear_target_context (tc);
     387                 :            : 
     388                 :       1276 :   if (targetm.sched.free_sched_context)
     389                 :          0 :     targetm.sched.free_sched_context (tc);
     390                 :          0 : }
     391                 :            : 
     392                 :            : /* Make a copy of FROM in TO.
     393                 :            :    NB: May be this should be a hook.  */
     394                 :            : static void
     395                 :        198 : copy_target_context (tc_t to, tc_t from)
     396                 :            : {
     397                 :        198 :   tc_t tmp = create_target_context (false);
     398                 :            : 
     399                 :        198 :   set_target_context (from);
     400                 :        198 :   init_target_context (to, false);
     401                 :            : 
     402                 :        198 :   set_target_context (tmp);
     403                 :        198 :   delete_target_context (tmp);
     404                 :        198 : }
     405                 :            : 
     406                 :            : /* Create a copy of TC.  */
     407                 :            : static tc_t
     408                 :        198 : create_copy_of_target_context (tc_t tc)
     409                 :            : {
     410                 :        198 :   tc_t copy = alloc_target_context ();
     411                 :            : 
     412                 :        198 :   copy_target_context (copy, tc);
     413                 :            : 
     414                 :        198 :   return copy;
     415                 :            : }
     416                 :            : 
     417                 :            : /* Clear TC and initialize it according to CLEAN_P.  The meaning of CLEAN_P
     418                 :            :    is the same as in init_target_context ().  */
     419                 :            : void
     420                 :       1917 : reset_target_context (tc_t tc, bool clean_p)
     421                 :            : {
     422                 :       1917 :   clear_target_context (tc);
     423                 :       1917 :   init_target_context (tc, clean_p);
     424                 :       1917 : }
     425                 :            : 
     426                 :            : /* Functions to work with dependence contexts.
     427                 :            :    Dc (aka deps context, aka deps_t, aka class deps_desc *) is short for dependence
     428                 :            :    context.  It accumulates information about processed insns to decide if
     429                 :            :    current insn is dependent on the processed ones.  */
     430                 :            : 
     431                 :            : /* Make a copy of FROM in TO.  */
     432                 :            : static void
     433                 :        198 : copy_deps_context (deps_t to, deps_t from)
     434                 :            : {
     435                 :          0 :   init_deps (to, false);
     436                 :        198 :   deps_join (to, from);
     437                 :          0 : }
     438                 :            : 
     439                 :            : /* Allocate store for dep context.  */
     440                 :            : static deps_t
     441                 :       1078 : alloc_deps_context (void)
     442                 :            : {
     443                 :          0 :   return XNEW (class deps_desc);
     444                 :            : }
     445                 :            : 
     446                 :            : /* Allocate and initialize dep context.  */
     447                 :            : static deps_t
     448                 :        880 : create_deps_context (void)
     449                 :            : {
     450                 :        880 :   deps_t dc = alloc_deps_context ();
     451                 :            : 
     452                 :        880 :   init_deps (dc, false);
     453                 :        880 :   return dc;
     454                 :            : }
     455                 :            : 
     456                 :            : /* Create a copy of FROM.  */
     457                 :            : static deps_t
     458                 :        198 : create_copy_of_deps_context (deps_t from)
     459                 :            : {
     460                 :        198 :   deps_t to = alloc_deps_context ();
     461                 :            : 
     462                 :        198 :   copy_deps_context (to, from);
     463                 :        198 :   return to;
     464                 :            : }
     465                 :            : 
     466                 :            : /* Clean up internal data of DC.  */
     467                 :            : static void
     468                 :       1085 : clear_deps_context (deps_t dc)
     469                 :            : {
     470                 :          0 :   free_deps (dc);
     471                 :          0 : }
     472                 :            : 
     473                 :            : /* Clear and free DC.  */
     474                 :            : static void
     475                 :       1078 : delete_deps_context (deps_t dc)
     476                 :            : {
     477                 :          0 :   clear_deps_context (dc);
     478                 :       1078 :   free (dc);
     479                 :       1071 : }
     480                 :            : 
     481                 :            : /* Clear and init DC.  */
     482                 :            : static void
     483                 :          7 : reset_deps_context (deps_t dc)
     484                 :            : {
     485                 :          0 :   clear_deps_context (dc);
     486                 :          7 :   init_deps (dc, false);
     487                 :          0 : }
     488                 :            : 
     489                 :            : /* This structure describes the dependence analysis hooks for advancing
     490                 :            :    dependence context.  */
     491                 :            : static struct sched_deps_info_def advance_deps_context_sched_deps_info =
     492                 :            :   {
     493                 :            :     NULL,
     494                 :            : 
     495                 :            :     NULL, /* start_insn */
     496                 :            :     NULL, /* finish_insn */
     497                 :            :     NULL, /* start_lhs */
     498                 :            :     NULL, /* finish_lhs */
     499                 :            :     NULL, /* start_rhs */
     500                 :            :     NULL, /* finish_rhs */
     501                 :            :     haifa_note_reg_set,
     502                 :            :     haifa_note_reg_clobber,
     503                 :            :     haifa_note_reg_use,
     504                 :            :     NULL, /* note_mem_dep */
     505                 :            :     NULL, /* note_dep */
     506                 :            : 
     507                 :            :     0, 0, 0
     508                 :            :   };
     509                 :            : 
     510                 :            : /* Process INSN and add its impact on DC.  */
     511                 :            : void
     512                 :       8564 : advance_deps_context (deps_t dc, insn_t insn)
     513                 :            : {
     514                 :       8564 :   sched_deps_info = &advance_deps_context_sched_deps_info;
     515                 :       8564 :   deps_analyze_insn (dc, insn);
     516                 :       8564 : }
     517                 :            : 
     518                 :            : 
     519                 :            : /* Functions to work with DFA states.  */
     520                 :            : 
     521                 :            : /* Allocate store for a DFA state.  */
     522                 :            : static state_t
     523                 :       1078 : state_alloc (void)
     524                 :            : {
     525                 :          0 :   return xmalloc (dfa_state_size);
     526                 :            : }
     527                 :            : 
     528                 :            : /* Allocate and initialize DFA state.  */
     529                 :            : static state_t
     530                 :        880 : state_create (void)
     531                 :            : {
     532                 :        880 :   state_t state = state_alloc ();
     533                 :            : 
     534                 :        880 :   state_reset (state);
     535                 :        880 :   advance_state (state);
     536                 :        880 :   return state;
     537                 :            : }
     538                 :            : 
     539                 :            : /* Free DFA state.  */
     540                 :            : static void
     541                 :          7 : state_free (state_t state)
     542                 :            : {
     543                 :          7 :   free (state);
     544                 :          0 : }
     545                 :            : 
     546                 :            : /* Make a copy of FROM in TO.  */
     547                 :            : static void
     548                 :        198 : state_copy (state_t to, state_t from)
     549                 :            : {
     550                 :        198 :   memcpy (to, from, dfa_state_size);
     551                 :          0 : }
     552                 :            : 
     553                 :            : /* Create a copy of FROM.  */
     554                 :            : static state_t
     555                 :        198 : state_create_copy (state_t from)
     556                 :            : {
     557                 :        198 :   state_t to = state_alloc ();
     558                 :            : 
     559                 :        198 :   state_copy (to, from);
     560                 :        198 :   return to;
     561                 :            : }
     562                 :            : 
     563                 :            : 
     564                 :            : /* Functions to work with fences.  */
     565                 :            : 
     566                 :            : /* Clear the fence.  */
     567                 :            : static void
     568                 :       1071 : fence_clear (fence_t f)
     569                 :            : {
     570                 :       1071 :   state_t s = FENCE_STATE (f);
     571                 :       1071 :   deps_t dc = FENCE_DC (f);
     572                 :       1071 :   void *tc = FENCE_TC (f);
     573                 :            : 
     574                 :       1071 :   ilist_clear (&FENCE_BNDS (f));
     575                 :            : 
     576                 :       1071 :   gcc_assert ((s != NULL && dc != NULL && tc != NULL)
     577                 :            :               || (s == NULL && dc == NULL && tc == NULL));
     578                 :            : 
     579                 :       1071 :   free (s);
     580                 :            : 
     581                 :       1071 :   if (dc != NULL)
     582                 :       1071 :     delete_deps_context (dc);
     583                 :            : 
     584                 :       1071 :   if (tc != NULL)
     585                 :       1071 :     delete_target_context (tc);
     586                 :       1071 :   vec_free (FENCE_EXECUTING_INSNS (f));
     587                 :       1071 :   free (FENCE_READY_TICKS (f));
     588                 :       1071 :   FENCE_READY_TICKS (f) = NULL;
     589                 :       1071 : }
     590                 :            : 
     591                 :            : /* Init a list of fences with successors of OLD_FENCE.  */
     592                 :            : void
     593                 :        755 : init_fences (insn_t old_fence)
     594                 :            : {
     595                 :        755 :   insn_t succ;
     596                 :        755 :   succ_iterator si;
     597                 :        755 :   bool first = true;
     598                 :        755 :   int ready_ticks_size = get_max_uid () + 1;
     599                 :            : 
     600                 :       1510 :   FOR_EACH_SUCC_1 (succ, si, old_fence,
     601                 :            :                    SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     602                 :            :     {
     603                 :            : 
     604                 :        755 :       if (first)
     605                 :            :         first = false;
     606                 :            :       else
     607                 :          0 :         gcc_assert (flag_sel_sched_pipelining_outer_loops);
     608                 :            : 
     609                 :       1510 :       flist_add (&fences, succ,
     610                 :            :                  state_create (),
     611                 :            :                  create_deps_context () /* dc */,
     612                 :            :                  create_target_context (true) /* tc */,
     613                 :            :                  NULL /* last_scheduled_insn */,
     614                 :            :                  NULL, /* executing_insns */
     615                 :        755 :                  XCNEWVEC (int, ready_ticks_size), /* ready_ticks */
     616                 :            :                  ready_ticks_size,
     617                 :            :                  NULL /* sched_next */,
     618                 :            :                  1 /* cycle */, 0 /* cycle_issued_insns */,
     619                 :            :                  issue_rate, /* issue_more */
     620                 :            :                  1 /* starts_cycle_p */, 0 /* after_stall_p */);
     621                 :            :     }
     622                 :        755 : }
     623                 :            : 
     624                 :            : /* Merges two fences (filling fields of fence F with resulting values) by
     625                 :            :    following rules: 1) state, target context and last scheduled insn are
     626                 :            :    propagated from fallthrough edge if it is available;
     627                 :            :    2) deps context and cycle is propagated from more probable edge;
     628                 :            :    3) all other fields are set to corresponding constant values.
     629                 :            : 
     630                 :            :    INSN, STATE, DC, TC, LAST_SCHEDULED_INSN, EXECUTING_INSNS,
     631                 :            :    READY_TICKS, READY_TICKS_SIZE, SCHED_NEXT, CYCLE, ISSUE_MORE
     632                 :            :    and AFTER_STALL_P are the corresponding fields of the second fence.  */
     633                 :            : static void
     634                 :          7 : merge_fences (fence_t f, insn_t insn,
     635                 :            :               state_t state, deps_t dc, void *tc,
     636                 :            :               rtx_insn *last_scheduled_insn,
     637                 :            :               vec<rtx_insn *, va_gc> *executing_insns,
     638                 :            :               int *ready_ticks, int ready_ticks_size,
     639                 :            :               rtx sched_next, int cycle, int issue_more, bool after_stall_p)
     640                 :            : {
     641                 :          7 :   insn_t last_scheduled_insn_old = FENCE_LAST_SCHEDULED_INSN (f);
     642                 :            : 
     643                 :          7 :   gcc_assert (sel_bb_head_p (FENCE_INSN (f))
     644                 :            :               && !sched_next && !FENCE_SCHED_NEXT (f));
     645                 :            : 
     646                 :            :   /* Check if we can decide which path fences came.
     647                 :            :      If we can't (or don't want to) - reset all.  */
     648                 :          7 :   if (last_scheduled_insn == NULL
     649                 :          7 :       || last_scheduled_insn_old == NULL
     650                 :            :       /* This is a case when INSN is reachable on several paths from
     651                 :            :          one insn (this can happen when pipelining of outer loops is on and
     652                 :            :          there are two edges: one going around of inner loop and the other -
     653                 :            :          right through it; in such case just reset everything).  */
     654                 :          1 :       || last_scheduled_insn == last_scheduled_insn_old)
     655                 :            :     {
     656                 :          6 :       state_reset (FENCE_STATE (f));
     657                 :          6 :       state_free (state);
     658                 :            : 
     659                 :          6 :       reset_deps_context (FENCE_DC (f));
     660                 :          6 :       delete_deps_context (dc);
     661                 :            : 
     662                 :          6 :       reset_target_context (FENCE_TC (f), true);
     663                 :          6 :       delete_target_context (tc);
     664                 :            : 
     665                 :          6 :       if (cycle > FENCE_CYCLE (f))
     666                 :          1 :         FENCE_CYCLE (f) = cycle;
     667                 :            : 
     668                 :          6 :       FENCE_LAST_SCHEDULED_INSN (f) = NULL;
     669                 :          6 :       FENCE_ISSUE_MORE (f) = issue_rate;
     670                 :          6 :       vec_free (executing_insns);
     671                 :          6 :       free (ready_ticks);
     672                 :          6 :       if (FENCE_EXECUTING_INSNS (f))
     673                 :          1 :         FENCE_EXECUTING_INSNS (f)->block_remove (0,
     674                 :            :                                           FENCE_EXECUTING_INSNS (f)->length ());
     675                 :          6 :       if (FENCE_READY_TICKS (f))
     676                 :          6 :         memset (FENCE_READY_TICKS (f), 0, FENCE_READY_TICKS_SIZE (f));
     677                 :            :     }
     678                 :            :   else
     679                 :            :     {
     680                 :          1 :       edge edge_old = NULL, edge_new = NULL;
     681                 :          1 :       edge candidate;
     682                 :          1 :       succ_iterator si;
     683                 :          1 :       insn_t succ;
     684                 :            : 
     685                 :            :       /* Find fallthrough edge.  */
     686                 :          1 :       gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
     687                 :          1 :       candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
     688                 :            : 
     689                 :          1 :       if (!candidate
     690                 :          1 :           || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn)
     691                 :          0 :               && candidate->src != BLOCK_FOR_INSN (last_scheduled_insn_old)))
     692                 :            :         {
     693                 :            :           /* No fallthrough edge leading to basic block of INSN.  */
     694                 :          0 :           state_reset (FENCE_STATE (f));
     695                 :          0 :           state_free (state);
     696                 :            : 
     697                 :          0 :           reset_target_context (FENCE_TC (f), true);
     698                 :          0 :           delete_target_context (tc);
     699                 :            : 
     700                 :          0 :           FENCE_LAST_SCHEDULED_INSN (f) = NULL;
     701                 :          0 :           FENCE_ISSUE_MORE (f) = issue_rate;
     702                 :            :         }
     703                 :            :       else
     704                 :          1 :         if (candidate->src == BLOCK_FOR_INSN (last_scheduled_insn))
     705                 :            :           {
     706                 :          1 :             state_free (FENCE_STATE (f));
     707                 :          1 :             FENCE_STATE (f) = state;
     708                 :            : 
     709                 :          1 :             delete_target_context (FENCE_TC (f));
     710                 :          1 :             FENCE_TC (f) = tc;
     711                 :            : 
     712                 :          1 :             FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn;
     713                 :          1 :             FENCE_ISSUE_MORE (f) = issue_more;
     714                 :            :           }
     715                 :            :         else
     716                 :            :           {
     717                 :            :             /* Leave STATE, TC and LAST_SCHEDULED_INSN fields untouched.  */
     718                 :          0 :             state_free (state);
     719                 :          0 :             delete_target_context (tc);
     720                 :            : 
     721                 :          0 :             gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb
     722                 :            :                         != BLOCK_FOR_INSN (last_scheduled_insn));
     723                 :            :           }
     724                 :            : 
     725                 :            :         /* Find edge of first predecessor (last_scheduled_insn_old->insn).  */
     726                 :          2 :         FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn_old,
     727                 :            :                          SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     728                 :            :           {
     729                 :          1 :             if (succ == insn)
     730                 :            :               {
     731                 :            :                 /* No same successor allowed from several edges.  */
     732                 :          1 :                 gcc_assert (!edge_old);
     733                 :          1 :                 edge_old = si.e1;
     734                 :            :               }
     735                 :            :           }
     736                 :            :         /* Find edge of second predecessor (last_scheduled_insn->insn).  */
     737                 :          2 :         FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn,
     738                 :            :                          SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     739                 :            :           {
     740                 :          1 :             if (succ == insn)
     741                 :            :               {
     742                 :            :                 /* No same successor allowed from several edges.  */
     743                 :          0 :                 gcc_assert (!edge_new);
     744                 :          0 :                 edge_new = si.e1;
     745                 :            :               }
     746                 :            :           }
     747                 :            : 
     748                 :            :         /* Check if we can choose most probable predecessor.  */
     749                 :          1 :         if (edge_old == NULL || edge_new == NULL)
     750                 :            :           {
     751                 :          1 :             reset_deps_context (FENCE_DC (f));
     752                 :          1 :             delete_deps_context (dc);
     753                 :          1 :             vec_free (executing_insns);
     754                 :          1 :             free (ready_ticks);
     755                 :            : 
     756                 :          1 :             FENCE_CYCLE (f) = MAX (FENCE_CYCLE (f), cycle);
     757                 :          1 :             if (FENCE_EXECUTING_INSNS (f))
     758                 :          1 :               FENCE_EXECUTING_INSNS (f)->block_remove (0,
     759                 :            :                                 FENCE_EXECUTING_INSNS (f)->length ());
     760                 :          1 :             if (FENCE_READY_TICKS (f))
     761                 :          1 :               memset (FENCE_READY_TICKS (f), 0, FENCE_READY_TICKS_SIZE (f));
     762                 :            :           }
     763                 :            :         else
     764                 :          0 :           if (edge_new->probability > edge_old->probability)
     765                 :            :             {
     766                 :          0 :               delete_deps_context (FENCE_DC (f));
     767                 :          0 :               FENCE_DC (f) = dc;
     768                 :          0 :               vec_free (FENCE_EXECUTING_INSNS (f));
     769                 :          0 :               FENCE_EXECUTING_INSNS (f) = executing_insns;
     770                 :          0 :               free (FENCE_READY_TICKS (f));
     771                 :          0 :               FENCE_READY_TICKS (f) = ready_ticks;
     772                 :          0 :               FENCE_READY_TICKS_SIZE (f) = ready_ticks_size;
     773                 :          0 :               FENCE_CYCLE (f) = cycle;
     774                 :            :             }
     775                 :            :           else
     776                 :            :             {
     777                 :            :               /* Leave DC and CYCLE untouched.  */
     778                 :          0 :               delete_deps_context (dc);
     779                 :          0 :               vec_free (executing_insns);
     780                 :          0 :               free (ready_ticks);
     781                 :            :             }
     782                 :            :     }
     783                 :            : 
     784                 :            :   /* Fill remaining invariant fields.  */
     785                 :          7 :   if (after_stall_p)
     786                 :          1 :     FENCE_AFTER_STALL_P (f) = 1;
     787                 :            : 
     788                 :          7 :   FENCE_ISSUED_INSNS (f) = 0;
     789                 :          7 :   FENCE_STARTS_CYCLE_P (f) = 1;
     790                 :          7 :   FENCE_SCHED_NEXT (f) = NULL;
     791                 :          7 : }
     792                 :            : 
     793                 :            : /* Add a new fence to NEW_FENCES list, initializing it from all
     794                 :            :    other parameters.  */
     795                 :            : static void
     796                 :        323 : add_to_fences (flist_tail_t new_fences, insn_t insn,
     797                 :            :                state_t state, deps_t dc, void *tc,
     798                 :            :                rtx_insn *last_scheduled_insn,
     799                 :            :                vec<rtx_insn *, va_gc> *executing_insns, int *ready_ticks,
     800                 :            :                int ready_ticks_size, rtx_insn *sched_next, int cycle,
     801                 :            :                int cycle_issued_insns, int issue_rate,
     802                 :            :                bool starts_cycle_p, bool after_stall_p)
     803                 :            : {
     804                 :        323 :   fence_t f = flist_lookup (FLIST_TAIL_HEAD (new_fences), insn);
     805                 :            : 
     806                 :        323 :   if (! f)
     807                 :            :     {
     808                 :        317 :       flist_add (FLIST_TAIL_TAILP (new_fences), insn, state, dc, tc,
     809                 :            :                  last_scheduled_insn, executing_insns, ready_ticks,
     810                 :            :                  ready_ticks_size, sched_next, cycle, cycle_issued_insns,
     811                 :            :                  issue_rate, starts_cycle_p, after_stall_p);
     812                 :            : 
     813                 :        317 :       FLIST_TAIL_TAILP (new_fences)
     814                 :        317 :         = &FLIST_NEXT (*FLIST_TAIL_TAILP (new_fences));
     815                 :            :     }
     816                 :            :   else
     817                 :            :     {
     818                 :          6 :       merge_fences (f, insn, state, dc, tc, last_scheduled_insn,
     819                 :            :                     executing_insns, ready_ticks, ready_ticks_size,
     820                 :            :                     sched_next, cycle, issue_rate, after_stall_p);
     821                 :            :     }
     822                 :        323 : }
     823                 :            : 
     824                 :            : /* Move the first fence in the OLD_FENCES list to NEW_FENCES.  */
     825                 :            : void
     826                 :        840 : move_fence_to_fences (flist_t old_fences, flist_tail_t new_fences)
     827                 :            : {
     828                 :        840 :   fence_t f, old;
     829                 :        840 :   flist_t *tailp = FLIST_TAIL_TAILP (new_fences);
     830                 :            : 
     831                 :        840 :   old = FLIST_FENCE (old_fences);
     832                 :        840 :   f = flist_lookup (FLIST_TAIL_HEAD (new_fences),
     833                 :            :                     FENCE_INSN (FLIST_FENCE (old_fences)));
     834                 :        840 :   if (f)
     835                 :            :     {
     836                 :          1 :       merge_fences (f, old->insn, old->state, old->dc, old->tc,
     837                 :            :                     old->last_scheduled_insn, old->executing_insns,
     838                 :            :                     old->ready_ticks, old->ready_ticks_size,
     839                 :          1 :                     old->sched_next, old->cycle, old->issue_more,
     840                 :          1 :                     old->after_stall_p);
     841                 :            :     }
     842                 :            :   else
     843                 :            :     {
     844                 :        839 :       _list_add (tailp);
     845                 :        839 :       FLIST_TAIL_TAILP (new_fences) = &FLIST_NEXT (*tailp);
     846                 :        839 :       *FLIST_FENCE (*tailp) = *old;
     847                 :        839 :       init_fence_for_scheduling (FLIST_FENCE (*tailp));
     848                 :            :     }
     849                 :        840 :   FENCE_INSN (old) = NULL;
     850                 :        840 : }
     851                 :            : 
     852                 :            : /* Add a new fence to NEW_FENCES list and initialize most of its data
     853                 :            :    as a clean one.  */
     854                 :            : void
     855                 :        125 : add_clean_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence)
     856                 :            : {
     857                 :        125 :   int ready_ticks_size = get_max_uid () + 1;
     858                 :            : 
     859                 :        250 :   add_to_fences (new_fences,
     860                 :            :                  succ, state_create (), create_deps_context (),
     861                 :            :                  create_target_context (true),
     862                 :            :                  NULL, NULL,
     863                 :        125 :                  XCNEWVEC (int, ready_ticks_size), ready_ticks_size,
     864                 :        125 :                  NULL, FENCE_CYCLE (fence) + 1,
     865                 :        125 :                  0, issue_rate, 1, FENCE_AFTER_STALL_P (fence));
     866                 :        125 : }
     867                 :            : 
     868                 :            : /* Add a new fence to NEW_FENCES list and initialize all of its data
     869                 :            :    from FENCE and SUCC.  */
     870                 :            : void
     871                 :        198 : add_dirty_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence)
     872                 :            : {
     873                 :        198 :   int * new_ready_ticks
     874                 :        198 :     = XNEWVEC (int, FENCE_READY_TICKS_SIZE (fence));
     875                 :            : 
     876                 :        198 :   memcpy (new_ready_ticks, FENCE_READY_TICKS (fence),
     877                 :        198 :           FENCE_READY_TICKS_SIZE (fence) * sizeof (int));
     878                 :        198 :   add_to_fences (new_fences,
     879                 :            :                  succ, state_create_copy (FENCE_STATE (fence)),
     880                 :            :                  create_copy_of_deps_context (FENCE_DC (fence)),
     881                 :            :                  create_copy_of_target_context (FENCE_TC (fence)),
     882                 :            :                  FENCE_LAST_SCHEDULED_INSN (fence),
     883                 :            :                  vec_safe_copy (FENCE_EXECUTING_INSNS (fence)),
     884                 :            :                  new_ready_ticks,
     885                 :            :                  FENCE_READY_TICKS_SIZE (fence),
     886                 :            :                  FENCE_SCHED_NEXT (fence),
     887                 :            :                  FENCE_CYCLE (fence),
     888                 :            :                  FENCE_ISSUED_INSNS (fence),
     889                 :            :                  FENCE_ISSUE_MORE (fence),
     890                 :            :                  FENCE_STARTS_CYCLE_P (fence),
     891                 :        198 :                  FENCE_AFTER_STALL_P (fence));
     892                 :        198 : }
     893                 :            : 
     894                 :            : 
     895                 :            : /* Functions to work with regset and nop pools.  */
     896                 :            : 
     897                 :            : /* Returns the new regset from pool.  It might have some of the bits set
     898                 :            :    from the previous usage.  */
     899                 :            : regset
     900                 :      56880 : get_regset_from_pool (void)
     901                 :            : {
     902                 :      56880 :   regset rs;
     903                 :            : 
     904                 :      56880 :   if (regset_pool.n != 0)
     905                 :      45354 :     rs = regset_pool.v[--regset_pool.n];
     906                 :            :   else
     907                 :            :     /* We need to create the regset.  */
     908                 :            :     {
     909                 :      11526 :       rs = ALLOC_REG_SET (&reg_obstack);
     910                 :            : 
     911                 :      11526 :       if (regset_pool.nn == regset_pool.ss)
     912                 :        777 :         regset_pool.vv = XRESIZEVEC (regset, regset_pool.vv,
     913                 :            :                                      (regset_pool.ss = 2 * regset_pool.ss + 1));
     914                 :      11526 :       regset_pool.vv[regset_pool.nn++] = rs;
     915                 :            :     }
     916                 :            : 
     917                 :      56880 :   regset_pool.diff++;
     918                 :            : 
     919                 :      56880 :   return rs;
     920                 :            : }
     921                 :            : 
     922                 :            : /* Same as above, but returns the empty regset.  */
     923                 :            : regset
     924                 :      30066 : get_clear_regset_from_pool (void)
     925                 :            : {
     926                 :      30066 :   regset rs = get_regset_from_pool ();
     927                 :            : 
     928                 :      30066 :   CLEAR_REG_SET (rs);
     929                 :      30066 :   return rs;
     930                 :            : }
     931                 :            : 
     932                 :            : /* Return regset RS to the pool for future use.  */
     933                 :            : void
     934                 :      56880 : return_regset_to_pool (regset rs)
     935                 :            : {
     936                 :      56880 :   gcc_assert (rs);
     937                 :      56880 :   regset_pool.diff--;
     938                 :            : 
     939                 :      56880 :   if (regset_pool.n == regset_pool.s)
     940                 :        777 :     regset_pool.v = XRESIZEVEC (regset, regset_pool.v,
     941                 :            :                                 (regset_pool.s = 2 * regset_pool.s + 1));
     942                 :      56880 :   regset_pool.v[regset_pool.n++] = rs;
     943                 :      56880 : }
     944                 :            : 
     945                 :            : /* This is used as a qsort callback for sorting regset pool stacks.
     946                 :            :    X and XX are addresses of two regsets.  They are never equal.  */
     947                 :            : static int
     948                 :     859393 : cmp_v_in_regset_pool (const void *x, const void *xx)
     949                 :            : {
     950                 :     859393 :   uintptr_t r1 = (uintptr_t) *((const regset *) x);
     951                 :     859393 :   uintptr_t r2 = (uintptr_t) *((const regset *) xx);
     952                 :     859393 :   if (r1 > r2)
     953                 :            :     return 1;
     954                 :     433193 :   else if (r1 < r2)
     955                 :            :     return -1;
     956                 :          0 :   gcc_unreachable ();
     957                 :            : }
     958                 :            : 
     959                 :            : /* Free the regset pool possibly checking for memory leaks.  */
     960                 :            : void
     961                 :        128 : free_regset_pool (void)
     962                 :            : {
     963                 :        128 :   if (flag_checking)
     964                 :            :     {
     965                 :        128 :       regset *v = regset_pool.v;
     966                 :        128 :       int i = 0;
     967                 :        128 :       int n = regset_pool.n;
     968                 :            : 
     969                 :        128 :       regset *vv = regset_pool.vv;
     970                 :        128 :       int ii = 0;
     971                 :        128 :       int nn = regset_pool.nn;
     972                 :            : 
     973                 :        128 :       int diff = 0;
     974                 :            : 
     975                 :        128 :       gcc_assert (n <= nn);
     976                 :            : 
     977                 :            :       /* Sort both vectors so it will be possible to compare them.  */
     978                 :        128 :       qsort (v, n, sizeof (*v), cmp_v_in_regset_pool);
     979                 :        128 :       qsort (vv, nn, sizeof (*vv), cmp_v_in_regset_pool);
     980                 :            : 
     981                 :      11654 :       while (ii < nn)
     982                 :            :         {
     983                 :      11526 :           if (v[i] == vv[ii])
     984                 :      11526 :             i++;
     985                 :            :           else
     986                 :            :             /* VV[II] was lost.  */
     987                 :          0 :             diff++;
     988                 :            : 
     989                 :      11526 :           ii++;
     990                 :            :         }
     991                 :            : 
     992                 :        128 :       gcc_assert (diff == regset_pool.diff);
     993                 :            :     }
     994                 :            : 
     995                 :            :   /* If not true - we have a memory leak.  */
     996                 :        128 :   gcc_assert (regset_pool.diff == 0);
     997                 :            : 
     998                 :      11654 :   while (regset_pool.n)
     999                 :            :     {
    1000                 :      11526 :       --regset_pool.n;
    1001                 :      11526 :       FREE_REG_SET (regset_pool.v[regset_pool.n]);
    1002                 :            :     }
    1003                 :            : 
    1004                 :        128 :   free (regset_pool.v);
    1005                 :        128 :   regset_pool.v = NULL;
    1006                 :        128 :   regset_pool.s = 0;
    1007                 :            : 
    1008                 :        128 :   free (regset_pool.vv);
    1009                 :        128 :   regset_pool.vv = NULL;
    1010                 :        128 :   regset_pool.nn = 0;
    1011                 :        128 :   regset_pool.ss = 0;
    1012                 :            : 
    1013                 :        128 :   regset_pool.diff = 0;
    1014                 :        128 : }
    1015                 :            : 
    1016                 :            : 
    1017                 :            : /* Functions to work with nop pools.  NOP insns are used as temporary
    1018                 :            :    placeholders of the insns being scheduled to allow correct update of
    1019                 :            :    the data sets.  When update is finished, NOPs are deleted.  */
    1020                 :            : 
    1021                 :            : /* A vinsn that is used to represent a nop.  This vinsn is shared among all
    1022                 :            :    nops sel-sched generates.  */
    1023                 :            : static vinsn_t nop_vinsn = NULL;
    1024                 :            : 
    1025                 :            : /* Emit a nop before INSN, taking it from pool.  */
    1026                 :            : insn_t
    1027                 :       2196 : get_nop_from_pool (insn_t insn)
    1028                 :            : {
    1029                 :       2196 :   rtx nop_pat;
    1030                 :       2196 :   insn_t nop;
    1031                 :       2196 :   bool old_p = nop_pool.n != 0;
    1032                 :       2196 :   int flags;
    1033                 :            : 
    1034                 :       2196 :   if (old_p)
    1035                 :       1353 :     nop_pat = nop_pool.v[--nop_pool.n];
    1036                 :            :   else
    1037                 :        843 :     nop_pat = nop_pattern;
    1038                 :            : 
    1039                 :       2196 :   nop = emit_insn_before (nop_pat, insn);
    1040                 :            : 
    1041                 :       2196 :   if (old_p)
    1042                 :            :     flags = INSN_INIT_TODO_SSID;
    1043                 :            :   else
    1044                 :        843 :     flags = INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID;
    1045                 :            : 
    1046                 :       2196 :   set_insn_init (INSN_EXPR (insn), nop_vinsn, INSN_SEQNO (insn));
    1047                 :       2196 :   sel_init_new_insn (nop, flags);
    1048                 :            : 
    1049                 :       2196 :   return nop;
    1050                 :            : }
    1051                 :            : 
    1052                 :            : /* Remove NOP from the instruction stream and return it to the pool.  */
    1053                 :            : void
    1054                 :       2196 : return_nop_to_pool (insn_t nop, bool full_tidying)
    1055                 :            : {
    1056                 :       2196 :   gcc_assert (INSN_IN_STREAM_P (nop));
    1057                 :       2196 :   sel_remove_insn (nop, false, full_tidying);
    1058                 :            : 
    1059                 :            :   /* We'll recycle this nop.  */
    1060                 :       2196 :   nop->set_undeleted ();
    1061                 :            : 
    1062                 :       2196 :   if (nop_pool.n == nop_pool.s)
    1063                 :        839 :     nop_pool.v = XRESIZEVEC (rtx_insn *, nop_pool.v,
    1064                 :            :                              (nop_pool.s = 2 * nop_pool.s + 1));
    1065                 :       2196 :   nop_pool.v[nop_pool.n++] = nop;
    1066                 :       2196 : }
    1067                 :            : 
    1068                 :            : /* Free the nop pool.  */
    1069                 :            : void
    1070                 :        730 : free_nop_pool (void)
    1071                 :            : {
    1072                 :        730 :   nop_pool.n = 0;
    1073                 :        730 :   nop_pool.s = 0;
    1074                 :        730 :   free (nop_pool.v);
    1075                 :        730 :   nop_pool.v = NULL;
    1076                 :        730 : }
    1077                 :            : 
    1078                 :            : 
    1079                 :            : /* Skip unspec to support ia64 speculation. Called from rtx_equal_p_cb.
    1080                 :            :    The callback is given two rtxes XX and YY and writes the new rtxes
    1081                 :            :    to NX and NY in case some needs to be skipped.  */
    1082                 :            : static int
    1083                 :          0 : skip_unspecs_callback (const_rtx *xx, const_rtx *yy, rtx *nx, rtx* ny)
    1084                 :            : {
    1085                 :          0 :   const_rtx x = *xx;
    1086                 :          0 :   const_rtx y = *yy;
    1087                 :            : 
    1088                 :          0 :   if (GET_CODE (x) == UNSPEC
    1089                 :          0 :       && (targetm.sched.skip_rtx_p == NULL
    1090                 :          0 :           || targetm.sched.skip_rtx_p (x)))
    1091                 :            :     {
    1092                 :          0 :       *nx = XVECEXP (x, 0, 0);
    1093                 :          0 :       *ny = CONST_CAST_RTX (y);
    1094                 :          0 :       return 1;
    1095                 :            :     }
    1096                 :            : 
    1097                 :          0 :   if (GET_CODE (y) == UNSPEC
    1098                 :          0 :       && (targetm.sched.skip_rtx_p == NULL
    1099                 :          0 :           || targetm.sched.skip_rtx_p (y)))
    1100                 :            :     {
    1101                 :          0 :       *nx = CONST_CAST_RTX (x);
    1102                 :          0 :       *ny = XVECEXP (y, 0, 0);
    1103                 :          0 :       return 1;
    1104                 :            :     }
    1105                 :            : 
    1106                 :            :   return 0;
    1107                 :            : }
    1108                 :            : 
    1109                 :            : /* Callback, called from hash_rtx_cb.  Helps to hash UNSPEC rtx X in a correct way
    1110                 :            :    to support ia64 speculation.  When changes are needed, new rtx X and new mode
    1111                 :            :    NMODE are written, and the callback returns true.  */
    1112                 :            : static int
    1113                 :          0 : hash_with_unspec_callback (const_rtx x, machine_mode mode ATTRIBUTE_UNUSED,
    1114                 :            :                            rtx *nx, machine_mode* nmode)
    1115                 :            : {
    1116                 :          0 :   if (GET_CODE (x) == UNSPEC
    1117                 :          0 :       && targetm.sched.skip_rtx_p
    1118                 :          0 :       && targetm.sched.skip_rtx_p (x))
    1119                 :            :     {
    1120                 :          0 :       *nx = XVECEXP (x, 0 ,0);
    1121                 :          0 :       *nmode = VOIDmode;
    1122                 :          0 :       return 1;
    1123                 :            :     }
    1124                 :            : 
    1125                 :            :   return 0;
    1126                 :            : }
    1127                 :            : 
    1128                 :            : /* Returns LHS and RHS are ok to be scheduled separately.  */
    1129                 :            : static bool
    1130                 :       2849 : lhs_and_rhs_separable_p (rtx lhs, rtx rhs)
    1131                 :            : {
    1132                 :       2119 :   if (lhs == NULL || rhs == NULL)
    1133                 :            :     return false;
    1134                 :            : 
    1135                 :            :   /* Do not schedule constants as rhs: no point to use reg, if const
    1136                 :            :      can be used.  Moreover, scheduling const as rhs may lead to mode
    1137                 :            :      mismatch cause consts don't have modes but they could be merged
    1138                 :            :      from branches where the same const used in different modes.  */
    1139                 :       2849 :   if (CONSTANT_P (rhs))
    1140                 :            :     return false;
    1141                 :            : 
    1142                 :            :   /* ??? Do not rename predicate registers to avoid ICEs in bundling.  */
    1143                 :       2444 :   if (COMPARISON_P (rhs))
    1144                 :            :       return false;
    1145                 :            : 
    1146                 :            :   /* Do not allow single REG to be an rhs.  */
    1147                 :       2429 :   if (REG_P (rhs))
    1148                 :            :     return false;
    1149                 :            : 
    1150                 :            :   /* See comment at find_used_regs_1 (*1) for explanation of this
    1151                 :            :      restriction.  */
    1152                 :            :   /* FIXME: remove this later.  */
    1153                 :       1342 :   if (MEM_P (lhs))
    1154                 :            :     return false;
    1155                 :            : 
    1156                 :            :   /* This will filter all tricky things like ZERO_EXTRACT etc.
    1157                 :            :      For now we don't handle it.  */
    1158                 :       1342 :   if (!REG_P (lhs) && !MEM_P (lhs))
    1159                 :          0 :     return false;
    1160                 :            : 
    1161                 :            :   return true;
    1162                 :            : }
    1163                 :            : 
    1164                 :            : /* Initialize vinsn VI for INSN.  Only for use from vinsn_create ().  When
    1165                 :            :    FORCE_UNIQUE_P is true, the resulting vinsn will not be clonable.  This is
    1166                 :            :    used e.g. for insns from recovery blocks.  */
    1167                 :            : static void
    1168                 :       5954 : vinsn_init (vinsn_t vi, insn_t insn, bool force_unique_p)
    1169                 :            : {
    1170                 :       5954 :   hash_rtx_callback_function hrcf;
    1171                 :       5954 :   int insn_class;
    1172                 :            : 
    1173                 :       5954 :   VINSN_INSN_RTX (vi) = insn;
    1174                 :       5954 :   VINSN_COUNT (vi) = 0;
    1175                 :       5954 :   vi->cost = -1;
    1176                 :            : 
    1177                 :       5954 :   if (INSN_NOP_P (insn))
    1178                 :            :     return;
    1179                 :            : 
    1180                 :       5224 :   if (DF_INSN_UID_SAFE_GET (INSN_UID (insn)) != NULL)
    1181                 :       4452 :     init_id_from_df (VINSN_ID (vi), insn, force_unique_p);
    1182                 :            :   else
    1183                 :        772 :     deps_init_id (VINSN_ID (vi), insn, force_unique_p);
    1184                 :            : 
    1185                 :            :   /* Hash vinsn depending on whether it is separable or not.  */
    1186                 :       5224 :   hrcf = targetm.sched.skip_rtx_p ? hash_with_unspec_callback : NULL;
    1187                 :       5224 :   if (VINSN_SEPARABLE_P (vi))
    1188                 :            :     {
    1189                 :       1338 :       rtx rhs = VINSN_RHS (vi);
    1190                 :            : 
    1191                 :       1338 :       VINSN_HASH (vi) = hash_rtx_cb (rhs, GET_MODE (rhs),
    1192                 :            :                                      NULL, NULL, false, hrcf);
    1193                 :       1338 :       VINSN_HASH_RTX (vi) = hash_rtx_cb (VINSN_PATTERN (vi),
    1194                 :            :                                          VOIDmode, NULL, NULL,
    1195                 :            :                                          false, hrcf);
    1196                 :            :     }
    1197                 :            :   else
    1198                 :            :     {
    1199                 :       3886 :       VINSN_HASH (vi) = hash_rtx_cb (VINSN_PATTERN (vi), VOIDmode,
    1200                 :            :                                      NULL, NULL, false, hrcf);
    1201                 :       3886 :       VINSN_HASH_RTX (vi) = VINSN_HASH (vi);
    1202                 :            :     }
    1203                 :            : 
    1204                 :       5224 :   insn_class = haifa_classify_insn (insn);
    1205                 :       5224 :   if (insn_class >= 2
    1206                 :       5224 :       && (!targetm.sched.get_insn_spec_ds
    1207                 :          0 :           || ((targetm.sched.get_insn_spec_ds (insn) & BEGIN_CONTROL)
    1208                 :            :               == 0)))
    1209                 :        597 :     VINSN_MAY_TRAP_P (vi) = true;
    1210                 :            :   else
    1211                 :       4627 :     VINSN_MAY_TRAP_P (vi) = false;
    1212                 :            : }
    1213                 :            : 
    1214                 :            : /* Indicate that VI has become the part of an rtx object.  */
    1215                 :            : void
    1216                 :     228695 : vinsn_attach (vinsn_t vi)
    1217                 :            : {
    1218                 :            :   /* Assert that VI is not pending for deletion.  */
    1219                 :     228695 :   gcc_assert (VINSN_INSN_RTX (vi));
    1220                 :            : 
    1221                 :     228695 :   VINSN_COUNT (vi)++;
    1222                 :     228695 : }
    1223                 :            : 
    1224                 :            : /* Create and init VI from the INSN.  Use UNIQUE_P for determining the correct
    1225                 :            :    VINSN_TYPE (VI).  */
    1226                 :            : static vinsn_t
    1227                 :       5954 : vinsn_create (insn_t insn, bool force_unique_p)
    1228                 :            : {
    1229                 :          0 :   vinsn_t vi = XCNEW (struct vinsn_def);
    1230                 :            : 
    1231                 :       5954 :   vinsn_init (vi, insn, force_unique_p);
    1232                 :       5954 :   return vi;
    1233                 :            : }
    1234                 :            : 
    1235                 :            : /* Return a copy of VI.  When REATTACH_P is true, detach VI and attach
    1236                 :            :    the copy.  */
    1237                 :            : vinsn_t
    1238                 :          3 : vinsn_copy (vinsn_t vi, bool reattach_p)
    1239                 :            : {
    1240                 :          3 :   rtx_insn *copy;
    1241                 :          3 :   bool unique = VINSN_UNIQUE_P (vi);
    1242                 :          3 :   vinsn_t new_vi;
    1243                 :            : 
    1244                 :          3 :   copy = create_copy_of_insn_rtx (VINSN_INSN_RTX (vi));
    1245                 :          3 :   new_vi = create_vinsn_from_insn_rtx (copy, unique);
    1246                 :          3 :   if (reattach_p)
    1247                 :            :     {
    1248                 :          2 :       vinsn_detach (vi);
    1249                 :          2 :       vinsn_attach (new_vi);
    1250                 :            :     }
    1251                 :            : 
    1252                 :          3 :   return new_vi;
    1253                 :            : }
    1254                 :            : 
    1255                 :            : /* Delete the VI vinsn and free its data.  */
    1256                 :            : static void
    1257                 :       5954 : vinsn_delete (vinsn_t vi)
    1258                 :            : {
    1259                 :       5954 :   gcc_assert (VINSN_COUNT (vi) == 0);
    1260                 :            : 
    1261                 :       5954 :   if (!INSN_NOP_P (VINSN_INSN_RTX (vi)))
    1262                 :            :     {
    1263                 :       5224 :       return_regset_to_pool (VINSN_REG_SETS (vi));
    1264                 :       5224 :       return_regset_to_pool (VINSN_REG_USES (vi));
    1265                 :       5224 :       return_regset_to_pool (VINSN_REG_CLOBBERS (vi));
    1266                 :            :     }
    1267                 :            : 
    1268                 :       5954 :   free (vi);
    1269                 :       5954 : }
    1270                 :            : 
    1271                 :            : /* Indicate that VI is no longer a part of some rtx object.
    1272                 :            :    Remove VI if it is no longer needed.  */
    1273                 :            : void
    1274                 :     228695 : vinsn_detach (vinsn_t vi)
    1275                 :            : {
    1276                 :     228695 :   gcc_assert (VINSN_COUNT (vi) > 0);
    1277                 :            : 
    1278                 :     228695 :   if (--VINSN_COUNT (vi) == 0)
    1279                 :       5954 :     vinsn_delete (vi);
    1280                 :     228695 : }
    1281                 :            : 
    1282                 :            : /* Returns TRUE if VI is a branch.  */
    1283                 :            : bool
    1284                 :      21146 : vinsn_cond_branch_p (vinsn_t vi)
    1285                 :            : {
    1286                 :      21146 :   insn_t insn;
    1287                 :            : 
    1288                 :      21146 :   if (!VINSN_UNIQUE_P (vi))
    1289                 :            :     return false;
    1290                 :            : 
    1291                 :       2547 :   insn = VINSN_INSN_RTX (vi);
    1292                 :       2547 :   if (BB_END (BLOCK_FOR_INSN (insn)) != insn)
    1293                 :            :     return false;
    1294                 :            : 
    1295                 :       1271 :   return control_flow_insn_p (insn);
    1296                 :            : }
    1297                 :            : 
    1298                 :            : /* Return latency of INSN.  */
    1299                 :            : static int
    1300                 :        214 : sel_insn_rtx_cost (rtx_insn *insn)
    1301                 :            : {
    1302                 :        214 :   int cost;
    1303                 :            : 
    1304                 :            :   /* A USE insn, or something else we don't need to
    1305                 :            :      understand.  We can't pass these directly to
    1306                 :            :      result_ready_cost or insn_default_latency because it will
    1307                 :            :      trigger a fatal error for unrecognizable insns.  */
    1308                 :        214 :   if (recog_memoized (insn) < 0)
    1309                 :            :     cost = 0;
    1310                 :            :   else
    1311                 :            :     {
    1312                 :        214 :       cost = insn_default_latency (insn);
    1313                 :            : 
    1314                 :        214 :       if (cost < 0)
    1315                 :            :         cost = 0;
    1316                 :            :     }
    1317                 :            : 
    1318                 :        214 :   return cost;
    1319                 :            : }
    1320                 :            : 
    1321                 :            : /* Return the cost of the VI.
    1322                 :            :    !!! FIXME: Unify with haifa-sched.c: insn_sched_cost ().  */
    1323                 :            : int
    1324                 :       1408 : sel_vinsn_cost (vinsn_t vi)
    1325                 :            : {
    1326                 :       1408 :   int cost = vi->cost;
    1327                 :            : 
    1328                 :       1408 :   if (cost < 0)
    1329                 :            :     {
    1330                 :        214 :       cost = sel_insn_rtx_cost (VINSN_INSN_RTX (vi));
    1331                 :        214 :       vi->cost = cost;
    1332                 :            :     }
    1333                 :            : 
    1334                 :       1408 :   return cost;
    1335                 :            : }
    1336                 :            : 
    1337                 :            : 
    1338                 :            : /* Functions for insn emitting.  */
    1339                 :            : 
    1340                 :            : /* Emit new insn after AFTER based on PATTERN and initialize its data from
    1341                 :            :    EXPR and SEQNO.  */
    1342                 :            : insn_t
    1343                 :         22 : sel_gen_insn_from_rtx_after (rtx pattern, expr_t expr, int seqno, insn_t after)
    1344                 :            : {
    1345                 :         22 :   insn_t new_insn;
    1346                 :            : 
    1347                 :         22 :   gcc_assert (EXPR_TARGET_AVAILABLE (expr) == true);
    1348                 :            : 
    1349                 :         22 :   new_insn = emit_insn_after (pattern, after);
    1350                 :         44 :   set_insn_init (expr, NULL, seqno);
    1351                 :         22 :   sel_init_new_insn (new_insn, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID);
    1352                 :            : 
    1353                 :         22 :   return new_insn;
    1354                 :            : }
    1355                 :            : 
    1356                 :            : /* Force newly generated vinsns to be unique.  */
    1357                 :            : static bool init_insn_force_unique_p = false;
    1358                 :            : 
    1359                 :            : /* Emit new speculation recovery insn after AFTER based on PATTERN and
    1360                 :            :    initialize its data from EXPR and SEQNO.  */
    1361                 :            : insn_t
    1362                 :          0 : sel_gen_recovery_insn_from_rtx_after (rtx pattern, expr_t expr, int seqno,
    1363                 :            :                                       insn_t after)
    1364                 :            : {
    1365                 :          0 :   insn_t insn;
    1366                 :            : 
    1367                 :          0 :   gcc_assert (!init_insn_force_unique_p);
    1368                 :            : 
    1369                 :          0 :   init_insn_force_unique_p = true;
    1370                 :          0 :   insn = sel_gen_insn_from_rtx_after (pattern, expr, seqno, after);
    1371                 :          0 :   CANT_MOVE (insn) = 1;
    1372                 :          0 :   init_insn_force_unique_p = false;
    1373                 :            : 
    1374                 :          0 :   return insn;
    1375                 :            : }
    1376                 :            : 
    1377                 :            : /* Emit new insn after AFTER based on EXPR and SEQNO.  If VINSN is not NULL,
    1378                 :            :    take it as a new vinsn instead of EXPR's vinsn.
    1379                 :            :    We simplify insns later, after scheduling region in
    1380                 :            :    simplify_changed_insns.  */
    1381                 :            : insn_t
    1382                 :        604 : sel_gen_insn_from_expr_after (expr_t expr, vinsn_t vinsn, int seqno,
    1383                 :            :                               insn_t after)
    1384                 :            : {
    1385                 :        604 :   expr_t emit_expr;
    1386                 :        604 :   insn_t insn;
    1387                 :        604 :   int flags;
    1388                 :            : 
    1389                 :        604 :   emit_expr = set_insn_init (expr, vinsn ? vinsn : EXPR_VINSN (expr),
    1390                 :            :                              seqno);
    1391                 :        604 :   insn = EXPR_INSN_RTX (emit_expr);
    1392                 :            : 
    1393                 :            :   /* The insn may come from the transformation cache, which may hold already
    1394                 :            :      deleted insns, so mark it as not deleted.  */
    1395                 :        604 :   insn->set_undeleted ();
    1396                 :            : 
    1397                 :        604 :   add_insn_after (insn, after, BLOCK_FOR_INSN (insn));
    1398                 :            : 
    1399                 :        604 :   flags = INSN_INIT_TODO_SSID;
    1400                 :        604 :   if (INSN_LUID (insn) == 0)
    1401                 :        604 :     flags |= INSN_INIT_TODO_LUID;
    1402                 :        604 :   sel_init_new_insn (insn, flags);
    1403                 :            : 
    1404                 :        604 :   return insn;
    1405                 :            : }
    1406                 :            : 
    1407                 :            : /* Move insn from EXPR after AFTER.  */
    1408                 :            : insn_t
    1409                 :       5006 : sel_move_insn (expr_t expr, int seqno, insn_t after)
    1410                 :            : {
    1411                 :       5006 :   insn_t insn = EXPR_INSN_RTX (expr);
    1412                 :       5006 :   basic_block bb = BLOCK_FOR_INSN (after);
    1413                 :       5006 :   insn_t next = NEXT_INSN (after);
    1414                 :            : 
    1415                 :            :   /* Assert that in move_op we disconnected this insn properly.  */
    1416                 :       5006 :   gcc_assert (EXPR_VINSN (INSN_EXPR (insn)) != NULL);
    1417                 :       5006 :   SET_PREV_INSN (insn) = after;
    1418                 :       5006 :   SET_NEXT_INSN (insn) = next;
    1419                 :            : 
    1420                 :       5006 :   SET_NEXT_INSN (after) = insn;
    1421                 :       5006 :   SET_PREV_INSN (next) = insn;
    1422                 :            : 
    1423                 :            :   /* Update links from insn to bb and vice versa.  */
    1424                 :       5006 :   df_insn_change_bb (insn, bb);
    1425                 :       5006 :   if (BB_END (bb) == after)
    1426                 :        764 :     BB_END (bb) = insn;
    1427                 :            : 
    1428                 :       5006 :   prepare_insn_expr (insn, seqno);
    1429                 :       5006 :   return insn;
    1430                 :            : }
    1431                 :            : 
    1432                 :            : 
    1433                 :            : /* Functions to work with right-hand sides.  */
    1434                 :            : 
    1435                 :            : /* Search for a hash value determined by UID/NEW_VINSN in a sorted vector
    1436                 :            :    VECT and return true when found.  Use NEW_VINSN for comparison only when
    1437                 :            :    COMPARE_VINSNS is true.  Write to INDP the index on which
    1438                 :            :    the search has stopped, such that inserting the new element at INDP will
    1439                 :            :    retain VECT's sort order.  */
    1440                 :            : static bool
    1441                 :     198919 : find_in_history_vect_1 (vec<expr_history_def> vect,
    1442                 :            :                         unsigned uid, vinsn_t new_vinsn,
    1443                 :            :                         bool compare_vinsns, int *indp)
    1444                 :            : {
    1445                 :     198919 :   expr_history_def *arr;
    1446                 :     198919 :   int i, j, len = vect.length ();
    1447                 :            : 
    1448                 :     198919 :   if (len == 0)
    1449                 :            :     {
    1450                 :     195805 :       *indp = 0;
    1451                 :     195805 :       return false;
    1452                 :            :     }
    1453                 :            : 
    1454                 :       3114 :   arr = vect.address ();
    1455                 :       3114 :   i = 0, j = len - 1;
    1456                 :            : 
    1457                 :       4932 :   while (i <= j)
    1458                 :            :     {
    1459                 :       3333 :       unsigned auid = arr[i].uid;
    1460                 :       3333 :       vinsn_t avinsn = arr[i].new_expr_vinsn;
    1461                 :            : 
    1462                 :       3333 :       if (auid == uid
    1463                 :            :           /* When undoing transformation on a bookkeeping copy, the new vinsn
    1464                 :            :              may not be exactly equal to the one that is saved in the vector.
    1465                 :            :              This is because the insn whose copy we're checking was possibly
    1466                 :            :              substituted itself.  */
    1467                 :       3333 :           && (! compare_vinsns
    1468                 :        354 :               || vinsn_equal_p (avinsn, new_vinsn)))
    1469                 :            :         {
    1470                 :        557 :           *indp = i;
    1471                 :        557 :           return true;
    1472                 :            :         }
    1473                 :       2776 :       else if (auid > uid)
    1474                 :            :         break;
    1475                 :       1818 :       i++;
    1476                 :            :     }
    1477                 :            : 
    1478                 :       2557 :   *indp = i;
    1479                 :       2557 :   return false;
    1480                 :            : }
    1481                 :            : 
    1482                 :            : /* Search for a uid of INSN and NEW_VINSN in a sorted vector VECT.  Return
    1483                 :            :    the position found or -1, if no such value is in vector.
    1484                 :            :    Search also for UIDs of insn's originators, if ORIGINATORS_P is true.  */
    1485                 :            : int
    1486                 :      57289 : find_in_history_vect (vec<expr_history_def> vect, rtx insn,
    1487                 :            :                       vinsn_t new_vinsn, bool originators_p)
    1488                 :            : {
    1489                 :      57289 :   int ind;
    1490                 :            : 
    1491                 :      57289 :   if (find_in_history_vect_1 (vect, INSN_UID (insn), new_vinsn,
    1492                 :            :                               false, &ind))
    1493                 :        203 :     return ind;
    1494                 :            : 
    1495                 :      57086 :   if (INSN_ORIGINATORS (insn) && originators_p)
    1496                 :            :     {
    1497                 :       3473 :       unsigned uid;
    1498                 :       3473 :       bitmap_iterator bi;
    1499                 :            : 
    1500                 :     144315 :       EXECUTE_IF_SET_IN_BITMAP (INSN_ORIGINATORS (insn), 0, uid, bi)
    1501                 :     140842 :         if (find_in_history_vect_1 (vect, uid, new_vinsn, false, &ind))
    1502                 :          0 :           return ind;
    1503                 :            :     }
    1504                 :            : 
    1505                 :            :   return -1;
    1506                 :            : }
    1507                 :            : 
    1508                 :            : /* Insert new element in a sorted history vector pointed to by PVECT,
    1509                 :            :    if it is not there already.  The element is searched using
    1510                 :            :    UID/NEW_EXPR_VINSN pair.  TYPE, OLD_EXPR_VINSN and SPEC_DS save
    1511                 :            :    the history of a transformation.  */
    1512                 :            : void
    1513                 :        788 : insert_in_history_vect (vec<expr_history_def> *pvect,
    1514                 :            :                         unsigned uid, enum local_trans_type type,
    1515                 :            :                         vinsn_t old_expr_vinsn, vinsn_t new_expr_vinsn,
    1516                 :            :                         ds_t spec_ds)
    1517                 :            : {
    1518                 :        788 :   vec<expr_history_def> vect = *pvect;
    1519                 :        788 :   expr_history_def temp;
    1520                 :        788 :   bool res;
    1521                 :        788 :   int ind;
    1522                 :            : 
    1523                 :        788 :   res = find_in_history_vect_1 (vect, uid, new_expr_vinsn, true, &ind);
    1524                 :            : 
    1525                 :        788 :   if (res)
    1526                 :            :     {
    1527                 :        354 :       expr_history_def *phist = &vect[ind];
    1528                 :            : 
    1529                 :            :       /* It is possible that speculation types of expressions that were
    1530                 :            :          propagated through different paths will be different here.  In this
    1531                 :            :          case, merge the status to get the correct check later.  */
    1532                 :        354 :       if (phist->spec_ds != spec_ds)
    1533                 :          0 :         phist->spec_ds = ds_max_merge (phist->spec_ds, spec_ds);
    1534                 :        354 :       return;
    1535                 :            :     }
    1536                 :            : 
    1537                 :        434 :   temp.uid = uid;
    1538                 :        434 :   temp.old_expr_vinsn = old_expr_vinsn;
    1539                 :        434 :   temp.new_expr_vinsn = new_expr_vinsn;
    1540                 :        434 :   temp.spec_ds = spec_ds;
    1541                 :        434 :   temp.type = type;
    1542                 :            : 
    1543                 :        434 :   vinsn_attach (old_expr_vinsn);
    1544                 :        434 :   vinsn_attach (new_expr_vinsn);
    1545                 :        434 :   vect.safe_insert (ind, temp);
    1546                 :        434 :   *pvect = vect;
    1547                 :            : }
    1548                 :            : 
    1549                 :            : /* Free history vector PVECT.  */
    1550                 :            : static void
    1551                 :     200415 : free_history_vect (vec<expr_history_def> &pvect)
    1552                 :            : {
    1553                 :     200415 :   unsigned i;
    1554                 :     200415 :   expr_history_def *phist;
    1555                 :            : 
    1556                 :     200415 :   if (! pvect.exists ())
    1557                 :     200415 :     return;
    1558                 :            : 
    1559                 :       7692 :   for (i = 0; pvect.iterate (i, &phist); i++)
    1560                 :            :     {
    1561                 :       3983 :       vinsn_detach (phist->old_expr_vinsn);
    1562                 :       3983 :       vinsn_detach (phist->new_expr_vinsn);
    1563                 :            :     }
    1564                 :            : 
    1565                 :       3709 :   pvect.release ();
    1566                 :            : }
    1567                 :            : 
    1568                 :            : /* Merge vector FROM to PVECT.  */
    1569                 :            : static void
    1570                 :      13541 : merge_history_vect (vec<expr_history_def> *pvect,
    1571                 :            :                     vec<expr_history_def> from)
    1572                 :            : {
    1573                 :      13541 :   expr_history_def *phist;
    1574                 :      13541 :   int i;
    1575                 :            : 
    1576                 :            :   /* We keep this vector sorted.  */
    1577                 :      13919 :   for (i = 0; from.iterate (i, &phist); i++)
    1578                 :        378 :     insert_in_history_vect (pvect, phist->uid, phist->type,
    1579                 :            :                             phist->old_expr_vinsn, phist->new_expr_vinsn,
    1580                 :            :                             phist->spec_ds);
    1581                 :      13541 : }
    1582                 :            : 
    1583                 :            : /* Compare two vinsns as rhses if possible and as vinsns otherwise.  */
    1584                 :            : bool
    1585                 :     348997 : vinsn_equal_p (vinsn_t x, vinsn_t y)
    1586                 :            : {
    1587                 :     348997 :   rtx_equal_p_callback_function repcf;
    1588                 :            : 
    1589                 :     348997 :   if (x == y)
    1590                 :            :     return true;
    1591                 :            : 
    1592                 :     312523 :   if (VINSN_TYPE (x) != VINSN_TYPE (y))
    1593                 :            :     return false;
    1594                 :            : 
    1595                 :     144942 :   if (VINSN_HASH (x) != VINSN_HASH (y))
    1596                 :            :     return false;
    1597                 :            : 
    1598                 :      19255 :   repcf = targetm.sched.skip_rtx_p ? skip_unspecs_callback : NULL;
    1599                 :      19255 :   if (VINSN_SEPARABLE_P (x))
    1600                 :            :     {
    1601                 :            :       /* Compare RHSes of VINSNs.  */
    1602                 :       7251 :       gcc_assert (VINSN_RHS (x));
    1603                 :       7251 :       gcc_assert (VINSN_RHS (y));
    1604                 :            : 
    1605                 :       7251 :       return rtx_equal_p_cb (VINSN_RHS (x), VINSN_RHS (y), repcf);
    1606                 :            :     }
    1607                 :            : 
    1608                 :      12004 :   return rtx_equal_p_cb (VINSN_PATTERN (x), VINSN_PATTERN (y), repcf);
    1609                 :            : }
    1610                 :            : 
    1611                 :            : 
    1612                 :            : /* Functions for working with expressions.  */
    1613                 :            : 
    1614                 :            : /* Initialize EXPR.  */
    1615                 :            : static void
    1616                 :     192587 : init_expr (expr_t expr, vinsn_t vi, int spec, int use, int priority,
    1617                 :            :            int sched_times, int orig_bb_index, ds_t spec_done_ds,
    1618                 :            :            ds_t spec_to_check_ds, int orig_sched_cycle,
    1619                 :            :            vec<expr_history_def> history,
    1620                 :            :            signed char target_available,
    1621                 :            :            bool was_substituted, bool was_renamed, bool needs_spec_check_p,
    1622                 :            :            bool cant_move)
    1623                 :            : {
    1624                 :          0 :   vinsn_attach (vi);
    1625                 :            : 
    1626                 :     192587 :   EXPR_VINSN (expr) = vi;
    1627                 :     192587 :   EXPR_SPEC (expr) = spec;
    1628                 :     192587 :   EXPR_USEFULNESS (expr) = use;
    1629                 :     192587 :   EXPR_PRIORITY (expr) = priority;
    1630                 :     192587 :   EXPR_PRIORITY_ADJ (expr) = 0;
    1631                 :     192587 :   EXPR_SCHED_TIMES (expr) = sched_times;
    1632                 :     192587 :   EXPR_ORIG_BB_INDEX (expr) = orig_bb_index;
    1633                 :     192587 :   EXPR_ORIG_SCHED_CYCLE (expr) = orig_sched_cycle;
    1634                 :     192587 :   EXPR_SPEC_DONE_DS (expr) = spec_done_ds;
    1635                 :     192587 :   EXPR_SPEC_TO_CHECK_DS (expr) = spec_to_check_ds;
    1636                 :            : 
    1637                 :     165850 :   if (history.exists ())
    1638                 :       3294 :     EXPR_HISTORY_OF_CHANGES (expr) = history;
    1639                 :            :   else
    1640                 :     162556 :     EXPR_HISTORY_OF_CHANGES (expr).create (0);
    1641                 :            : 
    1642                 :     192587 :   EXPR_TARGET_AVAILABLE (expr) = target_available;
    1643                 :     192587 :   EXPR_WAS_SUBSTITUTED (expr) = was_substituted;
    1644                 :     192587 :   EXPR_WAS_RENAMED (expr) = was_renamed;
    1645                 :     192587 :   EXPR_NEEDS_SPEC_CHECK_P (expr) = needs_spec_check_p;
    1646                 :     192587 :   EXPR_CANT_MOVE (expr) = cant_move;
    1647                 :          0 : }
    1648                 :            : 
    1649                 :            : /* Make a copy of the expr FROM into the expr TO.  */
    1650                 :            : void
    1651                 :     161420 : copy_expr (expr_t to, expr_t from)
    1652                 :            : {
    1653                 :     161420 :   vec<expr_history_def> temp = vNULL;
    1654                 :            : 
    1655                 :     161420 :   if (EXPR_HISTORY_OF_CHANGES (from).exists ())
    1656                 :            :     {
    1657                 :       3294 :       unsigned i;
    1658                 :       3294 :       expr_history_def *phist;
    1659                 :            : 
    1660                 :       3294 :       temp = EXPR_HISTORY_OF_CHANGES (from).copy ();
    1661                 :       6843 :       for (i = 0;
    1662                 :       6843 :            temp.iterate (i, &phist);
    1663                 :            :            i++)
    1664                 :            :         {
    1665                 :       3549 :           vinsn_attach (phist->old_expr_vinsn);
    1666                 :       3549 :           vinsn_attach (phist->new_expr_vinsn);
    1667                 :            :         }
    1668                 :            :     }
    1669                 :            : 
    1670                 :     322840 :   init_expr (to, EXPR_VINSN (from), EXPR_SPEC (from),
    1671                 :            :              EXPR_USEFULNESS (from), EXPR_PRIORITY (from),
    1672                 :            :              EXPR_SCHED_TIMES (from), EXPR_ORIG_BB_INDEX (from),
    1673                 :            :              EXPR_SPEC_DONE_DS (from), EXPR_SPEC_TO_CHECK_DS (from),
    1674                 :            :              EXPR_ORIG_SCHED_CYCLE (from), temp,
    1675                 :     161420 :              EXPR_TARGET_AVAILABLE (from), EXPR_WAS_SUBSTITUTED (from),
    1676                 :            :              EXPR_WAS_RENAMED (from), EXPR_NEEDS_SPEC_CHECK_P (from),
    1677                 :     161420 :              EXPR_CANT_MOVE (from));
    1678                 :     161420 : }
    1679                 :            : 
    1680                 :            : /* Same, but the final expr will not ever be in av sets, so don't copy
    1681                 :            :    "uninteresting" data such as bitmap cache.  */
    1682                 :            : void
    1683                 :      26737 : copy_expr_onside (expr_t to, expr_t from)
    1684                 :            : {
    1685                 :      53474 :   init_expr (to, EXPR_VINSN (from), EXPR_SPEC (from), EXPR_USEFULNESS (from),
    1686                 :            :              EXPR_PRIORITY (from), EXPR_SCHED_TIMES (from), 0,
    1687                 :            :              EXPR_SPEC_DONE_DS (from), EXPR_SPEC_TO_CHECK_DS (from), 0,
    1688                 :            :              vNULL,
    1689                 :      26737 :              EXPR_TARGET_AVAILABLE (from), EXPR_WAS_SUBSTITUTED (from),
    1690                 :            :              EXPR_WAS_RENAMED (from), EXPR_NEEDS_SPEC_CHECK_P (from),
    1691                 :      26737 :              EXPR_CANT_MOVE (from));
    1692                 :      26737 : }
    1693                 :            : 
    1694                 :            : /* Prepare the expr of INSN for scheduling.  Used when moving insn and when
    1695                 :            :    initializing new insns.  */
    1696                 :            : static void
    1697                 :       7828 : prepare_insn_expr (insn_t insn, int seqno)
    1698                 :            : {
    1699                 :       7828 :   expr_t expr = INSN_EXPR (insn);
    1700                 :       7828 :   ds_t ds;
    1701                 :            : 
    1702                 :       7828 :   INSN_SEQNO (insn) = seqno;
    1703                 :       7828 :   EXPR_ORIG_BB_INDEX (expr) = BLOCK_NUM (insn);
    1704                 :       7828 :   EXPR_SPEC (expr) = 0;
    1705                 :       7828 :   EXPR_ORIG_SCHED_CYCLE (expr) = 0;
    1706                 :       7828 :   EXPR_WAS_SUBSTITUTED (expr) = 0;
    1707                 :       7828 :   EXPR_WAS_RENAMED (expr) = 0;
    1708                 :       7828 :   EXPR_TARGET_AVAILABLE (expr) = 1;
    1709                 :       7828 :   INSN_LIVE_VALID_P (insn) = false;
    1710                 :            : 
    1711                 :            :   /* ??? If this expression is speculative, make its dependence
    1712                 :            :      as weak as possible.  We can filter this expression later
    1713                 :            :      in process_spec_exprs, because we do not distinguish
    1714                 :            :      between the status we got during compute_av_set and the
    1715                 :            :      existing status.  To be fixed.  */
    1716                 :       7828 :   ds = EXPR_SPEC_DONE_DS (expr);
    1717                 :       7828 :   if (ds)
    1718                 :          0 :     EXPR_SPEC_DONE_DS (expr) = ds_get_max_dep_weak (ds);
    1719                 :            : 
    1720                 :       7828 :   free_history_vect (EXPR_HISTORY_OF_CHANGES (expr));
    1721                 :       7828 : }
    1722                 :            : 
    1723                 :            : /* Update target_available bits when merging exprs TO and FROM.  SPLIT_POINT
    1724                 :            :    is non-null when expressions are merged from different successors at
    1725                 :            :    a split point.  */
    1726                 :            : static void
    1727                 :       3062 : update_target_availability (expr_t to, expr_t from, insn_t split_point)
    1728                 :            : {
    1729                 :       3062 :   if (EXPR_TARGET_AVAILABLE (to) < 0
    1730                 :       1758 :       || EXPR_TARGET_AVAILABLE (from) < 0)
    1731                 :       1384 :     EXPR_TARGET_AVAILABLE (to) = -1;
    1732                 :            :   else
    1733                 :            :     {
    1734                 :            :       /* We try to detect the case when one of the expressions
    1735                 :            :          can only be reached through another one.  In this case,
    1736                 :            :          we can do better.  */
    1737                 :       1678 :       if (split_point == NULL)
    1738                 :            :         {
    1739                 :        112 :           int toind, fromind;
    1740                 :            : 
    1741                 :        112 :           toind = EXPR_ORIG_BB_INDEX (to);
    1742                 :        112 :           fromind = EXPR_ORIG_BB_INDEX (from);
    1743                 :            : 
    1744                 :        112 :           if (toind && toind == fromind)
    1745                 :            :             /* Do nothing -- everything is done in
    1746                 :            :                merge_with_other_exprs.  */
    1747                 :            :             ;
    1748                 :            :           else
    1749                 :        112 :             EXPR_TARGET_AVAILABLE (to) = -1;
    1750                 :            :         }
    1751                 :       1566 :       else if (EXPR_TARGET_AVAILABLE (from) == 0
    1752                 :        718 :                && EXPR_LHS (from)
    1753                 :        718 :                && REG_P (EXPR_LHS (from))
    1754                 :       2284 :                && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
    1755                 :          0 :         EXPR_TARGET_AVAILABLE (to) = -1;
    1756                 :            :       else
    1757                 :       1566 :         EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
    1758                 :            :     }
    1759                 :       3062 : }
    1760                 :            : 
    1761                 :            : /* Update speculation bits when merging exprs TO and FROM.  SPLIT_POINT
    1762                 :            :    is non-null when expressions are merged from different successors at
    1763                 :            :    a split point.  */
    1764                 :            : static void
    1765                 :       3062 : update_speculative_bits (expr_t to, expr_t from, insn_t split_point)
    1766                 :            : {
    1767                 :       3062 :   ds_t old_to_ds, old_from_ds;
    1768                 :            : 
    1769                 :       3062 :   old_to_ds = EXPR_SPEC_DONE_DS (to);
    1770                 :       3062 :   old_from_ds = EXPR_SPEC_DONE_DS (from);
    1771                 :            : 
    1772                 :       3062 :   EXPR_SPEC_DONE_DS (to) = ds_max_merge (old_to_ds, old_from_ds);
    1773                 :       3062 :   EXPR_SPEC_TO_CHECK_DS (to) |= EXPR_SPEC_TO_CHECK_DS (from);
    1774                 :       3062 :   EXPR_NEEDS_SPEC_CHECK_P (to) |= EXPR_NEEDS_SPEC_CHECK_P (from);
    1775                 :            : 
    1776                 :            :   /* When merging e.g. control & data speculative exprs, or a control
    1777                 :            :      speculative with a control&data speculative one, we really have
    1778                 :            :      to change vinsn too.  Also, when speculative status is changed,
    1779                 :            :      we also need to record this as a transformation in expr's history.  */
    1780                 :       3062 :   if ((old_to_ds & SPECULATIVE) || (old_from_ds & SPECULATIVE))
    1781                 :            :     {
    1782                 :          0 :       old_to_ds = ds_get_speculation_types (old_to_ds);
    1783                 :          0 :       old_from_ds = ds_get_speculation_types (old_from_ds);
    1784                 :            : 
    1785                 :          0 :       if (old_to_ds != old_from_ds)
    1786                 :            :         {
    1787                 :          0 :           ds_t record_ds;
    1788                 :            : 
    1789                 :            :           /* When both expressions are speculative, we need to change
    1790                 :            :              the vinsn first.  */
    1791                 :          0 :           if ((old_to_ds & SPECULATIVE) && (old_from_ds & SPECULATIVE))
    1792                 :            :             {
    1793                 :          0 :               int res;
    1794                 :            : 
    1795                 :          0 :               res = speculate_expr (to, EXPR_SPEC_DONE_DS (to));
    1796                 :          0 :               gcc_assert (res >= 0);
    1797                 :            :             }
    1798                 :            : 
    1799                 :          0 :           if (split_point != NULL)
    1800                 :            :             {
    1801                 :            :               /* Record the change with proper status.  */
    1802                 :          0 :               record_ds = EXPR_SPEC_DONE_DS (to) & SPECULATIVE;
    1803                 :          0 :               record_ds &= ~(old_to_ds & SPECULATIVE);
    1804                 :          0 :               record_ds &= ~(old_from_ds & SPECULATIVE);
    1805                 :            : 
    1806                 :          0 :               insert_in_history_vect (&EXPR_HISTORY_OF_CHANGES (to),
    1807                 :          0 :                                       INSN_UID (split_point), TRANS_SPECULATION,
    1808                 :            :                                       EXPR_VINSN (from), EXPR_VINSN (to),
    1809                 :            :                                       record_ds);
    1810                 :            :             }
    1811                 :            :         }
    1812                 :            :     }
    1813                 :       3062 : }
    1814                 :            : 
    1815                 :            : 
    1816                 :            : /* Merge bits of FROM expr to TO expr.  When SPLIT_POINT is not NULL,
    1817                 :            :    this is done along different paths.  */
    1818                 :            : void
    1819                 :       3062 : merge_expr_data (expr_t to, expr_t from, insn_t split_point)
    1820                 :            : {
    1821                 :            :   /* Choose the maximum of the specs of merged exprs.  This is required
    1822                 :            :      for correctness of bookkeeping.  */
    1823                 :       3062 :   if (EXPR_SPEC (to) < EXPR_SPEC (from))
    1824                 :       1243 :     EXPR_SPEC (to) = EXPR_SPEC (from);
    1825                 :            : 
    1826                 :       3062 :   if (split_point)
    1827                 :       2708 :     EXPR_USEFULNESS (to) += EXPR_USEFULNESS (from);
    1828                 :            :   else
    1829                 :        354 :     EXPR_USEFULNESS (to) = MAX (EXPR_USEFULNESS (to),
    1830                 :            :                                 EXPR_USEFULNESS (from));
    1831                 :            : 
    1832                 :       3062 :   if (EXPR_PRIORITY (to) < EXPR_PRIORITY (from))
    1833                 :        122 :     EXPR_PRIORITY (to) = EXPR_PRIORITY (from);
    1834                 :            : 
    1835                 :            :   /* We merge sched-times half-way to the larger value to avoid the endless
    1836                 :            :      pipelining of unneeded insns.  The average seems to be good compromise
    1837                 :            :      between pipelining opportunities and avoiding extra work.  */
    1838                 :       3062 :   if (EXPR_SCHED_TIMES (to) != EXPR_SCHED_TIMES (from))
    1839                 :        849 :     EXPR_SCHED_TIMES (to) = ((EXPR_SCHED_TIMES (from) + EXPR_SCHED_TIMES (to)
    1840                 :        849 :                              + 1) / 2);
    1841                 :            : 
    1842                 :       3062 :   if (EXPR_ORIG_BB_INDEX (to) != EXPR_ORIG_BB_INDEX (from))
    1843                 :       1552 :     EXPR_ORIG_BB_INDEX (to) = 0;
    1844                 :            : 
    1845                 :       3062 :   EXPR_ORIG_SCHED_CYCLE (to) = MIN (EXPR_ORIG_SCHED_CYCLE (to),
    1846                 :            :                                     EXPR_ORIG_SCHED_CYCLE (from));
    1847                 :            : 
    1848                 :       3062 :   EXPR_WAS_SUBSTITUTED (to) |= EXPR_WAS_SUBSTITUTED (from);
    1849                 :       3062 :   EXPR_WAS_RENAMED (to) |= EXPR_WAS_RENAMED (from);
    1850                 :       3062 :   EXPR_CANT_MOVE (to) |= EXPR_CANT_MOVE (from);
    1851                 :            : 
    1852                 :       3062 :   merge_history_vect (&EXPR_HISTORY_OF_CHANGES (to),
    1853                 :            :                       EXPR_HISTORY_OF_CHANGES (from));
    1854                 :       3062 :   update_target_availability (to, from, split_point);
    1855                 :       3062 :   update_speculative_bits (to, from, split_point);
    1856                 :       3062 : }
    1857                 :            : 
    1858                 :            : /* Merge bits of FROM expr to TO expr.  Vinsns in the exprs should be equal
    1859                 :            :    in terms of vinsn_equal_p.  SPLIT_POINT is non-null when expressions
    1860                 :            :    are merged from different successors at a split point.  */
    1861                 :            : void
    1862                 :       2732 : merge_expr (expr_t to, expr_t from, insn_t split_point)
    1863                 :            : {
    1864                 :       2732 :   vinsn_t to_vi = EXPR_VINSN (to);
    1865                 :       2732 :   vinsn_t from_vi = EXPR_VINSN (from);
    1866                 :            : 
    1867                 :       2732 :   gcc_assert (vinsn_equal_p (to_vi, from_vi));
    1868                 :            : 
    1869                 :            :   /* Make sure that speculative pattern is propagated into exprs that
    1870                 :            :      have non-speculative one.  This will provide us with consistent
    1871                 :            :      speculative bits and speculative patterns inside expr.  */
    1872                 :       2732 :   if (EXPR_SPEC_DONE_DS (to) == 0
    1873                 :       2732 :       && (EXPR_SPEC_DONE_DS (from) != 0
    1874                 :            :           /* Do likewise for volatile insns, so that we always retain
    1875                 :            :              the may_trap_p bit on the resulting expression.  However,
    1876                 :            :              avoid propagating the trapping bit into the instructions
    1877                 :            :              already speculated.  This would result in replacing the
    1878                 :            :              speculative pattern with the non-speculative one and breaking
    1879                 :            :              the speculation support.  */
    1880                 :       2732 :           || (!VINSN_MAY_TRAP_P (EXPR_VINSN (to))
    1881                 :       2705 :               && VINSN_MAY_TRAP_P (EXPR_VINSN (from)))))
    1882                 :          0 :     change_vinsn_in_expr (to, EXPR_VINSN (from));
    1883                 :            : 
    1884                 :       2732 :   merge_expr_data (to, from, split_point);
    1885                 :       2732 :   gcc_assert (EXPR_USEFULNESS (to) <= REG_BR_PROB_BASE);
    1886                 :       2732 : }
    1887                 :            : 
    1888                 :            : /* Clear the information of this EXPR.  */
    1889                 :            : void
    1890                 :     192587 : clear_expr (expr_t expr)
    1891                 :            : {
    1892                 :            : 
    1893                 :     192587 :   vinsn_detach (EXPR_VINSN (expr));
    1894                 :     192587 :   EXPR_VINSN (expr) = NULL;
    1895                 :            : 
    1896                 :     192587 :   free_history_vect (EXPR_HISTORY_OF_CHANGES (expr));
    1897                 :     192587 : }
    1898                 :            : 
    1899                 :            : /* For a given LV_SET, mark EXPR having unavailable target register.  */
    1900                 :            : static void
    1901                 :      13407 : set_unavailable_target_for_expr (expr_t expr, regset lv_set)
    1902                 :            : {
    1903                 :      13407 :   if (EXPR_SEPARABLE_P (expr))
    1904                 :            :     {
    1905                 :       6897 :       if (REG_P (EXPR_LHS (expr))
    1906                 :       6897 :           && register_unavailable_p (lv_set, EXPR_LHS (expr)))
    1907                 :            :         {
    1908                 :            :           /* If it's an insn like r1 = use (r1, ...), and it exists in
    1909                 :            :              different forms in each of the av_sets being merged, we can't say
    1910                 :            :              whether original destination register is available or not.
    1911                 :            :              However, this still works if destination register is not used
    1912                 :            :              in the original expression: if the branch at which LV_SET we're
    1913                 :            :              looking here is not actually 'other branch' in sense that same
    1914                 :            :              expression is available through it (but it can't be determined
    1915                 :            :              at computation stage because of transformations on one of the
    1916                 :            :              branches), it still won't affect the availability.
    1917                 :            :              Liveness of a register somewhere on a code motion path means
    1918                 :            :              it's either read somewhere on a codemotion path, live on
    1919                 :            :              'other' branch, live at the point immediately following
    1920                 :            :              the original operation, or is read by the original operation.
    1921                 :            :              The latter case is filtered out in the condition below.
    1922                 :            :              It still doesn't cover the case when register is defined and used
    1923                 :            :              somewhere within the code motion path, and in this case we could
    1924                 :            :              miss a unifying code motion along both branches using a renamed
    1925                 :            :              register, but it won't affect a code correctness since upon
    1926                 :            :              an actual code motion a bookkeeping code would be generated.  */
    1927                 :       1193 :           if (register_unavailable_p (VINSN_REG_USES (EXPR_VINSN (expr)),
    1928                 :       1193 :                                       EXPR_LHS (expr)))
    1929                 :        285 :             EXPR_TARGET_AVAILABLE (expr) = -1;
    1930                 :            :           else
    1931                 :        908 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1932                 :            :         }
    1933                 :            :     }
    1934                 :            :   else
    1935                 :            :     {
    1936                 :       6510 :       unsigned regno;
    1937                 :       6510 :       reg_set_iterator rsi;
    1938                 :            : 
    1939                 :      10009 :       EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_SETS (EXPR_VINSN (expr)),
    1940                 :            :                                  0, regno, rsi)
    1941                 :       5928 :         if (bitmap_bit_p (lv_set, regno))
    1942                 :            :           {
    1943                 :       2429 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1944                 :       2429 :             break;
    1945                 :            :           }
    1946                 :            : 
    1947                 :       8550 :       EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_CLOBBERS (EXPR_VINSN (expr)),
    1948                 :            :                                  0, regno, rsi)
    1949                 :       2057 :         if (bitmap_bit_p (lv_set, regno))
    1950                 :            :           {
    1951                 :         17 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1952                 :         17 :             break;
    1953                 :            :           }
    1954                 :            :     }
    1955                 :      13407 : }
    1956                 :            : 
    1957                 :            : /* Try to make EXPR speculative.  Return 1 when EXPR's pattern
    1958                 :            :    or dependence status have changed, 2 when also the target register
    1959                 :            :    became unavailable, 0 if nothing had to be changed.  */
    1960                 :            : int
    1961                 :          0 : speculate_expr (expr_t expr, ds_t ds)
    1962                 :            : {
    1963                 :          0 :   int res;
    1964                 :          0 :   rtx_insn *orig_insn_rtx;
    1965                 :          0 :   rtx spec_pat;
    1966                 :          0 :   ds_t target_ds, current_ds;
    1967                 :            : 
    1968                 :            :   /* Obtain the status we need to put on EXPR.   */
    1969                 :          0 :   target_ds = (ds & SPECULATIVE);
    1970                 :          0 :   current_ds = EXPR_SPEC_DONE_DS (expr);
    1971                 :          0 :   ds = ds_full_merge (current_ds, target_ds, NULL_RTX, NULL_RTX);
    1972                 :            : 
    1973                 :          0 :   orig_insn_rtx = EXPR_INSN_RTX (expr);
    1974                 :            : 
    1975                 :          0 :   res = sched_speculate_insn (orig_insn_rtx, ds, &spec_pat);
    1976                 :            : 
    1977                 :          0 :   switch (res)
    1978                 :            :     {
    1979                 :          0 :     case 0:
    1980                 :          0 :       EXPR_SPEC_DONE_DS (expr) = ds;
    1981                 :          0 :       return current_ds != ds ? 1 : 0;
    1982                 :            : 
    1983                 :          0 :     case 1:
    1984                 :          0 :       {
    1985                 :          0 :         rtx_insn *spec_insn_rtx =
    1986                 :          0 :           create_insn_rtx_from_pattern (spec_pat, NULL_RTX);
    1987                 :          0 :         vinsn_t spec_vinsn = create_vinsn_from_insn_rtx (spec_insn_rtx, false);
    1988                 :            : 
    1989                 :          0 :         change_vinsn_in_expr (expr, spec_vinsn);
    1990                 :          0 :         EXPR_SPEC_DONE_DS (expr) = ds;
    1991                 :          0 :         EXPR_NEEDS_SPEC_CHECK_P (expr) = true;
    1992                 :            : 
    1993                 :            :         /* Do not allow clobbering the address register of speculative
    1994                 :            :            insns.  */
    1995                 :          0 :         if (register_unavailable_p (VINSN_REG_USES (EXPR_VINSN (expr)),
    1996                 :            :                                     expr_dest_reg (expr)))
    1997                 :            :           {
    1998                 :          0 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1999                 :          0 :             return 2;
    2000                 :            :           }
    2001                 :            : 
    2002                 :            :         return 1;
    2003                 :            :       }
    2004                 :            : 
    2005                 :            :     case -1:
    2006                 :            :       return -1;
    2007                 :            : 
    2008                 :          0 :     default:
    2009                 :          0 :       gcc_unreachable ();
    2010                 :            :       return -1;
    2011                 :            :     }
    2012                 :            : }
    2013                 :            : 
    2014                 :            : /* Return a destination register, if any, of EXPR.  */
    2015                 :            : rtx
    2016                 :       8924 : expr_dest_reg (expr_t expr)
    2017                 :            : {
    2018                 :       8924 :   rtx dest = VINSN_LHS (EXPR_VINSN (expr));
    2019                 :            : 
    2020                 :       8924 :   if (dest != NULL_RTX && REG_P (dest))
    2021                 :       8924 :     return dest;
    2022                 :            : 
    2023                 :            :   return NULL_RTX;
    2024                 :            : }
    2025                 :            : 
    2026                 :            : /* Returns the REGNO of the R's destination.  */
    2027                 :            : unsigned
    2028                 :       7563 : expr_dest_regno (expr_t expr)
    2029                 :            : {
    2030                 :       7563 :   rtx dest = expr_dest_reg (expr);
    2031                 :            : 
    2032                 :       7563 :   gcc_assert (dest != NULL_RTX);
    2033                 :       7563 :   return REGNO (dest);
    2034                 :            : }
    2035                 :            : 
    2036                 :            : /* For a given LV_SET, mark all expressions in JOIN_SET, but not present in
    2037                 :            :    AV_SET having unavailable target register.  */
    2038                 :            : void
    2039                 :       6937 : mark_unavailable_targets (av_set_t join_set, av_set_t av_set, regset lv_set)
    2040                 :            : {
    2041                 :       6937 :   expr_t expr;
    2042                 :       6937 :   av_set_iterator avi;
    2043                 :            : 
    2044                 :      15354 :   FOR_EACH_EXPR (expr, avi, join_set)
    2045                 :       8417 :     if (av_set_lookup (av_set, EXPR_VINSN (expr)) == NULL)
    2046                 :       8417 :       set_unavailable_target_for_expr (expr, lv_set);
    2047                 :       6937 : }
    2048                 :            : 
    2049                 :            : 
    2050                 :            : /* Returns true if REG (at least partially) is present in REGS.  */
    2051                 :            : bool
    2052                 :       8090 : register_unavailable_p (regset regs, rtx reg)
    2053                 :            : {
    2054                 :       8090 :   unsigned regno, end_regno;
    2055                 :            : 
    2056                 :       8090 :   regno = REGNO (reg);
    2057                 :       8090 :   if (bitmap_bit_p (regs, regno))
    2058                 :            :     return true;
    2059                 :            : 
    2060                 :       6612 :   end_regno = END_REGNO (reg);
    2061                 :            : 
    2062                 :       6612 :   while (++regno < end_regno)
    2063                 :          0 :     if (bitmap_bit_p (regs, regno))
    2064                 :            :       return true;
    2065                 :            : 
    2066                 :            :   return false;
    2067                 :            : }
    2068                 :            : 
    2069                 :            : /* Av set functions.  */
    2070                 :            : 
    2071                 :            : /* Add a new element to av set SETP.
    2072                 :            :    Return the element added.  */
    2073                 :            : static av_set_t
    2074                 :     160429 : av_set_add_element (av_set_t *setp)
    2075                 :            : {
    2076                 :            :   /* Insert at the beginning of the list.  */
    2077                 :          0 :   _list_add (setp);
    2078                 :     160429 :   return *setp;
    2079                 :            : }
    2080                 :            : 
    2081                 :            : /* Add EXPR to SETP.  */
    2082                 :            : void
    2083                 :     157721 : av_set_add (av_set_t *setp, expr_t expr)
    2084                 :            : {
    2085                 :     157721 :   av_set_t elem;
    2086                 :            : 
    2087                 :     157721 :   gcc_assert (!INSN_NOP_P (EXPR_INSN_RTX (expr)));
    2088                 :     157721 :   elem = av_set_add_element (setp);
    2089                 :     157721 :   copy_expr (_AV_SET_EXPR (elem), expr);
    2090                 :     157721 : }
    2091                 :            : 
    2092                 :            : /* Same, but do not copy EXPR.  */
    2093                 :            : static void
    2094                 :       2708 : av_set_add_nocopy (av_set_t *setp, expr_t expr)
    2095                 :            : {
    2096                 :       2708 :   av_set_t elem;
    2097                 :            : 
    2098                 :       2708 :   elem = av_set_add_element (setp);
    2099                 :       2708 :   *_AV_SET_EXPR (elem) = *expr;
    2100                 :       2708 : }
    2101                 :            : 
    2102                 :            : /* Remove expr pointed to by IP from the av_set.  */
    2103                 :            : void
    2104                 :     157721 : av_set_iter_remove (av_set_iterator *ip)
    2105                 :            : {
    2106                 :     157721 :   clear_expr (_AV_SET_EXPR (*ip->lp));
    2107                 :     157721 :   _list_iter_remove (ip);
    2108                 :     157721 : }
    2109                 :            : 
    2110                 :            : /* Search for an expr in SET, such that it's equivalent to SOUGHT_VINSN in the
    2111                 :            :    sense of vinsn_equal_p function. Return NULL if no such expr is
    2112                 :            :    in SET was found.  */
    2113                 :            : expr_t
    2114                 :     238821 : av_set_lookup (av_set_t set, vinsn_t sought_vinsn)
    2115                 :            : {
    2116                 :     238821 :   expr_t expr;
    2117                 :     238821 :   av_set_iterator i;
    2118                 :            : 
    2119                 :     514000 :   FOR_EACH_EXPR (expr, i, set)
    2120                 :     319841 :     if (vinsn_equal_p (EXPR_VINSN (expr), sought_vinsn))
    2121                 :      44662 :       return expr;
    2122                 :            :   return NULL;
    2123                 :            : }
    2124                 :            : 
    2125                 :            : /* Same, but also remove the EXPR found.   */
    2126                 :            : static expr_t
    2127                 :       5596 : av_set_lookup_and_remove (av_set_t *setp, vinsn_t sought_vinsn)
    2128                 :            : {
    2129                 :       5596 :   expr_t expr;
    2130                 :       5596 :   av_set_iterator i;
    2131                 :            : 
    2132                 :      27068 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2133                 :      13444 :     if (vinsn_equal_p (EXPR_VINSN (expr), sought_vinsn))
    2134                 :            :       {
    2135                 :       2708 :         _list_iter_remove_nofree (&i);
    2136                 :       2708 :         return expr;
    2137                 :            :       }
    2138                 :            :   return NULL;
    2139                 :            : }
    2140                 :            : 
    2141                 :            : /* Search for an expr in SET, such that it's equivalent to EXPR in the
    2142                 :            :    sense of vinsn_equal_p function of their vinsns, but not EXPR itself.
    2143                 :            :    Returns NULL if no such expr is in SET was found.  */
    2144                 :            : static expr_t
    2145                 :        404 : av_set_lookup_other_equiv_expr (av_set_t set, expr_t expr)
    2146                 :            : {
    2147                 :        404 :   expr_t cur_expr;
    2148                 :        404 :   av_set_iterator i;
    2149                 :            : 
    2150                 :       1851 :   FOR_EACH_EXPR (cur_expr, i, set)
    2151                 :            :     {
    2152                 :       1471 :       if (cur_expr == expr)
    2153                 :        382 :         continue;
    2154                 :       1089 :       if (vinsn_equal_p (EXPR_VINSN (cur_expr), EXPR_VINSN (expr)))
    2155                 :         24 :         return cur_expr;
    2156                 :            :     }
    2157                 :            : 
    2158                 :            :   return NULL;
    2159                 :            : }
    2160                 :            : 
    2161                 :            : /* If other expression is already in AVP, remove one of them.  */
    2162                 :            : expr_t
    2163                 :        404 : merge_with_other_exprs (av_set_t *avp, av_set_iterator *ip, expr_t expr)
    2164                 :            : {
    2165                 :        404 :   expr_t expr2;
    2166                 :            : 
    2167                 :        404 :   expr2 = av_set_lookup_other_equiv_expr (*avp, expr);
    2168                 :        404 :   if (expr2 != NULL)
    2169                 :            :     {
    2170                 :            :       /* Reset target availability on merge, since taking it only from one
    2171                 :            :          of the exprs would be controversial for different code.  */
    2172                 :         24 :       EXPR_TARGET_AVAILABLE (expr2) = -1;
    2173                 :         24 :       EXPR_USEFULNESS (expr2) = 0;
    2174                 :            : 
    2175                 :         24 :       merge_expr (expr2, expr, NULL);
    2176                 :            : 
    2177                 :            :       /* Fix usefulness as it should be now REG_BR_PROB_BASE.  */
    2178                 :         24 :       EXPR_USEFULNESS (expr2) = REG_BR_PROB_BASE;
    2179                 :            : 
    2180                 :         24 :       av_set_iter_remove (ip);
    2181                 :         24 :       return expr2;
    2182                 :            :     }
    2183                 :            : 
    2184                 :            :   return expr;
    2185                 :            : }
    2186                 :            : 
    2187                 :            : /* Return true if there is an expr that correlates to VI in SET.  */
    2188                 :            : bool
    2189                 :      34116 : av_set_is_in_p (av_set_t set, vinsn_t vi)
    2190                 :            : {
    2191                 :      34116 :   return av_set_lookup (set, vi) != NULL;
    2192                 :            : }
    2193                 :            : 
    2194                 :            : /* Return a copy of SET.  */
    2195                 :            : av_set_t
    2196                 :      42829 : av_set_copy (av_set_t set)
    2197                 :            : {
    2198                 :      42829 :   expr_t expr;
    2199                 :      42829 :   av_set_iterator i;
    2200                 :      42829 :   av_set_t res = NULL;
    2201                 :            : 
    2202                 :     134635 :   FOR_EACH_EXPR (expr, i, set)
    2203                 :      91806 :     av_set_add (&res, expr);
    2204                 :            : 
    2205                 :      42829 :   return res;
    2206                 :            : }
    2207                 :            : 
    2208                 :            : /* Join two av sets that do not have common elements by attaching second set
    2209                 :            :    (pointed to by FROMP) to the end of first set (TO_TAILP must point to
    2210                 :            :    _AV_SET_NEXT of first set's last element).  */
    2211                 :            : static void
    2212                 :      70276 : join_distinct_sets (av_set_t *to_tailp, av_set_t *fromp)
    2213                 :            : {
    2214                 :          0 :   gcc_assert (*to_tailp == NULL);
    2215                 :      71737 :   *to_tailp = *fromp;
    2216                 :      71737 :   *fromp = NULL;
    2217                 :          0 : }
    2218                 :            : 
    2219                 :            : /* Makes set pointed to by TO to be the union of TO and FROM.  Clear av_set
    2220                 :            :    pointed to by FROMP afterwards.  */
    2221                 :            : void
    2222                 :      68815 : av_set_union_and_clear (av_set_t *top, av_set_t *fromp, insn_t insn)
    2223                 :            : {
    2224                 :      68815 :   expr_t expr1;
    2225                 :      68815 :   av_set_iterator i;
    2226                 :            : 
    2227                 :            :   /* Delete from TOP all exprs, that present in FROMP.  */
    2228                 :     183393 :   FOR_EACH_EXPR_1 (expr1, i, top)
    2229                 :            :     {
    2230                 :      57289 :       expr_t expr2 = av_set_lookup (*fromp, EXPR_VINSN (expr1));
    2231                 :            : 
    2232                 :      57289 :       if (expr2)
    2233                 :            :         {
    2234                 :          0 :           merge_expr (expr2, expr1, insn);
    2235                 :          0 :           av_set_iter_remove (&i);
    2236                 :            :         }
    2237                 :            :     }
    2238                 :            : 
    2239                 :      68815 :   join_distinct_sets (i.lp, fromp);
    2240                 :      68815 : }
    2241                 :            : 
    2242                 :            : /* Same as above, but also update availability of target register in
    2243                 :            :    TOP judging by TO_LV_SET and FROM_LV_SET.  */
    2244                 :            : void
    2245                 :       1461 : av_set_union_and_live (av_set_t *top, av_set_t *fromp, regset to_lv_set,
    2246                 :            :                        regset from_lv_set, insn_t insn)
    2247                 :            : {
    2248                 :       1461 :   expr_t expr1;
    2249                 :       1461 :   av_set_iterator i;
    2250                 :       1461 :   av_set_t *to_tailp, in_both_set = NULL;
    2251                 :            : 
    2252                 :            :   /* Delete from TOP all expres, that present in FROMP.  */
    2253                 :      12653 :   FOR_EACH_EXPR_1 (expr1, i, top)
    2254                 :            :     {
    2255                 :       5596 :       expr_t expr2 = av_set_lookup_and_remove (fromp, EXPR_VINSN (expr1));
    2256                 :            : 
    2257                 :       5596 :       if (expr2)
    2258                 :            :         {
    2259                 :            :           /* It may be that the expressions have different destination
    2260                 :            :              registers, in which case we need to check liveness here.  */
    2261                 :       2708 :           if (EXPR_SEPARABLE_P (expr1))
    2262                 :            :             {
    2263                 :       1099 :               int regno1 = (REG_P (EXPR_LHS (expr1))
    2264                 :       1099 :                             ? (int) expr_dest_regno (expr1) : -1);
    2265                 :       1099 :               int regno2 = (REG_P (EXPR_LHS (expr2))
    2266                 :       1099 :                             ? (int) expr_dest_regno (expr2) : -1);
    2267                 :            : 
    2268                 :            :               /* ??? We don't have a way to check restrictions for
    2269                 :            :                *other* register on the current path, we did it only
    2270                 :            :                for the current target register.  Give up.  */
    2271                 :       1099 :               if (regno1 != regno2)
    2272                 :        108 :                 EXPR_TARGET_AVAILABLE (expr2) = -1;
    2273                 :            :             }
    2274                 :       1609 :           else if (EXPR_INSN_RTX (expr1) != EXPR_INSN_RTX (expr2))
    2275                 :        757 :             EXPR_TARGET_AVAILABLE (expr2) = -1;
    2276                 :            : 
    2277                 :       2708 :           merge_expr (expr2, expr1, insn);
    2278                 :       2708 :           av_set_add_nocopy (&in_both_set, expr2);
    2279                 :       2708 :           av_set_iter_remove (&i);
    2280                 :            :         }
    2281                 :            :       else
    2282                 :            :         /* EXPR1 is present in TOP, but not in FROMP.  Check it on
    2283                 :            :            FROM_LV_SET.  */
    2284                 :       2888 :         set_unavailable_target_for_expr (expr1, from_lv_set);
    2285                 :            :     }
    2286                 :       1461 :   to_tailp = i.lp;
    2287                 :            : 
    2288                 :            :   /* These expressions are not present in TOP.  Check liveness
    2289                 :            :      restrictions on TO_LV_SET.  */
    2290                 :       5665 :   FOR_EACH_EXPR (expr1, i, *fromp)
    2291                 :       2102 :     set_unavailable_target_for_expr (expr1, to_lv_set);
    2292                 :            : 
    2293                 :       1461 :   join_distinct_sets (i.lp, &in_both_set);
    2294                 :       1461 :   join_distinct_sets (to_tailp, fromp);
    2295                 :       1461 : }
    2296                 :            : 
    2297                 :            : /* Clear av_set pointed to by SETP.  */
    2298                 :            : void
    2299                 :      67917 : av_set_clear (av_set_t *setp)
    2300                 :            : {
    2301                 :      67917 :   expr_t expr;
    2302                 :      67917 :   av_set_iterator i;
    2303                 :            : 
    2304                 :     267491 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2305                 :      99787 :     av_set_iter_remove (&i);
    2306                 :            : 
    2307                 :      67917 :   gcc_assert (*setp == NULL);
    2308                 :      67917 : }
    2309                 :            : 
    2310                 :            : /* Leave only one non-speculative element in the SETP.  */
    2311                 :            : void
    2312                 :      18159 : av_set_leave_one_nonspec (av_set_t *setp)
    2313                 :            : {
    2314                 :      18159 :   expr_t expr;
    2315                 :      18159 :   av_set_iterator i;
    2316                 :      18159 :   bool has_one_nonspec = false;
    2317                 :            : 
    2318                 :            :   /* Keep all speculative exprs, and leave one non-speculative
    2319                 :            :      (the first one).  */
    2320                 :      54581 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2321                 :            :     {
    2322                 :      18211 :       if (!EXPR_SPEC_DONE_DS (expr))
    2323                 :            :         {
    2324                 :      18211 :           if (has_one_nonspec)
    2325                 :         52 :             av_set_iter_remove (&i);
    2326                 :            :           else
    2327                 :            :             has_one_nonspec = true;
    2328                 :            :         }
    2329                 :            :     }
    2330                 :      18159 : }
    2331                 :            : 
    2332                 :            : /* Return the N'th element of the SET.  */
    2333                 :            : expr_t
    2334                 :          0 : av_set_element (av_set_t set, int n)
    2335                 :            : {
    2336                 :          0 :   expr_t expr;
    2337                 :          0 :   av_set_iterator i;
    2338                 :            : 
    2339                 :          0 :   FOR_EACH_EXPR (expr, i, set)
    2340                 :          0 :     if (n-- == 0)
    2341                 :          0 :       return expr;
    2342                 :            : 
    2343                 :          0 :   gcc_unreachable ();
    2344                 :            :   return NULL;
    2345                 :            : }
    2346                 :            : 
    2347                 :            : /* Deletes all expressions from AVP that are conditional branches (IFs).  */
    2348                 :            : void
    2349                 :       5187 : av_set_substract_cond_branches (av_set_t *avp)
    2350                 :            : {
    2351                 :       5187 :   av_set_iterator i;
    2352                 :       5187 :   expr_t expr;
    2353                 :            : 
    2354                 :      37417 :   FOR_EACH_EXPR_1 (expr, i, avp)
    2355                 :      16115 :     if (vinsn_cond_branch_p (EXPR_VINSN (expr)))
    2356                 :        390 :       av_set_iter_remove (&i);
    2357                 :       5187 : }
    2358                 :            : 
    2359                 :            : /* Multiplies usefulness attribute of each member of av-set *AVP by
    2360                 :            :    value PROB / ALL_PROB.  */
    2361                 :            : void
    2362                 :       7913 : av_set_split_usefulness (av_set_t av, int prob, int all_prob)
    2363                 :            : {
    2364                 :       7913 :   av_set_iterator i;
    2365                 :       7913 :   expr_t expr;
    2366                 :            : 
    2367                 :      36076 :   FOR_EACH_EXPR (expr, i, av)
    2368                 :      56326 :     EXPR_USEFULNESS (expr) = (all_prob
    2369                 :      28163 :                               ? (EXPR_USEFULNESS (expr) * prob) / all_prob
    2370                 :            :                               : 0);
    2371                 :       7913 : }
    2372                 :            : 
    2373                 :            : /* Leave in AVP only those expressions, which are present in AV,
    2374                 :            :    and return it, merging history expressions.  */
    2375                 :            : void
    2376                 :      11706 : av_set_code_motion_filter (av_set_t *avp, av_set_t av)
    2377                 :            : {
    2378                 :      11706 :   av_set_iterator i;
    2379                 :      11706 :   expr_t expr, expr2;
    2380                 :            : 
    2381                 :      35402 :   FOR_EACH_EXPR_1 (expr, i, avp)
    2382                 :      11848 :     if ((expr2 = av_set_lookup (av, EXPR_VINSN (expr))) == NULL)
    2383                 :       1369 :       av_set_iter_remove (&i);
    2384                 :            :     else
    2385                 :            :       /* When updating av sets in bookkeeping blocks, we can add more insns
    2386                 :            :          there which will be transformed but the upper av sets will not
    2387                 :            :          reflect those transformations.  We then fail to undo those
    2388                 :            :          when searching for such insns.  So merge the history saved
    2389                 :            :          in the av set of the block we are processing.  */
    2390                 :      10479 :       merge_history_vect (&EXPR_HISTORY_OF_CHANGES (expr),
    2391                 :            :                           EXPR_HISTORY_OF_CHANGES (expr2));
    2392                 :      11706 : }
    2393                 :            : 
    2394                 :            : 
    2395                 :            : 
    2396                 :            : /* Dependence hooks to initialize insn data.  */
    2397                 :            : 
    2398                 :            : /* This is used in hooks callable from dependence analysis when initializing
    2399                 :            :    instruction's data.  */
    2400                 :            : static struct
    2401                 :            : {
    2402                 :            :   /* Where the dependence was found (lhs/rhs).  */
    2403                 :            :   deps_where_t where;
    2404                 :            : 
    2405                 :            :   /* The actual data object to initialize.  */
    2406                 :            :   idata_t id;
    2407                 :            : 
    2408                 :            :   /* True when the insn should not be made clonable.  */
    2409                 :            :   bool force_unique_p;
    2410                 :            : 
    2411                 :            :   /* True when insn should be treated as of type USE, i.e. never renamed.  */
    2412                 :            :   bool force_use_p;
    2413                 :            : } deps_init_id_data;
    2414                 :            : 
    2415                 :            : 
    2416                 :            : /* Setup ID for INSN.  FORCE_UNIQUE_P is true when INSN should not be
    2417                 :            :    clonable.  */
    2418                 :            : static void
    2419                 :       5224 : setup_id_for_insn (idata_t id, insn_t insn, bool force_unique_p)
    2420                 :            : {
    2421                 :       5224 :   int type;
    2422                 :            : 
    2423                 :            :   /* Determine whether INSN could be cloned and return appropriate vinsn type.
    2424                 :            :      That clonable insns which can be separated into lhs and rhs have type SET.
    2425                 :            :      Other clonable insns have type USE.  */
    2426                 :       5224 :   type = GET_CODE (insn);
    2427                 :            : 
    2428                 :            :   /* Only regular insns could be cloned.  */
    2429                 :       5224 :   if (type == INSN && !force_unique_p)
    2430                 :            :     type = SET;
    2431                 :       1716 :   else if (type == JUMP_INSN && simplejump_p (insn))
    2432                 :            :     type = PC;
    2433                 :       1480 :   else if (type == DEBUG_INSN)
    2434                 :         96 :     type = !force_unique_p ? USE : INSN;
    2435                 :            : 
    2436                 :       5224 :   IDATA_TYPE (id) = type;
    2437                 :       5224 :   IDATA_REG_SETS (id) = get_clear_regset_from_pool ();
    2438                 :       5224 :   IDATA_REG_USES (id) = get_clear_regset_from_pool ();
    2439                 :       5224 :   IDATA_REG_CLOBBERS (id) = get_clear_regset_from_pool ();
    2440                 :       5224 : }
    2441                 :            : 
    2442                 :            : /* Start initializing insn data.  */
    2443                 :            : static void
    2444                 :        772 : deps_init_id_start_insn (insn_t insn)
    2445                 :            : {
    2446                 :        772 :   gcc_assert (deps_init_id_data.where == DEPS_IN_NOWHERE);
    2447                 :            : 
    2448                 :        772 :   setup_id_for_insn (deps_init_id_data.id, insn,
    2449                 :        772 :                      deps_init_id_data.force_unique_p);
    2450                 :        772 :   deps_init_id_data.where = DEPS_IN_INSN;
    2451                 :        772 : }
    2452                 :            : 
    2453                 :            : /* Start initializing lhs data.  */
    2454                 :            : static void
    2455                 :        730 : deps_init_id_start_lhs (rtx lhs)
    2456                 :            : {
    2457                 :        730 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2458                 :        730 :   gcc_assert (IDATA_LHS (deps_init_id_data.id) == NULL);
    2459                 :            : 
    2460                 :        730 :   if (IDATA_TYPE (deps_init_id_data.id) == SET)
    2461                 :            :     {
    2462                 :        730 :       IDATA_LHS (deps_init_id_data.id) = lhs;
    2463                 :        730 :       deps_init_id_data.where = DEPS_IN_LHS;
    2464                 :            :     }
    2465                 :        730 : }
    2466                 :            : 
    2467                 :            : /* Finish initializing lhs data.  */
    2468                 :            : static void
    2469                 :        730 : deps_init_id_finish_lhs (void)
    2470                 :            : {
    2471                 :        730 :   deps_init_id_data.where = DEPS_IN_INSN;
    2472                 :        730 : }
    2473                 :            : 
    2474                 :            : /* Note a set of REGNO.  */
    2475                 :            : static void
    2476                 :        743 : deps_init_id_note_reg_set (int regno)
    2477                 :            : {
    2478                 :        743 :   haifa_note_reg_set (regno);
    2479                 :            : 
    2480                 :        743 :   if (deps_init_id_data.where == DEPS_IN_RHS)
    2481                 :          0 :     deps_init_id_data.force_use_p = true;
    2482                 :            : 
    2483                 :        743 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2484                 :        743 :     SET_REGNO_REG_SET (IDATA_REG_SETS (deps_init_id_data.id), regno);
    2485                 :            : 
    2486                 :            : #ifdef STACK_REGS
    2487                 :            :   /* Make instructions that set stack registers to be ineligible for
    2488                 :            :      renaming to avoid issues with find_used_regs.  */
    2489                 :        743 :   if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2490                 :          0 :     deps_init_id_data.force_use_p = true;
    2491                 :            : #endif
    2492                 :        743 : }
    2493                 :            : 
    2494                 :            : /* Note a clobber of REGNO.  */
    2495                 :            : static void
    2496                 :         19 : deps_init_id_note_reg_clobber (int regno)
    2497                 :            : {
    2498                 :         19 :   haifa_note_reg_clobber (regno);
    2499                 :            : 
    2500                 :         19 :   if (deps_init_id_data.where == DEPS_IN_RHS)
    2501                 :          0 :     deps_init_id_data.force_use_p = true;
    2502                 :            : 
    2503                 :         19 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2504                 :         19 :     SET_REGNO_REG_SET (IDATA_REG_CLOBBERS (deps_init_id_data.id), regno);
    2505                 :         19 : }
    2506                 :            : 
    2507                 :            : /* Note a use of REGNO.  */
    2508                 :            : static void
    2509                 :        646 : deps_init_id_note_reg_use (int regno)
    2510                 :            : {
    2511                 :        646 :   haifa_note_reg_use (regno);
    2512                 :            : 
    2513                 :        646 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2514                 :        646 :     SET_REGNO_REG_SET (IDATA_REG_USES (deps_init_id_data.id), regno);
    2515                 :        646 : }
    2516                 :            : 
    2517                 :            : /* Start initializing rhs data.  */
    2518                 :            : static void
    2519                 :        730 : deps_init_id_start_rhs (rtx rhs)
    2520                 :            : {
    2521                 :        730 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2522                 :            : 
    2523                 :            :   /* And there was no sel_deps_reset_to_insn ().  */
    2524                 :        730 :   if (IDATA_LHS (deps_init_id_data.id) != NULL)
    2525                 :            :     {
    2526                 :        730 :       IDATA_RHS (deps_init_id_data.id) = rhs;
    2527                 :        730 :       deps_init_id_data.where = DEPS_IN_RHS;
    2528                 :            :     }
    2529                 :        730 : }
    2530                 :            : 
    2531                 :            : /* Finish initializing rhs data.  */
    2532                 :            : static void
    2533                 :        730 : deps_init_id_finish_rhs (void)
    2534                 :            : {
    2535                 :        730 :   gcc_assert (deps_init_id_data.where == DEPS_IN_RHS
    2536                 :            :               || deps_init_id_data.where == DEPS_IN_INSN);
    2537                 :        730 :   deps_init_id_data.where = DEPS_IN_INSN;
    2538                 :        730 : }
    2539                 :            : 
    2540                 :            : /* Finish initializing insn data.  */
    2541                 :            : static void
    2542                 :        772 : deps_init_id_finish_insn (void)
    2543                 :            : {
    2544                 :        772 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2545                 :            : 
    2546                 :        772 :   if (IDATA_TYPE (deps_init_id_data.id) == SET)
    2547                 :            :     {
    2548                 :        751 :       rtx lhs = IDATA_LHS (deps_init_id_data.id);
    2549                 :        751 :       rtx rhs = IDATA_RHS (deps_init_id_data.id);
    2550                 :            : 
    2551                 :       1502 :       if (lhs == NULL || rhs == NULL || !lhs_and_rhs_separable_p (lhs, rhs)
    2552                 :        999 :           || deps_init_id_data.force_use_p)
    2553                 :            :         {
    2554                 :            :           /* This should be a USE, as we don't want to schedule its RHS
    2555                 :            :              separately.  However, we still want to have them recorded
    2556                 :            :              for the purposes of substitution.  That's why we don't
    2557                 :            :              simply call downgrade_to_use () here.  */
    2558                 :        503 :           gcc_assert (IDATA_TYPE (deps_init_id_data.id) == SET);
    2559                 :        503 :           gcc_assert (!lhs == !rhs);
    2560                 :            : 
    2561                 :        503 :           IDATA_TYPE (deps_init_id_data.id) = USE;
    2562                 :            :         }
    2563                 :            :     }
    2564                 :            : 
    2565                 :        772 :   deps_init_id_data.where = DEPS_IN_NOWHERE;
    2566                 :        772 : }
    2567                 :            : 
    2568                 :            : /* This is dependence info used for initializing insn's data.  */
    2569                 :            : static struct sched_deps_info_def deps_init_id_sched_deps_info;
    2570                 :            : 
    2571                 :            : /* This initializes most of the static part of the above structure.  */
    2572                 :            : static const struct sched_deps_info_def const_deps_init_id_sched_deps_info =
    2573                 :            :   {
    2574                 :            :     NULL,
    2575                 :            : 
    2576                 :            :     deps_init_id_start_insn,
    2577                 :            :     deps_init_id_finish_insn,
    2578                 :            :     deps_init_id_start_lhs,
    2579                 :            :     deps_init_id_finish_lhs,
    2580                 :            :     deps_init_id_start_rhs,
    2581                 :            :     deps_init_id_finish_rhs,
    2582                 :            :     deps_init_id_note_reg_set,
    2583                 :            :     deps_init_id_note_reg_clobber,
    2584                 :            :     deps_init_id_note_reg_use,
    2585                 :            :     NULL, /* note_mem_dep */
    2586                 :            :     NULL, /* note_dep */
    2587                 :            : 
    2588                 :            :     0, /* use_cselib */
    2589                 :            :     0, /* use_deps_list */
    2590                 :            :     0 /* generate_spec_deps */
    2591                 :            :   };
    2592                 :            : 
    2593                 :            : /* Initialize INSN's lhs and rhs in ID.  When FORCE_UNIQUE_P is true,
    2594                 :            :    we don't actually need information about lhs and rhs.  */
    2595                 :            : static void
    2596                 :       4452 : setup_id_lhs_rhs (idata_t id, insn_t insn, bool force_unique_p)
    2597                 :            : {
    2598                 :          0 :   rtx pat = PATTERN (insn);
    2599                 :            : 
    2600                 :       4452 :   if (NONJUMP_INSN_P (insn)
    2601                 :       3433 :       && GET_CODE (pat) == SET
    2602                 :       2666 :       && !force_unique_p)
    2603                 :            :     {
    2604                 :       2119 :       IDATA_RHS (id) = SET_SRC (pat);
    2605                 :       2119 :       IDATA_LHS (id) = SET_DEST (pat);
    2606                 :            :     }
    2607                 :            :   else
    2608                 :       2333 :     IDATA_LHS (id) = IDATA_RHS (id) = NULL;
    2609                 :          0 : }
    2610                 :            : 
    2611                 :            : /* Possibly downgrade INSN to USE.  */
    2612                 :            : static void
    2613                 :       4452 : maybe_downgrade_id_to_use (idata_t id, insn_t insn)
    2614                 :            : {
    2615                 :       4452 :   bool must_be_use = false;
    2616                 :       4452 :   df_ref def;
    2617                 :       4452 :   rtx lhs = IDATA_LHS (id);
    2618                 :       4452 :   rtx rhs = IDATA_RHS (id);
    2619                 :            : 
    2620                 :            :   /* We downgrade only SETs.  */
    2621                 :       4452 :   if (IDATA_TYPE (id) != SET)
    2622                 :            :     return;
    2623                 :            : 
    2624                 :       2757 :   if (!lhs || !lhs_and_rhs_separable_p (lhs, rhs))
    2625                 :            :     {
    2626                 :       1665 :       IDATA_TYPE (id) = USE;
    2627                 :       1665 :       return;
    2628                 :            :     }
    2629                 :            : 
    2630                 :       2184 :   FOR_EACH_INSN_DEF (def, insn)
    2631                 :            :     {
    2632                 :       1094 :       if (DF_REF_INSN (def)
    2633                 :       1094 :           && DF_REF_FLAGS_IS_SET (def, DF_REF_PRE_POST_MODIFY)
    2634                 :       1096 :           && loc_mentioned_in_p (DF_REF_LOC (def), IDATA_RHS (id)))
    2635                 :            :         {
    2636                 :            :           must_be_use = true;
    2637                 :            :           break;
    2638                 :            :         }
    2639                 :            : 
    2640                 :            : #ifdef STACK_REGS
    2641                 :            :       /* Make instructions that set stack registers to be ineligible for
    2642                 :            :          renaming to avoid issues with find_used_regs.  */
    2643                 :       1092 :       if (IN_RANGE (DF_REF_REGNO (def), FIRST_STACK_REG, LAST_STACK_REG))
    2644                 :            :         {
    2645                 :            :           must_be_use = true;
    2646                 :            :           break;
    2647                 :            :         }
    2648                 :            : #endif
    2649                 :            :     }
    2650                 :            : 
    2651                 :       1092 :   if (must_be_use)
    2652                 :          2 :     IDATA_TYPE (id) = USE;
    2653                 :            : }
    2654                 :            : 
    2655                 :            : /* Setup implicit register clobbers calculated by sched-deps for INSN
    2656                 :            :    before reload and save them in ID.  */
    2657                 :            : static void
    2658                 :       5224 : setup_id_implicit_regs (idata_t id, insn_t insn)
    2659                 :            : {
    2660                 :       5224 :   if (reload_completed)
    2661                 :       3397 :     return;
    2662                 :            : 
    2663                 :       1827 :   HARD_REG_SET temp;
    2664                 :            : 
    2665                 :       1827 :   get_implicit_reg_pending_clobbers (&temp, insn);
    2666                 :       1827 :   IOR_REG_SET_HRS (IDATA_REG_SETS (id), temp);
    2667                 :            : }
    2668                 :            : 
    2669                 :            : /* Setup register sets describing INSN in ID.  */
    2670                 :            : static void
    2671                 :       4452 : setup_id_reg_sets (idata_t id, insn_t insn)
    2672                 :            : {
    2673                 :       4452 :   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
    2674                 :       4452 :   df_ref def, use;
    2675                 :       4452 :   regset tmp = get_clear_regset_from_pool ();
    2676                 :            : 
    2677                 :      18951 :   FOR_EACH_INSN_INFO_DEF (def, insn_info)
    2678                 :            :     {
    2679                 :      14499 :       unsigned int regno = DF_REF_REGNO (def);
    2680                 :            : 
    2681                 :            :       /* Post modifies are treated like clobbers by sched-deps.c.  */
    2682                 :      14499 :       if (DF_REF_FLAGS_IS_SET (def, (DF_REF_MUST_CLOBBER
    2683                 :            :                                      | DF_REF_PRE_POST_MODIFY)))
    2684                 :        852 :         SET_REGNO_REG_SET (IDATA_REG_CLOBBERS (id), regno);
    2685                 :      13647 :       else if (! DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
    2686                 :            :         {
    2687                 :       3085 :           SET_REGNO_REG_SET (IDATA_REG_SETS (id), regno);
    2688                 :            : 
    2689                 :            : #ifdef STACK_REGS
    2690                 :            :           /* For stack registers, treat writes to them as writes
    2691                 :            :              to the first one to be consistent with sched-deps.c.  */
    2692                 :       3085 :           if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2693                 :          0 :             SET_REGNO_REG_SET (IDATA_REG_SETS (id), FIRST_STACK_REG);
    2694                 :            : #endif
    2695                 :            :         }
    2696                 :            :       /* Mark special refs that generate read/write def pair.  */
    2697                 :      14499 :       if (DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)
    2698                 :      14499 :           || regno == STACK_POINTER_REGNUM)
    2699                 :        266 :         bitmap_set_bit (tmp, regno);
    2700                 :            :     }
    2701                 :            : 
    2702                 :       9453 :   FOR_EACH_INSN_INFO_USE (use, insn_info)
    2703                 :            :     {
    2704                 :       5001 :       unsigned int regno = DF_REF_REGNO (use);
    2705                 :            : 
    2706                 :            :       /* When these refs are met for the first time, skip them, as
    2707                 :            :          these uses are just counterparts of some defs.  */
    2708                 :       5001 :       if (bitmap_bit_p (tmp, regno))
    2709                 :        266 :         bitmap_clear_bit (tmp, regno);
    2710                 :       4735 :       else if (! DF_REF_FLAGS_IS_SET (use, DF_REF_CALL_STACK_USAGE))
    2711                 :            :         {
    2712                 :       4576 :           SET_REGNO_REG_SET (IDATA_REG_USES (id), regno);
    2713                 :            : 
    2714                 :            : #ifdef STACK_REGS
    2715                 :            :           /* For stack registers, treat reads from them as reads from
    2716                 :            :              the first one to be consistent with sched-deps.c.  */
    2717                 :       4576 :           if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2718                 :          0 :             SET_REGNO_REG_SET (IDATA_REG_USES (id), FIRST_STACK_REG);
    2719                 :            : #endif
    2720                 :            :         }
    2721                 :            :     }
    2722                 :            : 
    2723                 :            :   /* Also get implicit reg clobbers from sched-deps.  */
    2724                 :       4452 :   setup_id_implicit_regs (id, insn);
    2725                 :            : 
    2726                 :       4452 :   return_regset_to_pool (tmp);
    2727                 :       4452 : }
    2728                 :            : 
    2729                 :            : /* Initialize instruction data for INSN in ID using DF's data.  */
    2730                 :            : static void
    2731                 :       4452 : init_id_from_df (idata_t id, insn_t insn, bool force_unique_p)
    2732                 :            : {
    2733                 :       4452 :   gcc_assert (DF_INSN_UID_SAFE_GET (INSN_UID (insn)) != NULL);
    2734                 :            : 
    2735                 :       4452 :   setup_id_for_insn (id, insn, force_unique_p);
    2736                 :       4452 :   setup_id_lhs_rhs (id, insn, force_unique_p);
    2737                 :            : 
    2738                 :       4452 :   if (INSN_NOP_P (insn))
    2739                 :            :     return;
    2740                 :            : 
    2741                 :       4452 :   maybe_downgrade_id_to_use (id, insn);
    2742                 :       4452 :   setup_id_reg_sets (id, insn);
    2743                 :            : }
    2744                 :            : 
    2745                 :            : /* Initialize instruction data for INSN in ID.  */
    2746                 :            : static void
    2747                 :        772 : deps_init_id (idata_t id, insn_t insn, bool force_unique_p)
    2748                 :            : {
    2749                 :        772 :   class deps_desc _dc, *dc = &_dc;
    2750                 :            : 
    2751                 :        772 :   deps_init_id_data.where = DEPS_IN_NOWHERE;
    2752                 :        772 :   deps_init_id_data.id = id;
    2753                 :        772 :   deps_init_id_data.force_unique_p = force_unique_p;
    2754                 :        772 :   deps_init_id_data.force_use_p = false;
    2755                 :            : 
    2756                 :        772 :   init_deps (dc, false);
    2757                 :        772 :   memcpy (&deps_init_id_sched_deps_info,
    2758                 :            :           &const_deps_init_id_sched_deps_info,
    2759                 :            :           sizeof (deps_init_id_sched_deps_info));
    2760                 :        772 :   if (spec_info != NULL)
    2761                 :          0 :     deps_init_id_sched_deps_info.generate_spec_deps = 1;
    2762                 :        772 :   sched_deps_info = &deps_init_id_sched_deps_info;
    2763                 :            : 
    2764                 :        772 :   deps_analyze_insn (dc, insn);
    2765                 :            :   /* Implicit reg clobbers received from sched-deps separately.  */
    2766                 :        772 :   setup_id_implicit_regs (id, insn);
    2767                 :            : 
    2768                 :        772 :   free_deps (dc);
    2769                 :        772 :   deps_init_id_data.id = NULL;
    2770                 :        772 : }
    2771                 :            : 
    2772                 :            : 
    2773                 :            : struct sched_scan_info_def
    2774                 :            : {
    2775                 :            :   /* This hook notifies scheduler frontend to extend its internal per basic
    2776                 :            :      block data structures.  This hook should be called once before a series of
    2777                 :            :      calls to bb_init ().  */
    2778                 :            :   void (*extend_bb) (void);
    2779                 :            : 
    2780                 :            :   /* This hook makes scheduler frontend to initialize its internal data
    2781                 :            :      structures for the passed basic block.  */
    2782                 :            :   void (*init_bb) (basic_block);
    2783                 :            : 
    2784                 :            :   /* This hook notifies scheduler frontend to extend its internal per insn data
    2785                 :            :      structures.  This hook should be called once before a series of calls to
    2786                 :            :      insn_init ().  */
    2787                 :            :   void (*extend_insn) (void);
    2788                 :            : 
    2789                 :            :   /* This hook makes scheduler frontend to initialize its internal data
    2790                 :            :      structures for the passed insn.  */
    2791                 :            :   void (*init_insn) (insn_t);
    2792                 :            : };
    2793                 :            : 
    2794                 :            : /* A driver function to add a set of basic blocks (BBS) to the
    2795                 :            :    scheduling region.  */
    2796                 :            : static void
    2797                 :       2263 : sched_scan (const struct sched_scan_info_def *ssi, bb_vec_t bbs)
    2798                 :            : {
    2799                 :       2263 :   unsigned i;
    2800                 :       2263 :   basic_block bb;
    2801                 :            : 
    2802                 :       2263 :   if (ssi->extend_bb)
    2803                 :        803 :     ssi->extend_bb ();
    2804                 :            : 
    2805                 :       2263 :   if (ssi->init_bb)
    2806                 :       5524 :     FOR_EACH_VEC_ELT (bbs, i, bb)
    2807                 :       3261 :       ssi->init_bb (bb);
    2808                 :            : 
    2809                 :       2263 :   if (ssi->extend_insn)
    2810                 :        730 :     ssi->extend_insn ();
    2811                 :            : 
    2812                 :       2263 :   if (ssi->init_insn)
    2813                 :       3594 :     FOR_EACH_VEC_ELT (bbs, i, bb)
    2814                 :            :       {
    2815                 :       2134 :         rtx_insn *insn;
    2816                 :            : 
    2817                 :      26702 :         FOR_BB_INSNS (bb, insn)
    2818                 :      12284 :           ssi->init_insn (insn);
    2819                 :            :       }
    2820                 :       2263 : }
    2821                 :            : 
    2822                 :            : /* Implement hooks for collecting fundamental insn properties like if insn is
    2823                 :            :    an ASM or is within a SCHED_GROUP.  */
    2824                 :            : 
    2825                 :            : /* True when a "one-time init" data for INSN was already inited.  */
    2826                 :            : static bool
    2827                 :      21735 : first_time_insn_init (insn_t insn)
    2828                 :            : {
    2829                 :      21735 :   return INSN_LIVE (insn) == NULL;
    2830                 :            : }
    2831                 :            : 
    2832                 :            : /* Hash an entry in a transformed_insns hashtable.  */
    2833                 :            : static hashval_t
    2834                 :          0 : hash_transformed_insns (const void *p)
    2835                 :            : {
    2836                 :          0 :   return VINSN_HASH_RTX (((const struct transformed_insns *) p)->vinsn_old);
    2837                 :            : }
    2838                 :            : 
    2839                 :            : /* Compare the entries in a transformed_insns hashtable.  */
    2840                 :            : static int
    2841                 :        347 : eq_transformed_insns (const void *p, const void *q)
    2842                 :            : {
    2843                 :        347 :   rtx_insn *i1 =
    2844                 :        347 :     VINSN_INSN_RTX (((const struct transformed_insns *) p)->vinsn_old);
    2845                 :        347 :   rtx_insn *i2 =
    2846                 :        347 :     VINSN_INSN_RTX (((const struct transformed_insns *) q)->vinsn_old);
    2847                 :            : 
    2848                 :        347 :   if (INSN_UID (i1) == INSN_UID (i2))
    2849                 :            :     return 1;
    2850                 :         34 :   return rtx_equal_p (PATTERN (i1), PATTERN (i2));
    2851                 :            : }
    2852                 :            : 
    2853                 :            : /* Free an entry in a transformed_insns hashtable.  */
    2854                 :            : static void
    2855                 :         80 : free_transformed_insns (void *p)
    2856                 :            : {
    2857                 :         80 :   struct transformed_insns *pti = (struct transformed_insns *) p;
    2858                 :            : 
    2859                 :         80 :   vinsn_detach (pti->vinsn_old);
    2860                 :         80 :   vinsn_detach (pti->vinsn_new);
    2861                 :         80 :   free (pti);
    2862                 :         80 : }
    2863                 :            : 
    2864                 :            : /* Init the s_i_d data for INSN which should be inited just once, when
    2865                 :            :    we first see the insn.  */
    2866                 :            : static void
    2867                 :       5899 : init_first_time_insn_data (insn_t insn)
    2868                 :            : {
    2869                 :            :   /* This should not be set if this is the first time we init data for
    2870                 :            :      insn.  */
    2871                 :       5899 :   gcc_assert (first_time_insn_init (insn));
    2872                 :            : 
    2873                 :            :   /* These are needed for nops too.  */
    2874                 :       5899 :   INSN_LIVE (insn) = get_regset_from_pool ();
    2875                 :       5899 :   INSN_LIVE_VALID_P (insn) = false;
    2876                 :            : 
    2877                 :       5899 :   if (!INSN_NOP_P (insn))
    2878                 :            :     {
    2879                 :       5056 :       INSN_ANALYZED_DEPS (insn) = BITMAP_ALLOC (NULL);
    2880                 :       5056 :       INSN_FOUND_DEPS (insn) = BITMAP_ALLOC (NULL);
    2881                 :       5056 :       INSN_TRANSFORMED_INSNS (insn)
    2882                 :       5056 :         = htab_create (16, hash_transformed_insns,
    2883                 :            :                        eq_transformed_insns, free_transformed_insns);
    2884                 :       5056 :       init_deps (&INSN_DEPS_CONTEXT (insn), true);
    2885                 :            :     }
    2886                 :       5899 : }
    2887                 :            : 
    2888                 :            : /* Free almost all above data for INSN that is scheduled already.
    2889                 :            :    Used for extra-large basic blocks.  */
    2890                 :            : void
    2891                 :       8337 : free_data_for_scheduled_insn (insn_t insn)
    2892                 :            : {
    2893                 :       8337 :   gcc_assert (! first_time_insn_init (insn));
    2894                 :            : 
    2895                 :       8337 :   if (! INSN_ANALYZED_DEPS (insn))
    2896                 :            :     return;
    2897                 :            : 
    2898                 :       4677 :   BITMAP_FREE (INSN_ANALYZED_DEPS (insn));
    2899                 :       4677 :   BITMAP_FREE (INSN_FOUND_DEPS (insn));
    2900                 :       4677 :   htab_delete (INSN_TRANSFORMED_INSNS (insn));
    2901                 :            : 
    2902                 :            :   /* This is allocated only for bookkeeping insns.  */
    2903                 :       4677 :   if (INSN_ORIGINATORS (insn))
    2904                 :        281 :     BITMAP_FREE (INSN_ORIGINATORS (insn));
    2905                 :       4677 :   free_deps (&INSN_DEPS_CONTEXT (insn));
    2906                 :            : 
    2907                 :       4677 :   INSN_ANALYZED_DEPS (insn) = NULL;
    2908                 :            : 
    2909                 :            :   /* Clear the readonly flag so we would ICE when trying to recalculate
    2910                 :            :      the deps context (as we believe that it should not happen).  */
    2911                 :       4677 :   (&INSN_DEPS_CONTEXT (insn))->readonly = 0;
    2912                 :            : }
    2913                 :            : 
    2914                 :            : /* Free the same data as above for INSN.  */
    2915                 :            : static void
    2916                 :       4677 : free_first_time_insn_data (insn_t insn)
    2917                 :            : {
    2918                 :       4677 :   gcc_assert (! first_time_insn_init (insn));
    2919                 :            : 
    2920                 :       4677 :   free_data_for_scheduled_insn (insn);
    2921                 :       4677 :   return_regset_to_pool (INSN_LIVE (insn));
    2922                 :       4677 :   INSN_LIVE (insn) = NULL;
    2923                 :       4677 :   INSN_LIVE_VALID_P (insn) = false;
    2924                 :       4677 : }
    2925                 :            : 
    2926                 :            : /* Initialize region-scope data structures for basic blocks.  */
    2927                 :            : static void
    2928                 :       1061 : init_global_and_expr_for_bb (basic_block bb)
    2929                 :            : {
    2930                 :       1061 :   if (sel_bb_empty_p (bb))
    2931                 :            :     return;
    2932                 :            : 
    2933                 :       1024 :   invalidate_av_set (bb);
    2934                 :            : }
    2935                 :            : 
    2936                 :            : /* Data for global dependency analysis (to initialize CANT_MOVE and
    2937                 :            :    SCHED_GROUP_P).  */
    2938                 :            : static struct
    2939                 :            : {
    2940                 :            :   /* Previous insn.  */
    2941                 :            :   insn_t prev_insn;
    2942                 :            : } init_global_data;
    2943                 :            : 
    2944                 :            : /* Determine if INSN is in the sched_group, is an asm or should not be
    2945                 :            :    cloned.  After that initialize its expr.  */
    2946                 :            : static void
    2947                 :       5992 : init_global_and_expr_for_insn (insn_t insn)
    2948                 :            : {
    2949                 :       5992 :   if (LABEL_P (insn))
    2950                 :            :     return;
    2951                 :            : 
    2952                 :       5461 :   if (NOTE_INSN_BASIC_BLOCK_P (insn))
    2953                 :            :     {
    2954                 :       1061 :       init_global_data.prev_insn = NULL;
    2955                 :       1061 :       return;
    2956                 :            :     }
    2957                 :            : 
    2958                 :       4400 :   gcc_assert (INSN_P (insn));
    2959                 :            : 
    2960                 :       4400 :   if (SCHED_GROUP_P (insn))
    2961                 :            :     /* Setup a sched_group.  */
    2962                 :            :     {
    2963                 :        342 :       insn_t prev_insn = init_global_data.prev_insn;
    2964                 :            : 
    2965                 :        342 :       if (prev_insn)
    2966                 :          1 :         INSN_SCHED_NEXT (prev_insn) = insn;
    2967                 :            : 
    2968                 :        342 :       init_global_data.prev_insn = insn;
    2969                 :            :     }
    2970                 :            :   else
    2971                 :       4058 :     init_global_data.prev_insn = NULL;
    2972                 :            : 
    2973                 :       4400 :   if (GET_CODE (PATTERN (insn)) == ASM_INPUT
    2974                 :       4400 :       || asm_noperands (PATTERN (insn)) >= 0)
    2975                 :            :     /* Mark INSN as an asm.  */
    2976                 :         12 :     INSN_ASM_P (insn) = true;
    2977                 :            : 
    2978                 :       4400 :   {
    2979                 :       4400 :     bool force_unique_p;
    2980                 :       4400 :     ds_t spec_done_ds;
    2981                 :            : 
    2982                 :            :     /* Certain instructions cannot be cloned, and frame related insns and
    2983                 :            :        the insn adjacent to NOTE_INSN_EPILOGUE_BEG cannot be moved out of
    2984                 :            :        their block.  */
    2985                 :       4400 :     if (prologue_epilogue_contains (insn))
    2986                 :            :       {
    2987                 :        299 :         if (RTX_FRAME_RELATED_P (insn))
    2988                 :        239 :           CANT_MOVE (insn) = 1;
    2989                 :            :         else
    2990                 :            :           {
    2991                 :         60 :             rtx note;
    2992                 :         60 :             for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
    2993                 :         20 :               if (REG_NOTE_KIND (note) == REG_SAVE_NOTE
    2994                 :         20 :                   && ((enum insn_note) INTVAL (XEXP (note, 0))
    2995                 :            :                       == NOTE_INSN_EPILOGUE_BEG))
    2996                 :            :                 {
    2997                 :         20 :                   CANT_MOVE (insn) = 1;
    2998                 :         20 :                   break;
    2999                 :            :                 }
    3000                 :            :           }
    3001                 :            :         force_unique_p = true;
    3002                 :            :       }
    3003                 :            :     else
    3004                 :       4101 :       if (CANT_MOVE (insn)
    3005                 :       2826 :           || INSN_ASM_P (insn)
    3006                 :       2816 :           || SCHED_GROUP_P (insn)
    3007                 :       2816 :           || CALL_P (insn)
    3008                 :            :           /* Exception handling insns are always unique.  */
    3009                 :       2816 :           || (cfun->can_throw_non_call_exceptions && can_throw_internal (insn))
    3010                 :            :           /* TRAP_IF though have an INSN code is control_flow_insn_p ().  */
    3011                 :       2816 :           || control_flow_insn_p (insn)
    3012                 :       2811 :           || volatile_insn_p (PATTERN (insn))
    3013                 :       6911 :           || (targetm.cannot_copy_insn_p
    3014                 :          0 :               && targetm.cannot_copy_insn_p (insn)))
    3015                 :            :         force_unique_p = true;
    3016                 :            :       else
    3017                 :            :         force_unique_p = false;
    3018                 :            : 
    3019                 :       4400 :     if (targetm.sched.get_insn_spec_ds)
    3020                 :            :       {
    3021                 :          0 :         spec_done_ds = targetm.sched.get_insn_spec_ds (insn);
    3022                 :          0 :         spec_done_ds = ds_get_max_dep_weak (spec_done_ds);
    3023                 :            :       }
    3024                 :            :     else
    3025                 :            :       spec_done_ds = 0;
    3026                 :            : 
    3027                 :            :     /* Initialize INSN's expr.  */
    3028                 :       8800 :     init_expr (INSN_EXPR (insn), vinsn_create (insn, force_unique_p), 0,
    3029                 :       4400 :                REG_BR_PROB_BASE, INSN_PRIORITY (insn), 0, BLOCK_NUM (insn),
    3030                 :            :                spec_done_ds, 0, 0, vNULL, true,
    3031                 :       4400 :                false, false, false, CANT_MOVE (insn));
    3032                 :            :   }
    3033                 :            : 
    3034                 :       4400 :   init_first_time_insn_data (insn);
    3035                 :            : }
    3036                 :            : 
    3037                 :            : /* Scan the region and initialize instruction data for basic blocks BBS.  */
    3038                 :            : void
    3039                 :        730 : sel_init_global_and_expr (bb_vec_t bbs)
    3040                 :            : {
    3041                 :            :   /* ??? It would be nice to implement push / pop scheme for sched_infos.  */
    3042                 :        730 :   const struct sched_scan_info_def ssi =
    3043                 :            :     {
    3044                 :            :       NULL, /* extend_bb */
    3045                 :            :       init_global_and_expr_for_bb, /* init_bb */
    3046                 :            :       extend_insn_data, /* extend_insn */
    3047                 :            :       init_global_and_expr_for_insn /* init_insn */
    3048                 :            :     };
    3049                 :            : 
    3050                 :        730 :   sched_scan (&ssi, bbs);
    3051                 :        730 : }
    3052                 :            : 
    3053                 :            : /* Finalize region-scope data structures for basic blocks.  */
    3054                 :            : static void
    3055                 :       1073 : finish_global_and_expr_for_bb (basic_block bb)
    3056                 :            : {
    3057                 :       1073 :   av_set_clear (&BB_AV_SET (bb));
    3058                 :       1073 :   BB_AV_LEVEL (bb) = 0;
    3059                 :       1073 : }
    3060                 :            : 
    3061                 :            : /* Finalize INSN's data.  */
    3062                 :            : static void
    3063                 :       6292 : finish_global_and_expr_insn (insn_t insn)
    3064                 :            : {
    3065                 :       6292 :   if (LABEL_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn))
    3066                 :            :     return;
    3067                 :            : 
    3068                 :       4677 :   gcc_assert (INSN_P (insn));
    3069                 :            : 
    3070                 :       4677 :   if (INSN_LUID (insn) > 0)
    3071                 :            :     {
    3072                 :       4677 :       free_first_time_insn_data (insn);
    3073                 :       4677 :       INSN_WS_LEVEL (insn) = 0;
    3074                 :       4677 :       CANT_MOVE (insn) = 0;
    3075                 :            : 
    3076                 :            :       /* We can no longer assert this, as vinsns of this insn could be
    3077                 :            :          easily live in other insn's caches.  This should be changed to
    3078                 :            :          a counter-like approach among all vinsns.  */
    3079                 :       4677 :       gcc_assert (true || VINSN_COUNT (INSN_VINSN (insn)) == 1);
    3080                 :       4677 :       clear_expr (INSN_EXPR (insn));
    3081                 :            :     }
    3082                 :            : }
    3083                 :            : 
    3084                 :            : /* Finalize per instruction data for the whole region.  */
    3085                 :            : void
    3086                 :        730 : sel_finish_global_and_expr (void)
    3087                 :            : {
    3088                 :        730 :   {
    3089                 :        730 :     bb_vec_t bbs;
    3090                 :        730 :     int i;
    3091                 :            : 
    3092                 :        730 :     bbs.create (current_nr_blocks);
    3093                 :            : 
    3094                 :       1803 :     for (i = 0; i < current_nr_blocks; i++)
    3095                 :       1073 :       bbs.quick_push (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i)));
    3096                 :            : 
    3097                 :            :     /* Clear AV_SETs and INSN_EXPRs.  */
    3098                 :        730 :     {
    3099                 :        730 :       const struct sched_scan_info_def ssi =
    3100                 :            :         {
    3101                 :            :           NULL, /* extend_bb */
    3102                 :            :           finish_global_and_expr_for_bb, /* init_bb */
    3103                 :            :           NULL, /* extend_insn */
    3104                 :            :           finish_global_and_expr_insn /* init_insn */
    3105                 :            :         };
    3106                 :            : 
    3107                 :        730 :       sched_scan (&ssi, bbs);
    3108                 :            :     }
    3109                 :            : 
    3110                 :        730 :     bbs.release ();
    3111                 :            :   }
    3112                 :            : 
    3113                 :        730 :   finish_insns ();
    3114                 :        730 : }
    3115                 :            : 
    3116                 :            : 
    3117                 :            : /* In the below hooks, we merely calculate whether or not a dependence
    3118                 :            :    exists, and in what part of insn.  However, we will need more data
    3119                 :            :    when we'll start caching dependence requests.  */
    3120                 :            : 
    3121                 :            : /* Container to hold information for dependency analysis.  */
    3122                 :            : static struct
    3123                 :            : {
    3124                 :            :   deps_t dc;
    3125                 :            : 
    3126                 :            :   /* A variable to track which part of rtx we are scanning in
    3127                 :            :      sched-deps.c: sched_analyze_insn ().  */
    3128                 :            :   deps_where_t where;
    3129                 :            : 
    3130                 :            :   /* Current producer.  */
    3131                 :            :   insn_t pro;
    3132                 :            : 
    3133                 :            :   /* Current consumer.  */
    3134                 :            :   vinsn_t con;
    3135                 :            : 
    3136                 :            :   /* Is SEL_DEPS_HAS_DEP_P[DEPS_IN_X] is true, then X has a dependence.
    3137                 :            :      X is from { INSN, LHS, RHS }.  */
    3138                 :            :   ds_t has_dep_p[DEPS_IN_NOWHERE];
    3139                 :            : } has_dependence_data;
    3140                 :            : 
    3141                 :            : /* Start analyzing dependencies of INSN.  */
    3142                 :            : static void
    3143                 :      21416 : has_dependence_start_insn (insn_t insn ATTRIBUTE_UNUSED)
    3144                 :            : {
    3145                 :      21416 :   gcc_assert (has_dependence_data.where == DEPS_IN_NOWHERE);
    3146                 :            : 
    3147                 :      21416 :   has_dependence_data.where = DEPS_IN_INSN;
    3148                 :      21416 : }
    3149                 :            : 
    3150                 :            : /* Finish analyzing dependencies of an insn.  */
    3151                 :            : static void
    3152                 :      21416 : has_dependence_finish_insn (void)
    3153                 :            : {
    3154                 :      21416 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3155                 :            : 
    3156                 :      21416 :   has_dependence_data.where = DEPS_IN_NOWHERE;
    3157                 :      21416 : }
    3158                 :            : 
    3159                 :            : /* Start analyzing dependencies of LHS.  */
    3160                 :            : static void
    3161                 :      18078 : has_dependence_start_lhs (rtx lhs ATTRIBUTE_UNUSED)
    3162                 :            : {
    3163                 :      18078 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3164                 :            : 
    3165                 :      18078 :   if (VINSN_LHS (has_dependence_data.con) != NULL)
    3166                 :      17511 :     has_dependence_data.where = DEPS_IN_LHS;
    3167                 :      18078 : }
    3168                 :            : 
    3169                 :            : /* Finish analyzing dependencies of an lhs.  */
    3170                 :            : static void
    3171                 :      18078 : has_dependence_finish_lhs (void)
    3172                 :            : {
    3173                 :      18078 :   has_dependence_data.where = DEPS_IN_INSN;
    3174                 :      18078 : }
    3175                 :            : 
    3176                 :            : /* Start analyzing dependencies of RHS.  */
    3177                 :            : static void
    3178                 :      18078 : has_dependence_start_rhs (rtx rhs ATTRIBUTE_UNUSED)
    3179                 :            : {
    3180                 :      18078 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3181                 :            : 
    3182                 :      18078 :   if (VINSN_RHS (has_dependence_data.con) != NULL)
    3183                 :      17511 :     has_dependence_data.where = DEPS_IN_RHS;
    3184                 :      18078 : }
    3185                 :            : 
    3186                 :            : /* Start analyzing dependencies of an rhs.  */
    3187                 :            : static void
    3188                 :      18078 : has_dependence_finish_rhs (void)
    3189                 :            : {
    3190                 :      18078 :   gcc_assert (has_dependence_data.where == DEPS_IN_RHS
    3191                 :            :               || has_dependence_data.where == DEPS_IN_INSN);
    3192                 :            : 
    3193                 :      18078 :   has_dependence_data.where = DEPS_IN_INSN;
    3194                 :      18078 : }
    3195                 :            : 
    3196                 :            : /* Note a set of REGNO.  */
    3197                 :            : static void
    3198                 :      19668 : has_dependence_note_reg_set (int regno)
    3199                 :            : {
    3200                 :      19668 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3201                 :            : 
    3202                 :      19668 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3203                 :      19668 :                                        VINSN_INSN_RTX
    3204                 :            :                                        (has_dependence_data.con)))
    3205                 :            :     {
    3206                 :      19668 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3207                 :            : 
    3208                 :      19668 :       if (reg_last->sets != NULL
    3209                 :      18468 :           || reg_last->clobbers != NULL)
    3210                 :       1757 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_OUTPUT;
    3211                 :            : 
    3212                 :      19668 :       if (reg_last->uses || reg_last->implicit_sets)
    3213                 :        897 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
    3214                 :            :     }
    3215                 :      19668 : }
    3216                 :            : 
    3217                 :            : /* Note a clobber of REGNO.  */
    3218                 :            : static void
    3219                 :       1760 : has_dependence_note_reg_clobber (int regno)
    3220                 :            : {
    3221                 :       1760 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3222                 :            : 
    3223                 :       1760 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3224                 :       1760 :                                        VINSN_INSN_RTX
    3225                 :            :                                        (has_dependence_data.con)))
    3226                 :            :     {
    3227                 :       1760 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3228                 :            : 
    3229                 :       1760 :       if (reg_last->sets)
    3230                 :         27 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_OUTPUT;
    3231                 :            : 
    3232                 :       1760 :       if (reg_last->uses || reg_last->implicit_sets)
    3233                 :        277 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
    3234                 :            :     }
    3235                 :       1760 : }
    3236                 :            : 
    3237                 :            : /* Note a use of REGNO.  */
    3238                 :            : static void
    3239                 :      20408 : has_dependence_note_reg_use (int regno)
    3240                 :            : {
    3241                 :      20408 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3242                 :            : 
    3243                 :      20408 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3244                 :      20408 :                                        VINSN_INSN_RTX
    3245                 :            :                                        (has_dependence_data.con)))
    3246                 :            :     {
    3247                 :      20408 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3248                 :            : 
    3249                 :      20408 :       if (reg_last->sets)
    3250                 :       1829 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_TRUE;
    3251                 :            : 
    3252                 :      20408 :       if (reg_last->clobbers || reg_last->implicit_sets)
    3253                 :        152 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
    3254                 :            : 
    3255                 :            :       /* Merge BE_IN_SPEC bits into *DSP when the dependency producer
    3256                 :            :          is actually a check insn.  We need to do this for any register
    3257                 :            :          read-read dependency with the check unless we track properly
    3258                 :            :          all registers written by BE_IN_SPEC-speculated insns, as
    3259                 :            :          we don't have explicit dependence lists.  See PR 53975.  */
    3260                 :      20408 :       if (reg_last->uses)
    3261                 :            :         {
    3262                 :       2624 :           ds_t pro_spec_checked_ds;
    3263                 :            : 
    3264                 :       2624 :           pro_spec_checked_ds = INSN_SPEC_CHECKED_DS (has_dependence_data.pro);
    3265                 :       2624 :           pro_spec_checked_ds = ds_get_max_dep_weak (pro_spec_checked_ds);
    3266                 :            : 
    3267                 :       2624 :           if (pro_spec_checked_ds != 0)
    3268                 :          0 :             *dsp = ds_full_merge (*dsp, pro_spec_checked_ds,
    3269                 :            :                                   NULL_RTX, NULL_RTX);
    3270                 :            :         }
    3271                 :            :     }
    3272                 :      20408 : }
    3273                 :            : 
    3274                 :            : /* Note a memory dependence.  */
    3275                 :            : static void
    3276                 :        375 : has_dependence_note_mem_dep (rtx mem ATTRIBUTE_UNUSED,
    3277                 :            :                              rtx pending_mem ATTRIBUTE_UNUSED,
    3278                 :            :                              insn_t pending_insn ATTRIBUTE_UNUSED,
    3279                 :            :                              ds_t ds ATTRIBUTE_UNUSED)
    3280                 :            : {
    3281                 :        375 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3282                 :        375 :                                        VINSN_INSN_RTX (has_dependence_data.con)))
    3283                 :            :     {
    3284                 :        375 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3285                 :            : 
    3286                 :        375 :       *dsp = ds_full_merge (ds, *dsp, pending_mem, mem);
    3287                 :            :     }
    3288                 :        375 : }
    3289                 :            : 
    3290                 :            : /* Note a dependence.  */
    3291                 :            : static void
    3292                 :        969 : has_dependence_note_dep (insn_t pro, ds_t ds ATTRIBUTE_UNUSED)
    3293                 :            : {
    3294                 :        969 :   insn_t real_pro = has_dependence_data.pro;
    3295                 :        969 :   insn_t real_con = VINSN_INSN_RTX (has_dependence_data.con);
    3296                 :            : 
    3297                 :            :   /* We do not allow for debug insns to move through others unless they
    3298                 :            :      are at the start of bb.  This movement may create bookkeeping copies
    3299                 :            :      that later would not be able to move up, violating the invariant
    3300                 :            :      that a bookkeeping copy should be movable as the original insn.
    3301                 :            :      Detect that here and allow that movement if we allowed it before
    3302                 :            :      in the first place.  */
    3303                 :        329 :   if (DEBUG_INSN_P (real_con) && !DEBUG_INSN_P (real_pro)
    3304                 :       1188 :       && INSN_UID (NEXT_INSN (pro)) == INSN_UID (real_con))
    3305                 :            :     return;
    3306                 :            : 
    3307                 :        750 :   if (!sched_insns_conditions_mutex_p (real_pro, real_con))
    3308                 :            :     {
    3309                 :        750 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3310                 :            : 
    3311                 :        750 :       *dsp = ds_full_merge (ds, *dsp, NULL_RTX, NULL_RTX);
    3312                 :            :     }
    3313                 :            : }
    3314                 :            : 
    3315                 :            : /* Mark the insn as having a hard dependence that prevents speculation.  */
    3316                 :            : void
    3317                 :          0 : sel_mark_hard_insn (rtx insn)
    3318                 :            : {
    3319                 :          0 :   int i;
    3320                 :            : 
    3321                 :            :   /* Only work when we're in has_dependence_p mode.
    3322                 :            :      ??? This is a hack, this should actually be a hook.  */
    3323                 :          0 :   if (!has_dependence_data.dc || !has_dependence_data.pro)
    3324                 :            :     return;
    3325                 :            : 
    3326                 :          0 :   gcc_assert (insn == VINSN_INSN_RTX (has_dependence_data.con));
    3327                 :          0 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3328                 :            : 
    3329                 :          0 :   for (i = 0; i < DEPS_IN_NOWHERE; i++)
    3330                 :          0 :     has_dependence_data.has_dep_p[i] &= ~SPECULATIVE;
    3331                 :            : }
    3332                 :            : 
    3333                 :            : /* This structure holds the hooks for the dependency analysis used when
    3334                 :            :    actually processing dependencies in the scheduler.  */
    3335                 :            : static struct sched_deps_info_def has_dependence_sched_deps_info;
    3336                 :            : 
    3337                 :            : /* This initializes most of the fields of the above structure.  */
    3338                 :            : static const struct sched_deps_info_def const_has_dependence_sched_deps_info =
    3339                 :            :   {
    3340                 :            :     NULL,
    3341                 :            : 
    3342                 :            :     has_dependence_start_insn,
    3343                 :            :     has_dependence_finish_insn,
    3344                 :            :     has_dependence_start_lhs,
    3345                 :            :     has_dependence_finish_lhs,
    3346                 :            :     has_dependence_start_rhs,
    3347                 :            :     has_dependence_finish_rhs,
    3348                 :            :     has_dependence_note_reg_set,
    3349                 :            :     has_dependence_note_reg_clobber,
    3350                 :            :     has_dependence_note_reg_use,
    3351                 :            :     has_dependence_note_mem_dep,
    3352                 :            :     has_dependence_note_dep,
    3353                 :            : 
    3354                 :            :     0, /* use_cselib */
    3355                 :            :     0, /* use_deps_list */
    3356                 :            :     0 /* generate_spec_deps */
    3357                 :            :   };
    3358                 :            : 
    3359                 :            : /* Initialize has_dependence_sched_deps_info with extra spec field.  */
    3360                 :            : static void
    3361                 :      21416 : setup_has_dependence_sched_deps_info (void)
    3362                 :            : {
    3363                 :      21416 :   memcpy (&has_dependence_sched_deps_info,
    3364                 :            :           &const_has_dependence_sched_deps_info,
    3365                 :            :           sizeof (has_dependence_sched_deps_info));
    3366                 :            : 
    3367                 :          0 :   if (spec_info != NULL)
    3368                 :          0 :     has_dependence_sched_deps_info.generate_spec_deps = 1;
    3369                 :            : 
    3370                 :      21416 :   sched_deps_info = &has_dependence_sched_deps_info;
    3371                 :          0 : }
    3372                 :            : 
    3373                 :            : /* Remove all dependences found and recorded in has_dependence_data array.  */
    3374                 :            : void
    3375                 :      21416 : sel_clear_has_dependence (void)
    3376                 :            : {
    3377                 :      21416 :   int i;
    3378                 :            : 
    3379                 :      85664 :   for (i = 0; i < DEPS_IN_NOWHERE; i++)
    3380                 :      64248 :     has_dependence_data.has_dep_p[i] = 0;
    3381                 :      21416 : }
    3382                 :            : 
    3383                 :            : /* Return nonzero if EXPR has is dependent upon PRED.  Return the pointer
    3384                 :            :    to the dependence information array in HAS_DEP_PP.  */
    3385                 :            : ds_t
    3386                 :      21961 : has_dependence_p (expr_t expr, insn_t pred, ds_t **has_dep_pp)
    3387                 :            : {
    3388                 :      21961 :   int i;
    3389                 :      21961 :   ds_t ds;
    3390                 :      21961 :   class deps_desc *dc;
    3391                 :            : 
    3392                 :      21961 :   if (INSN_SIMPLEJUMP_P (pred))
    3393                 :            :     /* Unconditional jump is just a transfer of control flow.
    3394                 :            :        Ignore it.  */
    3395                 :            :     return false;
    3396                 :            : 
    3397                 :      21416 :   dc = &INSN_DEPS_CONTEXT (pred);
    3398                 :            : 
    3399                 :            :   /* We init this field lazily.  */
    3400                 :      21416 :   if (dc->reg_last == NULL)
    3401                 :       3533 :     init_deps_reg_last (dc);
    3402                 :            : 
    3403                 :      21416 :   if (!dc->readonly)
    3404                 :            :     {
    3405                 :       3533 :       has_dependence_data.pro = NULL;
    3406                 :            :       /* Initialize empty dep context with information about PRED.  */
    3407                 :       3533 :       advance_deps_context (dc, pred);
    3408                 :       3533 :       dc->readonly = 1;
    3409                 :            :     }
    3410                 :            : 
    3411                 :      21416 :   has_dependence_data.where = DEPS_IN_NOWHERE;
    3412                 :      21416 :   has_dependence_data.pro = pred;
    3413                 :      21416 :   has_dependence_data.con = EXPR_VINSN (expr);
    3414                 :      21416 :   has_dependence_data.dc = dc;
    3415                 :            : 
    3416                 :      21416 :   sel_clear_has_dependence ();
    3417                 :            : 
    3418                 :            :   /* Now catch all dependencies that would be generated between PRED and
    3419                 :            :      INSN.  */
    3420                 :      21416 :   setup_has_dependence_sched_deps_info ();
    3421                 :      21416 :   deps_analyze_insn (dc, EXPR_INSN_RTX (expr));
    3422                 :      21416 :   has_dependence_data.dc = NULL;
    3423                 :            : 
    3424                 :            :   /* When a barrier was found, set DEPS_IN_INSN bits.  */
    3425                 :      21416 :   if (dc->last_reg_pending_barrier == TRUE_BARRIER)
    3426                 :         16 :     has_dependence_data.has_dep_p[DEPS_IN_INSN] = DEP_TRUE;
    3427                 :      21400 :   else if (dc->last_reg_pending_barrier == MOVE_BARRIER)
    3428                 :          0 :     has_dependence_data.has_dep_p[DEPS_IN_INSN] = DEP_ANTI;
    3429                 :            : 
    3430                 :            :   /* Do not allow stores to memory to move through checks.  Currently
    3431                 :            :      we don't move this to sched-deps.c as the check doesn't have
    3432                 :            :      obvious places to which this dependence can be attached.
    3433                 :            :      FIMXE: this should go to a hook.  */
    3434                 :      21416 :   if (EXPR_LHS (expr)
    3435                 :      17511 :       && MEM_P (EXPR_LHS (expr))
    3436                 :      21894 :       && sel_insn_is_speculation_check (pred))
    3437                 :          0 :     has_dependence_data.has_dep_p[DEPS_IN_INSN] = DEP_ANTI;
    3438                 :            : 
    3439                 :      21416 :   *has_dep_pp = has_dependence_data.has_dep_p;
    3440                 :      21416 :   ds = 0;
    3441                 :      85664 :   for (i = 0; i < DEPS_IN_NOWHERE; i++)
    3442                 :      64248 :     ds = ds_full_merge (ds, has_dependence_data.has_dep_p[i],
    3443                 :            :                         NULL_RTX, NULL_RTX);
    3444                 :            : 
    3445                 :            :   return ds;
    3446                 :            : }
    3447                 :            : 
    3448                 :            : 
    3449                 :            : /* Dependence hooks implementation that checks dependence latency constraints
    3450                 :            :    on the insns being scheduled.  The entry point for these routines is
    3451                 :            :    tick_check_p predicate.  */
    3452                 :            : 
    3453                 :            : static struct
    3454                 :            : {
    3455                 :            :   /* An expr we are currently checking.  */
    3456                 :            :   expr_t expr;
    3457                 :            : 
    3458                 :            :   /* A minimal cycle for its scheduling.  */
    3459                 :            :   int cycle;
    3460                 :            : 
    3461                 :            :   /* Whether we have seen a true dependence while checking.  */
    3462                 :            :   bool seen_true_dep_p;
    3463                 :            : } tick_check_data;
    3464                 :            : 
    3465                 :            : /* Update minimal scheduling cycle for tick_check_insn given that it depends
    3466                 :            :    on PRO with status DS and weight DW.  */
    3467                 :            : static void
    3468                 :      25147 : tick_check_dep_with_dw (insn_t pro_insn, ds_t ds, dw_t dw)
    3469                 :            : {
    3470                 :      25147 :   expr_t con_expr = tick_check_data.expr;
    3471                 :      25147 :   insn_t con_insn = EXPR_INSN_RTX (con_expr);
    3472                 :            : 
    3473                 :      25147 :   if (con_insn != pro_insn)
    3474                 :            :     {
    3475                 :      25141 :       enum reg_note dt;
    3476                 :      25141 :       int tick;
    3477                 :            : 
    3478                 :      25141 :       if (/* PROducer was removed from above due to pipelining.  */
    3479                 :      50278 :           !INSN_IN_STREAM_P (pro_insn)
    3480                 :            :           /* Or PROducer was originally on the next iteration regarding the
    3481                 :            :              CONsumer.  */
    3482                 :      50278 :           || (INSN_SCHED_TIMES (pro_insn)
    3483                 :      25137 :               - EXPR_SCHED_TIMES (con_expr)) > 1)
    3484                 :            :         /* Don't count this dependence.  */
    3485                 :            :         return;
    3486                 :            : 
    3487                 :      25062 :       dt = ds_to_dt (ds);
    3488                 :      25062 :       if (dt == REG_DEP_TRUE)
    3489                 :       6373 :         tick_check_data.seen_true_dep_p = true;
    3490                 :            : 
    3491                 :      25062 :       gcc_assert (INSN_SCHED_CYCLE (pro_insn) > 0);
    3492                 :            : 
    3493                 :      25062 :       {
    3494                 :      25062 :         dep_def _dep, *dep = &_dep;
    3495                 :            : 
    3496                 :      25062 :         init_dep (dep, pro_insn, con_insn, dt);
    3497                 :            : 
    3498                 :      25062 :         tick = INSN_SCHED_CYCLE (pro_insn) + dep_cost_1 (dep, dw);
    3499                 :            :       }
    3500                 :            : 
    3501                 :            :       /* When there are several kinds of dependencies between pro and con,
    3502                 :            :          only REG_DEP_TRUE should be taken into account.  */
    3503                 :      25062 :       if (tick > tick_check_data.cycle
    3504                 :       9788 :           && (dt == REG_DEP_TRUE || !tick_check_data.seen_true_dep_p))
    3505                 :       9676 :         tick_check_data.cycle = tick;
    3506                 :            :     }
    3507                 :            : }
    3508                 :            : 
    3509                 :            : /* An implementation of note_dep hook.  */
    3510                 :            : static void
    3511                 :      22653 : tick_check_note_dep (insn_t pro, ds_t ds)
    3512                 :            : {
    3513                 :      22653 :   tick_check_dep_with_dw (pro, ds, 0);
    3514                 :      22653 : }
    3515                 :            : 
    3516                 :            : /* An implementation of note_mem_dep hook.  */
    3517                 :            : static void
    3518                 :       2494 : tick_check_note_mem_dep (rtx mem1, rtx mem2, insn_t pro, ds_t ds)
    3519                 :            : {
    3520                 :       2494 :   dw_t dw;
    3521                 :            : 
    3522                 :       2494 :   dw = (ds_to_dt (ds) == REG_DEP_TRUE
    3523                 :       2494 :         ? estimate_dep_weak (mem1, mem2)
    3524                 :            :         : 0);
    3525                 :            : 
    3526                 :       2494 :   tick_check_dep_with_dw (pro, ds, dw);
    3527                 :       2494 : }
    3528                 :            : 
    3529                 :            : /* This structure contains hooks for dependence analysis used when determining
    3530                 :            :    whether an insn is ready for scheduling.  */
    3531                 :            : static struct sched_deps_info_def tick_check_sched_deps_info =
    3532                 :            :   {
    3533                 :            :     NULL,
    3534                 :            : 
    3535                 :            :     NULL,
    3536                 :            :     NULL,
    3537                 :            :     NULL,
    3538                 :            :     NULL,
    3539                 :            :     NULL,
    3540                 :            :     NULL,
    3541                 :            :     haifa_note_reg_set,
    3542                 :            :     haifa_note_reg_clobber,
    3543                 :            :     haifa_note_reg_use,
    3544                 :            :     tick_check_note_mem_dep,
    3545                 :            :     tick_check_note_dep,
    3546                 :            : 
    3547                 :            :     0, 0, 0
    3548                 :            :   };
    3549                 :            : 
    3550                 :            : /* Estimate number of cycles from the current cycle of FENCE until EXPR can be
    3551                 :            :    scheduled.  Return 0 if all data from producers in DC is ready.  */
    3552                 :            : int
    3553                 :      11247 : tick_check_p (expr_t expr, deps_t dc, fence_t fence)
    3554                 :            : {
    3555                 :      11247 :   int cycles_left;
    3556                 :            :   /* Initialize variables.  */
    3557                 :      11247 :   tick_check_data.expr = expr;
    3558                 :      11247 :   tick_check_data.cycle = 0;
    3559                 :      11247 :   tick_check_data.seen_true_dep_p = false;
    3560                 :      11247 :   sched_deps_info = &tick_check_sched_deps_info;
    3561                 :            : 
    3562                 :      11247 :   gcc_assert (!dc->readonly);
    3563                 :      11247 :   dc->readonly = 1;
    3564                 :      11247 :   deps_analyze_insn (dc, EXPR_INSN_RTX (expr));
    3565                 :      11247 :   dc->readonly = 0;
    3566                 :            : 
    3567                 :      11247 :   cycles_left = tick_check_data.cycle - FENCE_CYCLE (fence);
    3568                 :            : 
    3569                 :      11247 :   return cycles_left >= 0 ? cycles_left : 0;
    3570                 :            : }
    3571                 :            : 
    3572                 :            : 
    3573                 :            : /* Functions to work with insns.  */
    3574                 :            : 
    3575                 :            : /* Returns true if LHS of INSN is the same as DEST of an insn
    3576                 :            :    being moved.  */
    3577                 :            : bool
    3578                 :       7852 : lhs_of_insn_equals_to_dest_p (insn_t insn, rtx dest)
    3579                 :            : {
    3580                 :       7852 :   rtx lhs = INSN_LHS (insn);
    3581                 :            : 
    3582                 :       7852 :   if (lhs == NULL || dest == NULL)
    3583                 :            :     return false;
    3584                 :            : 
    3585                 :       4171 :   return rtx_equal_p (lhs, dest);
    3586                 :            : }
    3587                 :            : 
    3588                 :            : /* Return s_i_d entry of INSN.  Callable from debugger.  */
    3589                 :            : sel_insn_data_def
    3590                 :          0 : insn_sid (insn_t insn)
    3591                 :            : {
    3592                 :          0 :   return *SID (insn);
    3593                 :            : }
    3594                 :            : 
    3595                 :            : /* True when INSN is a speculative check.  We can tell this by looking
    3596                 :            :    at the data structures of the selective scheduler, not by examining
    3597                 :            :    the pattern.  */
    3598                 :            : bool
    3599                 :     224149 : sel_insn_is_speculation_check (rtx insn)
    3600                 :            : {
    3601                 :     447208 :   return s_i_d.exists () && !! INSN_SPEC_CHECKED_DS (insn);
    3602                 :            : }
    3603                 :            : 
    3604                 :            : /* Extracts machine mode MODE and destination location DST_LOC
    3605                 :            :    for given INSN.  */
    3606                 :            : void
    3607                 :         77 : get_dest_and_mode (rtx insn, rtx *dst_loc, machine_mode *mode)
    3608                 :            : {
    3609                 :         77 :   rtx pat = PATTERN (insn);
    3610                 :            : 
    3611                 :         77 :   gcc_assert (dst_loc);
    3612                 :         77 :   gcc_assert (GET_CODE (pat) == SET);
    3613                 :            : 
    3614                 :         77 :   *dst_loc = SET_DEST (pat);
    3615                 :            : 
    3616                 :         77 :   gcc_assert (*dst_loc);
    3617                 :         77 :   gcc_assert (MEM_P (*dst_loc) || REG_P (*dst_loc));
    3618                 :            : 
    3619                 :         77 :   if (mode)
    3620                 :         77 :     *mode = GET_MODE (*dst_loc);
    3621                 :         77 : }
    3622                 :            : 
    3623                 :            : /* Returns true when moving through JUMP will result in bookkeeping
    3624                 :            :    creation.  */
    3625                 :            : bool
    3626                 :       2069 : bookkeeping_can_be_created_if_moved_through_p (insn_t jump)
    3627                 :            : {
    3628                 :       2069 :   insn_t succ;
    3629                 :       2069 :   succ_iterator si;
    3630                 :            : 
    3631                 :       3968 :   FOR_EACH_SUCC (succ, si, jump)
    3632                 :       2181 :     if (sel_num_cfg_preds_gt_1 (succ))
    3633                 :            :       return true;
    3634                 :            : 
    3635                 :            :   return false;
    3636                 :            : }
    3637                 :            : 
    3638                 :            : /* Return 'true' if INSN is the only one in its basic block.  */
    3639                 :            : static bool
    3640                 :       2852 : insn_is_the_only_one_in_bb_p (insn_t insn)
    3641                 :            : {
    3642                 :       2852 :   return sel_bb_head_p (insn) && sel_bb_end_p (insn);
    3643                 :            : }
    3644                 :            : 
    3645                 :            : /* Check that the region we're scheduling still has at most one
    3646                 :            :    backedge.  */
    3647                 :            : static void
    3648                 :       3334 : verify_backedges (void)
    3649                 :            : {
    3650                 :       3334 :   if (pipelining_p)
    3651                 :            :     {
    3652                 :            :       int i, n = 0;
    3653                 :            :       edge e;
    3654                 :            :       edge_iterator ei;
    3655                 :            : 
    3656                 :      25557 :       for (i = 0; i < current_nr_blocks; i++)
    3657                 :      58295 :         FOR_EACH_EDGE (e, ei, BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i))->succs)
    3658                 :      34713 :           if (in_current_region_p (e->dest)
    3659                 :      34713 :               && BLOCK_TO_BB (e->dest->index) < i)
    3660                 :       1802 :             n++;
    3661                 :            : 
    3662                 :       1975 :       gcc_assert (n <= 1);
    3663                 :            :     }
    3664                 :       3334 : }
    3665                 :            : 
    3666                 :            : 
    3667                 :            : /* Functions to work with control flow.  */
    3668                 :            : 
    3669                 :            : /* Recompute BLOCK_TO_BB and BB_FOR_BLOCK for current region so that blocks
    3670                 :            :    are sorted in topological order (it might have been invalidated by
    3671                 :            :    redirecting an edge).  */
    3672                 :            : static void
    3673                 :          0 : sel_recompute_toporder (void)
    3674                 :            : {
    3675                 :          0 :   int i, n, rgn;
    3676                 :          0 :   int *postorder, n_blocks;
    3677                 :            : 
    3678                 :          0 :   postorder = XALLOCAVEC (int, n_basic_blocks_for_fn (cfun));
    3679                 :          0 :   n_blocks = post_order_compute (postorder, false, false);
    3680                 :            : 
    3681                 :          0 :   rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    3682                 :          0 :   for (n = 0, i = n_blocks - 1; i >= 0; i--)
    3683                 :          0 :     if (CONTAINING_RGN (postorder[i]) == rgn)
    3684                 :            :       {
    3685                 :          0 :         BLOCK_TO_BB (postorder[i]) = n;
    3686                 :          0 :         BB_TO_BLOCK (n) = postorder[i];
    3687                 :          0 :         n++;
    3688                 :            :       }
    3689                 :            : 
    3690                 :            :   /* Assert that we updated info for all blocks.  We may miss some blocks if
    3691                 :            :      this function is called when redirecting an edge made a block
    3692                 :            :      unreachable, but that block is not deleted yet.  */
    3693                 :          0 :   gcc_assert (n == RGN_NR_BLOCKS (rgn));
    3694                 :          0 : }
    3695                 :            : 
    3696                 :            : /* Tidy the possibly empty block BB.  */
    3697                 :            : static bool
    3698                 :       9178 : maybe_tidy_empty_bb (basic_block bb)
    3699                 :            : {
    3700                 :       9178 :   basic_block succ_bb, pred_bb, note_bb;
    3701                 :       9178 :   vec<basic_block> dom_bbs;
    3702                 :       9178 :   edge e;
    3703                 :       9178 :   edge_iterator ei;
    3704                 :       9178 :   bool rescan_p;
    3705                 :            : 
    3706                 :            :   /* Keep empty bb only if this block immediately precedes EXIT and
    3707                 :            :      has incoming non-fallthrough edge, or it has no predecessors or
    3708                 :            :      successors.  Otherwise remove it.  */
    3709                 :       9178 :   if (!sel_bb_empty_p (bb)
    3710                 :         55 :       || (single_succ_p (bb)
    3711                 :         55 :           && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)
    3712                 :          1 :           && (!single_pred_p (bb)
    3713                 :          1 :               || !(single_pred_edge (bb)->flags & EDGE_FALLTHRU)))
    3714                 :         55 :       || EDGE_COUNT (bb->preds) == 0
    3715                 :       9233 :       || EDGE_COUNT (bb->succs) == 0)
    3716                 :            :     return false;
    3717                 :            : 
    3718                 :            :   /* Do not attempt to redirect complex edges.  */
    3719                 :        141 :   FOR_EACH_EDGE (e, ei, bb->preds)
    3720                 :         87 :     if (e->flags & EDGE_COMPLEX)
    3721                 :            :       return false;
    3722                 :         87 :     else if (e->flags & EDGE_FALLTHRU)
    3723                 :            :       {
    3724                 :         37 :         rtx note;
    3725                 :            :         /* If prev bb ends with asm goto, see if any of the
    3726                 :            :            ASM_OPERANDS_LABELs don't point to the fallthru
    3727                 :            :            label.  Do not attempt to redirect it in that case.  */
    3728                 :         37 :         if (JUMP_P (BB_END (e->src))
    3729                 :         37 :             && (note = extract_asm_operands (PATTERN (BB_END (e->src)))))
    3730                 :            :           {
    3731                 :          1 :             int i, n = ASM_OPERANDS_LABEL_LENGTH (note);
    3732                 :            : 
    3733                 :          1 :             for (i = 0; i < n; ++i)
    3734                 :          1 :               if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (bb))
    3735                 :            :                 return false;
    3736                 :            :           }
    3737                 :            :       }
    3738                 :            : 
    3739                 :         54 :   free_data_sets (bb);
    3740                 :            : 
    3741                 :            :   /* Do not delete BB if it has more than one successor.
    3742                 :            :      That can occur when we moving a jump.  */
    3743                 :         54 :   if (!single_succ_p (bb))
    3744                 :            :     {
    3745                 :          0 :       gcc_assert (can_merge_blocks_p (bb->prev_bb, bb));
    3746                 :          0 :       sel_merge_blocks (bb->prev_bb, bb);
    3747                 :          0 :       return true;
    3748                 :            :     }
    3749                 :            : 
    3750                 :         54 :   succ_bb = single_succ (bb);
    3751                 :         54 :   rescan_p = true;
    3752                 :         54 :   pred_bb = NULL;
    3753                 :         54 :   dom_bbs.create (0);
    3754                 :            : 
    3755                 :            :   /* Save a pred/succ from the current region to attach the notes to.  */
    3756                 :         54 :   note_bb = NULL;
    3757                 :         54 :   FOR_EACH_EDGE (e, ei, bb->preds)
    3758                 :         54 :     if (in_current_region_p (e->src))
    3759                 :            :       {
    3760                 :         54 :         note_bb = e->src;
    3761                 :         54 :         break;
    3762                 :            :       }
    3763                 :         54 :   if (note_bb == NULL)
    3764                 :          0 :     note_bb = succ_bb;
    3765                 :            : 
    3766                 :            :   /* Redirect all non-fallthru edges to the next bb.  */
    3767                 :        108 :   while (rescan_p)
    3768                 :            :     {
    3769                 :        104 :       rescan_p = false;
    3770                 :            : 
    3771                 :        151 :       FOR_EACH_EDGE (e, ei, bb->preds)
    3772                 :            :         {
    3773                 :         97 :           pred_bb = e->src;
    3774                 :            : 
    3775                 :         97 :           if (!(e->flags & EDGE_FALLTHRU))
    3776                 :            :             {
    3777                 :            :               /* We cannot invalidate computed topological order by moving
    3778                 :            :                  the edge destination block (E->SUCC) along a fallthru edge.
    3779                 :            : 
    3780                 :            :                  We will update dominators here only when we'll get
    3781                 :            :                  an unreachable block when redirecting, otherwise
    3782                 :            :                  sel_redirect_edge_and_branch will take care of it.  */
    3783                 :         50 :               if (e->dest != bb
    3784                 :         50 :                   && single_pred_p (e->dest))
    3785                 :          0 :                 dom_bbs.safe_push (e->dest);
    3786                 :         50 :               sel_redirect_edge_and_branch (e, succ_bb);
    3787                 :         50 :               rescan_p = true;
    3788                 :         50 :               break;
    3789                 :            :             }
    3790                 :            :           /* If the edge is fallthru, but PRED_BB ends in a conditional jump
    3791                 :            :              to BB (so there is no non-fallthru edge from PRED_BB to BB), we
    3792                 :            :              still have to adjust it.  */
    3793                 :         47 :           else if (single_succ_p (pred_bb) && any_condjump_p (BB_END (pred_bb)))
    3794                 :            :             {
    3795                 :            :               /* If possible, try to remove the unneeded conditional jump.  */
    3796                 :          0 :               if (INSN_SCHED_TIMES (BB_END (pred_bb)) == 0
    3797                 :          0 :                   && !IN_CURRENT_FENCE_P (BB_END (pred_bb)))
    3798                 :            :                 {
    3799                 :          0 :                   if (!sel_remove_insn (BB_END (pred_bb), false, false))
    3800                 :          0 :                     tidy_fallthru_edge (e);
    3801                 :            :                 }
    3802                 :            :               else
    3803                 :          0 :                 sel_redirect_edge_and_branch (e, succ_bb);
    3804                 :            :               rescan_p = true;
    3805                 :            :               break;
    3806                 :            :             }
    3807                 :            :         }
    3808                 :            :     }
    3809                 :            : 
    3810                 :         54 :   if (can_merge_blocks_p (bb->prev_bb, bb))
    3811                 :         32 :     sel_merge_blocks (bb->prev_bb, bb);
    3812                 :            :   else
    3813                 :            :     {
    3814                 :            :       /* This is a block without fallthru predecessor.  Just delete it.  */
    3815                 :         22 :       gcc_assert (note_bb);
    3816                 :         22 :       move_bb_info (note_bb, bb);
    3817                 :         22 :       remove_empty_bb (bb, true);
    3818                 :            :     }
    3819                 :            : 
    3820                 :         54 :   if (!dom_bbs.is_empty ())
    3821                 :            :     {
    3822                 :          0 :       dom_bbs.safe_push (succ_bb);
    3823                 :          0 :       iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false);
    3824                 :          0 :       dom_bbs.release ();
    3825                 :            :     }
    3826                 :            : 
    3827                 :            :   return true;
    3828                 :            : }
    3829                 :            : 
    3830                 :            : /* Tidy the control flow after we have removed original insn from
    3831                 :            :    XBB.  Return true if we have removed some blocks.  When FULL_TIDYING
    3832                 :            :    is true, also try to optimize control flow on non-empty blocks.  */
    3833                 :            : bool
    3834                 :       8847 : tidy_control_flow (basic_block xbb, bool full_tidying)
    3835                 :            : {
    3836                 :       8847 :   bool changed = true;
    3837                 :       8847 :   insn_t first, last;
    3838                 :            : 
    3839                 :            :   /* First check whether XBB is empty.  */
    3840                 :       8847 :   changed = maybe_tidy_empty_bb (xbb);
    3841                 :       8847 :   if (changed || !full_tidying)
    3842                 :            :     return changed;
    3843                 :            : 
    3844                 :            :   /* Check if there is a unnecessary jump after insn left.  */
    3845                 :       3334 :   if (bb_has_removable_jump_to_p (xbb, xbb->next_bb)
    3846                 :          3 :       && INSN_SCHED_TIMES (BB_END (xbb)) == 0
    3847                 :       3337 :       && !IN_CURRENT_FENCE_P (BB_END (xbb)))
    3848                 :            :     {
    3849                 :            :       /* We used to call sel_remove_insn here that can trigger tidy_control_flow
    3850                 :            :          before we fix up the fallthru edge.  Correct that ordering by
    3851                 :            :          explicitly doing the latter before the former.  */
    3852                 :          3 :       clear_expr (INSN_EXPR (BB_END (xbb)));
    3853                 :          3 :       tidy_fallthru_edge (EDGE_SUCC (xbb, 0));
    3854                 :          3 :       if (tidy_control_flow (xbb, false))
    3855                 :            :         return true;
    3856                 :            :     }
    3857                 :            : 
    3858                 :       3334 :   first = sel_bb_head (xbb);
    3859                 :       3334 :   last = sel_bb_end (xbb);
    3860                 :       3334 :   if (MAY_HAVE_DEBUG_INSNS)
    3861                 :            :     {
    3862                 :        358 :       if (first != last && DEBUG_INSN_P (first))
    3863                 :        151 :         do
    3864                 :        151 :           first = NEXT_INSN (first);
    3865                 :        151 :         while (first != last && (DEBUG_INSN_P (first) || NOTE_P (first)));
    3866                 :            : 
    3867                 :        358 :       if (first != last && DEBUG_INSN_P (last))
    3868                 :          7 :         do
    3869                 :          7 :           last = PREV_INSN (last);
    3870                 :          7 :         while (first != last && (DEBUG_INSN_P (last) || NOTE_P (last)));
    3871                 :            :     }
    3872                 :            :   /* Check if there is an unnecessary jump in previous basic block leading
    3873                 :            :      to next basic block left after removing INSN from stream.
    3874                 :            :      If it is so, remove that jump and redirect edge to current
    3875                 :            :      basic block (where there was INSN before deletion).  This way
    3876                 :            :      when NOP will be deleted several instructions later with its
    3877                 :            :      basic block we will not get a jump to next instruction, which
    3878                 :            :      can be harmful.  */
    3879                 :       3334 :   if (first == last
    3880                 :        357 :       && !sel_bb_empty_p (xbb)
    3881                 :        357 :       && INSN_NOP_P (last)
    3882                 :            :       /* Flow goes fallthru from current block to the next.  */
    3883                 :         49 :       && EDGE_COUNT (xbb->succs) == 1
    3884                 :         49 :       && (EDGE_SUCC (xbb, 0)->flags & EDGE_FALLTHRU)
    3885                 :            :       /* When successor is an EXIT block, it may not be the next block.  */
    3886                 :         49 :       && single_succ (xbb) != EXIT_BLOCK_PTR_FOR_FN (cfun)
    3887                 :            :       /* And unconditional jump in previous basic block leads to
    3888                 :            :          next basic block of XBB and this jump can be safely removed.  */
    3889                 :         49 :       && in_current_region_p (xbb->prev_bb)
    3890                 :         37 :       && bb_has_removable_jump_to_p (xbb->prev_bb, xbb->next_bb)
    3891                 :         21 :       && INSN_SCHED_TIMES (BB_END (xbb->prev_bb)) == 0
    3892                 :            :       /* Also this jump is not at the scheduling boundary.  */
    3893                 :       3355 :       && !IN_CURRENT_FENCE_P (BB_END (xbb->prev_bb)))
    3894                 :            :     {
    3895                 :         21 :       bool recompute_toporder_p;
    3896                 :            :       /* Clear data structures of jump - jump itself will be removed
    3897                 :            :          by sel_redirect_edge_and_branch.  */
    3898                 :         21 :       clear_expr (INSN_EXPR (BB_END (xbb->prev_bb)));
    3899                 :         21 :       recompute_toporder_p
    3900                 :         21 :         = sel_redirect_edge_and_branch (EDGE_SUCC (xbb->prev_bb, 0), xbb);
    3901                 :            : 
    3902                 :         21 :       gcc_assert (EDGE_SUCC (xbb->prev_bb, 0)->flags & EDGE_FALLTHRU);
    3903                 :            : 
    3904                 :            :       /* We could have skipped some debug insns which did not get removed with the block,
    3905                 :            :          and the seqnos could become incorrect.  Fix them up here.  */
    3906                 :         21 :       if (MAY_HAVE_DEBUG_INSNS && (sel_bb_head (xbb) != first || sel_bb_end (xbb) != last))
    3907                 :            :        {
    3908                 :          0 :          if (!sel_bb_empty_p (xbb->prev_bb))
    3909                 :            :            {
    3910                 :          0 :              int prev_seqno = INSN_SEQNO (sel_bb_end (xbb->prev_bb));
    3911                 :          0 :              if (prev_seqno > INSN_SEQNO (sel_bb_head (xbb)))
    3912                 :          0 :                for (insn_t insn = sel_bb_head (xbb); insn != first; insn = NEXT_INSN (insn))
    3913                 :          0 :                  INSN_SEQNO (insn) = prev_seqno + 1;
    3914                 :            :            }
    3915                 :            :        }
    3916                 :            : 
    3917                 :            :       /* It can turn out that after removing unused jump, basic block
    3918                 :            :          that contained that jump, becomes empty too.  In such case
    3919                 :            :          remove it too.  */
    3920                 :         21 :       if (sel_bb_empty_p (xbb->prev_bb))
    3921                 :          0 :         changed = maybe_tidy_empty_bb (xbb->prev_bb);
    3922                 :         21 :       if (recompute_toporder_p)
    3923                 :          0 :         sel_recompute_toporder ();
    3924                 :            :     }
    3925                 :            : 
    3926                 :            :   /* TODO: use separate flag for CFG checking.  */
    3927                 :       3334 :   if (flag_checking)
    3928                 :            :     {
    3929                 :       3334 :       verify_backedges ();
    3930                 :       3334 :       verify_dominators (CDI_DOMINATORS);
    3931                 :            :     }
    3932                 :            : 
    3933                 :            :   return changed;
    3934                 :            : }
    3935                 :            : 
    3936                 :            : /* Purge meaningless empty blocks in the middle of a region.  */
    3937                 :            : void
    3938                 :        730 : purge_empty_blocks (void)
    3939                 :            : {
    3940                 :        730 :   int i;
    3941                 :            : 
    3942                 :            :   /* Do not attempt to delete the first basic block in the region.  */
    3943                 :       1061 :   for (i = 1; i < current_nr_blocks; )
    3944                 :            :     {
    3945                 :        331 :       basic_block b = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i));
    3946                 :            : 
    3947                 :        331 :       if (maybe_tidy_empty_bb (b))
    3948                 :          5 :         continue;
    3949                 :            : 
    3950                 :        326 :       i++;
    3951                 :            :     }
    3952                 :        730 : }
    3953                 :            : 
    3954                 :            : /* Rip-off INSN from the insn stream.  When ONLY_DISCONNECT is true,
    3955                 :            :    do not delete insn's data, because it will be later re-emitted.
    3956                 :            :    Return true if we have removed some blocks afterwards.  */
    3957                 :            : bool
    3958                 :       7557 : sel_remove_insn (insn_t insn, bool only_disconnect, bool full_tidying)
    3959                 :            : {
    3960                 :       7557 :   basic_block bb = BLOCK_FOR_INSN (insn);
    3961                 :            : 
    3962                 :       7557 :   gcc_assert (INSN_IN_STREAM_P (insn));
    3963                 :            : 
    3964                 :       7557 :   if (DEBUG_INSN_P (insn) && BB_AV_SET_VALID_P (bb))
    3965                 :            :     {
    3966                 :        101 :       expr_t expr;
    3967                 :        101 :       av_set_iterator i;
    3968                 :            : 
    3969                 :            :       /* When we remove a debug insn that is head of a BB, it remains
    3970                 :            :          in the AV_SET of the block, but it shouldn't.  */
    3971                 :        490 :       FOR_EACH_EXPR_1 (expr, i, &BB_AV_SET (bb))
    3972                 :        229 :         if (EXPR_INSN_RTX (expr) == insn)
    3973                 :            :           {
    3974                 :         69 :             av_set_iter_remove (&i);
    3975                 :         69 :             break;
    3976                 :            :           }
    3977                 :            :     }
    3978                 :            : 
    3979                 :       7557 :   if (only_disconnect)
    3980                 :       5006 :     remove_insn (insn);
    3981                 :            :   else
    3982                 :            :     {
    3983                 :       2551 :       delete_insn (insn);
    3984                 :       2551 :       clear_expr (INSN_EXPR (insn));
    3985                 :            :     }
    3986                 :            : 
    3987                 :            :   /* It is necessary to NULL these fields in case we are going to re-insert
    3988                 :            :      INSN into the insns stream, as will usually happen in the ONLY_DISCONNECT
    3989                 :            :      case, but also for NOPs that we will return to the nop pool.  */
    3990                 :       7557 :   SET_PREV_INSN (insn) = NULL_RTX;
    3991                 :       7557 :   SET_NEXT_INSN (insn) = NULL_RTX;
    3992                 :       7557 :   set_block_for_insn (insn, NULL);
    3993                 :            : 
    3994                 :       7557 :   return tidy_control_flow (bb, full_tidying);
    3995                 :            : }
    3996                 :            : 
    3997                 :            : /* Estimate number of the insns in BB.  */
    3998                 :            : static int
    3999                 :        111 : sel_estimate_number_of_insns (basic_block bb)
    4000                 :            : {
    4001                 :        111 :   int res = 0;
    4002                 :        111 :   insn_t insn = NEXT_INSN (BB_HEAD (bb)), next_tail = NEXT_INSN (BB_END (bb));
    4003                 :            : 
    4004                 :       1397 :   for (; insn != next_tail; insn = NEXT_INSN (insn))
    4005                 :        643 :     if (NONDEBUG_INSN_P (insn))
    4006                 :        488 :       res++;
    4007                 :            : 
    4008                 :        111 :   return res;
    4009                 :            : }
    4010                 :            : 
    4011                 :            : /* We don't need separate luids for notes or labels.  */
    4012                 :            : static int
    4013                 :       1592 : sel_luid_for_non_insn (rtx x)
    4014                 :            : {
    4015                 :       1592 :   gcc_assert (NOTE_P (x) || LABEL_P (x));
    4016                 :            : 
    4017                 :       1592 :   return -1;
    4018                 :            : }
    4019                 :            : 
    4020                 :            : /*  Find the proper seqno for inserting at INSN by successors.
    4021                 :            :     Return -1 if no successors with positive seqno exist.  */
    4022                 :            : static int
    4023                 :          0 : get_seqno_by_succs (rtx_insn *insn)
    4024                 :            : {
    4025                 :          0 :   basic_block bb = BLOCK_FOR_INSN (insn);
    4026                 :          0 :   rtx_insn *tmp = insn, *end = BB_END (bb);
    4027                 :          0 :   int seqno;
    4028                 :          0 :   insn_t succ = NULL;
    4029                 :          0 :   succ_iterator si;
    4030                 :            : 
    4031                 :          0 :   while (tmp != end)
    4032                 :            :     {
    4033                 :          0 :       tmp = NEXT_INSN (tmp);
    4034                 :          0 :       if (INSN_P (tmp))
    4035                 :          0 :         return INSN_SEQNO (tmp);
    4036                 :            :     }
    4037                 :            : 
    4038                 :          0 :   seqno = INT_MAX;
    4039                 :            : 
    4040                 :          0 :   FOR_EACH_SUCC_1 (succ, si, end, SUCCS_NORMAL)
    4041                 :          0 :     if (INSN_SEQNO (succ) > 0)
    4042                 :          0 :       seqno = MIN (seqno, INSN_SEQNO (succ));
    4043                 :            : 
    4044                 :          0 :   if (seqno == INT_MAX)
    4045                 :          0 :     return -1;
    4046                 :            : 
    4047                 :            :   return seqno;
    4048                 :            : }
    4049                 :            : 
    4050                 :            : /* Compute seqno for INSN by its preds or succs.  Use OLD_SEQNO to compute
    4051                 :            :    seqno in corner cases.  */
    4052                 :            : static int
    4053                 :         30 : get_seqno_for_a_jump (insn_t insn, int old_seqno)
    4054                 :            : {
    4055                 :         30 :   int seqno;
    4056                 :            : 
    4057                 :         30 :   gcc_assert (INSN_SIMPLEJUMP_P (insn));
    4058                 :            : 
    4059                 :         30 :   if (!sel_bb_head_p (insn))
    4060                 :         27 :     seqno = INSN_SEQNO (PREV_INSN (insn));
    4061                 :            :   else
    4062                 :            :     {
    4063                 :          3 :       basic_block bb = BLOCK_FOR_INSN (insn);
    4064                 :            : 
    4065                 :          3 :       if (single_pred_p (bb)
    4066                 :          6 :           && !in_current_region_p (single_pred (bb)))
    4067                 :            :         {
    4068                 :            :           /* We can have preds outside a region when splitting edges
    4069                 :            :              for pipelining of an outer loop.  Use succ instead.
    4070                 :            :              There should be only one of them.  */
    4071                 :          0 :           insn_t succ = NULL;
    4072                 :          0 :           succ_iterator si;
    4073                 :          0 :           bool first = true;
    4074                 :            : 
    4075                 :          0 :           gcc_assert (flag_sel_sched_pipelining_outer_loops
    4076                 :            :                       && current_loop_nest);
    4077                 :          0 :           FOR_EACH_SUCC_1 (succ, si, insn,
    4078                 :            :                            SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
    4079                 :            :             {
    4080                 :          0 :               gcc_assert (first);
    4081                 :          0 :               first = false;
    4082                 :            :             }
    4083                 :            : 
    4084                 :          0 :           gcc_assert (succ != NULL);
    4085                 :          0 :           seqno = INSN_SEQNO (succ);
    4086                 :            :         }
    4087                 :            :       else
    4088                 :            :         {
    4089                 :          3 :           insn_t *preds;
    4090                 :          3 :           int n;
    4091                 :            : 
    4092                 :          3 :           cfg_preds (BLOCK_FOR_INSN (insn), &preds, &n);
    4093                 :            : 
    4094                 :          3 :           gcc_assert (n > 0);
    4095                 :            :           /* For one predecessor, use simple method.  */
    4096                 :          3 :           if (n == 1)
    4097                 :          3 :             seqno = INSN_SEQNO (preds[0]);
    4098                 :            :           else
    4099                 :          0 :             seqno = get_seqno_by_preds (insn);
    4100                 :            : 
    4101                 :          3 :           free (preds);
    4102                 :            :         }
    4103                 :            :     }
    4104                 :            : 
    4105                 :            :   /* We were unable to find a good seqno among preds.  */
    4106                 :         30 :   if (seqno < 0)
    4107                 :          0 :     seqno = get_seqno_by_succs (insn);
    4108                 :            : 
    4109                 :         30 :   if (seqno < 0)
    4110                 :            :     {
    4111                 :            :       /* The only case where this could be here legally is that the only
    4112                 :            :          unscheduled insn was a conditional jump that got removed and turned
    4113                 :            :          into this unconditional one.  Initialize from the old seqno
    4114                 :            :          of that jump passed down to here.  */
    4115                 :          0 :       seqno = old_seqno;
    4116                 :            :     }
    4117                 :            : 
    4118                 :         30 :   gcc_assert (seqno >= 0);
    4119                 :         30 :   return seqno;
    4120                 :            : }
    4121                 :            : 
    4122                 :            : /*  Find the proper seqno for inserting at INSN.  Returns -1 if no predecessors
    4123                 :            :     with positive seqno exist.  */
    4124                 :            : int
    4125                 :          0 : get_seqno_by_preds (rtx_insn *insn)
    4126                 :            : {
    4127                 :          0 :   basic_block bb = BLOCK_FOR_INSN (insn);
    4128                 :          0 :   rtx_insn *tmp = insn, *head = BB_HEAD (bb);
    4129                 :          0 :   insn_t *preds;
    4130                 :          0 :   int n, i, seqno;
    4131                 :            : 
    4132                 :            :   /* Loop backwards from INSN to HEAD including both.  */
    4133                 :          0 :   while (1)
    4134                 :            :     {
    4135                 :          0 :       if (INSN_P (tmp))
    4136                 :          0 :         return INSN_SEQNO (tmp);
    4137                 :          0 :       if (tmp == head)
    4138                 :            :         break;
    4139                 :          0 :       tmp = PREV_INSN (tmp);
    4140                 :            :     }
    4141                 :            : 
    4142                 :          0 :   cfg_preds (bb, &preds, &n);
    4143                 :          0 :   for (i = 0, seqno = -1; i < n; i++)
    4144                 :          0 :     seqno = MAX (seqno, INSN_SEQNO (preds[i]));
    4145                 :            : 
    4146                 :            :   return seqno;
    4147                 :            : }
    4148                 :            : 
    4149                 :            : 
    4150                 :            : 
    4151                 :            : /* Extend pass-scope data structures for basic blocks.  */
    4152                 :            : void
    4153                 :       1009 : sel_extend_global_bb_info (void)
    4154                 :            : {
    4155                 :       1009 :   sel_global_bb_info.safe_grow_cleared (last_basic_block_for_fn (cfun));
    4156                 :       1009 : }
    4157                 :            : 
    4158                 :            : /* Extend region-scope data structures for basic blocks.  */
    4159                 :            : static void
    4160                 :        881 : extend_region_bb_info (void)
    4161                 :            : {
    4162                 :          0 :   sel_region_bb_info.safe_grow_cleared (last_basic_block_for_fn (cfun));
    4163                 :          0 : }
    4164                 :            : 
    4165                 :            : /* Extend all data structures to fit for all basic blocks.  */
    4166                 :            : static void
    4167                 :        881 : extend_bb_info (void)
    4168                 :            : {
    4169                 :        881 :   sel_extend_global_bb_info ();
    4170                 :        881 :   extend_region_bb_info ();
    4171                 :        881 : }
    4172                 :            : 
    4173                 :            : /* Finalize pass-scope data structures for basic blocks.  */
    4174                 :            : void
    4175                 :        128 : sel_finish_global_bb_info (void)
    4176                 :            : {
    4177                 :        128 :   sel_global_bb_info.release ();
    4178                 :        128 : }
    4179                 :            : 
    4180                 :            : /* Finalize region-scope data structures for basic blocks.  */
    4181                 :            : static void
    4182                 :        730 : finish_region_bb_info (void)
    4183                 :            : {
    4184                 :        730 :   sel_region_bb_info.release ();
    4185                 :        730 : }
    4186                 :            : 
    4187                 :            : 
    4188                 :            : /* Data for each insn in current region.  */
    4189                 :            : vec<sel_insn_data_def> s_i_d;
    4190                 :            : 
    4191                 :            : /* Extend data structures for insns from current region.  */
    4192                 :            : static void
    4193                 :       3582 : extend_insn_data (void)
    4194                 :            : {
    4195                 :       3582 :   int reserve;
    4196                 :            : 
    4197                 :       3582 :   sched_extend_target ();
    4198                 :       3582 :   sched_deps_init (false);
    4199                 :            : 
    4200                 :            :   /* Extend data structures for insns from current region.  */
    4201                 :       3582 :   reserve = (sched_max_luid + 1 - s_i_d.length ());
    4202                 :       4007 :   if (reserve > 0 && ! s_i_d.space (reserve))
    4203                 :            :     {
    4204                 :       1155 :       int size;
    4205                 :            : 
    4206                 :       1155 :       if (sched_max_luid / 2 > 1024)
    4207                 :          0 :         size = sched_max_luid + 1024;
    4208                 :            :       else
    4209                 :       1155 :         size = 3 * sched_max_luid / 2;
    4210                 :            : 
    4211                 :            : 
    4212                 :       1155 :       s_i_d.safe_grow_cleared (size);
    4213                 :            :     }
    4214                 :       3582 : }
    4215                 :            : 
    4216                 :            : /* Finalize data structures for insns from current region.  */
    4217                 :            : static void
    4218                 :        730 : finish_insns (void)
    4219                 :            : {
    4220                 :        730 :   unsigned i;
    4221                 :            : 
    4222                 :            :   /* Clear here all dependence contexts that may have left from insns that were
    4223                 :            :      removed during the scheduling.  */
    4224                 :      19258 :   for (i = 0; i < s_i_d.length (); i++)
    4225                 :            :     {
    4226                 :       8899 :       sel_insn_data_def *sid_entry = &s_i_d[i];
    4227                 :            : 
    4228                 :       8899 :       if (sid_entry->live)
    4229                 :       1222 :         return_regset_to_pool (sid_entry->live);
    4230                 :       8899 :       if (sid_entry->analyzed_deps)
    4231                 :            :         {
    4232                 :        379 :           BITMAP_FREE (sid_entry->analyzed_deps);
    4233                 :        379 :           BITMAP_FREE (sid_entry->found_deps);
    4234                 :        379 :           htab_delete (sid_entry->transformed_insns);
    4235                 :        379 :           free_deps (&sid_entry->deps_context);
    4236                 :            :         }
    4237                 :       8899 :       if (EXPR_VINSN (&sid_entry->expr))
    4238                 :            :         {
    4239                 :          0 :           clear_expr (&sid_entry->expr);
    4240                 :            : 
    4241                 :            :           /* Also, clear CANT_MOVE bit here, because we really don't want it
    4242                 :            :              to be passed to the next region.  */
    4243                 :          0 :           CANT_MOVE_BY_LUID (i) = 0;
    4244                 :            :         }
    4245                 :            :     }
    4246                 :            : 
    4247                 :        730 :   s_i_d.release ();
    4248                 :        730 : }
    4249                 :            : 
    4250                 :            : /* A proxy to pass initialization data to init_insn ().  */
    4251                 :            : static sel_insn_data_def _insn_init_ssid;
    4252                 :            : static sel_insn_data_t insn_init_ssid = &_insn_init_ssid;
    4253                 :            : 
    4254                 :            : /* If true create a new vinsn.  Otherwise use the one from EXPR.  */
    4255                 :            : static bool insn_init_create_new_vinsn_p;
    4256                 :            : 
    4257                 :            : /* Set all necessary data for initialization of the new insn[s].  */
    4258                 :            : static expr_t
    4259                 :       2822 : set_insn_init (expr_t expr, vinsn_t vi, int seqno)
    4260                 :            : {
    4261                 :       2822 :   expr_t x = &insn_init_ssid->expr;
    4262                 :            : 
    4263                 :       2822 :   copy_expr_onside (x, expr);
    4264                 :       2800 :   if (vi != NULL)
    4265                 :            :     {
    4266                 :       2800 :       insn_init_create_new_vinsn_p = false;
    4267                 :       2800 :       change_vinsn_in_expr (x, vi);
    4268                 :            :     }
    4269                 :            :   else
    4270                 :          0 :     insn_init_create_new_vinsn_p = true;
    4271                 :            : 
    4272                 :       2822 :   insn_init_ssid->seqno = seqno;
    4273                 :         22 :   return x;
    4274                 :            : }
    4275                 :            : 
    4276                 :            : /* Init data for INSN.  */
    4277                 :            : static void
    4278                 :       2822 : init_insn_data (insn_t insn)
    4279                 :            : {
    4280                 :       2822 :   expr_t expr;
    4281                 :       2822 :   sel_insn_data_t ssid = insn_init_ssid;
    4282                 :            : 
    4283                 :            :   /* The fields mentioned below are special and hence are not being
    4284                 :            :      propagated to the new insns.  */
    4285                 :       2822 :   gcc_assert (!ssid->asm_p && ssid->sched_next == NULL
    4286                 :            :               && !ssid->after_stall_p && ssid->sched_cycle == 0);
    4287                 :       2822 :   gcc_assert (INSN_P (insn) && INSN_LUID (insn) > 0);
    4288                 :            : 
    4289                 :       2822 :   expr = INSN_EXPR (insn);
    4290                 :       2822 :   copy_expr (expr, &ssid->expr);
    4291                 :       2822 :   prepare_insn_expr (insn, ssid->seqno);
    4292                 :            : 
    4293                 :       2822 :   if (insn_init_create_new_vinsn_p)
    4294                 :         44 :     change_vinsn_in_expr (expr, vinsn_create (insn, init_insn_force_unique_p));
    4295                 :            : 
    4296                 :       2822 :   if (first_time_insn_init (insn))
    4297                 :       1469 :     init_first_time_insn_data (insn);
    4298                 :       2822 : }
    4299                 :            : 
    4300                 :            : /* This is used to initialize spurious jumps generated by
    4301                 :            :    sel_redirect_edge ().  OLD_SEQNO is used for initializing seqnos
    4302                 :            :    in corner cases within get_seqno_for_a_jump.  */
    4303                 :            : static void
    4304                 :         30 : init_simplejump_data (insn_t insn, int old_seqno)
    4305                 :            : {
    4306                 :         60 :   init_expr (INSN_EXPR (insn), vinsn_create (insn, false), 0,
    4307                 :            :              REG_BR_PROB_BASE, 0, 0, 0, 0, 0, 0,
    4308                 :            :              vNULL, true, false, false,
    4309                 :            :              false, true);
    4310                 :         30 :   INSN_SEQNO (insn) = get_seqno_for_a_jump (insn, old_seqno);
    4311                 :         30 :   init_first_time_insn_data (insn);
    4312                 :         30 : }
    4313                 :            : 
    4314                 :            : /* Perform deferred initialization of insns.  This is used to process
    4315                 :            :    a new jump that may be created by redirect_edge.  OLD_SEQNO is used
    4316                 :            :    for initializing simplejumps in init_simplejump_data.  */
    4317                 :            : static void
    4318                 :       2852 : sel_init_new_insn (insn_t insn, int flags, int old_seqno)
    4319                 :            : {
    4320                 :            :   /* We create data structures for bb when the first insn is emitted in it.  */
    4321                 :       2852 :   if (INSN_P (insn)
    4322                 :       2852 :       && INSN_IN_STREAM_P (insn)
    4323                 :       5704 :       && insn_is_the_only_one_in_bb_p (insn))
    4324                 :            :     {
    4325                 :         78 :       extend_bb_info ();
    4326                 :         78 :       create_initial_data_sets (BLOCK_FOR_INSN (insn));
    4327                 :            :     }
    4328                 :            : 
    4329                 :       2852 :   if (flags & INSN_INIT_TODO_LUID)
    4330                 :            :     {
    4331                 :       1499 :       sched_extend_luids ();
    4332                 :       1499 :       sched_init_insn_luid (insn);
    4333                 :            :     }
    4334                 :            : 
    4335                 :       2852 :   if (flags & INSN_INIT_TODO_SSID)
    4336                 :            :     {
    4337                 :       2822 :       extend_insn_data ();
    4338                 :       2822 :       init_insn_data (insn);
    4339                 :       2822 :       clear_expr (&insn_init_ssid->expr);
    4340                 :            :     }
    4341                 :            : 
    4342                 :       2852 :   if (flags & INSN_INIT_TODO_SIMPLEJUMP)
    4343                 :            :     {
    4344                 :         30 :       extend_insn_data ();
    4345                 :         30 :       init_simplejump_data (insn, old_seqno);
    4346                 :            :     }
    4347                 :            : 
    4348                 :       2852 :   gcc_assert (CONTAINING_RGN (BLOCK_NUM (insn))
    4349                 :            :               == CONTAINING_RGN (BB_TO_BLOCK (0)));
    4350                 :       2852 : }
    4351                 :            : 
    4352                 :            : 
    4353                 :            : /* Functions to init/finish work with lv sets.  */
    4354                 :            : 
    4355                 :            : /* Init BB_LV_SET of BB from DF_LR_IN set of BB.  */
    4356                 :            : static void
    4357                 :       1169 : init_lv_set (basic_block bb)
    4358                 :            : {
    4359                 :       1169 :   gcc_assert (!BB_LV_SET_VALID_P (bb));
    4360                 :            : 
    4361                 :       1169 :   BB_LV_SET (bb) = get_regset_from_pool ();
    4362                 :       2338 :   COPY_REG_SET (BB_LV_SET (bb), DF_LR_IN (bb));
    4363                 :       1169 :   BB_LV_SET_VALID_P (bb) = true;
    4364                 :       1169 : }
    4365                 :            : 
    4366                 :            : /* Copy liveness information to BB from FROM_BB.  */
    4367                 :            : static void
    4368                 :          0 : copy_lv_set_from (basic_block bb, basic_block from_bb)
    4369                 :            : {
    4370                 :          0 :   gcc_assert (!BB_LV_SET_VALID_P (bb));
    4371                 :            : 
    4372                 :          0 :   COPY_REG_SET (BB_LV_SET (bb), BB_LV_SET (from_bb));
    4373                 :          0 :   BB_LV_SET_VALID_P (bb) = true;
    4374                 :          0 : }
    4375                 :            : 
    4376                 :            : /* Initialize lv set of all bb headers.  */
    4377                 :            : void
    4378                 :        128 : init_lv_sets (void)
    4379                 :            : {
    4380                 :        128 :   basic_block bb;
    4381                 :            : 
    4382                 :            :   /* Initialize of LV sets.  */
    4383                 :       1169 :   FOR_EACH_BB_FN (bb, cfun)
    4384                 :       1041 :     init_lv_set (bb);
    4385                 :            : 
    4386                 :            :   /* Don't forget EXIT_BLOCK.  */
    4387                 :        128 :   init_lv_set (EXIT_BLOCK_PTR_FOR_FN (cfun));
    4388                 :        128 : }
    4389                 :            : 
    4390                 :            : /* Release lv set of HEAD.  */
    4391                 :            : static void
    4392                 :       1298 : free_lv_set (basic_block bb)
    4393                 :            : {
    4394                 :       1298 :   gcc_assert (BB_LV_SET (bb) != NULL);
    4395                 :            : 
    4396                 :       1298 :   return_regset_to_pool (BB_LV_SET (bb));
    4397                 :       1298 :   BB_LV_SET (bb) = NULL;
    4398                 :       1298 :   BB_LV_SET_VALID_P (bb) = false;
    4399                 :       1298 : }
    4400                 :            : 
    4401                 :            : /* Finalize lv sets of all bb headers.  */
    4402                 :            : void
    4403                 :        128 : free_lv_sets (void)
    4404                 :            : {
    4405                 :        128 :   basic_block bb;
    4406                 :            : 
    4407                 :            :   /* Don't forget EXIT_BLOCK.  */
    4408                 :        128 :   free_lv_set (EXIT_BLOCK_PTR_FOR_FN (cfun));
    4409                 :            : 
    4410                 :            :   /* Free LV sets.  */
    4411                 :       1167 :   FOR_EACH_BB_FN (bb, cfun)
    4412                 :       1039 :     if (BB_LV_SET (bb))
    4413                 :       1039 :       free_lv_set (bb);
    4414                 :        128 : }
    4415                 :            : 
    4416                 :            : /* Mark AV_SET for BB as invalid, so this set will be updated the next time
    4417                 :            :    compute_av() processes BB.  This function is called when creating new basic
    4418                 :            :    blocks, as well as for blocks (either new or existing) where new jumps are
    4419                 :            :    created when the control flow is being updated.  */
    4420                 :            : static void
    4421                 :       1168 : invalidate_av_set (basic_block bb)
    4422                 :            : {
    4423                 :       1168 :   BB_AV_LEVEL (bb) = -1;
    4424                 :       1168 : }
    4425                 :            : 
    4426                 :            : /* Create initial data sets for BB (they will be invalid).  */
    4427                 :            : static void
    4428                 :        144 : create_initial_data_sets (basic_block bb)
    4429                 :            : {
    4430                 :        144 :   if (BB_LV_SET (bb))
    4431                 :         15 :     BB_LV_SET_VALID_P (bb) = false;
    4432                 :            :   else
    4433                 :        129 :     BB_LV_SET (bb) = get_regset_from_pool ();
    4434                 :        144 :   invalidate_av_set (bb);
    4435                 :        144 : }
    4436                 :            : 
    4437                 :            : /* Free av set of BB.  */
    4438                 :            : static void
    4439                 :        117 : free_av_set (basic_block bb)
    4440                 :            : {
    4441                 :        117 :   av_set_clear (&BB_AV_SET (bb));
    4442                 :        117 :   BB_AV_LEVEL (bb) = 0;
    4443                 :        117 : }
    4444                 :            : 
    4445                 :            : /* Free data sets of BB.  */
    4446                 :            : void
    4447                 :        117 : free_data_sets (basic_block bb)
    4448                 :            : {
    4449                 :        117 :   free_lv_set (bb);
    4450                 :        117 :   free_av_set (bb);
    4451                 :        117 : }
    4452                 :            : 
    4453                 :            : /* Exchange data sets of TO and FROM.  */
    4454                 :            : void
    4455                 :        138 : exchange_data_sets (basic_block to, basic_block from)
    4456                 :            : {
    4457                 :            :   /* Exchange lv sets of TO and FROM.  */
    4458                 :        138 :   std::swap (BB_LV_SET (from), BB_LV_SET (to));
    4459                 :        138 :   std::swap (BB_LV_SET_VALID_P (from), BB_LV_SET_VALID_P (to));
    4460                 :            : 
    4461                 :            :   /* Exchange av sets of TO and FROM.  */
    4462                 :        138 :   std::swap (BB_AV_SET (from), BB_AV_SET (to));
    4463                 :        138 :   std::swap (BB_AV_LEVEL (from), BB_AV_LEVEL (to));
    4464                 :        138 : }
    4465                 :            : 
    4466                 :            : /* Copy data sets of FROM to TO.  */
    4467                 :            : void
    4468                 :          0 : copy_data_sets (basic_block to, basic_block from)
    4469                 :            : {
    4470                 :          0 :   gcc_assert (!BB_LV_SET_VALID_P (to) && !BB_AV_SET_VALID_P (to));
    4471                 :          0 :   gcc_assert (BB_AV_SET (to) == NULL);
    4472                 :            : 
    4473                 :          0 :   BB_AV_LEVEL (to) = BB_AV_LEVEL (from);
    4474                 :          0 :   BB_LV_SET_VALID_P (to) = BB_LV_SET_VALID_P (from);
    4475                 :            : 
    4476                 :          0 :   if (BB_AV_SET_VALID_P (from))
    4477                 :            :     {
    4478                 :          0 :       BB_AV_SET (to) = av_set_copy (BB_AV_SET (from));
    4479                 :            :     }
    4480                 :          0 :   if (BB_LV_SET_VALID_P (from))
    4481                 :            :     {
    4482                 :          0 :       gcc_assert (BB_LV_SET (to) != NULL);
    4483                 :          0 :       COPY_REG_SET (BB_LV_SET (to), BB_LV_SET (from));
    4484                 :            :     }
    4485                 :          0 : }
    4486                 :            : 
    4487                 :            : /* Return an av set for INSN, if any.  */
    4488                 :            : av_set_t
    4489                 :      11706 : get_av_set (insn_t insn)
    4490                 :            : {
    4491                 :      11706 :   av_set_t av_set;
    4492                 :            : 
    4493                 :      11706 :   gcc_assert (AV_SET_VALID_P (insn));
    4494                 :            : 
    4495                 :      11706 :   if (sel_bb_head_p (insn))
    4496                 :      11706 :     av_set = BB_AV_SET (BLOCK_FOR_INSN (insn));
    4497                 :            :   else
    4498                 :            :     av_set = NULL;
    4499                 :            : 
    4500                 :      11706 :   return av_set;
    4501                 :            : }
    4502                 :            : 
    4503                 :            : /* Implementation of AV_LEVEL () macro.  Return AV_LEVEL () of INSN.  */
    4504                 :            : int
    4505                 :     128599 : get_av_level (insn_t insn)
    4506                 :            : {
    4507                 :     128599 :   int av_level;
    4508                 :            : 
    4509                 :     128599 :   gcc_assert (INSN_P (insn));
    4510                 :            : 
    4511                 :     128599 :   if (sel_bb_head_p (insn))
    4512                 :      63476 :     av_level = BB_AV_LEVEL (BLOCK_FOR_INSN (insn));
    4513                 :            :   else
    4514                 :      65123 :     av_level = INSN_WS_LEVEL (insn);
    4515                 :            : 
    4516                 :     128599 :   return av_level;
    4517                 :            : }
    4518                 :            : 
    4519                 :            : 
    4520                 :            : 
    4521                 :            : /* Variables to work with control-flow graph.  */
    4522                 :            : 
    4523                 :            : /* The basic block that already has been processed by the sched_data_update (),
    4524                 :            :    but hasn't been in sel_add_bb () yet.  */
    4525                 :            : static vec<basic_block> last_added_blocks;
    4526                 :            : 
    4527                 :            : /* A pool for allocating successor infos.  */
    4528                 :            : static struct
    4529                 :            : {
    4530                 :            :   /* A stack for saving succs_info structures.  */
    4531                 :            :   struct succs_info *stack;
    4532                 :            : 
    4533                 :            :   /* Its size.  */
    4534                 :            :   int size;
    4535                 :            : 
    4536                 :            :   /* Top of the stack.  */
    4537                 :            :   int top;
    4538                 :            : 
    4539                 :            :   /* Maximal value of the top.  */
    4540                 :            :   int max_top;
    4541                 :            : }  succs_info_pool;
    4542                 :            : 
    4543                 :            : /* Functions to work with control-flow graph.  */
    4544                 :            : 
    4545                 :            : /* Return basic block note of BB.  */
    4546                 :            : rtx_insn *
    4547                 :     444916 : sel_bb_head (basic_block bb)
    4548                 :            : {
    4549                 :     444916 :   rtx_insn *head;
    4550                 :            : 
    4551                 :     444916 :   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    4552                 :            :     {
    4553                 :       2288 :       gcc_assert (exit_insn != NULL_RTX);
    4554                 :            :       head = exit_insn;
    4555                 :            :     }
    4556                 :            :   else
    4557                 :            :     {
    4558                 :     442628 :       rtx_note *note = bb_note (bb);
    4559                 :     442628 :       head = next_nonnote_insn (note);
    4560                 :            : 
    4561                 :     442628 :       if (head && (BARRIER_P (head) || BLOCK_FOR_INSN (head) != bb))
    4562                 :            :         head = NULL;
    4563                 :            :     }
    4564                 :            : 
    4565                 :     444916 :   return head;
    4566                 :            : }
    4567                 :            : 
    4568                 :            : /* Return true if INSN is a basic block header.  */
    4569                 :            : bool
    4570                 :     234824 : sel_bb_head_p (insn_t insn)
    4571                 :            : {
    4572                 :     234824 :   return sel_bb_head (BLOCK_FOR_INSN (insn)) == insn;
    4573                 :            : }
    4574                 :            : 
    4575                 :            : /* Return last insn of BB.  */
    4576                 :            : rtx_insn *
    4577                 :      76352 : sel_bb_end (basic_block bb)
    4578                 :            : {
    4579                 :      76352 :   if (sel_bb_empty_p (bb))
    4580                 :            :     return NULL;
    4581                 :            : 
    4582                 :      76352 :   gcc_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
    4583                 :            : 
    4584                 :      76352 :   return BB_END (bb);
    4585                 :            : }
    4586                 :            : 
    4587                 :            : /* Return true if INSN is the last insn in its basic block.  */
    4588                 :            : bool
    4589                 :      25611 : sel_bb_end_p (insn_t insn)
    4590                 :            : {
    4591                 :      25611 :   return insn == sel_bb_end (BLOCK_FOR_INSN (insn));
    4592                 :            : }
    4593                 :            : 
    4594                 :            : /* Return true if BB consist of single NOTE_INSN_BASIC_BLOCK.  */
    4595                 :            : bool
    4596                 :     128247 : sel_bb_empty_p (basic_block bb)
    4597                 :            : {
    4598                 :     128247 :   return sel_bb_head (bb) == NULL;
    4599                 :            : }
    4600                 :            : 
    4601                 :            : /* True when BB belongs to the current scheduling region.  */
    4602                 :            : bool
    4603                 :     122700 : in_current_region_p (basic_block bb)
    4604                 :            : {
    4605                 :     122700 :   if (bb->index < NUM_FIXED_BLOCKS)
    4606                 :            :     return false;
    4607                 :            : 
    4608                 :     121529 :   return CONTAINING_RGN (bb->index) == CONTAINING_RGN (BB_TO_BLOCK (0));
    4609                 :            : }
    4610                 :            : 
    4611                 :            : /* Return the block which is a fallthru bb of a conditional jump JUMP.  */
    4612                 :            : basic_block
    4613                 :        917 : fallthru_bb_of_jump (const rtx_insn *jump)
    4614                 :            : {
    4615                 :        917 :   if (!JUMP_P (jump))
    4616                 :            :     return NULL;
    4617                 :            : 
    4618                 :        901 :   if (!any_condjump_p (jump))
    4619                 :            :     return NULL;
    4620                 :            : 
    4621                 :            :   /* A basic block that ends with a conditional jump may still have one successor
    4622                 :            :      (and be followed by a barrier), we are not interested.  */
    4623                 :        561 :   if (single_succ_p (BLOCK_FOR_INSN (jump)))
    4624                 :            :     return NULL;
    4625                 :            : 
    4626                 :        561 :   return FALLTHRU_EDGE (BLOCK_FOR_INSN (jump))->dest;
    4627                 :            : }
    4628                 :            : 
    4629                 :            : /* Remove all notes from BB.  */
    4630                 :            : static void
    4631                 :       1127 : init_bb (basic_block bb)
    4632                 :            : {
    4633                 :       1127 :   remove_notes (bb_note (bb), BB_END (bb));
    4634                 :       1127 :   BB_NOTE_LIST (bb) = note_list;
    4635                 :       1127 : }
    4636                 :            : 
    4637                 :            : void
    4638                 :        803 : sel_init_bbs (bb_vec_t bbs)
    4639                 :            : {
    4640                 :        803 :   const struct sched_scan_info_def ssi =
    4641                 :            :     {
    4642                 :            :       extend_bb_info, /* extend_bb */
    4643                 :            :       init_bb, /* init_bb */
    4644                 :            :       NULL, /* extend_insn */
    4645                 :            :       NULL /* init_insn */
    4646                 :            :     };
    4647                 :            : 
    4648                 :        803 :   sched_scan (&ssi, bbs);
    4649                 :        803 : }
    4650                 :            : 
    4651                 :            : /* Restore notes for the whole region.  */
    4652                 :            : static void
    4653                 :        730 : sel_restore_notes (void)
    4654                 :            : {
    4655                 :        730 :   int bb;
    4656                 :        730 :   insn_t insn;
    4657                 :            : 
    4658                 :       1803 :   for (bb = 0; bb < current_nr_blocks; bb++)
    4659                 :            :     {
    4660                 :       1073 :       basic_block first, last;
    4661                 :            : 
    4662                 :       1073 :       first = EBB_FIRST_BB (bb);
    4663                 :       1073 :       last = EBB_LAST_BB (bb)->next_bb;
    4664                 :            : 
    4665                 :       1073 :       do
    4666                 :            :         {
    4667                 :       1073 :           note_list = BB_NOTE_LIST (first);
    4668                 :       1073 :           restore_other_notes (NULL, first);
    4669                 :       1073 :           BB_NOTE_LIST (first) = NULL;
    4670                 :            : 
    4671                 :      15077 :           FOR_BB_INSNS (first, insn)
    4672                 :       7002 :             if (NONDEBUG_INSN_P (insn))
    4673                 :       4589 :               reemit_notes (insn);
    4674                 :            : 
    4675                 :       1073 :           first = first->next_bb;
    4676                 :            :         }
    4677                 :       1073 :       while (first != last);
    4678                 :            :     }
    4679                 :        730 : }
    4680                 :            : 
    4681                 :            : /* Free per-bb data structures.  */
    4682                 :            : void
    4683                 :        730 : sel_finish_bbs (void)
    4684                 :            : {
    4685                 :        730 :   sel_restore_notes ();
    4686                 :            : 
    4687                 :            :   /* Remove current loop preheader from this loop.  */
    4688                 :        730 :   if (current_loop_nest)
    4689                 :         50 :     sel_remove_loop_preheader ();
    4690                 :            : 
    4691                 :        730 :   finish_region_bb_info ();
    4692                 :        730 : }
    4693                 :            : 
    4694                 :            : /* Return true if INSN has a single successor of type FLAGS.  */
    4695                 :            : bool
    4696                 :       1045 : sel_insn_has_single_succ_p (insn_t insn, int flags)
    4697                 :            : {
    4698                 :       1045 :   insn_t succ;
    4699                 :       1045 :   succ_iterator si;
    4700                 :       1045 :   bool first_p = true;
    4701                 :            : 
    4702                 :       2090 :   FOR_EACH_SUCC_1 (succ, si, insn, flags)
    4703                 :            :     {
    4704                 :       1052 :       if (first_p)
    4705                 :       1045 :         first_p = false;
    4706                 :            :       else
    4707                 :            :         return false;
    4708                 :            :     }
    4709                 :            : 
    4710                 :            :   return true;
    4711                 :            : }
    4712                 :            : 
    4713                 :            : /* Allocate successor's info.  */
    4714                 :            : static struct succs_info *
    4715                 :       9508 : alloc_succs_info (void)
    4716                 :            : {
    4717                 :       9508 :   if (succs_info_pool.top == succs_info_pool.max_top)
    4718                 :            :     {
    4719                 :        324 :       int i;
    4720                 :            : 
    4721                 :        324 :       if (++succs_info_pool.max_top >= succs_info_pool.size)
    4722                 :          0 :         gcc_unreachable ();
    4723                 :            : 
    4724                 :        324 :       i = ++succs_info_pool.top;
    4725                 :        324 :       succs_info_pool.stack[i].succs_ok.create (10);
    4726                 :        324 :       succs_info_pool.stack[i].succs_other.create (10);
    4727                 :        324 :       succs_info_pool.stack[i].probs_ok.create (10);
    4728                 :            :     }
    4729                 :            :   else
    4730                 :       9184 :     succs_info_pool.top++;
    4731                 :            : 
    4732                 :       9508 :   return &succs_info_pool.stack[succs_info_pool.top];
    4733                 :            : }
    4734                 :            : 
    4735                 :            : /* Free successor's info.  */
    4736                 :            : void
    4737                 :       9508 : free_succs_info (struct succs_info * sinfo)
    4738                 :            : {
    4739                 :       9508 :   gcc_assert (succs_info_pool.top >= 0
    4740                 :            :               && &succs_info_pool.stack[succs_info_pool.top] == sinfo);
    4741                 :       9508 :   succs_info_pool.top--;
    4742                 :            : 
    4743                 :            :   /* Clear stale info.  */
    4744                 :      19016 :   sinfo->succs_ok.block_remove (0, sinfo->succs_ok.length ());
    4745                 :      19016 :   sinfo->succs_other.block_remove (0, sinfo->succs_other.length ());
    4746                 :      19016 :   sinfo->probs_ok.block_remove (0, sinfo->probs_ok.length ());
    4747                 :       9508 :   sinfo->all_prob = 0;
    4748                 :       9508 :   sinfo->succs_ok_n = 0;
    4749                 :       9508 :   sinfo->all_succs_n = 0;
    4750                 :       9508 : }
    4751                 :            : 
    4752                 :            : /* Compute successor info for INSN.  FLAGS are the flags passed
    4753                 :            :    to the FOR_EACH_SUCC_1 iterator.  */
    4754                 :            : struct succs_info *
    4755                 :       9508 : compute_succs_info (insn_t insn, short flags)
    4756                 :            : {
    4757                 :       9508 :   succ_iterator si;
    4758                 :       9508 :   insn_t succ;
    4759                 :       9508 :   struct succs_info *sinfo = alloc_succs_info ();
    4760                 :            : 
    4761                 :            :   /* Traverse *all* successors and decide what to do with each.  */
    4762                 :      24358 :   FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_ALL)
    4763                 :            :     {
    4764                 :            :       /* FIXME: this doesn't work for skipping to loop exits, as we don't
    4765                 :            :          perform code motion through inner loops.  */
    4766                 :      14850 :       short current_flags = si.current_flags & ~SUCCS_SKIP_TO_LOOP_EXITS;
    4767                 :            : 
    4768                 :      14850 :       if (current_flags & flags)
    4769                 :            :         {
    4770                 :       7913 :           sinfo->succs_ok.safe_push (succ);
    4771                 :      15826 :           sinfo->probs_ok.safe_push (
    4772                 :            :                     /* FIXME: Improve calculation when skipping
    4773                 :            :                        inner loop to exits.  */
    4774                 :       7913 :                     si.bb_end
    4775                 :      15175 :                     ? (si.e1->probability.initialized_p ()
    4776                 :       7913 :                        ? si.e1->probability.to_reg_br_prob_base ()
    4777                 :            :                        : 0)
    4778                 :            :                     : REG_BR_PROB_BASE);
    4779                 :       7913 :           sinfo->succs_ok_n++;
    4780                 :            :         }
    4781                 :            :       else
    4782                 :       6937 :         sinfo->succs_other.safe_push (succ);
    4783                 :            : 
    4784                 :            :       /* Compute all_prob.  */
    4785                 :      14850 :       if (!si.bb_end)
    4786                 :          0 :         sinfo->all_prob = REG_BR_PROB_BASE;
    4787                 :      14850 :       else if (si.e1->probability.initialized_p ())
    4788                 :      13964 :         sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
    4789                 :            : 
    4790                 :      14850 :       sinfo->all_succs_n++;
    4791                 :            :     }
    4792                 :            : 
    4793                 :       9508 :   return sinfo;
    4794                 :            : }
    4795                 :            : 
    4796                 :            : /* Return the predecessors of BB in PREDS and their number in N.
    4797                 :            :    Empty blocks are skipped.  SIZE is used to allocate PREDS.  */
    4798                 :            : static void
    4799                 :          3 : cfg_preds_1 (basic_block bb, insn_t **preds, int *n, int *size)
    4800                 :            : {
    4801                 :          3 :   edge e;
    4802                 :          3 :   edge_iterator ei;
    4803                 :            : 
    4804                 :          3 :   gcc_assert (BLOCK_TO_BB (bb->index) != 0);
    4805                 :            : 
    4806                 :          6 :   FOR_EACH_EDGE (e, ei, bb->preds)
    4807                 :            :     {
    4808                 :          3 :       basic_block pred_bb = e->src;
    4809                 :          3 :       insn_t bb_end = BB_END (pred_bb);
    4810                 :            : 
    4811                 :          3 :       if (!in_current_region_p (pred_bb))
    4812                 :            :         {
    4813                 :          0 :           gcc_assert (flag_sel_sched_pipelining_outer_loops
    4814                 :            :                       && current_loop_nest);
    4815                 :          0 :           continue;
    4816                 :            :         }
    4817                 :            : 
    4818                 :          3 :       if (sel_bb_empty_p (pred_bb))
    4819                 :          0 :         cfg_preds_1 (pred_bb, preds, n, size);
    4820                 :            :       else
    4821                 :            :         {
    4822                 :          3 :           if (*n == *size)
    4823                 :          3 :             *preds = XRESIZEVEC (insn_t, *preds,
    4824                 :            :                                  (*size = 2 * *size + 1));
    4825                 :          3 :           (*preds)[(*n)++] = bb_end;
    4826                 :            :         }
    4827                 :            :     }
    4828                 :            : 
    4829                 :          3 :   gcc_assert (*n != 0
    4830                 :            :               || (flag_sel_sched_pipelining_outer_loops
    4831                 :            :                   && current_loop_nest));
    4832                 :          3 : }
    4833                 :            : 
    4834                 :            : /* Find all predecessors of BB and record them in PREDS and their number
    4835                 :            :    in N.  Empty blocks are skipped, and only normal (forward in-region)
    4836                 :            :    edges are processed.  */
    4837                 :            : static void
    4838                 :          3 : cfg_preds (basic_block bb, insn_t **preds, int *n)
    4839                 :            : {
    4840                 :          3 :   int size = 0;
    4841                 :            : 
    4842                 :          3 :   *preds = NULL;
    4843                 :          3 :   *n = 0;
    4844                 :          3 :   cfg_preds_1 (bb, preds, n, &size);
    4845                 :          0 : }
    4846                 :            : 
    4847                 :            : /* Returns true if we are moving INSN through join point.  */
    4848                 :            : bool
    4849                 :       3468 : sel_num_cfg_preds_gt_1 (insn_t insn)
    4850                 :            : {
    4851                 :       3468 :   basic_block bb;
    4852                 :            : 
    4853                 :       3468 :   if (!sel_bb_head_p (insn) || INSN_BB (insn) == 0)
    4854                 :            :     return false;
    4855                 :            : 
    4856                 :       1808 :   bb = BLOCK_FOR_INSN (insn);
    4857                 :            : 
    4858                 :       1808 :   while (1)
    4859                 :            :     {
    4860                 :       1808 :       if (EDGE_COUNT (bb->preds) > 1)
    4861                 :            :         return true;
    4862                 :            : 
    4863                 :        947 :       gcc_assert (EDGE_PRED (bb, 0)->dest == bb);
    4864                 :        947 :       bb = EDGE_PRED (bb, 0)->src;
    4865                 :            : 
    4866                 :        947 :       if (!sel_bb_empty_p (bb))
    4867                 :            :         break;
    4868                 :            :     }
    4869                 :            : 
    4870                 :            :   return false;
    4871                 :            : }
    4872                 :            : 
    4873                 :            : /* Returns true when BB should be the end of an ebb.  Adapted from the
    4874                 :            :    code in sched-ebb.c.  */
    4875                 :            : bool
    4876                 :       1263 : bb_ends_ebb_p (basic_block bb)
    4877                 :            : {
    4878                 :       1263 :   basic_block next_bb = bb_next_bb (bb);
    4879                 :       1263 :   edge e;
    4880                 :            : 
    4881                 :       1263 :   if (next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
    4882                 :       1148 :       || bitmap_bit_p (forced_ebb_heads, next_bb->index)
    4883                 :       2300 :       || (LABEL_P (BB_HEAD (next_bb))
    4884                 :            :           /* NB: LABEL_NUSES () is not maintained outside of jump.c.
    4885                 :            :              Work around that.  */
    4886                 :        391 :           && !single_pred_p (next_bb)))
    4887                 :        593 :     return true;
    4888                 :            : 
    4889                 :        670 :   if (!in_current_region_p (next_bb))
    4890                 :            :     return true;
    4891                 :            : 
    4892                 :        469 :   e = find_fallthru_edge (bb->succs);
    4893                 :        469 :   if (e)
    4894                 :            :     {
    4895                 :        465 :       gcc_assert (e->dest == next_bb);
    4896                 :            :       
    4897                 :            :       return false;
    4898                 :            :     }
    4899                 :            : 
    4900                 :            :   return true;
    4901                 :            : }
    4902                 :            : 
    4903                 :            : /* Returns true when INSN and SUCC are in the same EBB, given that SUCC is a
    4904                 :            :    successor of INSN.  */
    4905                 :            : bool
    4906                 :        323 : in_same_ebb_p (insn_t insn, insn_t succ)
    4907                 :            : {
    4908                 :        323 :   basic_block ptr = BLOCK_FOR_INSN (insn);
    4909                 :            : 
    4910                 :        925 :   for (;;)
    4911                 :            :     {
    4912                 :        624 :       if (ptr == BLOCK_FOR_INSN (succ))
    4913                 :            :         return true;
    4914                 :            : 
    4915                 :        442 :       if (bb_ends_ebb_p (ptr))
    4916                 :            :         return false;
    4917                 :            : 
    4918                 :        301 :       ptr = bb_next_bb (ptr);
    4919                 :            :     }
    4920                 :            : 
    4921                 :            :   gcc_unreachable ();
    4922                 :            :   return false;
    4923                 :            : }
    4924                 :            : 
    4925                 :            : /* Recomputes the reverse topological order for the function and
    4926                 :            :    saves it in REV_TOP_ORDER_INDEX.  REV_TOP_ORDER_INDEX_LEN is also
    4927                 :            :    modified appropriately.  */
    4928                 :            : static void
    4929                 :         36 : recompute_rev_top_order (void)
    4930                 :            : {
    4931                 :         36 :   int *postorder;
    4932                 :         36 :   int n_blocks, i;
    4933                 :            : 
    4934                 :         36 :   if (!rev_top_order_index
    4935                 :          1 :       || rev_top_order_index_len < last_basic_block_for_fn (cfun))
    4936                 :            :     {
    4937                 :         36 :       rev_top_order_index_len = last_basic_block_for_fn (cfun);
    4938                 :         36 :       rev_top_order_index = XRESIZEVEC (int, rev_top_order_index,
    4939                 :            :                                         rev_top_order_index_len);
    4940                 :            :     }
    4941                 :            : 
    4942                 :         36 :   postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
    4943                 :            : 
    4944                 :         36 :   n_blocks = post_order_compute (postorder, true, false);
    4945                 :         36 :   gcc_assert (n_basic_blocks_for_fn (cfun) == n_blocks);
    4946                 :            : 
    4947                 :            :   /* Build reverse function: for each basic block with BB->INDEX == K
    4948                 :            :      rev_top_order_index[K] is it's reverse topological sort number.  */
    4949                 :        658 :   for (i = 0; i < n_blocks; i++)
    4950                 :            :     {
    4951                 :        622 :       gcc_assert (postorder[i] < rev_top_order_index_len);
    4952                 :        622 :       rev_top_order_index[postorder[i]] = i;
    4953                 :            :     }
    4954                 :            : 
    4955                 :         36 :   free (postorder);
    4956                 :         36 : }
    4957                 :            : 
    4958                 :            : /* Clear all flags from insns in BB that could spoil its rescheduling.  */
    4959                 :            : void
    4960                 :        177 : clear_outdated_rtx_info (basic_block bb)
    4961                 :            : {
    4962                 :        177 :   rtx_insn *insn;
    4963                 :            : 
    4964                 :       2811 :   FOR_BB_INSNS (bb, insn)
    4965                 :       1317 :     if (INSN_P (insn))
    4966                 :            :       {
    4967                 :       1028 :         SCHED_GROUP_P (insn) = 0;
    4968                 :       1028 :         INSN_AFTER_STALL_P (insn) = 0;
    4969                 :       1028 :         INSN_SCHED_TIMES (insn) = 0;
    4970                 :       1028 :         EXPR_PRIORITY_ADJ (INSN_EXPR (insn)) = 0;
    4971                 :            : 
    4972                 :            :         /* We cannot use the changed caches, as previously we could ignore
    4973                 :            :            the LHS dependence due to enabled renaming and transform
    4974                 :            :            the expression, and currently we'll be unable to do this.  */
    4975                 :       1028 :         htab_empty (INSN_TRANSFORMED_INSNS (insn));
    4976                 :            :       }
    4977                 :        177 : }
    4978                 :            : 
    4979                 :            : /* Add BB_NOTE to the pool of available basic block notes.  */
    4980                 :            : static void
    4981                 :        104 : return_bb_to_pool (basic_block bb)
    4982                 :            : {
    4983                 :        104 :   rtx_note *note = bb_note (bb);
    4984                 :            : 
    4985                 :        104 :   gcc_assert (NOTE_BASIC_BLOCK (note) == bb
    4986                 :            :               && bb->aux == NULL);
    4987                 :            : 
    4988                 :            :   /* It turns out that current cfg infrastructure does not support
    4989                 :            :      reuse of basic blocks.  Don't bother for now.  */
    4990                 :            :   /*bb_note_pool.safe_push (note);*/
    4991                 :        104 : }
    4992                 :            : 
    4993                 :            : /* Get a bb_note from pool or return NULL_RTX if pool is empty.  */
    4994                 :            : static rtx_note *
    4995                 :         66 : get_bb_note_from_pool (void)
    4996                 :            : {
    4997                 :          0 :   if (bb_note_pool.is_empty ())
    4998                 :            :     return NULL;
    4999                 :            :   else
    5000                 :            :     {
    5001                 :          0 :       rtx_note *note = bb_note_pool.pop ();
    5002                 :            : 
    5003                 :          0 :       SET_PREV_INSN (note) = NULL_RTX;
    5004                 :          0 :       SET_NEXT_INSN (note) = NULL_RTX;
    5005                 :            : 
    5006                 :          0 :       return note;
    5007                 :            :     }
    5008                 :            : }
    5009                 :            : 
    5010                 :            : /* Free bb_note_pool.  */
    5011                 :            : void
    5012                 :        128 : free_bb_note_pool (void)
    5013                 :            : {
    5014                 :        128 :   bb_note_pool.release ();
    5015                 :        128 : }
    5016                 :            : 
    5017                 :            : /* Setup scheduler pool and successor structure.  */
    5018                 :            : void
    5019                 :        128 : alloc_sched_pools (void)
    5020                 :            : {
    5021                 :        128 :   int succs_size;
    5022                 :            : 
    5023                 :        128 :   succs_size = MAX_WS + 1;
    5024                 :        128 :   succs_info_pool.stack = XCNEWVEC (struct succs_info, succs_size);
    5025                 :        128 :   succs_info_pool.size = succs_size;
    5026                 :        128 :   succs_info_pool.top = -1;
    5027                 :        128 :   succs_info_pool.max_top = -1;
    5028                 :        128 : }
    5029                 :            : 
    5030                 :            : /* Free the pools.  */
    5031                 :            : void
    5032                 :        128 : free_sched_pools (void)
    5033                 :            : {
    5034                 :        128 :   int i;
    5035                 :            : 
    5036                 :        128 :   sched_lists_pool.release ();
    5037                 :        128 :   gcc_assert (succs_info_pool.top == -1);
    5038                 :        452 :   for (i = 0; i <= succs_info_pool.max_top; i++)
    5039                 :            :     {
    5040                 :        324 :       succs_info_pool.stack[i].succs_ok.release ();
    5041                 :        324 :       succs_info_pool.stack[i].succs_other.release ();
    5042                 :        648 :       succs_info_pool.stack[i].probs_ok.release ();
    5043                 :            :     }
    5044                 :        128 :   free (succs_info_pool.stack);
    5045                 :        128 : }
    5046                 :            : 
    5047                 :            : 
    5048                 :            : /* Returns a position in RGN where BB can be inserted retaining
    5049                 :            :    topological order.  */
    5050                 :            : static int
    5051                 :         73 : find_place_to_insert_bb (basic_block bb, int rgn)
    5052                 :            : {
    5053                 :         73 :   bool has_preds_outside_rgn = false;
    5054                 :         73 :   edge e;
    5055                 :         73 :   edge_iterator ei;
    5056                 :            : 
    5057                 :            :   /* Find whether we have preds outside the region.  */
    5058                 :        147 :   FOR_EACH_EDGE (e, ei, bb->preds)
    5059                 :         74 :     if (!in_current_region_p (e->src))
    5060                 :            :       {
    5061                 :            :         has_preds_outside_rgn = true;
    5062                 :            :         break;
    5063                 :            :       }
    5064                 :            : 
    5065                 :            :   /* Recompute the top order -- needed when we have > 1 pred
    5066                 :            :      and in case we don't have preds outside.  */
    5067                 :         73 :   if (flag_sel_sched_pipelining_outer_loops
    5068                 :         73 :       && (has_preds_outside_rgn || EDGE_COUNT (bb->preds) > 1))
    5069                 :            :     {
    5070                 :          1 :       int i, bbi = bb->index, cur_bbi;
    5071                 :            : 
    5072                 :          1 :       recompute_rev_top_order ();
    5073                 :          2 :       for (i = RGN_NR_BLOCKS (rgn) - 1; i >= 0; i--)
    5074                 :            :         {
    5075                 :          2 :           cur_bbi = BB_TO_BLOCK (i);
    5076                 :          2 :           if (rev_top_order_index[bbi]
    5077                 :          2 :               < rev_top_order_index[cur_bbi])
    5078                 :            :             break;
    5079                 :            :         }
    5080                 :            : 
    5081                 :            :       /* We skipped the right block, so we increase i.  We accommodate
    5082                 :            :          it for increasing by step later, so we decrease i.  */
    5083                 :          1 :       return (i + 1) - 1;
    5084                 :            :     }
    5085                 :         72 :   else if (has_preds_outside_rgn)
    5086                 :            :     {
    5087                 :            :       /* This is the case when we generate an extra empty block
    5088                 :            :          to serve as region head during pipelining.  */
    5089                 :          0 :       e = EDGE_SUCC (bb, 0);
    5090                 :          0 :       gcc_assert (EDGE_COUNT (bb->succs) == 1
    5091                 :            :                   && in_current_region_p (EDGE_SUCC (bb, 0)->dest)
    5092                 :            :                   && (BLOCK_TO_BB (e->dest->index) == 0));
    5093                 :            :       return -1;
    5094                 :            :     }
    5095                 :            : 
    5096                 :            :   /* We don't have preds outside the region.  We should have
    5097                 :            :      the only pred, because the multiple preds case comes from
    5098                 :            :      the pipelining of outer loops, and that is handled above.
    5099                 :            :      Just take the bbi of this single pred.  */
    5100                 :         72 :   if (EDGE_COUNT (bb->succs) > 0)
    5101                 :            :     {
    5102                 :         72 :       int pred_bbi;
    5103                 :            : 
    5104                 :         72 :       gcc_assert (EDGE_COUNT (bb->preds) == 1);
    5105                 :            : 
    5106                 :         72 :       pred_bbi = EDGE_PRED (bb, 0)->src->index;
    5107                 :         72 :       return BLOCK_TO_BB (pred_bbi);
    5108                 :            :     }
    5109                 :            :   else
    5110                 :            :     /* BB has no successors.  It is safe to put it in the end.  */
    5111                 :          0 :     return current_nr_blocks - 1;
    5112                 :            : }
    5113                 :            : 
    5114                 :            : /* Deletes an empty basic block freeing its data.  */
    5115                 :            : static void
    5116                 :         36 : delete_and_free_basic_block (basic_block bb)
    5117                 :            : {
    5118                 :         36 :   gcc_assert (sel_bb_empty_p (bb));
    5119                 :            : 
    5120                 :         36 :   if (BB_LV_SET (bb))
    5121                 :         14 :     free_lv_set (bb);
    5122                 :            : 
    5123                 :         36 :   bitmap_clear_bit (blocks_to_reschedule, bb->index);
    5124                 :            : 
    5125                 :            :   /* Can't assert av_set properties because we use sel_aremove_bb
    5126                 :            :      when removing loop preheader from the region.  At the point of
    5127                 :            :      removing the preheader we already have deallocated sel_region_bb_info.  */
    5128                 :         36 :   gcc_assert (BB_LV_SET (bb) == NULL
    5129                 :            :               && !BB_LV_SET_VALID_P (bb)
    5130                 :            :               && BB_AV_LEVEL (bb) == 0
    5131                 :            :               && BB_AV_SET (bb) == NULL);
    5132                 :            : 
    5133                 :         36 :   delete_basic_block (bb);
    5134                 :         36 : }
    5135                 :            : 
    5136                 :            : /* Add BB to the current region and update the region data.  */
    5137                 :            : static void
    5138                 :         73 : add_block_to_current_region (basic_block bb)
    5139                 :            : {
    5140                 :         73 :   int i, pos, bbi = -2, rgn;
    5141                 :            : 
    5142                 :         73 :   rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    5143                 :         73 :   bbi = find_place_to_insert_bb (bb, rgn);
    5144                 :         73 :   bbi += 1;
    5145                 :         73 :   pos = RGN_BLOCKS (rgn) + bbi;
    5146                 :            : 
    5147                 :         73 :   gcc_assert (RGN_HAS_REAL_EBB (rgn) == 0
    5148                 :            :               && ebb_head[bbi] == pos);
    5149                 :            : 
    5150                 :            :   /* Make a place for the new block.  */
    5151                 :         73 :   extend_regions ();
    5152                 :            : 
    5153                 :        275 :   for (i = RGN_BLOCKS (rgn + 1) - 1; i >= pos; i--)
    5154                 :        202 :     BLOCK_TO_BB (rgn_bb_table[i])++;
    5155                 :            : 
    5156                 :         73 :   memmove (rgn_bb_table + pos + 1,
    5157                 :         73 :            rgn_bb_table + pos,
    5158                 :         73 :            (RGN_BLOCKS (nr_regions) - pos) * sizeof (*rgn_bb_table));
    5159                 :            : 
    5160                 :            :   /* Initialize data for BB.  */
    5161                 :         73 :   rgn_bb_table[pos] = bb->index;
    5162                 :         73 :   BLOCK_TO_BB (bb->index) = bbi;
    5163                 :         73 :   CONTAINING_RGN (bb->index) = rgn;
    5164                 :            : 
    5165                 :         73 :   RGN_NR_BLOCKS (rgn)++;
    5166                 :            : 
    5167                 :        519 :   for (i = rgn + 1; i <= nr_regions; i++)
    5168                 :        446 :     RGN_BLOCKS (i)++;
    5169                 :         73 : }
    5170                 :            : 
    5171                 :            : /* Remove BB from the current region and update the region data.  */
    5172                 :            : static void
    5173                 :        104 : remove_bb_from_region (basic_block bb)
    5174                 :            : {
    5175                 :        104 :   int i, pos, bbi = -2, rgn;
    5176                 :            : 
    5177                 :        104 :   rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    5178                 :        104 :   bbi = BLOCK_TO_BB (bb->index);
    5179                 :        104 :   pos = RGN_BLOCKS (rgn) + bbi;
    5180                 :            : 
    5181                 :        104 :   gcc_assert (RGN_HAS_REAL_EBB (rgn) == 0
    5182                 :            :               && ebb_head[bbi] == pos);
    5183                 :            : 
    5184                 :        603 :   for (i = RGN_BLOCKS (rgn + 1) - 1; i >= pos; i--)
    5185                 :        499 :     BLOCK_TO_BB (rgn_bb_table[i])--;
    5186                 :            : 
    5187                 :        104 :   memmove (rgn_bb_table + pos,
    5188                 :        104 :            rgn_bb_table + pos + 1,
    5189                 :        104 :            (RGN_BLOCKS (nr_regions) - pos) * sizeof (*rgn_bb_table));
    5190                 :            : 
    5191                 :        104 :   RGN_NR_BLOCKS (rgn)--;
    5192                 :       1019 :   for (i = rgn + 1; i <= nr_regions; i++)
    5193                 :        915 :     RGN_BLOCKS (i)--;
    5194                 :        104 : }
    5195                 :            : 
    5196                 :            : /* Add BB to the current region  and update all data.  If BB is NULL, add all
    5197                 :            :    blocks from last_added_blocks vector.  */
    5198                 :            : static void
    5199                 :         73 : sel_add_bb (basic_block bb)
    5200                 :            : {
    5201                 :            :   /* Extend luids so that new notes will receive zero luids.  */
    5202                 :         73 :   sched_extend_luids ();
    5203                 :         73 :   sched_init_bbs ();
    5204                 :         73 :   sel_init_bbs (last_added_blocks);
    5205                 :            : 
    5206                 :            :   /* When bb is passed explicitly, the vector should contain
    5207                 :            :      the only element that equals to bb; otherwise, the vector
    5208                 :            :      should not be NULL.  */
    5209                 :         73 :   gcc_assert (last_added_blocks.exists ());
    5210                 :            : 
    5211                 :         73 :   if (bb != NULL)
    5212                 :            :     {
    5213                 :         73 :       gcc_assert (last_added_blocks.length () == 1
    5214                 :            :                   && last_added_blocks[0] == bb);
    5215                 :         73 :       add_block_to_current_region (bb);
    5216                 :            : 
    5217                 :            :       /* We associate creating/deleting data sets with the first insn
    5218                 :            :          appearing / disappearing in the bb.  */
    5219                 :         73 :       if (!sel_bb_empty_p (bb) && BB_LV_SET (bb) == NULL)
    5220                 :         66 :         create_initial_data_sets (bb);
    5221                 :            : 
    5222                 :         73 :       last_added_blocks.release ();
    5223                 :            :     }
    5224                 :            :   else
    5225                 :            :     /* BB is NULL - process LAST_ADDED_BLOCKS instead.  */
    5226                 :            :     {
    5227                 :            :       int i;
    5228                 :            :       basic_block temp_bb = NULL;
    5229                 :            : 
    5230                 :          0 :       for (i = 0;
    5231                 :          0 :            last_added_blocks.iterate (i, &bb); i++)
    5232                 :            :         {
    5233                 :          0 :           add_block_to_current_region (bb);
    5234                 :          0 :           temp_bb = bb;
    5235                 :            :         }
    5236                 :            : 
    5237                 :            :       /* We need to fetch at least one bb so we know the region
    5238                 :            :          to update.  */
    5239                 :          0 :       gcc_assert (temp_bb != NULL);
    5240                 :          0 :       bb = temp_bb;
    5241                 :            : 
    5242                 :          0 :       last_added_blocks.release ();
    5243                 :            :     }
    5244                 :            : 
    5245                 :         73 :   rgn_setup_region (CONTAINING_RGN (bb->index));
    5246                 :         73 : }
    5247                 :            : 
    5248                 :            : /* Remove BB from the current region and update all data.
    5249                 :            :    If REMOVE_FROM_CFG_PBB is true, also remove the block cfom cfg.  */
    5250                 :            : static void
    5251                 :        104 : sel_remove_bb (basic_block bb, bool remove_from_cfg_p)
    5252                 :            : {
    5253                 :        104 :   unsigned idx = bb->index;
    5254                 :            : 
    5255                 :        104 :   gcc_assert (bb != NULL && BB_NOTE_LIST (bb) == NULL_RTX);
    5256                 :            : 
    5257                 :        104 :   remove_bb_from_region (bb);
    5258                 :        104 :   return_bb_to_pool (bb);
    5259                 :        104 :   bitmap_clear_bit (blocks_to_reschedule, idx);
    5260                 :            : 
    5261                 :        104 :   if (remove_from_cfg_p)
    5262                 :            :     {
    5263                 :         22 :       basic_block succ = single_succ (bb);
    5264                 :         22 :       delete_and_free_basic_block (bb);
    5265                 :         22 :       set_immediate_dominator (CDI_DOMINATORS, succ,
    5266                 :            :                                recompute_dominator (CDI_DOMINATORS, succ));
    5267                 :            :     }
    5268                 :            : 
    5269                 :        104 :   rgn_setup_region (CONTAINING_RGN (idx));
    5270                 :        104 : }
    5271                 :            : 
    5272                 :            : /* Concatenate info of EMPTY_BB to info of MERGE_BB.  */
    5273                 :            : static void
    5274                 :         54 : move_bb_info (basic_block merge_bb, basic_block empty_bb)
    5275                 :            : {
    5276                 :         54 :   if (in_current_region_p (merge_bb))
    5277                 :         54 :     concat_note_lists (BB_NOTE_LIST (empty_bb),
    5278                 :         54 :                        &BB_NOTE_LIST (merge_bb));
    5279                 :         54 :   BB_NOTE_LIST (empty_bb) = NULL;
    5280                 :            : 
    5281                 :         54 : }
    5282                 :            : 
    5283                 :            : /* Remove EMPTY_BB.  If REMOVE_FROM_CFG_P is false, remove EMPTY_BB from
    5284                 :            :    region, but keep it in CFG.  */
    5285                 :            : static void
    5286                 :         54 : remove_empty_bb (basic_block empty_bb, bool remove_from_cfg_p)
    5287                 :            : {
    5288                 :            :   /* The block should contain just a note or a label.
    5289                 :            :      We try to check whether it is unused below.  */
    5290                 :         54 :   gcc_assert (BB_HEAD (empty_bb) == BB_END (empty_bb)
    5291                 :            :               || LABEL_P (BB_HEAD (empty_bb)));
    5292                 :            : 
    5293                 :            :   /* If basic block has predecessors or successors, redirect them.  */
    5294                 :         54 :   if (remove_from_cfg_p
    5295                 :         54 :       && (EDGE_COUNT (empty_bb->preds) > 0
    5296                 :         18 :           || EDGE_COUNT (empty_bb->succs) > 0))
    5297                 :            :     {
    5298                 :         22 :       basic_block pred;
    5299                 :         22 :       basic_block succ;
    5300                 :            : 
    5301                 :            :       /* We need to init PRED and SUCC before redirecting edges.  */
    5302                 :         22 :       if (EDGE_COUNT (empty_bb->preds) > 0)
    5303                 :            :         {
    5304                 :          4 :           edge e;
    5305                 :            : 
    5306                 :          4 :           gcc_assert (EDGE_COUNT (empty_bb->preds) == 1);
    5307                 :            : 
    5308                 :          4 :           e = EDGE_PRED (empty_bb, 0);
    5309                 :          4 :           gcc_assert (e->src == empty_bb->prev_bb
    5310                 :            :                       && (e->flags & EDGE_FALLTHRU));
    5311                 :            : 
    5312                 :            :           pred = empty_bb->prev_bb;
    5313                 :            :         }
    5314                 :            :       else
    5315                 :            :         pred = NULL;
    5316                 :            : 
    5317                 :         22 :       if (EDGE_COUNT (empty_bb->succs) > 0)
    5318                 :            :         {
    5319                 :            :           /* We do not check fallthruness here as above, because
    5320                 :            :              after removing a jump the edge may actually be not fallthru.  */
    5321                 :         22 :           gcc_assert (EDGE_COUNT (empty_bb->succs) == 1);
    5322                 :         22 :           succ = EDGE_SUCC (empty_bb, 0)->dest;
    5323                 :            :         }
    5324                 :            :       else
    5325                 :            :         succ = NULL;
    5326                 :            : 
    5327                 :         22 :       if (EDGE_COUNT (empty_bb->preds) > 0 && succ != NULL)
    5328                 :            :         {
    5329                 :          4 :           edge e = EDGE_PRED (empty_bb, 0);
    5330                 :            : 
    5331                 :          4 :           if (e->flags & EDGE_FALLTHRU)
    5332                 :          4 :             redirect_edge_succ_nodup (e, succ);
    5333                 :            :           else
    5334                 :          0 :             sel_redirect_edge_and_branch (EDGE_PRED (empty_bb, 0), succ);
    5335                 :            :         }
    5336                 :            : 
    5337                 :         22 :       if (EDGE_COUNT (empty_bb->succs) > 0 && pred != NULL)
    5338                 :            :         {
    5339                 :          4 :           edge e = EDGE_SUCC (empty_bb, 0);
    5340                 :            : 
    5341                 :          4 :           if (find_edge (pred, e->dest) == NULL)
    5342                 :          0 :             redirect_edge_pred (e, pred);
    5343                 :            :         }
    5344                 :            :     }
    5345                 :            : 
    5346                 :            :   /* Finish removing.  */
    5347                 :         54 :   sel_remove_bb (empty_bb, remove_from_cfg_p);
    5348                 :         54 : }
    5349                 :            : 
    5350                 :            : /* An implementation of create_basic_block hook, which additionally updates
    5351                 :            :    per-bb data structures.  */
    5352                 :            : static basic_block
    5353                 :         66 : sel_create_basic_block (void *headp, void *endp, basic_block after)
    5354                 :            : {
    5355                 :         66 :   basic_block new_bb;
    5356                 :         66 :   rtx_note *new_bb_note;
    5357                 :            : 
    5358                 :         66 :   gcc_assert (flag_sel_sched_pipelining_outer_loops
    5359                 :            :               || !last_added_blocks.exists ());
    5360                 :            : 
    5361                 :         66 :   new_bb_note = get_bb_note_from_pool ();
    5362                 :            : 
    5363                 :          0 :   if (new_bb_note == NULL_RTX)
    5364                 :         66 :     new_bb = orig_cfg_hooks.create_basic_block (headp, endp, after);
    5365                 :            :   else
    5366                 :            :     {
    5367                 :          0 :       new_bb = create_basic_block_structure ((rtx_insn *) headp,
    5368                 :            :                                              (rtx_insn *) endp,
    5369                 :            :                                              new_bb_note, after);
    5370                 :          0 :       new_bb->aux = NULL;
    5371                 :            :     }
    5372                 :            : 
    5373                 :         66 :   last_added_blocks.safe_push (new_bb);
    5374                 :            : 
    5375                 :         66 :   return new_bb;
    5376                 :            : }
    5377                 :            : 
    5378                 :            : /* Implement sched_init_only_bb ().  */
    5379                 :            : static void
    5380                 :          0 : sel_init_only_bb (basic_block bb, basic_block after)
    5381                 :            : {
    5382                 :          0 :   gcc_assert (after == NULL);
    5383                 :            : 
    5384                 :          0 :   extend_regions ();
    5385                 :          0 :   rgn_make_new_region_out_of_new_block (bb);
    5386                 :          0 : }
    5387                 :            : 
    5388                 :            : /* Update the latch when we've splitted or merged it from FROM block to TO.
    5389                 :            :    This should be checked for all outer loops, too.  */
    5390                 :            : static void
    5391                 :         95 : change_loops_latches (basic_block from, basic_block to)
    5392                 :            : {
    5393                 :         95 :   gcc_assert (from != to);
    5394                 :            : 
    5395                 :         95 :   if (current_loop_nest)
    5396                 :            :     {
    5397                 :            :       class loop *loop;
    5398                 :            : 
    5399                 :        350 :       for (loop = current_loop_nest; loop; loop = loop_outer (loop))
    5400                 :        175 :         if (considered_for_pipelining_p (loop) && loop->latch == from)
    5401                 :            :           {
    5402                 :          0 :             gcc_assert (loop == current_loop_nest);
    5403                 :          0 :             loop->latch = to;
    5404                 :          0 :             gcc_assert (loop_latch_edge (loop));
    5405                 :            :           }
    5406                 :            :     }
    5407                 :         95 : }
    5408                 :            : 
    5409                 :            : /* Splits BB on two basic blocks, adding it to the region and extending
    5410                 :            :    per-bb data structures.  Returns the newly created bb.  */
    5411                 :            : static basic_block
    5412                 :         63 : sel_split_block (basic_block bb, rtx after)
    5413                 :            : {
    5414                 :         63 :   basic_block new_bb;
    5415                 :         63 :   insn_t insn;
    5416                 :            : 
    5417                 :         63 :   new_bb = sched_split_block_1 (bb, after);
    5418                 :         63 :   sel_add_bb (new_bb);
    5419                 :            : 
    5420                 :            :   /* This should be called after sel_add_bb, because this uses
    5421                 :            :      CONTAINING_RGN for the new block, which is not yet initialized.
    5422                 :            :      FIXME: this function may be a no-op now.  */
    5423                 :         63 :   change_loops_latches (bb, new_bb);
    5424                 :            : 
    5425                 :            :   /* Update ORIG_BB_INDEX for insns moved into the new block.  */
    5426                 :        627 :   FOR_BB_INSNS (new_bb, insn)
    5427                 :        282 :    if (INSN_P (insn))
    5428                 :        219 :      EXPR_ORIG_BB_INDEX (INSN_EXPR (insn)) = new_bb->index;
    5429                 :            : 
    5430                 :         63 :   if (sel_bb_empty_p (bb))
    5431                 :            :     {
    5432                 :         63 :       gcc_assert (!sel_bb_empty_p (new_bb));
    5433                 :            : 
    5434                 :            :       /* NEW_BB has data sets that need to be updated and BB holds
    5435                 :            :          data sets that should be removed.  Exchange these data sets
    5436                 :            :          so that we won't lose BB's valid data sets.  */
    5437                 :         63 :       exchange_data_sets (new_bb, bb);
    5438                 :         63 :       free_data_sets (bb);
    5439                 :            :     }
    5440                 :            : 
    5441                 :         63 :   if (!sel_bb_empty_p (new_bb)
    5442                 :         63 :       && bitmap_bit_p (blocks_to_reschedule, bb->index))
    5443                 :         13 :     bitmap_set_bit (blocks_to_reschedule, new_bb->index);
    5444                 :            : 
    5445                 :         63 :   return new_bb;
    5446                 :            : }
    5447                 :            : 
    5448                 :            : /* If BB ends with a jump insn whose ID is bigger then PREV_MAX_UID, return it.
    5449                 :            :    Otherwise returns NULL.  */
    5450                 :            : static rtx_insn *
    5451                 :         66 : check_for_new_jump (basic_block bb, int prev_max_uid)
    5452                 :            : {
    5453                 :         66 :   rtx_insn *end;
    5454                 :            : 
    5455                 :         66 :   end = sel_bb_end (bb);
    5456                 :        132 :   if (end && INSN_UID (end) >= prev_max_uid)
    5457                 :         30 :     return end;
    5458                 :            :   return NULL;
    5459                 :            : }
    5460                 :            : 
    5461                 :            : /* Look for a new jump either in FROM_BB block or in newly created JUMP_BB block.
    5462                 :            :    New means having UID at least equal to PREV_MAX_UID.  */
    5463                 :            : static rtx_insn *
    5464                 :        134 : find_new_jump (basic_block from, basic_block jump_bb, int prev_max_uid)
    5465                 :            : {
    5466                 :        134 :   rtx_insn *jump;
    5467                 :            : 
    5468                 :            :   /* Return immediately if no new insns were emitted.  */
    5469                 :         30 :   if (get_max_uid () == prev_max_uid)
    5470                 :            :     return NULL;
    5471                 :            : 
    5472                 :            :   /* Now check both blocks for new jumps.  It will ever be only one.  */
    5473                 :         63 :   if ((jump = check_for_new_jump (from, prev_max_uid)))
    5474                 :            :     return jump;
    5475                 :            : 
    5476                 :          3 :   if (jump_bb != NULL
    5477                 :          3 :       && (jump = check_for_new_jump (jump_bb, prev_max_uid)))
    5478                 :          3 :     return jump;
    5479                 :            :   return NULL;
    5480                 :            : }
    5481                 :            : 
    5482                 :            : /* Splits E and adds the newly created basic block to the current region.
    5483                 :            :    Returns this basic block.  */
    5484                 :            : basic_block
    5485                 :          0 : sel_split_edge (edge e)
    5486                 :            : {
    5487                 :          0 :   basic_block new_bb, src, other_bb = NULL;
    5488                 :          0 :   int prev_max_uid;
    5489                 :          0 :   rtx_insn *jump;
    5490                 :            : 
    5491                 :          0 :   src = e->src;
    5492                 :          0 :   prev_max_uid = get_max_uid ();
    5493                 :          0 :   new_bb = split_edge (e);
    5494                 :            : 
    5495                 :          0 :   if (flag_sel_sched_pipelining_outer_loops
    5496                 :          0 :       && current_loop_nest)
    5497                 :            :     {
    5498                 :            :       int i;
    5499                 :            :       basic_block bb;
    5500                 :            : 
    5501                 :            :       /* Some of the basic blocks might not have been added to the loop.
    5502                 :            :          Add them here, until this is fixed in force_fallthru.  */
    5503                 :          0 :       for (i = 0;
    5504                 :          0 :            last_added_blocks.iterate (i, &bb); i++)
    5505                 :          0 :         if (!bb->loop_father)
    5506                 :            :           {
    5507                 :          0 :             add_bb_to_loop (bb, e->dest->loop_father);
    5508                 :            : 
    5509                 :          0 :             gcc_assert (!other_bb && (new_bb->index != bb->index));
    5510                 :            :             other_bb = bb;
    5511                 :            :           }
    5512                 :            :     }
    5513                 :            : 
    5514                 :            :   /* Add all last_added_blocks to the region.  */
    5515                 :          0 :   sel_add_bb (NULL);
    5516                 :            : 
    5517                 :          0 :   jump = find_new_jump (src, new_bb, prev_max_uid);
    5518                 :          0 :   if (jump)
    5519                 :          0 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
    5520                 :            : 
    5521                 :            :   /* Put the correct lv set on this block.  */
    5522                 :          0 :   if (other_bb && !sel_bb_empty_p (other_bb))
    5523                 :          0 :     compute_live (sel_bb_head (other_bb));
    5524                 :            : 
    5525                 :          0 :   return new_bb;
    5526                 :            : }
    5527                 :            : 
    5528                 :            : /* Implement sched_create_empty_bb ().  */
    5529                 :            : static basic_block
    5530                 :          0 : sel_create_empty_bb (basic_block after)
    5531                 :            : {
    5532                 :          0 :   basic_block new_bb;
    5533                 :            : 
    5534                 :          0 :   new_bb = sched_create_empty_bb_1 (after);
    5535                 :            : 
    5536                 :            :   /* We'll explicitly initialize NEW_BB via sel_init_only_bb () a bit
    5537                 :            :      later.  */
    5538                 :          0 :   gcc_assert (last_added_blocks.length () == 1
    5539                 :            :               && last_added_blocks[0] == new_bb);
    5540                 :            : 
    5541                 :          0 :   last_added_blocks.release ();
    5542                 :          0 :   return new_bb;
    5543                 :            : }
    5544                 :            : 
    5545                 :            : /* Implement sched_create_recovery_block.  ORIG_INSN is where block
    5546                 :            :    will be splitted to insert a check.  */
    5547                 :            : basic_block
    5548                 :          0 : sel_create_recovery_block (insn_t orig_insn)
    5549                 :            : {
    5550                 :          0 :   basic_block first_bb, second_bb, recovery_block;
    5551                 :          0 :   basic_block before_recovery = NULL;
    5552                 :          0 :   rtx_insn *jump;
    5553                 :            : 
    5554                 :          0 :   first_bb = BLOCK_FOR_INSN (orig_insn);
    5555                 :          0 :   if (sel_bb_end_p (orig_insn))
    5556                 :            :     {
    5557                 :            :       /* Avoid introducing an empty block while splitting.  */
    5558                 :          0 :       gcc_assert (single_succ_p (first_bb));
    5559                 :          0 :       second_bb = single_succ (first_bb);
    5560                 :            :     }
    5561                 :            :   else
    5562                 :          0 :     second_bb = sched_split_block (first_bb, orig_insn);
    5563                 :            : 
    5564                 :          0 :   recovery_block = sched_create_recovery_block (&before_recovery);
    5565                 :          0 :   if (before_recovery)
    5566                 :          0 :     copy_lv_set_from (before_recovery, EXIT_BLOCK_PTR_FOR_FN (cfun));
    5567                 :            : 
    5568                 :          0 :   gcc_assert (sel_bb_empty_p (recovery_block));
    5569                 :          0 :   sched_create_recovery_edges (first_bb, recovery_block, second_bb);
    5570                 :          0 :   if (current_loops != NULL)
    5571                 :          0 :     add_bb_to_loop (recovery_block, first_bb->loop_father);
    5572                 :            : 
    5573                 :          0 :   sel_add_bb (recovery_block);
    5574                 :            : 
    5575                 :          0 :   jump = BB_END (recovery_block);
    5576                 :          0 :   gcc_assert (sel_bb_head (recovery_block) == jump);
    5577                 :          0 :   sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
    5578                 :            : 
    5579                 :          0 :   return recovery_block;
    5580                 :            : }
    5581                 :            : 
    5582                 :            : /* Merge basic block B into basic block A.  */
    5583                 :            : static void
    5584                 :         32 : sel_merge_blocks (basic_block a, basic_block b)
    5585                 :            : {
    5586                 :         32 :   gcc_assert (sel_bb_empty_p (b)
    5587                 :            :               && EDGE_COUNT (b->preds) == 1
    5588                 :            :               && EDGE_PRED (b, 0)->src == b->prev_bb);
    5589                 :            : 
    5590                 :         32 :   move_bb_info (b->prev_bb, b);
    5591                 :         32 :   remove_empty_bb (b, false);
    5592                 :         32 :   merge_blocks (a, b);
    5593                 :         32 :   change_loops_latches (b, a);
    5594                 :         32 : }
    5595                 :            : 
    5596                 :            : /* A wrapper for redirect_edge_and_branch_force, which also initializes
    5597                 :            :    data structures for possibly created bb and insns.  */
    5598                 :            : void
    5599                 :         30 : sel_redirect_edge_and_branch_force (edge e, basic_block to)
    5600                 :            : {
    5601                 :         30 :   basic_block jump_bb, src, orig_dest = e->dest;
    5602                 :         30 :   int prev_max_uid;
    5603                 :         30 :   rtx_insn *jump;
    5604                 :         30 :   int old_seqno = -1;
    5605                 :            : 
    5606                 :            :   /* This function is now used only for bookkeeping code creation, where
    5607                 :            :      we'll never get the single pred of orig_dest block and thus will not
    5608                 :            :      hit unreachable blocks when updating dominator info.  */
    5609                 :         30 :   gcc_assert (!sel_bb_empty_p (e->src)
    5610                 :            :               && !single_pred_p (orig_dest));
    5611                 :         30 :   src = e->src;
    5612                 :         30 :   prev_max_uid = get_max_uid ();
    5613                 :            :   /* Compute and pass old_seqno down to sel_init_new_insn only for the case
    5614                 :            :      when the conditional jump being redirected may become unconditional.  */
    5615                 :         30 :   if (any_condjump_p (BB_END (src))
    5616                 :         30 :       && INSN_SEQNO (BB_END (src)) >= 0)
    5617                 :         30 :     old_seqno = INSN_SEQNO (BB_END (src));
    5618                 :            : 
    5619                 :         30 :   jump_bb = redirect_edge_and_branch_force (e, to);
    5620                 :         30 :   if (jump_bb != NULL)
    5621                 :          3 :     sel_add_bb (jump_bb);
    5622                 :            : 
    5623                 :            :   /* This function could not be used to spoil the loop structure by now,
    5624                 :            :      thus we don't care to update anything.  But check it to be sure.  */
    5625                 :         30 :   if (current_loop_nest
    5626                 :         30 :       && pipelining_p)
    5627                 :         26 :     gcc_assert (loop_latch_edge (current_loop_nest));
    5628                 :            : 
    5629                 :         30 :   jump = find_new_jump (src, jump_bb, prev_max_uid);
    5630                 :         30 :   if (jump)
    5631                 :         30 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP,
    5632                 :            :                        old_seqno);
    5633                 :         30 :   set_immediate_dominator (CDI_DOMINATORS, to,
    5634                 :            :                            recompute_dominator (CDI_DOMINATORS, to));
    5635                 :         30 :   set_immediate_dominator (CDI_DOMINATORS, orig_dest,
    5636                 :            :                            recompute_dominator (CDI_DOMINATORS, orig_dest));
    5637                 :         30 :   if (jump && sel_bb_head_p (jump))
    5638                 :          3 :     compute_live (jump);
    5639                 :         30 : }
    5640                 :            : 
    5641                 :            : /* A wrapper for redirect_edge_and_branch.  Return TRUE if blocks connected by
    5642                 :            :    redirected edge are in reverse topological order.  */
    5643                 :            : bool
    5644                 :        104 : sel_redirect_edge_and_branch (edge e, basic_block to)
    5645                 :            : {
    5646                 :        104 :   bool latch_edge_p;
    5647                 :        104 :   basic_block src, orig_dest = e->dest;
    5648                 :        104 :   int prev_max_uid;
    5649                 :        104 :   rtx_insn *jump;
    5650                 :        104 :   edge redirected;
    5651                 :        104 :   bool recompute_toporder_p = false;
    5652                 :        104 :   bool maybe_unreachable = single_pred_p (orig_dest);
    5653                 :        104 :   int old_seqno = -1;
    5654                 :            : 
    5655                 :        208 :   latch_edge_p = (pipelining_p
    5656                 :         93 :                   && current_loop_nest
    5657                 :        197 :                   && e == loop_latch_edge (current_loop_nest));
    5658                 :            : 
    5659                 :        104 :   src = e->src;
    5660                 :        104 :   prev_max_uid = get_max_uid ();
    5661                 :            : 
    5662                 :            :   /* Compute and pass old_seqno down to sel_init_new_insn only for the case
    5663                 :            :      when the conditional jump being redirected may become unconditional.  */
    5664                 :        104 :   if (any_condjump_p (BB_END (src))
    5665                 :        104 :       && INSN_SEQNO (BB_END (src)) >= 0)
    5666                 :        104 :     old_seqno = INSN_SEQNO (BB_END (src));
    5667                 :            : 
    5668                 :        104 :   redirected = redirect_edge_and_branch (e, to);
    5669                 :            : 
    5670                 :        104 :   gcc_assert (redirected && !last_added_blocks.exists ());
    5671                 :            : 
    5672                 :            :   /* When we've redirected a latch edge, update the header.  */
    5673                 :        104 :   if (latch_edge_p)
    5674                 :            :     {
    5675                 :          0 :       current_loop_nest->header = to;
    5676                 :          0 :       gcc_assert (loop_latch_edge (current_loop_nest));
    5677                 :            :     }
    5678                 :            : 
    5679                 :            :   /* In rare situations, the topological relation between the blocks connected
    5680                 :            :      by the redirected edge can change (see PR42245 for an example).  Update
    5681                 :            :      block_to_bb/bb_to_block.  */
    5682                 :        104 :   if (CONTAINING_RGN (e->src->index) == CONTAINING_RGN (to->index)
    5683                 :         99 :       && BLOCK_TO_BB (e->src->index) > BLOCK_TO_BB (to->index))
    5684                 :          1 :     recompute_toporder_p = true;
    5685                 :            : 
    5686                 :        104 :   jump = find_new_jump (src, NULL, prev_max_uid);
    5687                 :          0 :   if (jump)
    5688                 :          0 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP, old_seqno);
    5689                 :            : 
    5690                 :            :   /* Only update dominator info when we don't have unreachable blocks.
    5691                 :            :      Otherwise we'll update in maybe_tidy_empty_bb.  */
    5692                 :        104 :   if (!maybe_unreachable)
    5693                 :            :     {
    5694                 :         86 :       set_immediate_dominator (CDI_DOMINATORS, to,
    5695                 :            :                                recompute_dominator (CDI_DOMINATORS, to));
    5696                 :         86 :       set_immediate_dominator (CDI_DOMINATORS, orig_dest,
    5697                 :            :                                recompute_dominator (CDI_DOMINATORS, orig_dest));
    5698                 :            :     }
    5699                 :        104 :   if (jump && sel_bb_head_p (jump))
    5700                 :          0 :     compute_live (jump);
    5701                 :        104 :   return recompute_toporder_p;
    5702                 :            : }
    5703                 :            : 
    5704                 :            : /* This variable holds the cfg hooks used by the selective scheduler.  */
    5705                 :            : static struct cfg_hooks sel_cfg_hooks;
    5706                 :            : 
    5707                 :            : /* Register sel-sched cfg hooks.  */
    5708                 :            : void
    5709                 :        730 : sel_register_cfg_hooks (void)
    5710                 :            : {
    5711                 :        730 :   sched_split_block = sel_split_block;
    5712                 :            : 
    5713                 :        730 :   orig_cfg_hooks = get_cfg_hooks ();
    5714                 :        730 :   sel_cfg_hooks = orig_cfg_hooks;
    5715                 :            : 
    5716                 :        730 :   sel_cfg_hooks.create_basic_block = sel_create_basic_block;
    5717                 :            : 
    5718                 :        730 :   set_cfg_hooks (sel_cfg_hooks);
    5719                 :            : 
    5720                 :        730 :   sched_init_only_bb = sel_init_only_bb;
    5721                 :        730 :   sched_split_block = sel_split_block;
    5722                 :        730 :   sched_create_empty_bb = sel_create_empty_bb;
    5723                 :        730 : }
    5724                 :            : 
    5725                 :            : /* Unregister sel-sched cfg hooks.  */
    5726                 :            : void
    5727                 :        730 : sel_unregister_cfg_hooks (void)
    5728                 :            : {
    5729                 :        730 :   sched_create_empty_bb = NULL;
    5730                 :        730 :   sched_split_block = NULL;
    5731                 :        730 :   sched_init_only_bb = NULL;
    5732                 :            : 
    5733                 :        730 :   set_cfg_hooks (orig_cfg_hooks);
    5734                 :        730 : }
    5735                 :            : 
    5736                 :            : 
    5737                 :            : /* Emit an insn rtx based on PATTERN.  If a jump insn is wanted,
    5738                 :            :    LABEL is where this jump should be directed.  */
    5739                 :            : rtx_insn *
    5740                 :        820 : create_insn_rtx_from_pattern (rtx pattern, rtx label)
    5741                 :            : {
    5742                 :        820 :   rtx_insn *insn_rtx;
    5743                 :            : 
    5744                 :        820 :   gcc_assert (!INSN_P (pattern));
    5745                 :            : 
    5746                 :        820 :   start_sequence ();
    5747                 :            : 
    5748                 :        820 :   if (label == NULL_RTX)
    5749                 :        799 :     insn_rtx = emit_insn (pattern);
    5750                 :         21 :   else if (DEBUG_INSN_P (label))
    5751                 :         21 :     insn_rtx = emit_debug_insn (pattern);
    5752                 :            :   else
    5753                 :            :     {
    5754                 :          0 :       insn_rtx = emit_jump_insn (pattern);
    5755                 :          0 :       JUMP_LABEL (insn_rtx) = label;
    5756                 :          0 :       ++LABEL_NUSES (label);
    5757                 :            :     }
    5758                 :            : 
    5759                 :        820 :   end_sequence ();
    5760                 :            : 
    5761                 :        820 :   sched_extend_luids ();
    5762                 :        820 :   sched_extend_target ();
    5763                 :        820 :   sched_deps_init (false);
    5764                 :            : 
    5765                 :            :   /* Initialize INSN_CODE now.  */
    5766                 :        820 :   recog_memoized (insn_rtx);
    5767                 :        820 :   return insn_rtx;
    5768                 :            : }
    5769                 :            : 
    5770                 :            : /* Create a new vinsn for INSN_RTX.  FORCE_UNIQUE_P is true when the vinsn
    5771                 :            :    must not be clonable.  */
    5772                 :            : vinsn_t
    5773                 :        772 : create_vinsn_from_insn_rtx (rtx_insn *insn_rtx, bool force_unique_p)
    5774                 :            : {
    5775                 :        772 :   gcc_assert (INSN_P (insn_rtx) && !INSN_IN_STREAM_P (insn_rtx));
    5776                 :            : 
    5777                 :            :   /* If VINSN_TYPE is not USE, retain its uniqueness.  */
    5778                 :        772 :   return vinsn_create (insn_rtx, force_unique_p);
    5779                 :            : }
    5780                 :            : 
    5781                 :            : /* Create a copy of INSN_RTX.  */
    5782                 :            : rtx_insn *
    5783                 :        688 : create_copy_of_insn_rtx (rtx insn_rtx)
    5784                 :            : {
    5785                 :        688 :   rtx_insn *res;
    5786                 :        688 :   rtx link;
    5787                 :            : 
    5788                 :        688 :   if (DEBUG_INSN_P (insn_rtx))
    5789                 :         21 :     return create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
    5790                 :         21 :                                          insn_rtx);
    5791                 :            : 
    5792                 :        667 :   gcc_assert (NONJUMP_INSN_P (insn_rtx));
    5793                 :            : 
    5794                 :        667 :   res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
    5795                 :            :                                       NULL_RTX);
    5796                 :            : 
    5797                 :            :   /* Locate the end of existing REG_NOTES in NEW_RTX.  */
    5798                 :        667 :   rtx *ptail = &REG_NOTES (res);
    5799                 :        667 :   while (*ptail != NULL_RTX)
    5800                 :          0 :     ptail = &XEXP (*ptail, 1);
    5801                 :            : 
    5802                 :            :   /* Copy all REG_NOTES except REG_EQUAL/REG_EQUIV and REG_LABEL_OPERAND
    5803                 :            :      since mark_jump_label will make them.  REG_LABEL_TARGETs are created
    5804                 :            :      there too, but are supposed to be sticky, so we copy them.  */
    5805                 :       1129 :   for (link = REG_NOTES (insn_rtx); link; link = XEXP (link, 1))
    5806                 :        462 :     if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND
    5807                 :        462 :         && REG_NOTE_KIND (link) != REG_EQUAL
    5808                 :        457 :         && REG_NOTE_KIND (link) != REG_EQUIV)
    5809                 :            :       {
    5810                 :        455 :         *ptail = duplicate_reg_note (link);
    5811                 :        455 :         ptail = &XEXP (*ptail, 1);
    5812                 :            :       }
    5813                 :            : 
    5814                 :            :   return res;
    5815                 :            : }
    5816                 :            : 
    5817                 :            : /* Change vinsn field of EXPR to hold NEW_VINSN.  */
    5818                 :            : void
    5819                 :       3546 : change_vinsn_in_expr (expr_t expr, vinsn_t new_vinsn)
    5820                 :            : {
    5821                 :       3546 :   vinsn_detach (EXPR_VINSN (expr));
    5822                 :            : 
    5823                 :       3546 :   EXPR_VINSN (expr) = new_vinsn;
    5824                 :       3546 :   vinsn_attach (new_vinsn);
    5825                 :       3546 : }
    5826                 :            : 
    5827                 :            : /* Helpers for global init.  */
    5828                 :            : /* This structure is used to be able to call existing bundling mechanism
    5829                 :            :    and calculate insn priorities.  */
    5830                 :            : static struct haifa_sched_info sched_sel_haifa_sched_info =
    5831                 :            : {
    5832                 :            :   NULL, /* init_ready_list */
    5833                 :            :   NULL, /* can_schedule_ready_p */
    5834                 :            :   NULL, /* schedule_more_p */
    5835                 :            :   NULL, /* new_ready */
    5836                 :            :   NULL, /* rgn_rank */
    5837                 :            :   sel_print_insn, /* rgn_print_insn */
    5838                 :            :   contributes_to_priority,
    5839                 :            :   NULL, /* insn_finishes_block_p */
    5840                 :            : 
    5841                 :            :   NULL, NULL,
    5842                 :            :   NULL, NULL,
    5843                 :            :   0, 0,
    5844                 :            : 
    5845                 :            :   NULL, /* add_remove_insn */
    5846                 :            :   NULL, /* begin_schedule_ready */
    5847                 :            :   NULL, /* begin_move_insn */
    5848                 :            :   NULL, /* advance_target_bb */
    5849                 :            : 
    5850                 :            :   NULL,
    5851                 :            :   NULL,
    5852                 :            : 
    5853                 :            :   SEL_SCHED | NEW_BBS
    5854                 :            : };
    5855                 :            : 
    5856                 :            : /* Setup special insns used in the scheduler.  */
    5857                 :            : void
    5858                 :        128 : setup_nop_and_exit_insns (void)
    5859                 :            : {
    5860                 :        128 :   gcc_assert (nop_pattern == NULL_RTX
    5861                 :            :               && exit_insn == NULL_RTX);
    5862                 :            : 
    5863                 :        128 :   nop_pattern = constm1_rtx;
    5864                 :            : 
    5865                 :        128 :   start_sequence ();
    5866                 :        128 :   emit_insn (nop_pattern);
    5867                 :        128 :   exit_insn = get_insns ();
    5868                 :        128 :   end_sequence ();
    5869                 :        128 :   set_block_for_insn (exit_insn, EXIT_BLOCK_PTR_FOR_FN (cfun));
    5870                 :        128 : }
    5871                 :            : 
    5872                 :            : /* Free special insns used in the scheduler.  */
    5873                 :            : void
    5874                 :        128 : free_nop_and_exit_insns (void)
    5875                 :            : {
    5876                 :        128 :   exit_insn = NULL;
    5877                 :        128 :   nop_pattern = NULL_RTX;
    5878                 :        128 : }
    5879                 :            : 
    5880                 :            : /* Setup a special vinsn used in new insns initialization.  */
    5881                 :            : void
    5882                 :        730 : setup_nop_vinsn (void)
    5883                 :            : {
    5884                 :        730 :   nop_vinsn = vinsn_create (exit_insn, false);
    5885                 :        730 :   vinsn_attach (nop_vinsn);
    5886                 :        730 : }
    5887                 :            : 
    5888                 :            : /* Free a special vinsn used in new insns initialization.  */
    5889                 :            : void
    5890                 :        730 : free_nop_vinsn (void)
    5891                 :            : {
    5892                 :        730 :   gcc_assert (VINSN_COUNT (nop_vinsn) == 1);
    5893                 :        730 :   vinsn_detach (nop_vinsn);
    5894                 :        730 :   nop_vinsn = NULL;
    5895                 :        730 : }
    5896                 :            : 
    5897                 :            : /* Call a set_sched_flags hook.  */
    5898                 :            : void
    5899                 :       1588 : sel_set_sched_flags (void)
    5900                 :            : {
    5901                 :            :   /* ??? This means that set_sched_flags were called, and we decided to
    5902                 :            :      support speculation.  However, set_sched_flags also modifies flags
    5903                 :            :      on current_sched_info, doing this only at global init.  And we
    5904                 :            :      sometimes change c_s_i later.  So put the correct flags again.  */
    5905                 :       1588 :   if (spec_info && targetm.sched.set_sched_flags)
    5906                 :          0 :     targetm.sched.set_sched_flags (spec_info);
    5907                 :       1588 : }
    5908                 :            : 
    5909                 :            : /* Setup pointers to global sched info structures.  */
    5910                 :            : void
    5911                 :        858 : sel_setup_sched_infos (void)
    5912                 :            : {
    5913                 :        858 :   rgn_setup_common_sched_info ();
    5914                 :            : 
    5915                 :        858 :   memcpy (&sel_common_sched_info, common_sched_info,
    5916                 :            :           sizeof (sel_common_sched_info));
    5917                 :            : 
    5918                 :        858 :   sel_common_sched_info.fix_recovery_cfg = NULL;
    5919                 :        858 :   sel_common_sched_info.add_block = NULL;
    5920                 :        858 :   sel_common_sched_info.estimate_number_of_insns
    5921                 :        858 :     = sel_estimate_number_of_insns;
    5922                 :        858 :   sel_common_sched_info.luid_for_non_insn = sel_luid_for_non_insn;
    5923                 :        858 :   sel_common_sched_info.sched_pass_id = SCHED_SEL_PASS;
    5924                 :            : 
    5925                 :        858 :   common_sched_info = &sel_common_sched_info;
    5926                 :            : 
    5927                 :        858 :   current_sched_info = &sched_sel_haifa_sched_info;
    5928                 :       1716 :   current_sched_info->sched_max_insns_priority =
    5929                 :        858 :     get_rgn_sched_max_insns_priority ();
    5930                 :            : 
    5931                 :        858 :   sel_set_sched_flags ();
    5932                 :        858 : }
    5933                 :            : 
    5934                 :            : 
    5935                 :            : /* Adds basic block BB to region RGN at the position *BB_ORD_INDEX,
    5936                 :            :    *BB_ORD_INDEX after that is increased.  */
    5937                 :            : static void
    5938                 :        311 : sel_add_block_to_region (basic_block bb, int *bb_ord_index, int rgn)
    5939                 :            : {
    5940                 :        311 :   RGN_NR_BLOCKS (rgn) += 1;
    5941                 :        311 :   RGN_DONT_CALC_DEPS (rgn) = 0;
    5942                 :        311 :   RGN_HAS_REAL_EBB (rgn) = 0;
    5943                 :        311 :   CONTAINING_RGN (bb->index) = rgn;
    5944                 :        311 :   BLOCK_TO_BB (bb->index) = *bb_ord_index;
    5945                 :        311 :   rgn_bb_table[RGN_BLOCKS (rgn) + *bb_ord_index] = bb->index;
    5946                 :        311 :   (*bb_ord_index)++;
    5947                 :            : 
    5948                 :            :   /* FIXME: it is true only when not scheduling ebbs.  */
    5949                 :        311 :   RGN_BLOCKS (rgn + 1) = RGN_BLOCKS (rgn) + RGN_NR_BLOCKS (rgn);
    5950                 :        311 : }
    5951                 :            : 
    5952                 :            : /* Functions to support pipelining of outer loops.  */
    5953                 :            : 
    5954                 :            : /* Creates a new empty region and returns it's number.  */
    5955                 :            : static int
    5956                 :         79 : sel_create_new_region (void)
    5957                 :            : {
    5958                 :         79 :   int new_rgn_number = nr_regions;
    5959                 :            : 
    5960                 :         79 :   RGN_NR_BLOCKS (new_rgn_number) = 0;
    5961                 :            : 
    5962                 :            :   /* FIXME: This will work only when EBBs are not created.  */
    5963                 :         79 :   if (new_rgn_number != 0)
    5964                 :         46 :     RGN_BLOCKS (new_rgn_number) = RGN_BLOCKS (new_rgn_number - 1) +
    5965                 :         46 :       RGN_NR_BLOCKS (new_rgn_number - 1);
    5966                 :            :   else
    5967                 :         33 :     RGN_BLOCKS (new_rgn_number) = 0;
    5968                 :            : 
    5969                 :            :   /* Set the blocks of the next region so the other functions may
    5970                 :            :      calculate the number of blocks in the region.  */
    5971                 :         79 :   RGN_BLOCKS (new_rgn_number + 1) = RGN_BLOCKS (new_rgn_number) +
    5972                 :            :     RGN_NR_BLOCKS (new_rgn_number);
    5973                 :            : 
    5974                 :         79 :   nr_regions++;
    5975                 :            : 
    5976                 :         79 :   return new_rgn_number;
    5977                 :            : }
    5978                 :            : 
    5979                 :            : /* If X has a smaller topological sort number than Y, returns -1;
    5980                 :            :    if greater, returns 1.  */
    5981                 :            : static int
    5982                 :       2512 : bb_top_order_comparator (const void *x, const void *y)
    5983                 :            : {
    5984                 :       2512 :   basic_block bb1 = *(const basic_block *) x;
    5985                 :       2512 :   basic_block bb2 = *(const basic_block *) y;
    5986                 :            : 
    5987                 :       2512 :   gcc_assert (bb1 == bb2
    5988                 :            :               || rev_top_order_index[bb1->index]
    5989                 :            :                  != rev_top_order_index[bb2->index]);
    5990                 :            : 
    5991                 :            :   /* It's a reverse topological order in REV_TOP_ORDER_INDEX, so
    5992                 :            :      bbs with greater number should go earlier.  */
    5993                 :       2512 :   if (rev_top_order_index[bb1->index] > rev_top_order_index[bb2->index])
    5994                 :            :     return -1;
    5995                 :            :   else
    5996                 :       1069 :     return 1;
    5997                 :            : }
    5998                 :            : 
    5999                 :            : /* Create a region for LOOP and return its number.  If we don't want
    6000                 :            :    to pipeline LOOP, return -1.  */
    6001                 :            : static int
    6002                 :         52 : make_region_from_loop (class loop *loop)
    6003                 :            : {
    6004                 :         52 :   unsigned int i;
    6005                 :         52 :   int new_rgn_number = -1;
    6006                 :         52 :   class loop *inner;
    6007                 :            : 
    6008                 :            :   /* Basic block index, to be assigned to BLOCK_TO_BB.  */
    6009                 :         52 :   int bb_ord_index = 0;
    6010                 :         52 :   basic_block *loop_blocks;
    6011                 :         52 :   basic_block preheader_block;
    6012                 :            : 
    6013                 :         52 :   if (loop->num_nodes
    6014                 :         52 :       > (unsigned) param_max_pipeline_region_blocks)
    6015                 :            :     return -1;
    6016                 :            : 
    6017                 :            :   /* Don't pipeline loops whose latch belongs to some of its inner loops.  */
    6018                 :         57 :   for (inner = loop->inner; inner; inner = inner->inner)
    6019                 :          7 :     if (flow_bb_inside_loop_p (inner, loop->latch))
    6020                 :            :       return -1;
    6021                 :            : 
    6022                 :         50 :   loop->ninsns = num_loop_insns (loop);
    6023                 :         50 :   if ((int) loop->ninsns > param_max_pipeline_region_insns)
    6024                 :            :     return -1;
    6025                 :            : 
    6026                 :         50 :   loop_blocks = get_loop_body_in_custom_order (loop, bb_top_order_comparator);
    6027                 :            : 
    6028                 :        311 :   for (i = 0; i < loop->num_nodes; i++)
    6029                 :        261 :     if (loop_blocks[i]->flags & BB_IRREDUCIBLE_LOOP)
    6030                 :            :       {
    6031                 :          0 :         free (loop_blocks);
    6032                 :          0 :         return -1;
    6033                 :            :       }
    6034                 :            : 
    6035                 :         50 :   preheader_block = loop_preheader_edge (loop)->src;
    6036                 :         50 :   gcc_assert (preheader_block);
    6037                 :         50 :   gcc_assert (loop_blocks[0] == loop->header);
    6038                 :            : 
    6039                 :         50 :   new_rgn_number = sel_create_new_region ();
    6040                 :            : 
    6041                 :         50 :   sel_add_block_to_region (preheader_block, &bb_ord_index, new_rgn_number);
    6042                 :         50 :   bitmap_set_bit (bbs_in_loop_rgns, preheader_block->index);
    6043                 :            : 
    6044                 :        311 :   for (i = 0; i < loop->num_nodes; i++)
    6045                 :            :     {
    6046                 :            :       /* Add only those blocks that haven't been scheduled in the inner loop.
    6047                 :            :          The exception is the basic blocks with bookkeeping code - they should
    6048                 :            :          be added to the region (and they actually don't belong to the loop
    6049                 :            :          body, but to the region containing that loop body).  */
    6050                 :            : 
    6051                 :        261 :       gcc_assert (new_rgn_number >= 0);
    6052                 :            : 
    6053                 :        261 :       if (! bitmap_bit_p (bbs_in_loop_rgns, loop_blocks[i]->index))
    6054                 :            :         {
    6055                 :        232 :           sel_add_block_to_region (loop_blocks[i], &bb_ord_index,
    6056                 :            :                                    new_rgn_number);
    6057                 :        493 :           bitmap_set_bit (bbs_in_loop_rgns, loop_blocks[i]->index);
    6058                 :            :         }
    6059                 :            :     }
    6060                 :            : 
    6061                 :         50 :   free (loop_blocks);
    6062                 :         50 :   MARK_LOOP_FOR_PIPELINING (loop);
    6063                 :            : 
    6064                 :         50 :   return new_rgn_number;
    6065                 :            : }
    6066                 :            : 
    6067                 :            : /* Create a new region from preheader blocks LOOP_BLOCKS.  */
    6068                 :            : void
    6069                 :         29 : make_region_from_loop_preheader (vec<basic_block> *&loop_blocks)
    6070                 :            : {
    6071                 :         29 :   unsigned int i;
    6072                 :         29 :   int new_rgn_number = -1;
    6073                 :         29 :   basic_block bb;
    6074                 :            : 
    6075                 :            :   /* Basic block index, to be assigned to BLOCK_TO_BB.  */
    6076                 :         29 :   int bb_ord_index = 0;
    6077                 :            : 
    6078                 :         29 :   new_rgn_number = sel_create_new_region ();
    6079                 :            : 
    6080                 :         58 :   FOR_EACH_VEC_ELT (*loop_blocks, i, bb)
    6081                 :            :     {
    6082                 :         29 :       gcc_assert (new_rgn_number >= 0);
    6083                 :            : 
    6084                 :         29 :       sel_add_block_to_region (bb, &bb_ord_index, new_rgn_number);
    6085                 :            :     }
    6086                 :            : 
    6087                 :         29 :   vec_free (loop_blocks);
    6088                 :         29 : }
    6089                 :            : 
    6090                 :            : 
    6091                 :            : /* Create region(s) from loop nest LOOP, such that inner loops will be
    6092                 :            :    pipelined before outer loops.  Returns true when a region for LOOP
    6093                 :            :    is created.  */
    6094                 :            : static bool
    6095                 :         52 : make_regions_from_loop_nest (class loop *loop)
    6096                 :            : {
    6097                 :         52 :   class loop *cur_loop;
    6098                 :         52 :   int rgn_number;
    6099                 :            : 
    6100                 :            :   /* Traverse all inner nodes of the loop.  */
    6101                 :         61 :   for (cur_loop = loop->inner; cur_loop; cur_loop = cur_loop->next)
    6102                 :          9 :     if (! bitmap_bit_p (bbs_in_loop_rgns, cur_loop->header->index))
    6103                 :            :       return false;
    6104                 :            : 
    6105                 :            :   /* At this moment all regular inner loops should have been pipelined.
    6106                 :            :      Try to create a region from this loop.  */
    6107                 :         52 :   rgn_number = make_region_from_loop (loop);
    6108                 :            : 
    6109                 :         52 :   if (rgn_number < 0)
    6110                 :            :     return false;
    6111                 :            : 
    6112                 :         50 :   loop_nests.safe_push (loop);
    6113                 :         50 :   return true;
    6114                 :            : }
    6115                 :            : 
    6116                 :            : /* Initalize data structures needed.  */
    6117                 :            : void
    6118                 :         35 : sel_init_pipelining (void)
    6119                 :            : {
    6120                 :            :   /* Collect loop information to be used in outer loops pipelining.  */
    6121                 :         35 :   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
    6122                 :            :                        | LOOPS_HAVE_FALLTHRU_PREHEADERS
    6123                 :            :                        | LOOPS_HAVE_RECORDED_EXITS
    6124                 :            :                        | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
    6125                 :         35 :   current_loop_nest = NULL;
    6126                 :            : 
    6127                 :         35 :   bbs_in_loop_rgns = sbitmap_alloc (last_basic_block_for_fn (cfun));
    6128                 :         35 :   bitmap_clear (bbs_in_loop_rgns);
    6129                 :            : 
    6130                 :         35 :   recompute_rev_top_order ();
    6131                 :         35 : }
    6132                 :            : 
    6133                 :            : /* Returns a class loop for region RGN.  */
    6134                 :            : loop_p
    6135                 :        352 : get_loop_nest_for_rgn (unsigned int rgn)
    6136                 :            : {
    6137                 :            :   /* Regions created with extend_rgns don't have corresponding loop nests,
    6138                 :            :      because they don't represent loops.  */
    6139                 :        675 :   if (rgn < loop_nests.length ())
    6140                 :         50 :     return loop_nests[rgn];
    6141                 :            :   else
    6142                 :            :     return NULL;
    6143                 :            : }
    6144                 :            : 
    6145                 :            : /* True when LOOP was included into pipelining regions.   */
    6146                 :            : bool
    6147                 :       1053 : considered_for_pipelining_p (class loop *loop)
    6148                 :            : {
    6149                 :       1053 :   if (loop_depth (loop) == 0)
    6150                 :            :     return false;
    6151                 :            : 
    6152                 :            :   /* Now, the loop could be too large or irreducible.  Check whether its
    6153                 :            :      region is in LOOP_NESTS.
    6154                 :            :      We determine the region number of LOOP as the region number of its
    6155                 :            :      latch.  We can't use header here, because this header could be
    6156                 :            :      just removed preheader and it will give us the wrong region number.
    6157                 :            :      Latch can't be used because it could be in the inner loop too.  */
    6158                 :        259 :   if (LOOP_MARKED_FOR_PIPELINING_P (loop))
    6159                 :            :     {
    6160                 :        157 :       int rgn = CONTAINING_RGN (loop->latch->index);
    6161                 :            : 
    6162                 :        314 :       gcc_assert ((unsigned) rgn < loop_nests.length ());
    6163                 :            :       return true;
    6164                 :            :     }
    6165                 :            : 
    6166                 :            :   return false;
    6167                 :            : }
    6168                 :            : 
    6169                 :            : /* Makes regions from the rest of the blocks, after loops are chosen
    6170                 :            :    for pipelining.  */
    6171                 :            : static void
    6172                 :         35 : make_regions_from_the_rest (void)
    6173                 :            : {
    6174                 :         35 :   int cur_rgn_blocks;
    6175                 :         35 :   int *loop_hdr;
    6176                 :         35 :   int i;
    6177                 :            : 
    6178                 :         35 :   basic_block bb;
    6179                 :         35 :   edge e;
    6180                 :         35 :   edge_iterator ei;
    6181                 :         35 :   int *degree;
    6182                 :            : 
    6183                 :            :   /* Index in rgn_bb_table where to start allocating new regions.  */
    6184                 :         35 :   cur_rgn_blocks = nr_regions ? RGN_BLOCKS (nr_regions) : 0;
    6185                 :            : 
    6186                 :            :   /* Make regions from all the rest basic blocks - those that don't belong to
    6187                 :            :      any loop or belong to irreducible loops.  Prepare the data structures
    6188                 :            :      for extend_rgns.  */
    6189                 :            : 
    6190                 :            :   /* LOOP_HDR[I] == -1 if I-th bb doesn't belong to any loop,
    6191                 :            :      LOOP_HDR[I] == LOOP_HDR[J] iff basic blocks I and J reside within the same
    6192                 :            :      loop.  */
    6193                 :         35 :   loop_hdr = XNEWVEC (int, last_basic_block_for_fn (cfun));
    6194                 :         35 :   degree = XCNEWVEC (int, last_basic_block_for_fn (cfun));
    6195                 :            : 
    6196                 :            : 
    6197                 :            :   /* For each basic block that belongs to some loop assign the number
    6198                 :            :      of innermost loop it belongs to.  */
    6199                 :        647 :   for (i = 0; i < last_basic_block_for_fn (cfun); i++)
    6200                 :        612 :     loop_hdr[i] = -1;
    6201                 :            : 
    6202                 :        575 :   FOR_EACH_BB_FN (bb, cfun)
    6203                 :            :     {
    6204                 :        540 :       if (bb->loop_father && bb->loop_father->num != 0
    6205                 :        319 :           && !(bb->flags & BB_IRREDUCIBLE_LOOP))
    6206                 :        319 :         loop_hdr[bb->index] = bb->loop_father->num;
    6207                 :            :     }
    6208                 :            : 
    6209                 :            :   /* For each basic block degree is calculated as the number of incoming
    6210                 :            :      edges, that are going out of bbs that are not yet scheduled.
    6211                 :            :      The basic blocks that are scheduled have degree value of zero.  */
    6212                 :        575 :   FOR_EACH_BB_FN (bb, cfun)
    6213                 :            :     {
    6214                 :        540 :       degree[bb->index] = 0;
    6215                 :            : 
    6216                 :        540 :       if (!bitmap_bit_p (bbs_in_loop_rgns, bb->index))
    6217                 :            :         {
    6218                 :        638 :           FOR_EACH_EDGE (e, ei, bb->preds)
    6219                 :        380 :             if (!bitmap_bit_p (bbs_in_loop_rgns, e->src->index))
    6220                 :        284 :               degree[bb->index]++;
    6221                 :            :         }
    6222                 :            :       else
    6223                 :        282 :         degree[bb->index] = -1;
    6224                 :            :     }
    6225                 :            : 
    6226                 :         35 :   extend_rgns (degree, &cur_rgn_blocks, bbs_in_loop_rgns, loop_hdr);
    6227                 :            : 
    6228                 :            :   /* Any block that did not end up in a region is placed into a region
    6229                 :            :      by itself.  */
    6230                 :        575 :   FOR_EACH_BB_FN (bb, cfun)
    6231                 :        540 :     if (degree[bb->index] >= 0)
    6232                 :            :       {
    6233                 :        258 :         rgn_bb_table[cur_rgn_blocks] = bb->index;
    6234                 :        258 :         RGN_NR_BLOCKS (nr_regions) = 1;
    6235                 :        258 :         RGN_BLOCKS (nr_regions) = cur_rgn_blocks++;
    6236                 :        258 :         RGN_DONT_CALC_DEPS (nr_regions) = 0;
    6237                 :        258 :         RGN_HAS_REAL_EBB (nr_regions) = 0;
    6238                 :        258 :         CONTAINING_RGN (bb->index) = nr_regions++;
    6239                 :        258 :         BLOCK_TO_BB (bb->index) = 0;
    6240                 :            :       }
    6241                 :            : 
    6242                 :         35 :   free (degree);
    6243                 :         35 :   free (loop_hdr);
    6244                 :         35 : }
    6245                 :            : 
    6246                 :            : /* Free data structures used in pipelining of loops.  */
    6247                 :         35 : void sel_finish_pipelining (void)
    6248                 :            : {
    6249                 :         35 :   class loop *loop;
    6250                 :            : 
    6251                 :            :   /* Release aux fields so we don't free them later by mistake.  */
    6252                 :         94 :   FOR_EACH_LOOP (loop, 0)
    6253                 :         59 :     loop->aux = NULL;
    6254                 :            : 
    6255                 :         35 :   loop_optimizer_finalize ();
    6256                 :            : 
    6257                 :         35 :   loop_nests.release ();
    6258                 :            : 
    6259                 :         35 :   free (rev_top_order_index);
    6260                 :         35 :   rev_top_order_index = NULL;
    6261                 :         35 : }
    6262                 :            : 
    6263                 :            : /* This function replaces the find_rgns when
    6264                 :            :    FLAG_SEL_SCHED_PIPELINING_OUTER_LOOPS is set.  */
    6265                 :            : void
    6266                 :         35 : sel_find_rgns (void)
    6267                 :            : {
    6268                 :         35 :   sel_init_pipelining ();
    6269                 :         35 :   extend_regions ();
    6270                 :            : 
    6271                 :         35 :   if (current_loops)
    6272                 :            :     {
    6273                 :         35 :       loop_p loop;
    6274                 :            : 
    6275                 :        149 :       FOR_EACH_LOOP (loop, (flag_sel_sched_pipelining_outer_loops
    6276                 :            :                             ? LI_FROM_INNERMOST
    6277                 :            :                             : LI_ONLY_INNERMOST))
    6278                 :         52 :         make_regions_from_loop_nest (loop);
    6279                 :            :     }
    6280                 :            : 
    6281                 :            :   /* Make regions from all the rest basic blocks and schedule them.
    6282                 :            :      These blocks include blocks that don't belong to any loop or belong
    6283                 :            :      to irreducible loops.  */
    6284                 :         35 :   make_regions_from_the_rest ();
    6285                 :            : 
    6286                 :            :   /* We don't need bbs_in_loop_rgns anymore.  */
    6287                 :         35 :   sbitmap_free (bbs_in_loop_rgns);
    6288                 :         35 :   bbs_in_loop_rgns = NULL;
    6289                 :         35 : }
    6290                 :            : 
    6291                 :            : /* Add the preheader blocks from previous loop to current region taking
    6292                 :            :    it from LOOP_PREHEADER_BLOCKS (current_loop_nest) and record them in *BBS.
    6293                 :            :    This function is only used with -fsel-sched-pipelining-outer-loops.  */
    6294                 :            : void
    6295                 :         50 : sel_add_loop_preheaders (bb_vec_t *bbs)
    6296                 :            : {
    6297                 :         50 :   int i;
    6298                 :         50 :   basic_block bb;
    6299                 :        100 :   vec<basic_block> *preheader_blocks
    6300                 :         50 :     = LOOP_PREHEADER_BLOCKS (current_loop_nest);
    6301                 :            : 
    6302                 :         50 :   if (!preheader_blocks)
    6303                 :         43 :     return;
    6304                 :            : 
    6305                 :         21 :   for (i = 0; preheader_blocks->iterate (i, &bb); i++)
    6306                 :            :     {
    6307                 :          7 :       bbs->safe_push (bb);
    6308                 :          7 :       last_added_blocks.safe_push (bb);
    6309                 :          7 :       sel_add_bb (bb);
    6310                 :            :     }
    6311                 :            : 
    6312                 :          7 :   vec_free (preheader_blocks);
    6313                 :            : }
    6314                 :            : 
    6315                 :            : /* While pipelining outer loops, returns TRUE if BB is a loop preheader.
    6316                 :            :    Please note that the function should also work when pipelining_p is
    6317                 :            :    false, because it is used when deciding whether we should or should
    6318                 :            :    not reschedule pipelined code.  */
    6319                 :            : bool
    6320                 :       1374 : sel_is_loop_preheader_p (basic_block bb)
    6321                 :            : {
    6322                 :       1374 :   if (current_loop_nest)
    6323                 :            :     {
    6324                 :        890 :       class loop *outer;
    6325                 :            : 
    6326                 :        890 :       if (preheader_removed)
    6327                 :            :         return false;
    6328                 :            : 
    6329                 :            :       /* Preheader is the first block in the region.  */
    6330                 :        890 :       if (BLOCK_TO_BB (bb->index) == 0)
    6331                 :            :         return true;
    6332                 :            : 
    6333                 :            :       /* We used to find a preheader with the topological information.
    6334                 :            :          Check that the above code is equivalent to what we did before.  */
    6335                 :            : 
    6336                 :        672 :       if (in_current_region_p (current_loop_nest->header))
    6337                 :        672 :         gcc_assert (!(BLOCK_TO_BB (bb->index)
    6338                 :            :                       < BLOCK_TO_BB (current_loop_nest->header->index)));
    6339                 :            : 
    6340                 :            :       /* Support the situation when the latch block of outer loop
    6341                 :            :          could be from here.  */
    6342                 :        672 :       for (outer = loop_outer (current_loop_nest);
    6343                 :        828 :            outer;
    6344                 :        984 :            outer = loop_outer (outer))
    6345                 :        828 :         if (considered_for_pipelining_p (outer) && outer->latch == bb)
    6346                 :          0 :           gcc_unreachable ();
    6347                 :            :     }
    6348                 :            : 
    6349                 :            :   return false;
    6350                 :            : }
    6351                 :            : 
    6352                 :            : /* Check whether JUMP_BB ends with a jump insn that leads only to DEST_BB and
    6353                 :            :    can be removed, making the corresponding edge fallthrough (assuming that
    6354                 :            :    all basic blocks between JUMP_BB and DEST_BB are empty).  */
    6355                 :            : static bool
    6356                 :       3385 : bb_has_removable_jump_to_p (basic_block jump_bb, basic_block dest_bb)
    6357                 :            : {
    6358                 :       3385 :   if (!onlyjump_p (BB_END (jump_bb))
    6359                 :       3385 :       || tablejump_p (BB_END (jump_bb), NULL, NULL))
    6360                 :       1002 :     return false;
    6361                 :            : 
    6362                 :            :   /* Several outgoing edges, abnormal edge or destination of jump is
    6363                 :            :      not DEST_BB.  */
    6364                 :       2383 :   if (EDGE_COUNT (jump_bb->succs) != 1
    6365                 :        594 :       || EDGE_SUCC (jump_bb, 0)->flags & (EDGE_ABNORMAL | EDGE_CROSSING)
    6366                 :       2966 :       || EDGE_SUCC (jump_bb, 0)->dest != dest_bb)
    6367                 :       2351 :     return false;
    6368                 :            : 
    6369                 :            :   /* If not anything of the upper.  */
    6370                 :            :   return true;
    6371                 :            : }
    6372                 :            : 
    6373                 :            : /* Removes the loop preheader from the current region and saves it in
    6374                 :            :    PREHEADER_BLOCKS of the father loop, so they will be added later to
    6375                 :            :    region that represents an outer loop.  */
    6376                 :            : static void
    6377                 :         50 : sel_remove_loop_preheader (void)
    6378                 :            : {
    6379                 :         50 :   int i, old_len;
    6380                 :         50 :   int cur_rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    6381                 :         50 :   basic_block bb;
    6382                 :         50 :   bool all_empty_p = true;
    6383                 :         50 :   vec<basic_block> *preheader_blocks
    6384                 :        143 :     = LOOP_PREHEADER_BLOCKS (loop_outer (current_loop_nest));
    6385                 :            : 
    6386                 :         50 :   vec_check_alloc (preheader_blocks, 0);
    6387                 :            : 
    6388                 :         50 :   gcc_assert (current_loop_nest);
    6389                 :         50 :   old_len = preheader_blocks->length ();
    6390                 :            : 
    6391                 :            :   /* Add blocks that aren't within the current loop to PREHEADER_BLOCKS.  */
    6392                 :        349 :   for (i = 0; i < RGN_NR_BLOCKS (cur_rgn); i++)
    6393                 :            :     {
    6394                 :        299 :       bb = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i));
    6395                 :            : 
    6396                 :            :       /* If the basic block belongs to region, but doesn't belong to
    6397                 :            :          corresponding loop, then it should be a preheader.  */
    6398                 :        299 :       if (sel_is_loop_preheader_p (bb))
    6399                 :            :         {
    6400                 :         50 :           preheader_blocks->safe_push (bb);
    6401                 :         50 :           if (BB_END (bb) != bb_note (bb))
    6402                 :         31 :             all_empty_p = false;
    6403                 :            :         }
    6404                 :            :     }
    6405                 :            : 
    6406                 :            :   /* Remove these blocks only after iterating over the whole region.  */
    6407                 :        150 :   for (i = preheader_blocks->length () - 1; i >= old_len; i--)
    6408                 :            :     {
    6409                 :         50 :       bb =  (*preheader_blocks)[i];
    6410                 :         50 :       sel_remove_bb (bb, false);
    6411                 :            :     }
    6412                 :            : 
    6413                 :        100 :   if (!considered_for_pipelining_p (loop_outer (current_loop_nest)))
    6414                 :            :     {
    6415                 :         43 :       if (!all_empty_p)
    6416                 :            :         /* Immediately create new region from preheader.  */
    6417                 :         29 :         make_region_from_loop_preheader (preheader_blocks);
    6418                 :            :       else
    6419                 :            :         {
    6420                 :            :           /* If all preheader blocks are empty - dont create new empty region.
    6421                 :            :              Instead, remove them completely.  */
    6422                 :         42 :           FOR_EACH_VEC_ELT (*preheader_blocks, i, bb)
    6423                 :            :             {
    6424                 :         14 :               edge e;
    6425                 :         14 :               edge_iterator ei;
    6426                 :         14 :               basic_block prev_bb = bb->prev_bb, next_bb = bb->next_bb;
    6427                 :            : 
    6428                 :            :               /* Redirect all incoming edges to next basic block.  */
    6429                 :         31 :               for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
    6430                 :            :                 {
    6431                 :         17 :                   if (! (e->flags & EDGE_FALLTHRU))
    6432                 :         13 :                     redirect_edge_and_branch (e, bb->next_bb);
    6433                 :            :                   else
    6434                 :          4 :                     redirect_edge_succ (e, bb->next_bb);
    6435                 :            :                 }
    6436                 :         14 :               gcc_assert (BB_NOTE_LIST (bb) == NULL);
    6437                 :         14 :               delete_and_free_basic_block (bb);
    6438                 :            : 
    6439                 :            :               /* Check if after deleting preheader there is a nonconditional
    6440                 :            :                  jump in PREV_BB that leads to the next basic block NEXT_BB.
    6441                 :            :                  If it is so - delete this jump and clear data sets of its
    6442                 :            :                  basic block if it becomes empty.  */
    6443                 :         14 :               if (next_bb->prev_bb == prev_bb
    6444                 :         14 :                   && prev_bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
    6445                 :         28 :                   && bb_has_removable_jump_to_p (prev_bb, next_bb))
    6446                 :            :                 {
    6447                 :          8 :                   redirect_edge_and_branch (EDGE_SUCC (prev_bb, 0), next_bb);
    6448                 :          8 :                   if (BB_END (prev_bb) == bb_note (prev_bb))
    6449                 :          0 :                     free_data_sets (prev_bb);
    6450                 :            :                 }
    6451                 :            : 
    6452                 :         14 :               set_immediate_dominator (CDI_DOMINATORS, next_bb,
    6453                 :            :                                        recompute_dominator (CDI_DOMINATORS,
    6454                 :            :                                                             next_bb));
    6455                 :            :             }
    6456                 :            :         }
    6457                 :         43 :       vec_free (preheader_blocks);
    6458                 :            :     }
    6459                 :            :   else
    6460                 :            :     /* Store preheader within the father's loop structure.  */
    6461                 :         14 :     SET_LOOP_PREHEADER_BLOCKS (loop_outer (current_loop_nest),
    6462                 :            :                                preheader_blocks);
    6463                 :         50 : }
    6464                 :            : 
    6465                 :            : #endif

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.