LCOV - code coverage report
Current view: top level - gcc - sel-sched-ir.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.6 % 2676 2290
Test Date: 2026-02-28 14:20:25 Functions: 93.3 % 269 251
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Instruction scheduling pass.  Selective scheduler and pipeliner.
       2              :    Copyright (C) 2006-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #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         4248 : ilist_copy (ilist_t l)
     168              : {
     169         4248 :   ilist_t head = NULL, *tailp = &head;
     170              : 
     171        18889 :   while (l)
     172              :     {
     173        14641 :       ilist_add (tailp, ILIST_INSN (l));
     174        14641 :       tailp = &ILIST_NEXT (*tailp);
     175        14641 :       l = ILIST_NEXT (l);
     176              :     }
     177              : 
     178         4248 :   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         6126 : blist_add (blist_t *lp, insn_t to, ilist_t ptr, deps_t dc)
     199              : {
     200         6126 :   bnd_t bnd;
     201              : 
     202         6126 :   _list_add (lp);
     203         6126 :   bnd = BLIST_BND (*lp);
     204              : 
     205         6126 :   BND_TO (bnd) = to;
     206         6126 :   BND_PTR (bnd) = ptr;
     207         6126 :   BND_AV (bnd) = NULL;
     208         6126 :   BND_AV1 (bnd) = NULL;
     209         6126 :   BND_DC (bnd) = dc;
     210         6126 : }
     211              : 
     212              : /* Remove the list note pointed to by LP.  */
     213              : void
     214         6126 : blist_remove (blist_t *lp)
     215              : {
     216         6126 :   bnd_t b = BLIST_BND (*lp);
     217              : 
     218         6126 :   av_set_clear (&BND_AV (b));
     219         6126 :   av_set_clear (&BND_AV1 (b));
     220         6126 :   ilist_clear (&BND_PTR (b));
     221              : 
     222         6126 :   _list_remove (lp);
     223         6126 : }
     224              : 
     225              : /* Init a fence tail L.  */
     226              : void
     227         1756 : flist_tail_init (flist_tail_t l)
     228              : {
     229         1756 :   FLIST_TAIL_HEAD (l) = NULL;
     230         1756 :   FLIST_TAIL_TAILP (l) = &FLIST_TAIL_HEAD (l);
     231         1756 : }
     232              : 
     233              : /* Try to find fence corresponding to INSN in L.  */
     234              : fence_t
     235        65491 : flist_lookup (flist_t l, insn_t insn)
     236              : {
     237       137933 :   while (l)
     238              :     {
     239        72460 :       if (FENCE_INSN (FLIST_FENCE (l)) == insn)
     240           18 :         return FLIST_FENCE (l);
     241              : 
     242        72442 :       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         1878 : init_fence_for_scheduling (fence_t f)
     251              : {
     252         1878 :   FENCE_BNDS (f) = NULL;
     253         1878 :   FENCE_PROCESSED_P (f) = false;
     254         1878 :   FENCE_SCHEDULED_P (f) = false;
     255          830 : }
     256              : 
     257              : /* Add new fence consisting of INSN and STATE to the list pointed to by LP.  */
     258              : static void
     259         1048 : 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         1048 :   fence_t f;
     266              : 
     267         1048 :   _list_add (lp);
     268         1048 :   f = FLIST_FENCE (*lp);
     269              : 
     270         1048 :   FENCE_INSN (f) = insn;
     271              : 
     272         1048 :   gcc_assert (state != NULL);
     273         1048 :   FENCE_STATE (f) = state;
     274              : 
     275         1048 :   FENCE_CYCLE (f) = cycle;
     276         1048 :   FENCE_ISSUED_INSNS (f) = cycle_issued_insns;
     277         1048 :   FENCE_STARTS_CYCLE_P (f) = starts_cycle_p;
     278         1048 :   FENCE_AFTER_STALL_P (f) = after_stall_p;
     279              : 
     280         1048 :   gcc_assert (dc != NULL);
     281         1048 :   FENCE_DC (f) = dc;
     282              : 
     283         1048 :   gcc_assert (tc != NULL || targetm.sched.alloc_sched_context == NULL);
     284         1048 :   FENCE_TC (f) = tc;
     285              : 
     286         1048 :   FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn;
     287         1048 :   FENCE_ISSUE_MORE (f) = issue_more;
     288         1048 :   FENCE_EXECUTING_INSNS (f) = executing_insns;
     289         1048 :   FENCE_READY_TICKS (f) = ready_ticks;
     290         1048 :   FENCE_READY_TICKS_SIZE (f) = ready_ticks_size;
     291         1048 :   FENCE_SCHED_NEXT (f) = sched_next;
     292              : 
     293         1048 :   init_fence_for_scheduling (f);
     294         1048 : }
     295              : 
     296              : /* Remove the head node of the list pointed to by LP.  */
     297              : static void
     298         1878 : flist_remove (flist_t *lp)
     299              : {
     300         1878 :   if (FENCE_INSN (FLIST_FENCE (*lp)))
     301         1047 :     fence_clear (FLIST_FENCE (*lp));
     302         1878 :   _list_remove (lp);
     303         1878 : }
     304              : 
     305              : /* Clear the fence list pointed to by LP.  */
     306              : void
     307         1736 : flist_clear (flist_t *lp)
     308              : {
     309         3614 :   while (*lp)
     310         1878 :     flist_remove (lp);
     311         1736 : }
     312              : 
     313              : /* Add ORIGINAL_INSN the def list DL honoring CROSSED_CALL_ABIS.  */
     314              : void
     315         3894 : def_list_add (def_list_t *dl, insn_t original_insn,
     316              :               unsigned int crossed_call_abis)
     317              : {
     318         3894 :   def_t d;
     319              : 
     320         3894 :   _list_add (dl);
     321         3894 :   d = DEF_LIST_DEF (*dl);
     322              : 
     323         3894 :   d->orig_insn = original_insn;
     324         3894 :   d->crossed_call_abis = crossed_call_abis;
     325         3894 : }
     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         1237 : alloc_target_context (void)
     340              : {
     341         1237 :   return (targetm.sched.alloc_sched_context
     342         1237 :           ? 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         3127 : 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         1059 : create_target_context (bool clean_p)
     359              : {
     360         1059 :   tc_t tc = alloc_target_context ();
     361              : 
     362         1059 :   init_target_context (tc, clean_p);
     363         1059 :   return tc;
     364              : }
     365              : 
     366              : /* Copy TC to the current backend context.  */
     367              : void
     368         2234 : set_target_context (tc_t tc)
     369              : {
     370         2234 :   if (targetm.sched.set_sched_context)
     371            0 :     targetm.sched.set_sched_context (tc);
     372         2234 : }
     373              : 
     374              : /* TC is about to be destroyed.  Free any internal data.  */
     375              : static void
     376         3127 : 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         1237 : delete_target_context (tc_t tc)
     385              : {
     386         1237 :   clear_target_context (tc);
     387              : 
     388         1237 :   if (targetm.sched.free_sched_context)
     389            0 :     targetm.sched.free_sched_context (tc);
     390         1237 : }
     391              : 
     392              : /* Make a copy of FROM in TO.
     393              :    NB: May be this should be a hook.  */
     394              : static void
     395          178 : copy_target_context (tc_t to, tc_t from)
     396              : {
     397          178 :   tc_t tmp = create_target_context (false);
     398              : 
     399          178 :   set_target_context (from);
     400          178 :   init_target_context (to, false);
     401              : 
     402          178 :   set_target_context (tmp);
     403          178 :   delete_target_context (tmp);
     404          178 : }
     405              : 
     406              : /* Create a copy of TC.  */
     407              : static tc_t
     408          178 : create_copy_of_target_context (tc_t tc)
     409              : {
     410          178 :   tc_t copy = alloc_target_context ();
     411              : 
     412          178 :   copy_target_context (copy, tc);
     413              : 
     414          178 :   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         1890 : reset_target_context (tc_t tc, bool clean_p)
     421              : {
     422         1890 :   clear_target_context (tc);
     423         1890 :   init_target_context (tc, clean_p);
     424         1890 : }
     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          178 : copy_deps_context (deps_t to, deps_t from)
     434              : {
     435          178 :   init_deps (to, false);
     436          178 :   deps_join (to, from);
     437          178 : }
     438              : 
     439              : /* Allocate store for dep context.  */
     440              : static deps_t
     441         1059 : 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          881 : create_deps_context (void)
     449              : {
     450          881 :   deps_t dc = alloc_deps_context ();
     451              : 
     452          881 :   init_deps (dc, false);
     453          881 :   return dc;
     454              : }
     455              : 
     456              : /* Create a copy of FROM.  */
     457              : static deps_t
     458          178 : create_copy_of_deps_context (deps_t from)
     459              : {
     460          178 :   deps_t to = alloc_deps_context ();
     461              : 
     462          178 :   copy_deps_context (to, from);
     463          178 :   return to;
     464              : }
     465              : 
     466              : /* Clean up internal data of DC.  */
     467              : static void
     468         1071 : clear_deps_context (deps_t dc)
     469              : {
     470            0 :   free_deps (dc);
     471            0 : }
     472              : 
     473              : /* Clear and free DC.  */
     474              : static void
     475         1059 : delete_deps_context (deps_t dc)
     476              : {
     477            0 :   clear_deps_context (dc);
     478         1059 :   free (dc);
     479         1047 : }
     480              : 
     481              : /* Clear and init DC.  */
     482              : static void
     483           12 : reset_deps_context (deps_t dc)
     484              : {
     485           12 :   clear_deps_context (dc);
     486           12 :   init_deps (dc, false);
     487           12 : }
     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         8281 : advance_deps_context (deps_t dc, insn_t insn)
     513              : {
     514         8281 :   sched_deps_info = &advance_deps_context_sched_deps_info;
     515         8281 :   deps_analyze_insn (dc, insn);
     516         8281 : }
     517              : 
     518              : 
     519              : /* Functions to work with DFA states.  */
     520              : 
     521              : /* Allocate store for a DFA state.  */
     522              : static state_t
     523         1059 : state_alloc (void)
     524              : {
     525            0 :   return xmalloc (dfa_state_size);
     526              : }
     527              : 
     528              : /* Allocate and initialize DFA state.  */
     529              : static state_t
     530          881 : state_create (void)
     531              : {
     532          881 :   state_t state = state_alloc ();
     533              : 
     534          881 :   state_reset (state);
     535          881 :   advance_state (state);
     536          881 :   return state;
     537              : }
     538              : 
     539              : /* Free DFA state.  */
     540              : static void
     541           12 : state_free (state_t state)
     542              : {
     543           12 :   free (state);
     544            0 : }
     545              : 
     546              : /* Make a copy of FROM in TO.  */
     547              : static void
     548          178 : state_copy (state_t to, state_t from)
     549              : {
     550          178 :   memcpy (to, from, dfa_state_size);
     551            0 : }
     552              : 
     553              : /* Create a copy of FROM.  */
     554              : static state_t
     555          178 : state_create_copy (state_t from)
     556              : {
     557          178 :   state_t to = state_alloc ();
     558              : 
     559          178 :   state_copy (to, from);
     560          178 :   return to;
     561              : }
     562              : 
     563              : 
     564              : /* Functions to work with fences.  */
     565              : 
     566              : /* Clear the fence.  */
     567              : static void
     568         1047 : fence_clear (fence_t f)
     569              : {
     570         1047 :   state_t s = FENCE_STATE (f);
     571         1047 :   deps_t dc = FENCE_DC (f);
     572         1047 :   void *tc = FENCE_TC (f);
     573              : 
     574         1047 :   ilist_clear (&FENCE_BNDS (f));
     575              : 
     576         1047 :   gcc_assert ((s != NULL && dc != NULL && tc != NULL)
     577              :               || (s == NULL && dc == NULL && tc == NULL));
     578              : 
     579         1047 :   free (s);
     580              : 
     581         1047 :   if (dc != NULL)
     582         1047 :     delete_deps_context (dc);
     583              : 
     584         1047 :   if (tc != NULL)
     585         1047 :     delete_target_context (tc);
     586         1047 :   vec_free (FENCE_EXECUTING_INSNS (f));
     587         1047 :   free (FENCE_READY_TICKS (f));
     588         1047 :   FENCE_READY_TICKS (f) = NULL;
     589         1047 : }
     590              : 
     591              : /* Init a list of fences with successors of OLD_FENCE.  */
     592              : void
     593          790 : init_fences (insn_t old_fence)
     594              : {
     595          790 :   insn_t succ;
     596          790 :   succ_iterator si;
     597          790 :   bool first = true;
     598          790 :   int ready_ticks_size = get_max_uid () + 1;
     599              : 
     600         1580 :   FOR_EACH_SUCC_1 (succ, si, old_fence,
     601              :                    SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     602              :     {
     603              : 
     604          790 :       if (first)
     605              :         first = false;
     606              :       else
     607            0 :         gcc_assert (flag_sel_sched_pipelining_outer_loops);
     608              : 
     609          790 :       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          790 :                  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          790 : }
     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           12 : 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           12 :   insn_t last_scheduled_insn_old = FENCE_LAST_SCHEDULED_INSN (f);
     642              : 
     643           12 :   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           12 :   if (last_scheduled_insn == NULL
     649           12 :       || 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            0 :       || last_scheduled_insn == last_scheduled_insn_old)
     655              :     {
     656           12 :       state_reset (FENCE_STATE (f));
     657           12 :       state_free (state);
     658              : 
     659           12 :       reset_deps_context (FENCE_DC (f));
     660           12 :       delete_deps_context (dc);
     661              : 
     662           12 :       reset_target_context (FENCE_TC (f), true);
     663           12 :       delete_target_context (tc);
     664              : 
     665           12 :       if (cycle > FENCE_CYCLE (f))
     666            1 :         FENCE_CYCLE (f) = cycle;
     667              : 
     668           12 :       FENCE_LAST_SCHEDULED_INSN (f) = NULL;
     669           12 :       FENCE_ISSUE_MORE (f) = issue_rate;
     670           12 :       vec_free (executing_insns);
     671           12 :       free (ready_ticks);
     672           12 :       if (FENCE_EXECUTING_INSNS (f))
     673            3 :         FENCE_EXECUTING_INSNS (f)->block_remove (0,
     674            3 :                                           FENCE_EXECUTING_INSNS (f)->length ());
     675           12 :       if (FENCE_READY_TICKS (f))
     676           12 :         memset (FENCE_READY_TICKS (f), 0, FENCE_READY_TICKS_SIZE (f));
     677              :     }
     678              :   else
     679              :     {
     680            0 :       edge edge_old = NULL, edge_new = NULL;
     681            0 :       edge candidate;
     682            0 :       succ_iterator si;
     683            0 :       insn_t succ;
     684              : 
     685              :       /* Find fallthrough edge.  */
     686            0 :       gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
     687            0 :       candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
     688              : 
     689            0 :       if (!candidate
     690            0 :           || (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            0 :         if (candidate->src == BLOCK_FOR_INSN (last_scheduled_insn))
     705              :           {
     706            0 :             state_free (FENCE_STATE (f));
     707            0 :             FENCE_STATE (f) = state;
     708              : 
     709            0 :             delete_target_context (FENCE_TC (f));
     710            0 :             FENCE_TC (f) = tc;
     711              : 
     712            0 :             FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn;
     713            0 :             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            0 :       FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn_old,
     727              :                        SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     728              :         {
     729            0 :           if (succ == insn)
     730              :             {
     731              :               /* No same successor allowed from several edges.  */
     732            0 :               gcc_assert (!edge_old);
     733            0 :               edge_old = si.e1;
     734              :             }
     735              :         }
     736              :       /* Find edge of second predecessor (last_scheduled_insn->insn).  */
     737            0 :       FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn,
     738              :                        SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
     739              :         {
     740            0 :           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            0 :       if (edge_old == NULL || edge_new == NULL)
     750              :         {
     751            0 :           reset_deps_context (FENCE_DC (f));
     752            0 :           delete_deps_context (dc);
     753            0 :           vec_free (executing_insns);
     754            0 :           free (ready_ticks);
     755              : 
     756            0 :           FENCE_CYCLE (f) = MAX (FENCE_CYCLE (f), cycle);
     757            0 :           if (FENCE_EXECUTING_INSNS (f))
     758            0 :             FENCE_EXECUTING_INSNS (f)->block_remove (0,
     759            0 :                               FENCE_EXECUTING_INSNS (f)->length ());
     760            0 :           if (FENCE_READY_TICKS (f))
     761            0 :             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           12 :   if (after_stall_p)
     786            1 :     FENCE_AFTER_STALL_P (f) = 1;
     787              : 
     788           12 :   FENCE_ISSUED_INSNS (f) = 0;
     789           12 :   FENCE_STARTS_CYCLE_P (f) = 1;
     790           12 :   FENCE_SCHED_NEXT (f) = NULL;
     791           12 : }
     792              : 
     793              : /* Add a new fence to NEW_FENCES list, initializing it from all
     794              :    other parameters.  */
     795              : static void
     796          269 : 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          269 :   fence_t f = flist_lookup (FLIST_TAIL_HEAD (new_fences), insn);
     805              : 
     806          269 :   if (! f)
     807              :     {
     808          258 :       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          258 :       FLIST_TAIL_TAILP (new_fences)
     814          258 :         = &FLIST_NEXT (*FLIST_TAIL_TAILP (new_fences));
     815              :     }
     816              :   else
     817              :     {
     818           11 :       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          269 : }
     823              : 
     824              : /* Move the first fence in the OLD_FENCES list to NEW_FENCES.  */
     825              : void
     826          831 : move_fence_to_fences (flist_t old_fences, flist_tail_t new_fences)
     827              : {
     828          831 :   fence_t f, old;
     829          831 :   flist_t *tailp = FLIST_TAIL_TAILP (new_fences);
     830              : 
     831          831 :   old = FLIST_FENCE (old_fences);
     832          831 :   f = flist_lookup (FLIST_TAIL_HEAD (new_fences),
     833              :                     FENCE_INSN (FLIST_FENCE (old_fences)));
     834          831 :   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          830 :       _list_add (tailp);
     845          830 :       FLIST_TAIL_TAILP (new_fences) = &FLIST_NEXT (*tailp);
     846          830 :       *FLIST_FENCE (*tailp) = *old;
     847          830 :       init_fence_for_scheduling (FLIST_FENCE (*tailp));
     848              :     }
     849          831 :   FENCE_INSN (old) = NULL;
     850          831 : }
     851              : 
     852              : /* Add a new fence to NEW_FENCES list and initialize most of its data
     853              :    as a clean one.  */
     854              : void
     855           91 : add_clean_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence)
     856              : {
     857           91 :   int ready_ticks_size = get_max_uid () + 1;
     858              : 
     859           91 :   add_to_fences (new_fences,
     860              :                  succ, state_create (), create_deps_context (),
     861              :                  create_target_context (true),
     862              :                  NULL, NULL,
     863           91 :                  XCNEWVEC (int, ready_ticks_size), ready_ticks_size,
     864           91 :                  NULL, FENCE_CYCLE (fence) + 1,
     865           91 :                  0, issue_rate, 1, FENCE_AFTER_STALL_P (fence));
     866           91 : }
     867              : 
     868              : /* Add a new fence to NEW_FENCES list and initialize all of its data
     869              :    from FENCE and SUCC.  */
     870              : void
     871          178 : add_dirty_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence)
     872              : {
     873          178 :   int * new_ready_ticks
     874          178 :     = XNEWVEC (int, FENCE_READY_TICKS_SIZE (fence));
     875              : 
     876          178 :   memcpy (new_ready_ticks, FENCE_READY_TICKS (fence),
     877          178 :           FENCE_READY_TICKS_SIZE (fence) * sizeof (int));
     878          178 :   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          178 :                  FENCE_AFTER_STALL_P (fence));
     892          178 : }
     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        51562 : get_regset_from_pool (void)
     901              : {
     902        51562 :   regset rs;
     903              : 
     904        51562 :   if (regset_pool.n != 0)
     905        40664 :     rs = regset_pool.v[--regset_pool.n];
     906              :   else
     907              :     /* We need to create the regset.  */
     908              :     {
     909        10898 :       rs = ALLOC_REG_SET (&reg_obstack);
     910              : 
     911        10898 :       if (regset_pool.nn == regset_pool.ss)
     912          802 :         regset_pool.vv = XRESIZEVEC (regset, regset_pool.vv,
     913              :                                      (regset_pool.ss = 2 * regset_pool.ss + 1));
     914        10898 :       regset_pool.vv[regset_pool.nn++] = rs;
     915              :     }
     916              : 
     917        51562 :   regset_pool.diff++;
     918              : 
     919        51562 :   return rs;
     920              : }
     921              : 
     922              : /* Same as above, but returns the empty regset.  */
     923              : regset
     924        28516 : get_clear_regset_from_pool (void)
     925              : {
     926        28516 :   regset rs = get_regset_from_pool ();
     927              : 
     928        28516 :   CLEAR_REG_SET (rs);
     929        28516 :   return rs;
     930              : }
     931              : 
     932              : /* Return regset RS to the pool for future use.  */
     933              : void
     934        51562 : return_regset_to_pool (regset rs)
     935              : {
     936        51562 :   gcc_assert (rs);
     937        51562 :   regset_pool.diff--;
     938              : 
     939        51562 :   if (regset_pool.n == regset_pool.s)
     940          802 :     regset_pool.v = XRESIZEVEC (regset, regset_pool.v,
     941              :                                 (regset_pool.s = 2 * regset_pool.s + 1));
     942        51562 :   regset_pool.v[regset_pool.n++] = rs;
     943        51562 : }
     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       792971 : cmp_v_in_regset_pool (const void *x, const void *xx)
     949              : {
     950       792971 :   uintptr_t r1 = (uintptr_t) *((const regset *) x);
     951       792971 :   uintptr_t r2 = (uintptr_t) *((const regset *) xx);
     952       792971 :   if (r1 > r2)
     953              :     return 1;
     954       399942 :   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          131 : free_regset_pool (void)
     962              : {
     963          131 :   if (flag_checking)
     964              :     {
     965          131 :       regset *v = regset_pool.v;
     966          131 :       int i = 0;
     967          131 :       int n = regset_pool.n;
     968              : 
     969          131 :       regset *vv = regset_pool.vv;
     970          131 :       int ii = 0;
     971          131 :       int nn = regset_pool.nn;
     972              : 
     973          131 :       int diff = 0;
     974              : 
     975          131 :       gcc_assert (n <= nn);
     976              : 
     977              :       /* Sort both vectors so it will be possible to compare them.  */
     978          131 :       qsort (v, n, sizeof (*v), cmp_v_in_regset_pool);
     979          131 :       qsort (vv, nn, sizeof (*vv), cmp_v_in_regset_pool);
     980              : 
     981        11160 :       while (ii < nn)
     982              :         {
     983        10898 :           if (v[i] == vv[ii])
     984        10898 :             i++;
     985              :           else
     986              :             /* VV[II] was lost.  */
     987            0 :             diff++;
     988              : 
     989        10898 :           ii++;
     990              :         }
     991              : 
     992          131 :       gcc_assert (diff == regset_pool.diff);
     993              :     }
     994              : 
     995              :   /* If not true - we have a memory leak.  */
     996          131 :   gcc_assert (regset_pool.diff == 0);
     997              : 
     998        11029 :   while (regset_pool.n)
     999              :     {
    1000        10898 :       --regset_pool.n;
    1001        10898 :       FREE_REG_SET (regset_pool.v[regset_pool.n]);
    1002              :     }
    1003              : 
    1004          131 :   free (regset_pool.v);
    1005          131 :   regset_pool.v = NULL;
    1006          131 :   regset_pool.s = 0;
    1007              : 
    1008          131 :   free (regset_pool.vv);
    1009          131 :   regset_pool.vv = NULL;
    1010          131 :   regset_pool.nn = 0;
    1011          131 :   regset_pool.ss = 0;
    1012              : 
    1013          131 :   regset_pool.diff = 0;
    1014          131 : }
    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         2065 : get_nop_from_pool (insn_t insn)
    1028              : {
    1029         2065 :   rtx nop_pat;
    1030         2065 :   insn_t nop;
    1031         2065 :   bool old_p = nop_pool.n != 0;
    1032         2065 :   int flags;
    1033              : 
    1034         2065 :   if (old_p)
    1035         1198 :     nop_pat = nop_pool.v[--nop_pool.n];
    1036              :   else
    1037          867 :     nop_pat = nop_pattern;
    1038              : 
    1039         2065 :   nop = emit_insn_before (nop_pat, insn);
    1040              : 
    1041         2065 :   if (old_p)
    1042              :     flags = INSN_INIT_TODO_SSID;
    1043              :   else
    1044          867 :     flags = INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID;
    1045              : 
    1046         2065 :   set_insn_init (INSN_EXPR (insn), nop_vinsn, INSN_SEQNO (insn));
    1047         2065 :   sel_init_new_insn (nop, flags);
    1048              : 
    1049         2065 :   return nop;
    1050              : }
    1051              : 
    1052              : /* Remove NOP from the instruction stream and return it to the pool.  */
    1053              : void
    1054         2065 : return_nop_to_pool (insn_t nop, bool full_tidying)
    1055              : {
    1056         4130 :   gcc_assert (INSN_IN_STREAM_P (nop));
    1057         2065 :   sel_remove_insn (nop, false, full_tidying);
    1058              : 
    1059              :   /* We'll recycle this nop.  */
    1060         2065 :   nop->set_undeleted ();
    1061              : 
    1062         2065 :   if (nop_pool.n == nop_pool.s)
    1063          864 :     nop_pool.v = XRESIZEVEC (rtx_insn *, nop_pool.v,
    1064              :                              (nop_pool.s = 2 * nop_pool.s + 1));
    1065         2065 :   nop_pool.v[nop_pool.n++] = nop;
    1066         2065 : }
    1067              : 
    1068              : /* Free the nop pool.  */
    1069              : void
    1070          770 : free_nop_pool (void)
    1071              : {
    1072          770 :   nop_pool.n = 0;
    1073          770 :   nop_pool.s = 0;
    1074          770 :   free (nop_pool.v);
    1075          770 :   nop_pool.v = NULL;
    1076          770 : }
    1077              : 
    1078              : 
    1079              : /* Skip unspec to support ia64 speculation. Called from rtx_equal_p.
    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 bool
    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 true;
    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 true;
    1104              :     }
    1105              : 
    1106              :   return false;
    1107              : }
    1108              : 
    1109              : /* Callback, called from hash_rtx.  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 bool
    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 true;
    1123              :     }
    1124              : 
    1125              :   return false;
    1126              : }
    1127              : 
    1128              : /* Returns LHS and RHS are ok to be scheduled separately.  */
    1129              : static bool
    1130         2779 : lhs_and_rhs_separable_p (rtx lhs, rtx rhs)
    1131              : {
    1132         2779 :   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         2779 :   if (CONSTANT_P (rhs))
    1140              :     return false;
    1141              : 
    1142              :   /* ??? Do not rename predicate registers to avoid ICEs in bundling.  */
    1143         2392 :   if (COMPARISON_P (rhs))
    1144              :       return false;
    1145              : 
    1146              :   /* Do not allow single REG to be an rhs.  */
    1147         2365 :   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         1434 :   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         1402 :   if (!REG_P (lhs) && !MEM_P (lhs))
    1159            1 :     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         5959 : vinsn_init (vinsn_t vi, insn_t insn, bool force_unique_p)
    1169              : {
    1170         5959 :   hash_rtx_callback_function hrcf;
    1171         5959 :   int insn_class;
    1172              : 
    1173         5959 :   VINSN_INSN_RTX (vi) = insn;
    1174         5959 :   VINSN_COUNT (vi) = 0;
    1175         5959 :   vi->cost = -1;
    1176              : 
    1177         5959 :   if (INSN_NOP_P (insn))
    1178              :     return;
    1179              : 
    1180         5189 :   if (DF_INSN_UID_SAFE_GET (INSN_UID (insn)) != NULL)
    1181         4524 :     init_id_from_df (VINSN_ID (vi), insn, force_unique_p);
    1182              :   else
    1183          665 :     deps_init_id (VINSN_ID (vi), insn, force_unique_p);
    1184              : 
    1185              :   /* Hash vinsn depending on whether it is separable or not.  */
    1186         5189 :   hrcf = targetm.sched.skip_rtx_p ? hash_with_unspec_callback : NULL;
    1187         5189 :   if (VINSN_SEPARABLE_P (vi))
    1188              :     {
    1189         1398 :       rtx rhs = VINSN_RHS (vi);
    1190              : 
    1191         1398 :       VINSN_HASH (vi) = hash_rtx (rhs, GET_MODE (rhs),
    1192              :                                   NULL, NULL, false, hrcf);
    1193         1398 :       VINSN_HASH_RTX (vi) = hash_rtx (VINSN_PATTERN (vi),
    1194              :                                       VOIDmode, NULL, NULL,
    1195              :                                       false, hrcf);
    1196              :     }
    1197              :   else
    1198              :     {
    1199         3791 :       VINSN_HASH (vi) = hash_rtx (VINSN_PATTERN (vi), VOIDmode,
    1200              :                                   NULL, NULL, false, hrcf);
    1201         3791 :       VINSN_HASH_RTX (vi) = VINSN_HASH (vi);
    1202              :     }
    1203              : 
    1204         5189 :   insn_class = haifa_classify_insn (insn);
    1205         5189 :   if (insn_class >= 2
    1206         5189 :       && (!targetm.sched.get_insn_spec_ds
    1207            0 :           || ((targetm.sched.get_insn_spec_ds (insn) & BEGIN_CONTROL)
    1208              :               == 0)))
    1209          723 :     VINSN_MAY_TRAP_P (vi) = true;
    1210              :   else
    1211         4466 :     VINSN_MAY_TRAP_P (vi) = false;
    1212              : }
    1213              : 
    1214              : /* Indicate that VI has become the part of an rtx object.  */
    1215              : void
    1216       199755 : vinsn_attach (vinsn_t vi)
    1217              : {
    1218              :   /* Assert that VI is not pending for deletion.  */
    1219       199755 :   gcc_assert (VINSN_INSN_RTX (vi));
    1220              : 
    1221       199755 :   VINSN_COUNT (vi)++;
    1222       199755 : }
    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         5959 : vinsn_create (insn_t insn, bool force_unique_p)
    1228              : {
    1229         5959 :   vinsn_t vi = XCNEW (struct vinsn_def);
    1230              : 
    1231         5959 :   vinsn_init (vi, insn, force_unique_p);
    1232         5959 :   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            2 : vinsn_copy (vinsn_t vi, bool reattach_p)
    1239              : {
    1240            2 :   rtx_insn *copy;
    1241            2 :   bool unique = VINSN_UNIQUE_P (vi);
    1242            2 :   vinsn_t new_vi;
    1243              : 
    1244            2 :   copy = create_copy_of_insn_rtx (VINSN_INSN_RTX (vi));
    1245            2 :   new_vi = create_vinsn_from_insn_rtx (copy, unique);
    1246            2 :   if (reattach_p)
    1247              :     {
    1248            2 :       vinsn_detach (vi);
    1249            2 :       vinsn_attach (new_vi);
    1250              :     }
    1251              : 
    1252            2 :   return new_vi;
    1253              : }
    1254              : 
    1255              : /* Delete the VI vinsn and free its data.  */
    1256              : static void
    1257         5959 : vinsn_delete (vinsn_t vi)
    1258              : {
    1259         5959 :   gcc_assert (VINSN_COUNT (vi) == 0);
    1260              : 
    1261         5959 :   if (!INSN_NOP_P (VINSN_INSN_RTX (vi)))
    1262              :     {
    1263         5189 :       return_regset_to_pool (VINSN_REG_SETS (vi));
    1264         5189 :       return_regset_to_pool (VINSN_REG_USES (vi));
    1265         5189 :       return_regset_to_pool (VINSN_REG_CLOBBERS (vi));
    1266              :     }
    1267              : 
    1268         5959 :   free (vi);
    1269         5959 : }
    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       199755 : vinsn_detach (vinsn_t vi)
    1275              : {
    1276       199755 :   gcc_assert (VINSN_COUNT (vi) > 0);
    1277              : 
    1278       199755 :   if (--VINSN_COUNT (vi) == 0)
    1279         5959 :     vinsn_delete (vi);
    1280       199755 : }
    1281              : 
    1282              : /* Returns TRUE if VI is a branch.  */
    1283              : bool
    1284        17738 : vinsn_cond_branch_p (vinsn_t vi)
    1285              : {
    1286        17738 :   insn_t insn;
    1287              : 
    1288        17738 :   if (!VINSN_UNIQUE_P (vi))
    1289              :     return false;
    1290              : 
    1291         2656 :   insn = VINSN_INSN_RTX (vi);
    1292         2656 :   if (BB_END (BLOCK_FOR_INSN (insn)) != insn)
    1293              :     return false;
    1294              : 
    1295         1295 :   return control_flow_insn_p (insn);
    1296              : }
    1297              : 
    1298              : /* Return latency of INSN.  */
    1299              : static int
    1300          200 : sel_insn_rtx_cost (rtx_insn *insn)
    1301              : {
    1302          200 :   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          200 :   if (recog_memoized (insn) < 0)
    1309              :     cost = 0;
    1310              :   else
    1311              :     {
    1312          200 :       cost = insn_default_latency (insn);
    1313              : 
    1314          200 :       if (cost < 0)
    1315            0 :         cost = 0;
    1316              :     }
    1317              : 
    1318          200 :   return cost;
    1319              : }
    1320              : 
    1321              : /* Return the cost of the VI.
    1322              :    !!! FIXME: Unify with haifa-sched.cc: insn_sched_cost ().  */
    1323              : int
    1324          997 : sel_vinsn_cost (vinsn_t vi)
    1325              : {
    1326          997 :   int cost = vi->cost;
    1327              : 
    1328          997 :   if (cost < 0)
    1329              :     {
    1330          200 :       cost = sel_insn_rtx_cost (VINSN_INSN_RTX (vi));
    1331          200 :       vi->cost = cost;
    1332              :     }
    1333              : 
    1334          997 :   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           29 : sel_gen_insn_from_rtx_after (rtx pattern, expr_t expr, int seqno, insn_t after)
    1344              : {
    1345           29 :   insn_t new_insn;
    1346              : 
    1347           29 :   gcc_assert (EXPR_TARGET_AVAILABLE (expr) == true);
    1348              : 
    1349           29 :   new_insn = emit_insn_after (pattern, after);
    1350           29 :   set_insn_init (expr, NULL, seqno);
    1351           29 :   sel_init_new_insn (new_insn, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID);
    1352              : 
    1353           29 :   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          419 : sel_gen_insn_from_expr_after (expr_t expr, vinsn_t vinsn, int seqno,
    1383              :                               insn_t after)
    1384              : {
    1385          419 :   expr_t emit_expr;
    1386          419 :   insn_t insn;
    1387          419 :   int flags;
    1388              : 
    1389          419 :   emit_expr = set_insn_init (expr, vinsn ? vinsn : EXPR_VINSN (expr),
    1390              :                              seqno);
    1391          419 :   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          419 :   insn->set_undeleted ();
    1396              : 
    1397          419 :   add_insn_after (insn, after, BLOCK_FOR_INSN (insn));
    1398              : 
    1399          419 :   flags = INSN_INIT_TODO_SSID;
    1400          419 :   if (INSN_LUID (insn) == 0)
    1401          419 :     flags |= INSN_INIT_TODO_LUID;
    1402          419 :   sel_init_new_insn (insn, flags);
    1403              : 
    1404          419 :   return insn;
    1405              : }
    1406              : 
    1407              : /* Move insn from EXPR after AFTER.  */
    1408              : insn_t
    1409         4871 : sel_move_insn (expr_t expr, int seqno, insn_t after)
    1410              : {
    1411         4871 :   insn_t insn = EXPR_INSN_RTX (expr);
    1412         4871 :   basic_block bb = BLOCK_FOR_INSN (after);
    1413         4871 :   insn_t next = NEXT_INSN (after);
    1414              : 
    1415              :   /* Assert that in move_op we disconnected this insn properly.  */
    1416         4871 :   gcc_assert (EXPR_VINSN (INSN_EXPR (insn)) != NULL);
    1417         4871 :   SET_PREV_INSN (insn) = after;
    1418         4871 :   SET_NEXT_INSN (insn) = next;
    1419              : 
    1420         4871 :   SET_NEXT_INSN (after) = insn;
    1421         4871 :   SET_PREV_INSN (next) = insn;
    1422              : 
    1423              :   /* Update links from insn to bb and vice versa.  */
    1424         4871 :   df_insn_change_bb (insn, bb);
    1425         4871 :   if (BB_END (bb) == after)
    1426          771 :     BB_END (bb) = insn;
    1427              : 
    1428         4871 :   prepare_insn_expr (insn, seqno);
    1429         4871 :   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        93691 : 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        93691 :   expr_history_def *arr;
    1446        93691 :   int i, j, len = vect.length ();
    1447              : 
    1448         2312 :   if (len == 0)
    1449              :     {
    1450        91379 :       *indp = 0;
    1451        91379 :       return false;
    1452              :     }
    1453              : 
    1454              :   arr = vect.address ();
    1455         3925 :   i = 0, j = len - 1;
    1456              : 
    1457         3925 :   while (i <= j)
    1458              :     {
    1459         2819 :       unsigned auid = arr[i].uid;
    1460         2819 :       vinsn_t avinsn = arr[i].new_expr_vinsn;
    1461              : 
    1462         2819 :       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         2819 :           && (! compare_vinsns
    1468          240 :               || vinsn_equal_p (avinsn, new_vinsn)))
    1469              :         {
    1470          406 :           *indp = i;
    1471          406 :           return true;
    1472              :         }
    1473         2413 :       else if (auid > uid)
    1474              :         break;
    1475         1613 :       i++;
    1476              :     }
    1477              : 
    1478         1906 :   *indp = i;
    1479         1906 :   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        49058 : find_in_history_vect (vec<expr_history_def> vect, rtx insn,
    1487              :                       vinsn_t new_vinsn, bool originators_p)
    1488              : {
    1489        49058 :   int ind;
    1490              : 
    1491        49058 :   if (find_in_history_vect_1 (vect, INSN_UID (insn), new_vinsn,
    1492              :                               false, &ind))
    1493          166 :     return ind;
    1494              : 
    1495        48892 :   if (INSN_ORIGINATORS (insn) && originators_p)
    1496              :     {
    1497         1567 :       unsigned uid;
    1498         1567 :       bitmap_iterator bi;
    1499              : 
    1500        45528 :       EXECUTE_IF_SET_IN_BITMAP (INSN_ORIGINATORS (insn), 0, uid, bi)
    1501        43961 :         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          672 : 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          672 :   vec<expr_history_def> vect = *pvect;
    1519          672 :   expr_history_def temp;
    1520          672 :   bool res;
    1521          672 :   int ind;
    1522              : 
    1523          672 :   res = find_in_history_vect_1 (vect, uid, new_expr_vinsn, true, &ind);
    1524              : 
    1525          672 :   if (res)
    1526              :     {
    1527          240 :       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          240 :       if (phist->spec_ds != spec_ds)
    1533            0 :         phist->spec_ds = ds_max_merge (phist->spec_ds, spec_ds);
    1534          240 :       return;
    1535              :     }
    1536              : 
    1537          432 :   temp.uid = uid;
    1538          432 :   temp.old_expr_vinsn = old_expr_vinsn;
    1539          432 :   temp.new_expr_vinsn = new_expr_vinsn;
    1540          432 :   temp.spec_ds = spec_ds;
    1541          432 :   temp.type = type;
    1542              : 
    1543          432 :   vinsn_attach (old_expr_vinsn);
    1544          432 :   vinsn_attach (new_expr_vinsn);
    1545          432 :   vect.safe_insert (ind, temp);
    1546          432 :   *pvect = vect;
    1547              : }
    1548              : 
    1549              : /* Free history vector PVECT.  */
    1550              : static void
    1551       178453 : free_history_vect (vec<expr_history_def> &pvect)
    1552              : {
    1553       178453 :   unsigned i;
    1554       178453 :   expr_history_def *phist;
    1555              : 
    1556       178453 :   if (! pvect.exists ())
    1557       178453 :     return;
    1558              : 
    1559         4710 :   for (i = 0; pvect.iterate (i, &phist); i++)
    1560              :     {
    1561         2558 :       vinsn_detach (phist->old_expr_vinsn);
    1562         2558 :       vinsn_detach (phist->new_expr_vinsn);
    1563              :     }
    1564              : 
    1565         2152 :   pvect.release ();
    1566              : }
    1567              : 
    1568              : /* Merge vector FROM to PVECT.  */
    1569              : static void
    1570         9832 : merge_history_vect (vec<expr_history_def> *pvect,
    1571              :                     vec<expr_history_def> from)
    1572              : {
    1573         9832 :   expr_history_def *phist;
    1574         9832 :   int i;
    1575              : 
    1576              :   /* We keep this vector sorted.  */
    1577        10078 :   for (i = 0; from.iterate (i, &phist); i++)
    1578          246 :     insert_in_history_vect (pvect, phist->uid, phist->type,
    1579              :                             phist->old_expr_vinsn, phist->new_expr_vinsn,
    1580              :                             phist->spec_ds);
    1581         9832 : }
    1582              : 
    1583              : /* Compare two vinsns as rhses if possible and as vinsns otherwise.  */
    1584              : bool
    1585       301379 : vinsn_equal_p (vinsn_t x, vinsn_t y)
    1586              : {
    1587       301379 :   rtx_equal_p_callback_function repcf;
    1588              : 
    1589       301379 :   if (x == y)
    1590              :     return true;
    1591              : 
    1592       269413 :   if (VINSN_TYPE (x) != VINSN_TYPE (y))
    1593              :     return false;
    1594              : 
    1595       125840 :   if (VINSN_HASH (x) != VINSN_HASH (y))
    1596              :     return false;
    1597              : 
    1598        10295 :   repcf = targetm.sched.skip_rtx_p ? skip_unspecs_callback : NULL;
    1599        10295 :   if (VINSN_SEPARABLE_P (x))
    1600              :     {
    1601              :       /* Compare RHSes of VINSNs.  */
    1602         4907 :       gcc_assert (VINSN_RHS (x));
    1603         4907 :       gcc_assert (VINSN_RHS (y));
    1604              : 
    1605         4907 :       return rtx_equal_p (VINSN_RHS (x), VINSN_RHS (y), repcf);
    1606              :     }
    1607              : 
    1608         5388 :   return rtx_equal_p (VINSN_PATTERN (x), VINSN_PATTERN (y), repcf);
    1609              : }
    1610              : 
    1611              : 
    1612              : /* Functions for working with expressions.  */
    1613              : 
    1614              : /* Initialize EXPR.  */
    1615              : static void
    1616       171069 : 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       171069 :   EXPR_VINSN (expr) = vi;
    1627       171069 :   EXPR_SPEC (expr) = spec;
    1628       171069 :   EXPR_USEFULNESS (expr) = use;
    1629       171069 :   EXPR_PRIORITY (expr) = priority;
    1630       171069 :   EXPR_PRIORITY_ADJ (expr) = 0;
    1631       171069 :   EXPR_SCHED_TIMES (expr) = sched_times;
    1632       171069 :   EXPR_ORIG_BB_INDEX (expr) = orig_bb_index;
    1633       171069 :   EXPR_ORIG_SCHED_CYCLE (expr) = orig_sched_cycle;
    1634       171069 :   EXPR_SPEC_DONE_DS (expr) = spec_done_ds;
    1635       171069 :   EXPR_SPEC_TO_CHECK_DS (expr) = spec_to_check_ds;
    1636              : 
    1637       141065 :   if (history.exists ())
    1638         1741 :     EXPR_HISTORY_OF_CHANGES (expr) = history;
    1639              :   else
    1640       143819 :     EXPR_HISTORY_OF_CHANGES (expr).create (0);
    1641              : 
    1642       171069 :   EXPR_TARGET_AVAILABLE (expr) = target_available;
    1643       171069 :   EXPR_WAS_SUBSTITUTED (expr) = was_substituted;
    1644       171069 :   EXPR_WAS_RENAMED (expr) = was_renamed;
    1645       171069 :   EXPR_NEEDS_SPEC_CHECK_P (expr) = needs_spec_check_p;
    1646       171069 :   EXPR_CANT_MOVE (expr) = cant_move;
    1647            0 : }
    1648              : 
    1649              : /* Make a copy of the expr FROM into the expr TO.  */
    1650              : void
    1651       141065 : copy_expr (expr_t to, expr_t from)
    1652              : {
    1653       141065 :   vec<expr_history_def> temp = vNULL;
    1654              : 
    1655       141065 :   if (EXPR_HISTORY_OF_CHANGES (from).exists ())
    1656              :     {
    1657         1741 :       unsigned i;
    1658         1741 :       expr_history_def *phist;
    1659              : 
    1660         1741 :       temp = EXPR_HISTORY_OF_CHANGES (from).copy ();
    1661         3867 :       for (i = 0;
    1662         3867 :            temp.iterate (i, &phist);
    1663              :            i++)
    1664              :         {
    1665         2126 :           vinsn_attach (phist->old_expr_vinsn);
    1666         2126 :           vinsn_attach (phist->new_expr_vinsn);
    1667              :         }
    1668              :     }
    1669              : 
    1670       282130 :   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       141065 :              EXPR_TARGET_AVAILABLE (from), EXPR_WAS_SUBSTITUTED (from),
    1676              :              EXPR_WAS_RENAMED (from), EXPR_NEEDS_SPEC_CHECK_P (from),
    1677       141065 :              EXPR_CANT_MOVE (from));
    1678       141065 : }
    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        25509 : copy_expr_onside (expr_t to, expr_t from)
    1684              : {
    1685        51018 :   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        25509 :              vNULL,
    1689        25509 :              EXPR_TARGET_AVAILABLE (from), EXPR_WAS_SUBSTITUTED (from),
    1690              :              EXPR_WAS_RENAMED (from), EXPR_NEEDS_SPEC_CHECK_P (from),
    1691        25509 :              EXPR_CANT_MOVE (from));
    1692        25509 : }
    1693              : 
    1694              : /* Prepare the expr of INSN for scheduling.  Used when moving insn and when
    1695              :    initializing new insns.  */
    1696              : static void
    1697         7384 : prepare_insn_expr (insn_t insn, int seqno)
    1698              : {
    1699         7384 :   expr_t expr = INSN_EXPR (insn);
    1700         7384 :   ds_t ds;
    1701              : 
    1702         7384 :   INSN_SEQNO (insn) = seqno;
    1703         7384 :   EXPR_ORIG_BB_INDEX (expr) = BLOCK_NUM (insn);
    1704         7384 :   EXPR_SPEC (expr) = 0;
    1705         7384 :   EXPR_ORIG_SCHED_CYCLE (expr) = 0;
    1706         7384 :   EXPR_WAS_SUBSTITUTED (expr) = 0;
    1707         7384 :   EXPR_WAS_RENAMED (expr) = 0;
    1708         7384 :   EXPR_TARGET_AVAILABLE (expr) = 1;
    1709         7384 :   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         7384 :   ds = EXPR_SPEC_DONE_DS (expr);
    1717         7384 :   if (ds)
    1718            0 :     EXPR_SPEC_DONE_DS (expr) = ds_get_max_dep_weak (ds);
    1719              : 
    1720         7384 :   free_history_vect (EXPR_HISTORY_OF_CHANGES (expr));
    1721         7384 : }
    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         2175 : update_target_availability (expr_t to, expr_t from, insn_t split_point)
    1728              : {
    1729         2175 :   if (EXPR_TARGET_AVAILABLE (to) < 0
    1730         1272 :       || EXPR_TARGET_AVAILABLE (from) < 0)
    1731          964 :     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         1211 :       if (split_point == NULL)
    1738              :         {
    1739           66 :           int toind, fromind;
    1740              : 
    1741           66 :           toind = EXPR_ORIG_BB_INDEX (to);
    1742           66 :           fromind = EXPR_ORIG_BB_INDEX (from);
    1743              : 
    1744           66 :           if (toind && toind == fromind)
    1745              :             /* Do nothing -- everything is done in
    1746              :                merge_with_other_exprs.  */
    1747              :             ;
    1748              :           else
    1749           66 :             EXPR_TARGET_AVAILABLE (to) = -1;
    1750              :         }
    1751         1145 :       else if (EXPR_TARGET_AVAILABLE (from) == 0
    1752          616 :                && EXPR_LHS (from)
    1753          616 :                && REG_P (EXPR_LHS (from))
    1754         1761 :                && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
    1755            0 :         EXPR_TARGET_AVAILABLE (to) = -1;
    1756              :       else
    1757         1145 :         EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
    1758              :     }
    1759         2175 : }
    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         2175 : update_speculative_bits (expr_t to, expr_t from, insn_t split_point)
    1766              : {
    1767         2175 :   ds_t old_to_ds, old_from_ds;
    1768              : 
    1769         2175 :   old_to_ds = EXPR_SPEC_DONE_DS (to);
    1770         2175 :   old_from_ds = EXPR_SPEC_DONE_DS (from);
    1771              : 
    1772         2175 :   EXPR_SPEC_DONE_DS (to) = ds_max_merge (old_to_ds, old_from_ds);
    1773         2175 :   EXPR_SPEC_TO_CHECK_DS (to) |= EXPR_SPEC_TO_CHECK_DS (from);
    1774         2175 :   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         2175 :   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         2175 : }
    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         2175 : 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         2175 :   if (EXPR_SPEC (to) < EXPR_SPEC (from))
    1824          929 :     EXPR_SPEC (to) = EXPR_SPEC (from);
    1825              : 
    1826         2175 :   if (split_point)
    1827         1917 :     EXPR_USEFULNESS (to) += EXPR_USEFULNESS (from);
    1828              :   else
    1829          258 :     EXPR_USEFULNESS (to) = MAX (EXPR_USEFULNESS (to),
    1830              :                                 EXPR_USEFULNESS (from));
    1831              : 
    1832         2175 :   if (EXPR_PRIORITY (to) < EXPR_PRIORITY (from))
    1833          101 :     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         2175 :   if (EXPR_SCHED_TIMES (to) != EXPR_SCHED_TIMES (from))
    1839          803 :     EXPR_SCHED_TIMES (to) = ((EXPR_SCHED_TIMES (from) + EXPR_SCHED_TIMES (to)
    1840          803 :                              + 1) / 2);
    1841              : 
    1842         2175 :   if (EXPR_ORIG_BB_INDEX (to) != EXPR_ORIG_BB_INDEX (from))
    1843         1085 :     EXPR_ORIG_BB_INDEX (to) = 0;
    1844              : 
    1845         2175 :   EXPR_ORIG_SCHED_CYCLE (to) = MIN (EXPR_ORIG_SCHED_CYCLE (to),
    1846              :                                     EXPR_ORIG_SCHED_CYCLE (from));
    1847              : 
    1848         2175 :   EXPR_WAS_SUBSTITUTED (to) |= EXPR_WAS_SUBSTITUTED (from);
    1849         2175 :   EXPR_WAS_RENAMED (to) |= EXPR_WAS_RENAMED (from);
    1850         2175 :   EXPR_CANT_MOVE (to) |= EXPR_CANT_MOVE (from);
    1851              : 
    1852         2175 :   merge_history_vect (&EXPR_HISTORY_OF_CHANGES (to),
    1853              :                       EXPR_HISTORY_OF_CHANGES (from));
    1854         2175 :   update_target_availability (to, from, split_point);
    1855         2175 :   update_speculative_bits (to, from, split_point);
    1856         2175 : }
    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         1921 : merge_expr (expr_t to, expr_t from, insn_t split_point)
    1863              : {
    1864         1921 :   vinsn_t to_vi = EXPR_VINSN (to);
    1865         1921 :   vinsn_t from_vi = EXPR_VINSN (from);
    1866              : 
    1867         1921 :   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         1921 :   if (EXPR_SPEC_DONE_DS (to) == 0
    1873         1921 :       && (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         1921 :           || (!VINSN_MAY_TRAP_P (EXPR_VINSN (to))
    1881         1921 :               && VINSN_MAY_TRAP_P (EXPR_VINSN (from)))))
    1882            0 :     change_vinsn_in_expr (to, EXPR_VINSN (from));
    1883              : 
    1884         1921 :   merge_expr_data (to, from, split_point);
    1885         1921 :   gcc_assert (EXPR_USEFULNESS (to) <= REG_BR_PROB_BASE);
    1886         1921 : }
    1887              : 
    1888              : /* Clear the information of this EXPR.  */
    1889              : void
    1890       171069 : clear_expr (expr_t expr)
    1891              : {
    1892              : 
    1893       171069 :   vinsn_detach (EXPR_VINSN (expr));
    1894       171069 :   EXPR_VINSN (expr) = NULL;
    1895              : 
    1896       171069 :   free_history_vect (EXPR_HISTORY_OF_CHANGES (expr));
    1897       171069 : }
    1898              : 
    1899              : /* For a given LV_SET, mark EXPR having unavailable target register.  */
    1900              : static void
    1901        10920 : set_unavailable_target_for_expr (expr_t expr, regset lv_set)
    1902              : {
    1903        10920 :   if (EXPR_SEPARABLE_P (expr))
    1904              :     {
    1905         6111 :       if (REG_P (EXPR_LHS (expr))
    1906         6111 :           && 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         1442 :           if (register_unavailable_p (VINSN_REG_USES (EXPR_VINSN (expr)),
    1928         1442 :                                       EXPR_LHS (expr)))
    1929          185 :             EXPR_TARGET_AVAILABLE (expr) = -1;
    1930              :           else
    1931         1257 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1932              :         }
    1933              :     }
    1934              :   else
    1935              :     {
    1936         4809 :       unsigned regno;
    1937         4809 :       reg_set_iterator rsi;
    1938              : 
    1939         6976 :       EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_SETS (EXPR_VINSN (expr)),
    1940              :                                  0, regno, rsi)
    1941         4110 :         if (bitmap_bit_p (lv_set, regno))
    1942              :           {
    1943         1943 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1944         1943 :             break;
    1945              :           }
    1946              : 
    1947         6484 :       EXECUTE_IF_SET_IN_REG_SET (VINSN_REG_CLOBBERS (EXPR_VINSN (expr)),
    1948              :                                  0, regno, rsi)
    1949         1717 :         if (bitmap_bit_p (lv_set, regno))
    1950              :           {
    1951           42 :             EXPR_TARGET_AVAILABLE (expr) = false;
    1952           42 :             break;
    1953              :           }
    1954              :     }
    1955        10920 : }
    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         8429 : expr_dest_reg (expr_t expr)
    2017              : {
    2018         8429 :   rtx dest = VINSN_LHS (EXPR_VINSN (expr));
    2019              : 
    2020         8429 :   if (dest != NULL_RTX && REG_P (dest))
    2021         8429 :     return dest;
    2022              : 
    2023              :   return NULL_RTX;
    2024              : }
    2025              : 
    2026              : /* Returns the REGNO of the R's destination.  */
    2027              : unsigned
    2028         7132 : expr_dest_regno (expr_t expr)
    2029              : {
    2030         7132 :   rtx dest = expr_dest_reg (expr);
    2031              : 
    2032         7132 :   gcc_assert (dest != NULL_RTX);
    2033         7132 :   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         7290 : mark_unavailable_targets (av_set_t join_set, av_set_t av_set, regset lv_set)
    2040              : {
    2041         7290 :   expr_t expr;
    2042         7290 :   av_set_iterator avi;
    2043              : 
    2044        14892 :   FOR_EACH_EXPR (expr, avi, join_set)
    2045         7602 :     if (av_set_lookup (av_set, EXPR_VINSN (expr)) == NULL)
    2046         7602 :       set_unavailable_target_for_expr (expr, lv_set);
    2047         7290 : }
    2048              : 
    2049              : 
    2050              : /* Returns true if REG (at least partially) is present in REGS.  */
    2051              : bool
    2052         7553 : register_unavailable_p (regset regs, rtx reg)
    2053              : {
    2054         7553 :   unsigned regno, end_regno;
    2055              : 
    2056         7553 :   regno = REGNO (reg);
    2057         7553 :   if (bitmap_bit_p (regs, regno))
    2058              :     return true;
    2059              : 
    2060         5926 :   end_regno = END_REGNO (reg);
    2061              : 
    2062         5926 :   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       139665 : av_set_add_element (av_set_t *setp)
    2075              : {
    2076              :   /* Insert at the beginning of the list.  */
    2077            0 :   _list_add (setp);
    2078       139665 :   return *setp;
    2079              : }
    2080              : 
    2081              : /* Add EXPR to SETP.  */
    2082              : void
    2083       137748 : av_set_add (av_set_t *setp, expr_t expr)
    2084              : {
    2085       137748 :   av_set_t elem;
    2086              : 
    2087       137748 :   gcc_assert (!INSN_NOP_P (EXPR_INSN_RTX (expr)));
    2088       137748 :   elem = av_set_add_element (setp);
    2089       137748 :   copy_expr (_AV_SET_EXPR (elem), expr);
    2090       137748 : }
    2091              : 
    2092              : /* Same, but do not copy EXPR.  */
    2093              : static void
    2094         1917 : av_set_add_nocopy (av_set_t *setp, expr_t expr)
    2095              : {
    2096         1917 :   av_set_t elem;
    2097              : 
    2098         1917 :   elem = av_set_add_element (setp);
    2099         1917 :   *_AV_SET_EXPR (elem) = *expr;
    2100         1917 : }
    2101              : 
    2102              : /* Remove expr pointed to by IP from the av_set.  */
    2103              : void
    2104       137748 : av_set_iter_remove (av_set_iterator *ip)
    2105              : {
    2106       137748 :   clear_expr (_AV_SET_EXPR (*ip->lp));
    2107       137748 :   _list_iter_remove (ip);
    2108       137748 : }
    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       206849 : av_set_lookup (av_set_t set, vinsn_t sought_vinsn)
    2115              : {
    2116       206849 :   expr_t expr;
    2117       206849 :   av_set_iterator i;
    2118              : 
    2119       445685 :   FOR_EACH_EXPR (expr, i, set)
    2120       276426 :     if (vinsn_equal_p (EXPR_VINSN (expr), sought_vinsn))
    2121              :       return expr;
    2122              :   return NULL;
    2123              : }
    2124              : 
    2125              : /* Same, but also remove the EXPR found.   */
    2126              : static expr_t
    2127         3762 : av_set_lookup_and_remove (av_set_t *setp, vinsn_t sought_vinsn)
    2128              : {
    2129         3762 :   expr_t expr;
    2130         3762 :   av_set_iterator i;
    2131              : 
    2132        10604 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2133         8759 :     if (vinsn_equal_p (EXPR_VINSN (expr), sought_vinsn))
    2134              :       {
    2135         1917 :         _list_iter_remove_nofree (&i);
    2136         1917 :         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          422 : av_set_lookup_other_equiv_expr (av_set_t set, expr_t expr)
    2146              : {
    2147          422 :   expr_t cur_expr;
    2148          422 :   av_set_iterator i;
    2149              : 
    2150         2225 :   FOR_EACH_EXPR (cur_expr, i, set)
    2151              :     {
    2152         1807 :       if (cur_expr == expr)
    2153          418 :         continue;
    2154         1389 :       if (vinsn_equal_p (EXPR_VINSN (cur_expr), EXPR_VINSN (expr)))
    2155              :         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          422 : merge_with_other_exprs (av_set_t *avp, av_set_iterator *ip, expr_t expr)
    2164              : {
    2165          422 :   expr_t expr2;
    2166              : 
    2167          422 :   expr2 = av_set_lookup_other_equiv_expr (*avp, expr);
    2168          422 :   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            4 :       EXPR_TARGET_AVAILABLE (expr2) = -1;
    2173            4 :       EXPR_USEFULNESS (expr2) = 0;
    2174              : 
    2175            4 :       merge_expr (expr2, expr, NULL);
    2176              : 
    2177              :       /* Fix usefulness as it should be now REG_BR_PROB_BASE.  */
    2178            4 :       EXPR_USEFULNESS (expr2) = REG_BR_PROB_BASE;
    2179              : 
    2180            4 :       av_set_iter_remove (ip);
    2181            4 :       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        28538 : av_set_is_in_p (av_set_t set, vinsn_t vi)
    2190              : {
    2191        28538 :   return av_set_lookup (set, vi) != NULL;
    2192              : }
    2193              : 
    2194              : /* Return a copy of SET.  */
    2195              : av_set_t
    2196        36943 : av_set_copy (av_set_t set)
    2197              : {
    2198        36943 :   expr_t expr;
    2199        36943 :   av_set_iterator i;
    2200        36943 :   av_set_t res = NULL;
    2201              : 
    2202       113289 :   FOR_EACH_EXPR (expr, i, set)
    2203        76346 :     av_set_add (&res, expr);
    2204              : 
    2205        36943 :   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        61347 : join_distinct_sets (av_set_t *to_tailp, av_set_t *fromp)
    2213              : {
    2214        61347 :   gcc_assert (*to_tailp == NULL);
    2215        61347 :   *to_tailp = *fromp;
    2216        61347 :   *fromp = NULL;
    2217        61347 : }
    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        59155 : av_set_union_and_clear (av_set_t *top, av_set_t *fromp, insn_t insn)
    2223              : {
    2224        59155 :   expr_t expr1;
    2225        59155 :   av_set_iterator i;
    2226              : 
    2227              :   /* Delete from TOP all exprs, that present in FROMP.  */
    2228       157271 :   FOR_EACH_EXPR_1 (expr1, i, top)
    2229              :     {
    2230        49058 :       expr_t expr2 = av_set_lookup (*fromp, EXPR_VINSN (expr1));
    2231              : 
    2232        49058 :       if (expr2)
    2233              :         {
    2234            0 :           merge_expr (expr2, expr1, insn);
    2235            0 :           av_set_iter_remove (&i);
    2236              :         }
    2237              :     }
    2238              : 
    2239        59155 :   join_distinct_sets (i.lp, fromp);
    2240        59155 : }
    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         1096 : 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         1096 :   expr_t expr1;
    2249         1096 :   av_set_iterator i;
    2250         1096 :   av_set_t *to_tailp, in_both_set = NULL;
    2251              : 
    2252              :   /* Delete from TOP all expres, that present in FROMP.  */
    2253         8620 :   FOR_EACH_EXPR_1 (expr1, i, top)
    2254              :     {
    2255         3762 :       expr_t expr2 = av_set_lookup_and_remove (fromp, EXPR_VINSN (expr1));
    2256              : 
    2257         3762 :       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         1917 :           if (EXPR_SEPARABLE_P (expr1))
    2262              :             {
    2263          903 :               int regno1 = (REG_P (EXPR_LHS (expr1))
    2264          903 :                             ? (int) expr_dest_regno (expr1) : -1);
    2265          903 :               int regno2 = (REG_P (EXPR_LHS (expr2))
    2266          903 :                             ? (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          903 :               if (regno1 != regno2)
    2272           64 :                 EXPR_TARGET_AVAILABLE (expr2) = -1;
    2273              :             }
    2274         1014 :           else if (EXPR_INSN_RTX (expr1) != EXPR_INSN_RTX (expr2))
    2275          535 :             EXPR_TARGET_AVAILABLE (expr2) = -1;
    2276              : 
    2277         1917 :           merge_expr (expr2, expr1, insn);
    2278         1917 :           av_set_add_nocopy (&in_both_set, expr2);
    2279         1917 :           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         1845 :         set_unavailable_target_for_expr (expr1, from_lv_set);
    2285              :     }
    2286         1096 :   to_tailp = i.lp;
    2287              : 
    2288              :   /* These expressions are not present in TOP.  Check liveness
    2289              :      restrictions on TO_LV_SET.  */
    2290         4042 :   FOR_EACH_EXPR (expr1, i, *fromp)
    2291         1473 :     set_unavailable_target_for_expr (expr1, to_lv_set);
    2292              : 
    2293         1096 :   join_distinct_sets (i.lp, &in_both_set);
    2294         1096 :   join_distinct_sets (to_tailp, fromp);
    2295         1096 : }
    2296              : 
    2297              : /* Clear av_set pointed to by SETP.  */
    2298              : void
    2299        62371 : av_set_clear (av_set_t *setp)
    2300              : {
    2301        62371 :   expr_t expr;
    2302        62371 :   av_set_iterator i;
    2303              : 
    2304       238913 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2305        88271 :     av_set_iter_remove (&i);
    2306              : 
    2307        62371 :   gcc_assert (*setp == NULL);
    2308        62371 : }
    2309              : 
    2310              : /* Leave only one non-speculative element in the SETP.  */
    2311              : void
    2312        15181 : av_set_leave_one_nonspec (av_set_t *setp)
    2313              : {
    2314        15181 :   expr_t expr;
    2315        15181 :   av_set_iterator i;
    2316        15181 :   bool has_one_nonspec = false;
    2317              : 
    2318              :   /* Keep all speculative exprs, and leave one non-speculative
    2319              :      (the first one).  */
    2320        45543 :   FOR_EACH_EXPR_1 (expr, i, setp)
    2321              :     {
    2322        15181 :       if (!EXPR_SPEC_DONE_DS (expr))
    2323              :         {
    2324        15181 :           if (has_one_nonspec)
    2325            0 :             av_set_iter_remove (&i);
    2326              :           else
    2327              :             has_one_nonspec = true;
    2328              :         }
    2329              :     }
    2330        15181 : }
    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         4892 : av_set_substract_cond_branches (av_set_t *avp)
    2350              : {
    2351         4892 :   av_set_iterator i;
    2352         4892 :   expr_t expr;
    2353              : 
    2354        30566 :   FOR_EACH_EXPR_1 (expr, i, avp)
    2355        12837 :     if (vinsn_cond_branch_p (EXPR_VINSN (expr)))
    2356          422 :       av_set_iter_remove (&i);
    2357         4892 : }
    2358              : 
    2359              : /* Multiplies usefulness attribute of each member of av-set *AVP by
    2360              :    value PROB / ALL_PROB.  */
    2361              : void
    2362         6291 : av_set_split_usefulness (av_set_t av, int prob, int all_prob)
    2363              : {
    2364         6291 :   av_set_iterator i;
    2365         6291 :   expr_t expr;
    2366              : 
    2367        26711 :   FOR_EACH_EXPR (expr, i, av)
    2368        20420 :     EXPR_USEFULNESS (expr) = (all_prob
    2369        19022 :                               ? (EXPR_USEFULNESS (expr) * prob) / all_prob
    2370              :                               : 0);
    2371         6291 : }
    2372              : 
    2373              : /* Leave in AVP only those expressions, which are present in AV,
    2374              :    and return it, merging history expressions.  */
    2375              : void
    2376         8424 : av_set_code_motion_filter (av_set_t *avp, av_set_t av)
    2377              : {
    2378         8424 :   av_set_iterator i;
    2379         8424 :   expr_t expr, expr2;
    2380              : 
    2381        25486 :   FOR_EACH_EXPR_1 (expr, i, avp)
    2382         8531 :     if ((expr2 = av_set_lookup (av, EXPR_VINSN (expr))) == NULL)
    2383          874 :       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         7657 :       merge_history_vect (&EXPR_HISTORY_OF_CHANGES (expr),
    2391              :                           EXPR_HISTORY_OF_CHANGES (expr2));
    2392         8424 : }
    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         5189 : setup_id_for_insn (idata_t id, insn_t insn, bool force_unique_p)
    2420              : {
    2421         5189 :   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         5189 :   type = GET_CODE (insn);
    2427              : 
    2428              :   /* Only regular insns could be cloned.  */
    2429         5189 :   if (type == INSN && !force_unique_p)
    2430              :     type = SET;
    2431         1732 :   else if (type == JUMP_INSN && simplejump_p (insn))
    2432              :     type = PC;
    2433         1525 :   else if (type == DEBUG_INSN)
    2434           44 :     type = !force_unique_p ? USE : INSN;
    2435              : 
    2436         5189 :   IDATA_TYPE (id) = type;
    2437         5189 :   IDATA_REG_SETS (id) = get_clear_regset_from_pool ();
    2438         5189 :   IDATA_REG_USES (id) = get_clear_regset_from_pool ();
    2439         5189 :   IDATA_REG_CLOBBERS (id) = get_clear_regset_from_pool ();
    2440         5189 : }
    2441              : 
    2442              : /* Start initializing insn data.  */
    2443              : static void
    2444          665 : deps_init_id_start_insn (insn_t insn)
    2445              : {
    2446          665 :   gcc_assert (deps_init_id_data.where == DEPS_IN_NOWHERE);
    2447              : 
    2448          665 :   setup_id_for_insn (deps_init_id_data.id, insn,
    2449          665 :                      deps_init_id_data.force_unique_p);
    2450          665 :   deps_init_id_data.where = DEPS_IN_INSN;
    2451          665 : }
    2452              : 
    2453              : /* Start initializing lhs data.  */
    2454              : static void
    2455          651 : deps_init_id_start_lhs (rtx lhs)
    2456              : {
    2457          651 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2458          651 :   gcc_assert (IDATA_LHS (deps_init_id_data.id) == NULL);
    2459              : 
    2460          651 :   if (IDATA_TYPE (deps_init_id_data.id) == SET)
    2461              :     {
    2462          651 :       IDATA_LHS (deps_init_id_data.id) = lhs;
    2463          651 :       deps_init_id_data.where = DEPS_IN_LHS;
    2464              :     }
    2465          651 : }
    2466              : 
    2467              : /* Finish initializing lhs data.  */
    2468              : static void
    2469          651 : deps_init_id_finish_lhs (void)
    2470              : {
    2471          651 :   deps_init_id_data.where = DEPS_IN_INSN;
    2472          651 : }
    2473              : 
    2474              : /* Note a set of REGNO.  */
    2475              : static void
    2476          657 : deps_init_id_note_reg_set (int regno)
    2477              : {
    2478          657 :   haifa_note_reg_set (regno);
    2479              : 
    2480          657 :   if (deps_init_id_data.where == DEPS_IN_RHS)
    2481            0 :     deps_init_id_data.force_use_p = true;
    2482              : 
    2483          657 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2484          657 :     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          657 :   if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2490            0 :     deps_init_id_data.force_use_p = true;
    2491              : #endif
    2492          657 : }
    2493              : 
    2494              : /* Note a clobber of REGNO.  */
    2495              : static void
    2496            9 : deps_init_id_note_reg_clobber (int regno)
    2497              : {
    2498            9 :   haifa_note_reg_clobber (regno);
    2499              : 
    2500            9 :   if (deps_init_id_data.where == DEPS_IN_RHS)
    2501            0 :     deps_init_id_data.force_use_p = true;
    2502              : 
    2503            9 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2504            9 :     SET_REGNO_REG_SET (IDATA_REG_CLOBBERS (deps_init_id_data.id), regno);
    2505            9 : }
    2506              : 
    2507              : /* Note a use of REGNO.  */
    2508              : static void
    2509          658 : deps_init_id_note_reg_use (int regno)
    2510              : {
    2511          658 :   haifa_note_reg_use (regno);
    2512              : 
    2513          658 :   if (IDATA_TYPE (deps_init_id_data.id) != PC)
    2514          658 :     SET_REGNO_REG_SET (IDATA_REG_USES (deps_init_id_data.id), regno);
    2515          658 : }
    2516              : 
    2517              : /* Start initializing rhs data.  */
    2518              : static void
    2519          651 : deps_init_id_start_rhs (rtx rhs)
    2520              : {
    2521          651 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2522              : 
    2523              :   /* And there was no sel_deps_reset_to_insn ().  */
    2524          651 :   if (IDATA_LHS (deps_init_id_data.id) != NULL)
    2525              :     {
    2526          651 :       IDATA_RHS (deps_init_id_data.id) = rhs;
    2527          651 :       deps_init_id_data.where = DEPS_IN_RHS;
    2528              :     }
    2529          651 : }
    2530              : 
    2531              : /* Finish initializing rhs data.  */
    2532              : static void
    2533          651 : deps_init_id_finish_rhs (void)
    2534              : {
    2535          651 :   gcc_assert (deps_init_id_data.where == DEPS_IN_RHS
    2536              :               || deps_init_id_data.where == DEPS_IN_INSN);
    2537          651 :   deps_init_id_data.where = DEPS_IN_INSN;
    2538          651 : }
    2539              : 
    2540              : /* Finish initializing insn data.  */
    2541              : static void
    2542          665 : deps_init_id_finish_insn (void)
    2543              : {
    2544          665 :   gcc_assert (deps_init_id_data.where == DEPS_IN_INSN);
    2545              : 
    2546          665 :   if (IDATA_TYPE (deps_init_id_data.id) == SET)
    2547              :     {
    2548          661 :       rtx lhs = IDATA_LHS (deps_init_id_data.id);
    2549          661 :       rtx rhs = IDATA_RHS (deps_init_id_data.id);
    2550              : 
    2551          651 :       if (lhs == NULL || rhs == NULL || !lhs_and_rhs_separable_p (lhs, rhs)
    2552          994 :           || 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          328 :           gcc_assert (IDATA_TYPE (deps_init_id_data.id) == SET);
    2559          328 :           gcc_assert (!lhs == !rhs);
    2560              : 
    2561          328 :           IDATA_TYPE (deps_init_id_data.id) = USE;
    2562              :         }
    2563              :     }
    2564              : 
    2565          665 :   deps_init_id_data.where = DEPS_IN_NOWHERE;
    2566          665 : }
    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         4524 : setup_id_lhs_rhs (idata_t id, insn_t insn, bool force_unique_p)
    2597              : {
    2598         4524 :   rtx pat = PATTERN (insn);
    2599              : 
    2600         4524 :   if (NONJUMP_INSN_P (insn)
    2601         3555 :       && GET_CODE (pat) == SET
    2602         2726 :       && !force_unique_p)
    2603              :     {
    2604         2128 :       IDATA_RHS (id) = SET_SRC (pat);
    2605         2128 :       IDATA_LHS (id) = SET_DEST (pat);
    2606              :     }
    2607              :   else
    2608         2396 :     IDATA_LHS (id) = IDATA_RHS (id) = NULL;
    2609         4524 : }
    2610              : 
    2611              : /* Possibly downgrade INSN to USE.  */
    2612              : static void
    2613         4524 : maybe_downgrade_id_to_use (idata_t id, insn_t insn)
    2614              : {
    2615         4524 :   bool must_be_use = false;
    2616         4524 :   df_ref def;
    2617         4524 :   rtx lhs = IDATA_LHS (id);
    2618         4524 :   rtx rhs = IDATA_RHS (id);
    2619              : 
    2620              :   /* We downgrade only SETs.  */
    2621         4524 :   if (IDATA_TYPE (id) != SET)
    2622              :     return;
    2623              : 
    2624         2796 :   if (!lhs || !lhs_and_rhs_separable_p (lhs, rhs))
    2625              :     {
    2626         1728 :       IDATA_TYPE (id) = USE;
    2627         1728 :       return;
    2628              :     }
    2629              : 
    2630         2135 :   FOR_EACH_INSN_DEF (def, insn)
    2631              :     {
    2632         1070 :       if (DF_REF_INSN (def)
    2633         1070 :           && DF_REF_FLAGS_IS_SET (def, DF_REF_PRE_POST_MODIFY)
    2634         1072 :           && 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         1068 :       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         1068 :   if (must_be_use)
    2652            3 :     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         5189 : setup_id_implicit_regs (idata_t id, insn_t insn)
    2659              : {
    2660         5189 :   if (reload_completed)
    2661         3502 :     return;
    2662              : 
    2663         1687 :   HARD_REG_SET temp;
    2664              : 
    2665         1687 :   get_implicit_reg_pending_clobbers (&temp, insn);
    2666         1687 :   IOR_REG_SET_HRS (IDATA_REG_SETS (id), temp);
    2667              : }
    2668              : 
    2669              : /* Setup register sets describing INSN in ID.  */
    2670              : static void
    2671         4524 : setup_id_reg_sets (idata_t id, insn_t insn)
    2672              : {
    2673         4524 :   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
    2674         4524 :   df_ref def, use;
    2675         4524 :   regset tmp = get_clear_regset_from_pool ();
    2676              : 
    2677        22300 :   FOR_EACH_INSN_INFO_DEF (def, insn_info)
    2678              :     {
    2679        17776 :       unsigned int regno = DF_REF_REGNO (def);
    2680              : 
    2681              :       /* Post modifies are treated like clobbers by sched-deps.cc.  */
    2682        17776 :       if (DF_REF_FLAGS_IS_SET (def, (DF_REF_MUST_CLOBBER
    2683              :                                      | DF_REF_PRE_POST_MODIFY)))
    2684          878 :         SET_REGNO_REG_SET (IDATA_REG_CLOBBERS (id), regno);
    2685        16898 :       else if (! DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
    2686              :         {
    2687         3141 :           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.cc.  */
    2692         3141 :           if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2693            1 :             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        17776 :       if (DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)
    2698        17776 :           || regno == STACK_POINTER_REGNUM)
    2699          285 :         bitmap_set_bit (tmp, regno);
    2700              :     }
    2701              : 
    2702         9677 :   FOR_EACH_INSN_INFO_USE (use, insn_info)
    2703              :     {
    2704         5153 :       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         5153 :       if (bitmap_bit_p (tmp, regno))
    2709          285 :         bitmap_clear_bit (tmp, regno);
    2710         4868 :       else if (! DF_REF_FLAGS_IS_SET (use, DF_REF_CALL_STACK_USAGE))
    2711              :         {
    2712         4701 :           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.cc.  */
    2717         4701 :           if (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG))
    2718            3 :             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         4524 :   setup_id_implicit_regs (id, insn);
    2725              : 
    2726         4524 :   return_regset_to_pool (tmp);
    2727         4524 : }
    2728              : 
    2729              : /* Initialize instruction data for INSN in ID using DF's data.  */
    2730              : static void
    2731         4524 : init_id_from_df (idata_t id, insn_t insn, bool force_unique_p)
    2732              : {
    2733         4524 :   gcc_assert (DF_INSN_UID_SAFE_GET (INSN_UID (insn)) != NULL);
    2734              : 
    2735         4524 :   setup_id_for_insn (id, insn, force_unique_p);
    2736         4524 :   setup_id_lhs_rhs (id, insn, force_unique_p);
    2737              : 
    2738         4524 :   if (INSN_NOP_P (insn))
    2739              :     return;
    2740              : 
    2741         4524 :   maybe_downgrade_id_to_use (id, insn);
    2742         4524 :   setup_id_reg_sets (id, insn);
    2743              : }
    2744              : 
    2745              : /* Initialize instruction data for INSN in ID.  */
    2746              : static void
    2747          665 : deps_init_id (idata_t id, insn_t insn, bool force_unique_p)
    2748              : {
    2749          665 :   class deps_desc _dc, *dc = &_dc;
    2750              : 
    2751          665 :   deps_init_id_data.where = DEPS_IN_NOWHERE;
    2752          665 :   deps_init_id_data.id = id;
    2753          665 :   deps_init_id_data.force_unique_p = force_unique_p;
    2754          665 :   deps_init_id_data.force_use_p = false;
    2755              : 
    2756          665 :   init_deps (dc, false);
    2757          665 :   memcpy (&deps_init_id_sched_deps_info,
    2758              :           &const_deps_init_id_sched_deps_info,
    2759              :           sizeof (deps_init_id_sched_deps_info));
    2760          665 :   if (spec_info != NULL)
    2761            0 :     deps_init_id_sched_deps_info.generate_spec_deps = 1;
    2762          665 :   sched_deps_info = &deps_init_id_sched_deps_info;
    2763              : 
    2764          665 :   deps_analyze_insn (dc, insn);
    2765              :   /* Implicit reg clobbers received from sched-deps separately.  */
    2766          665 :   setup_id_implicit_regs (id, insn);
    2767              : 
    2768          665 :   free_deps (dc);
    2769          665 :   deps_init_id_data.id = NULL;
    2770          665 : }
    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         2385 : sched_scan (const struct sched_scan_info_def *ssi, bb_vec_t bbs)
    2798              : {
    2799         2385 :   unsigned i;
    2800         2385 :   basic_block bb;
    2801              : 
    2802         2385 :   if (ssi->extend_bb)
    2803          845 :     ssi->extend_bb ();
    2804              : 
    2805         2385 :   if (ssi->init_bb)
    2806         5609 :     FOR_EACH_VEC_ELT (bbs, i, bb)
    2807         3224 :       ssi->init_bb (bb);
    2808              : 
    2809         2385 :   if (ssi->extend_insn)
    2810          770 :     ssi->extend_insn ();
    2811              : 
    2812         2385 :   if (ssi->init_insn)
    2813         3646 :     FOR_EACH_VEC_ELT (bbs, i, bb)
    2814              :       {
    2815         2106 :         rtx_insn *insn;
    2816              : 
    2817        14364 :         FOR_BB_INSNS (bb, insn)
    2818        12258 :           ssi->init_insn (insn);
    2819              :       }
    2820         2385 : }
    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        21253 : first_time_insn_init (insn_t insn)
    2828              : {
    2829        21253 :   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          372 : eq_transformed_insns (const void *p, const void *q)
    2842              : {
    2843          372 :   rtx_insn *i1 =
    2844          372 :     VINSN_INSN_RTX (((const struct transformed_insns *) p)->vinsn_old);
    2845          372 :   rtx_insn *i2 =
    2846          372 :     VINSN_INSN_RTX (((const struct transformed_insns *) q)->vinsn_old);
    2847              : 
    2848          372 :   if (INSN_UID (i1) == INSN_UID (i2))
    2849              :     return 1;
    2850           60 :   return rtx_equal_p (PATTERN (i1), PATTERN (i2));
    2851              : }
    2852              : 
    2853              : /* Free an entry in a transformed_insns hashtable.  */
    2854              : static void
    2855           64 : free_transformed_insns (void *p)
    2856              : {
    2857           64 :   struct transformed_insns *pti = (struct transformed_insns *) p;
    2858              : 
    2859           64 :   vinsn_detach (pti->vinsn_old);
    2860           64 :   vinsn_detach (pti->vinsn_new);
    2861           64 :   free (pti);
    2862           64 : }
    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         5810 : 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         5810 :   gcc_assert (first_time_insn_init (insn));
    2872              : 
    2873              :   /* These are needed for nops too.  */
    2874         5810 :   INSN_LIVE (insn) = get_regset_from_pool ();
    2875         5810 :   INSN_LIVE_VALID_P (insn) = false;
    2876              : 
    2877         5810 :   if (!INSN_NOP_P (insn))
    2878              :     {
    2879         4943 :       INSN_ANALYZED_DEPS (insn) = BITMAP_ALLOC (NULL);
    2880         4943 :       INSN_FOUND_DEPS (insn) = BITMAP_ALLOC (NULL);
    2881         4943 :       INSN_TRANSFORMED_INSNS (insn)
    2882         4943 :         = htab_create (16, hash_transformed_insns,
    2883              :                        eq_transformed_insns, free_transformed_insns);
    2884         4943 :       init_deps (&INSN_DEPS_CONTEXT (insn), true);
    2885              :     }
    2886         5810 : }
    2887              : 
    2888              : /* Free almost all above data for INSN that is scheduled already.
    2889              :    Used for extra-large basic blocks.  */
    2890              : void
    2891         8285 : free_data_for_scheduled_insn (insn_t insn)
    2892              : {
    2893         8285 :   gcc_assert (! first_time_insn_init (insn));
    2894              : 
    2895         8285 :   if (! INSN_ANALYZED_DEPS (insn))
    2896              :     return;
    2897              : 
    2898         4645 :   BITMAP_FREE (INSN_ANALYZED_DEPS (insn));
    2899         4645 :   BITMAP_FREE (INSN_FOUND_DEPS (insn));
    2900         4645 :   htab_delete (INSN_TRANSFORMED_INSNS (insn));
    2901              : 
    2902              :   /* This is allocated only for bookkeeping insns.  */
    2903         4645 :   if (INSN_ORIGINATORS (insn))
    2904          155 :     BITMAP_FREE (INSN_ORIGINATORS (insn));
    2905         4645 :   free_deps (&INSN_DEPS_CONTEXT (insn));
    2906              : 
    2907         4645 :   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         4645 :   (&INSN_DEPS_CONTEXT (insn))->readonly = 0;
    2912              : }
    2913              : 
    2914              : /* Free the same data as above for INSN.  */
    2915              : static void
    2916         4645 : free_first_time_insn_data (insn_t insn)
    2917              : {
    2918         4645 :   gcc_assert (! first_time_insn_init (insn));
    2919              : 
    2920         4645 :   free_data_for_scheduled_insn (insn);
    2921         4645 :   return_regset_to_pool (INSN_LIVE (insn));
    2922         4645 :   INSN_LIVE (insn) = NULL;
    2923         4645 :   INSN_LIVE_VALID_P (insn) = false;
    2924         4645 : }
    2925              : 
    2926              : /* Initialize region-scope data structures for basic blocks.  */
    2927              : static void
    2928         1050 : init_global_and_expr_for_bb (basic_block bb)
    2929              : {
    2930         1050 :   if (sel_bb_empty_p (bb))
    2931              :     return;
    2932              : 
    2933         1019 :   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         6040 : init_global_and_expr_for_insn (insn_t insn)
    2948              : {
    2949         6040 :   if (LABEL_P (insn))
    2950              :     return;
    2951              : 
    2952         5529 :   if (NOTE_INSN_BASIC_BLOCK_P (insn))
    2953              :     {
    2954         1050 :       init_global_data.prev_insn = NULL;
    2955         1050 :       return;
    2956              :     }
    2957              : 
    2958         4479 :   gcc_assert (INSN_P (insn));
    2959              : 
    2960         4479 :   if (SCHED_GROUP_P (insn))
    2961              :     /* Setup a sched_group.  */
    2962              :     {
    2963          361 :       insn_t prev_insn = init_global_data.prev_insn;
    2964              : 
    2965          361 :       if (prev_insn)
    2966            0 :         INSN_SCHED_NEXT (prev_insn) = insn;
    2967              : 
    2968          361 :       init_global_data.prev_insn = insn;
    2969              :     }
    2970              :   else
    2971         4118 :     init_global_data.prev_insn = NULL;
    2972              : 
    2973         4479 :   if (GET_CODE (PATTERN (insn)) == ASM_INPUT
    2974         4479 :       || asm_noperands (PATTERN (insn)) >= 0)
    2975              :     /* Mark INSN as an asm.  */
    2976           10 :     INSN_ASM_P (insn) = true;
    2977              : 
    2978         4479 :   {
    2979         4479 :     bool force_unique_p;
    2980         4479 :     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         4479 :     if (prologue_epilogue_contains (insn))
    2986              :       {
    2987          380 :         if (RTX_FRAME_RELATED_P (insn))
    2988          287 :           CANT_MOVE (insn) = 1;
    2989              :         else
    2990              :           {
    2991           93 :             rtx note;
    2992          100 :             for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
    2993           35 :               if (REG_NOTE_KIND (note) == REG_SAVE_NOTE
    2994           28 :                   && ((enum insn_note) INTVAL (XEXP (note, 0))
    2995              :                       == NOTE_INSN_EPILOGUE_BEG))
    2996              :                 {
    2997           28 :                   CANT_MOVE (insn) = 1;
    2998           28 :                   break;
    2999              :                 }
    3000              :           }
    3001              :         force_unique_p = true;
    3002              :       }
    3003              :     else
    3004         4099 :       if (CANT_MOVE (insn)
    3005         2827 :           || INSN_ASM_P (insn)
    3006         2819 :           || SCHED_GROUP_P (insn)
    3007         2819 :           || CALL_P (insn)
    3008              :           /* Exception handling insns are always unique.  */
    3009         2819 :           || (cfun->can_throw_non_call_exceptions && can_throw_internal (insn))
    3010              :           /* TRAP_IF though have an INSN code is control_flow_insn_p ().  */
    3011         2819 :           || control_flow_insn_p (insn)
    3012         2808 :           || volatile_insn_p (PATTERN (insn))
    3013         6906 :           || (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         4479 :     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         4479 :     init_expr (INSN_EXPR (insn), vinsn_create (insn, force_unique_p), 0,
    3029         4479 :                REG_BR_PROB_BASE, INSN_PRIORITY (insn), 0, BLOCK_NUM (insn),
    3030         4479 :                spec_done_ds, 0, 0, vNULL, true,
    3031         4479 :                false, false, false, CANT_MOVE (insn));
    3032              :   }
    3033              : 
    3034         4479 :   init_first_time_insn_data (insn);
    3035              : }
    3036              : 
    3037              : /* Scan the region and initialize instruction data for basic blocks BBS.  */
    3038              : void
    3039          770 : sel_init_global_and_expr (bb_vec_t bbs)
    3040              : {
    3041              :   /* ??? It would be nice to implement push / pop scheme for sched_infos.  */
    3042          770 :   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          770 :   sched_scan (&ssi, bbs);
    3051          770 : }
    3052              : 
    3053              : /* Finalize region-scope data structures for basic blocks.  */
    3054              : static void
    3055         1056 : finish_global_and_expr_for_bb (basic_block bb)
    3056              : {
    3057         1056 :   av_set_clear (&BB_AV_SET (bb));
    3058         1056 :   BB_AV_LEVEL (bb) = 0;
    3059         1056 : }
    3060              : 
    3061              : /* Finalize INSN's data.  */
    3062              : static void
    3063         6218 : finish_global_and_expr_insn (insn_t insn)
    3064              : {
    3065         6218 :   if (LABEL_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn))
    3066              :     return;
    3067              : 
    3068         4645 :   gcc_assert (INSN_P (insn));
    3069              : 
    3070         4645 :   if (INSN_LUID (insn) > 0)
    3071              :     {
    3072         4645 :       free_first_time_insn_data (insn);
    3073         4645 :       INSN_WS_LEVEL (insn) = 0;
    3074         4645 :       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         4645 :       gcc_assert (true || VINSN_COUNT (INSN_VINSN (insn)) == 1);
    3080         4645 :       clear_expr (INSN_EXPR (insn));
    3081              :     }
    3082              : }
    3083              : 
    3084              : /* Finalize per instruction data for the whole region.  */
    3085              : void
    3086          770 : sel_finish_global_and_expr (void)
    3087              : {
    3088          770 :   {
    3089          770 :     bb_vec_t bbs;
    3090          770 :     int i;
    3091              : 
    3092          770 :     bbs.create (current_nr_blocks);
    3093              : 
    3094         2596 :     for (i = 0; i < current_nr_blocks; i++)
    3095         1056 :       bbs.quick_push (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i)));
    3096              : 
    3097              :     /* Clear AV_SETs and INSN_EXPRs.  */
    3098          770 :     {
    3099          770 :       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          770 :       sched_scan (&ssi, bbs);
    3108              :     }
    3109              : 
    3110          770 :     bbs.release ();
    3111              :   }
    3112              : 
    3113          770 :   finish_insns ();
    3114          770 : }
    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.cc: 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        18040 : has_dependence_start_insn (insn_t insn ATTRIBUTE_UNUSED)
    3144              : {
    3145        18040 :   gcc_assert (has_dependence_data.where == DEPS_IN_NOWHERE);
    3146              : 
    3147        18040 :   has_dependence_data.where = DEPS_IN_INSN;
    3148        18040 : }
    3149              : 
    3150              : /* Finish analyzing dependencies of an insn.  */
    3151              : static void
    3152        18040 : has_dependence_finish_insn (void)
    3153              : {
    3154        18040 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3155              : 
    3156        18040 :   has_dependence_data.where = DEPS_IN_NOWHERE;
    3157        18040 : }
    3158              : 
    3159              : /* Start analyzing dependencies of LHS.  */
    3160              : static void
    3161        15836 : has_dependence_start_lhs (rtx lhs ATTRIBUTE_UNUSED)
    3162              : {
    3163        15836 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3164              : 
    3165        15836 :   if (VINSN_LHS (has_dependence_data.con) != NULL)
    3166        15248 :     has_dependence_data.where = DEPS_IN_LHS;
    3167        15836 : }
    3168              : 
    3169              : /* Finish analyzing dependencies of an lhs.  */
    3170              : static void
    3171        15836 : has_dependence_finish_lhs (void)
    3172              : {
    3173        15836 :   has_dependence_data.where = DEPS_IN_INSN;
    3174        15836 : }
    3175              : 
    3176              : /* Start analyzing dependencies of RHS.  */
    3177              : static void
    3178        15836 : has_dependence_start_rhs (rtx rhs ATTRIBUTE_UNUSED)
    3179              : {
    3180        15836 :   gcc_assert (has_dependence_data.where == DEPS_IN_INSN);
    3181              : 
    3182        15836 :   if (VINSN_RHS (has_dependence_data.con) != NULL)
    3183        15248 :     has_dependence_data.where = DEPS_IN_RHS;
    3184        15836 : }
    3185              : 
    3186              : /* Start analyzing dependencies of an rhs.  */
    3187              : static void
    3188        15836 : has_dependence_finish_rhs (void)
    3189              : {
    3190        15836 :   gcc_assert (has_dependence_data.where == DEPS_IN_RHS
    3191              :               || has_dependence_data.where == DEPS_IN_INSN);
    3192              : 
    3193        15836 :   has_dependence_data.where = DEPS_IN_INSN;
    3194        15836 : }
    3195              : 
    3196              : /* Note a set of REGNO.  */
    3197              : static void
    3198        17215 : has_dependence_note_reg_set (int regno)
    3199              : {
    3200        17215 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3201              : 
    3202        17215 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3203        17215 :                                        VINSN_INSN_RTX
    3204              :                                        (has_dependence_data.con)))
    3205              :     {
    3206        17215 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3207              : 
    3208        17215 :       if (reg_last->sets != NULL
    3209        16104 :           || reg_last->clobbers != NULL)
    3210         1628 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_OUTPUT;
    3211              : 
    3212        17215 :       if (reg_last->uses || reg_last->implicit_sets)
    3213          866 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
    3214              :     }
    3215        17215 : }
    3216              : 
    3217              : /* Note a clobber of REGNO.  */
    3218              : static void
    3219         1652 : has_dependence_note_reg_clobber (int regno)
    3220              : {
    3221         1652 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3222              : 
    3223         1652 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3224         1652 :                                        VINSN_INSN_RTX
    3225              :                                        (has_dependence_data.con)))
    3226              :     {
    3227         1652 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3228              : 
    3229         1652 :       if (reg_last->sets)
    3230           40 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_OUTPUT;
    3231              : 
    3232         1652 :       if (reg_last->uses || reg_last->implicit_sets)
    3233          240 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
    3234              :     }
    3235         1652 : }
    3236              : 
    3237              : /* Note a use of REGNO.  */
    3238              : static void
    3239        20182 : has_dependence_note_reg_use (int regno)
    3240              : {
    3241        20182 :   struct deps_reg *reg_last = &has_dependence_data.dc->reg_last[regno];
    3242              : 
    3243        20182 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3244        20182 :                                        VINSN_INSN_RTX
    3245              :                                        (has_dependence_data.con)))
    3246              :     {
    3247        20182 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3248              : 
    3249        20182 :       if (reg_last->sets)
    3250         1899 :         *dsp = (*dsp & ~SPECULATIVE) | DEP_TRUE;
    3251              : 
    3252        20182 :       if (reg_last->clobbers || reg_last->implicit_sets)
    3253          138 :         *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        20182 :       if (reg_last->uses)
    3261              :         {
    3262         2786 :           ds_t pro_spec_checked_ds;
    3263              : 
    3264         2786 :           pro_spec_checked_ds = INSN_SPEC_CHECKED_DS (has_dependence_data.pro);
    3265         2786 :           pro_spec_checked_ds = ds_get_max_dep_weak (pro_spec_checked_ds);
    3266              : 
    3267         2786 :           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        20182 : }
    3273              : 
    3274              : /* Note a memory dependence.  */
    3275              : static void
    3276          447 : 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          447 :   if (!sched_insns_conditions_mutex_p (has_dependence_data.pro,
    3282          447 :                                        VINSN_INSN_RTX (has_dependence_data.con)))
    3283              :     {
    3284          447 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3285              : 
    3286          447 :       *dsp = ds_full_merge (ds, *dsp, pending_mem, mem);
    3287              :     }
    3288          447 : }
    3289              : 
    3290              : /* Note a dependence.  */
    3291              : static void
    3292          841 : has_dependence_note_dep (insn_t pro, ds_t ds ATTRIBUTE_UNUSED)
    3293              : {
    3294          841 :   insn_t real_pro = has_dependence_data.pro;
    3295          841 :   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           73 :   if (DEBUG_INSN_P (real_con) && !DEBUG_INSN_P (real_pro)
    3304          881 :       && INSN_UID (NEXT_INSN (pro)) == INSN_UID (real_con))
    3305              :     return;
    3306              : 
    3307          801 :   if (!sched_insns_conditions_mutex_p (real_pro, real_con))
    3308              :     {
    3309          801 :       ds_t *dsp = &has_dependence_data.has_dep_p[has_dependence_data.where];
    3310              : 
    3311          801 :       *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        18040 : setup_has_dependence_sched_deps_info (void)
    3362              : {
    3363        18040 :   memcpy (&has_dependence_sched_deps_info,
    3364              :           &const_has_dependence_sched_deps_info,
    3365              :           sizeof (has_dependence_sched_deps_info));
    3366              : 
    3367        18040 :   if (spec_info != NULL)
    3368            0 :     has_dependence_sched_deps_info.generate_spec_deps = 1;
    3369              : 
    3370        18040 :   sched_deps_info = &has_dependence_sched_deps_info;
    3371        18040 : }
    3372              : 
    3373              : /* Remove all dependences found and recorded in has_dependence_data array.  */
    3374              : void
    3375        18040 : sel_clear_has_dependence (void)
    3376              : {
    3377        18040 :   int i;
    3378              : 
    3379        72160 :   for (i = 0; i < DEPS_IN_NOWHERE; i++)
    3380        54120 :     has_dependence_data.has_dep_p[i] = 0;
    3381        18040 : }
    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        18235 : has_dependence_p (expr_t expr, insn_t pred, ds_t **has_dep_pp)
    3387              : {
    3388        18235 :   int i;
    3389        18235 :   ds_t ds;
    3390        18235 :   class deps_desc *dc;
    3391              : 
    3392        18235 :   if (INSN_SIMPLEJUMP_P (pred))
    3393              :     /* Unconditional jump is just a transfer of control flow.
    3394              :        Ignore it.  */
    3395              :     return false;
    3396              : 
    3397        18040 :   dc = &INSN_DEPS_CONTEXT (pred);
    3398              : 
    3399              :   /* We init this field lazily.  */
    3400        18040 :   if (dc->reg_last == NULL)
    3401         3380 :     init_deps_reg_last (dc);
    3402              : 
    3403        18040 :   if (!dc->readonly)
    3404              :     {
    3405         3380 :       has_dependence_data.pro = NULL;
    3406              :       /* Initialize empty dep context with information about PRED.  */
    3407         3380 :       advance_deps_context (dc, pred);
    3408         3380 :       dc->readonly = 1;
    3409              :     }
    3410              : 
    3411        18040 :   has_dependence_data.where = DEPS_IN_NOWHERE;
    3412        18040 :   has_dependence_data.pro = pred;
    3413        18040 :   has_dependence_data.con = EXPR_VINSN (expr);
    3414        18040 :   has_dependence_data.dc = dc;
    3415              : 
    3416        18040 :   sel_clear_has_dependence ();
    3417              : 
    3418              :   /* Now catch all dependencies that would be generated between PRED and
    3419              :      INSN.  */
    3420        18040 :   setup_has_dependence_sched_deps_info ();
    3421        18040 :   deps_analyze_insn (dc, EXPR_INSN_RTX (expr));
    3422        18040 :   has_dependence_data.dc = NULL;
    3423              : 
    3424              :   /* When a barrier was found, set DEPS_IN_INSN bits.  */
    3425        18040 :   if (dc->last_reg_pending_barrier == TRUE_BARRIER)
    3426           10 :     has_dependence_data.has_dep_p[DEPS_IN_INSN] = DEP_TRUE;
    3427        18030 :   else if (dc->last_reg_pending_barrier == MOVE_BARRIER)
    3428           65 :     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.cc 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        18040 :   if (EXPR_LHS (expr)
    3435        15248 :       && MEM_P (EXPR_LHS (expr))
    3436        18767 :       && sel_insn_is_speculation_check (pred))
    3437            0 :     has_dependence_data.has_dep_p[DEPS_IN_INSN] = DEP_ANTI;
    3438              : 
    3439        18040 :   *has_dep_pp = has_dependence_data.has_dep_p;
    3440        18040 :   ds = 0;
    3441        72160 :   for (i = 0; i < DEPS_IN_NOWHERE; i++)
    3442        54120 :     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        28927 : tick_check_dep_with_dw (insn_t pro_insn, ds_t ds, dw_t dw)
    3469              : {
    3470        28927 :   expr_t con_expr = tick_check_data.expr;
    3471        28927 :   insn_t con_insn = EXPR_INSN_RTX (con_expr);
    3472              : 
    3473        28927 :   if (con_insn != pro_insn)
    3474              :     {
    3475        28923 :       enum reg_note dt;
    3476        28923 :       int tick;
    3477              : 
    3478        28923 :       if (/* PROducer was removed from above due to pipelining.  */
    3479        28915 :           !INSN_IN_STREAM_P (pro_insn)
    3480              :           /* Or PROducer was originally on the next iteration regarding the
    3481              :              CONsumer.  */
    3482        57838 :           || (INSN_SCHED_TIMES (pro_insn)
    3483        28915 :               - EXPR_SCHED_TIMES (con_expr)) > 1)
    3484              :         /* Don't count this dependence.  */
    3485              :         return;
    3486              : 
    3487        28865 :       dt = ds_to_dt (ds);
    3488        28865 :       if (dt == REG_DEP_TRUE)
    3489         7025 :         tick_check_data.seen_true_dep_p = true;
    3490              : 
    3491        28865 :       gcc_assert (INSN_SCHED_CYCLE (pro_insn) > 0);
    3492              : 
    3493        28865 :       {
    3494        28865 :         dep_def _dep, *dep = &_dep;
    3495              : 
    3496        28865 :         init_dep (dep, pro_insn, con_insn, dt);
    3497              : 
    3498        28865 :         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        28865 :       if (tick > tick_check_data.cycle
    3504        10336 :           && (dt == REG_DEP_TRUE || !tick_check_data.seen_true_dep_p))
    3505        10182 :         tick_check_data.cycle = tick;
    3506              :     }
    3507              : }
    3508              : 
    3509              : /* An implementation of note_dep hook.  */
    3510              : static void
    3511        25863 : tick_check_note_dep (insn_t pro, ds_t ds)
    3512              : {
    3513        25863 :   tick_check_dep_with_dw (pro, ds, 0);
    3514        25863 : }
    3515              : 
    3516              : /* An implementation of note_mem_dep hook.  */
    3517              : static void
    3518         3064 : tick_check_note_mem_dep (rtx mem1, rtx mem2, insn_t pro, ds_t ds)
    3519              : {
    3520         3064 :   dw_t dw;
    3521              : 
    3522         3064 :   dw = (ds_to_dt (ds) == REG_DEP_TRUE
    3523         3064 :         ? estimate_dep_weak (mem1, mem2)
    3524              :         : 0);
    3525              : 
    3526         3064 :   tick_check_dep_with_dw (pro, ds, dw);
    3527         3064 : }
    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        12008 : tick_check_p (expr_t expr, deps_t dc, fence_t fence)
    3554              : {
    3555        12008 :   int cycles_left;
    3556              :   /* Initialize variables.  */
    3557        12008 :   tick_check_data.expr = expr;
    3558        12008 :   tick_check_data.cycle = 0;
    3559        12008 :   tick_check_data.seen_true_dep_p = false;
    3560        12008 :   sched_deps_info = &tick_check_sched_deps_info;
    3561              : 
    3562        12008 :   gcc_assert (!dc->readonly);
    3563        12008 :   dc->readonly = 1;
    3564        12008 :   deps_analyze_insn (dc, EXPR_INSN_RTX (expr));
    3565        12008 :   dc->readonly = 0;
    3566              : 
    3567        12008 :   cycles_left = tick_check_data.cycle - FENCE_CYCLE (fence);
    3568              : 
    3569        12008 :   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         6717 : lhs_of_insn_equals_to_dest_p (insn_t insn, rtx dest)
    3579              : {
    3580         6717 :   rtx lhs = INSN_LHS (insn);
    3581              : 
    3582         6717 :   if (lhs == NULL || dest == NULL)
    3583              :     return false;
    3584              : 
    3585         3847 :   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       258049 : sel_insn_is_speculation_check (rtx insn)
    3600              : {
    3601       258049 :   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          166 : get_dest_and_mode (rtx insn, rtx *dst_loc, machine_mode *mode)
    3608              : {
    3609          166 :   rtx pat = PATTERN (insn);
    3610              : 
    3611          166 :   gcc_assert (dst_loc);
    3612          166 :   gcc_assert (GET_CODE (pat) == SET);
    3613              : 
    3614          166 :   *dst_loc = SET_DEST (pat);
    3615              : 
    3616          166 :   gcc_assert (*dst_loc);
    3617          166 :   gcc_assert (MEM_P (*dst_loc) || REG_P (*dst_loc));
    3618              : 
    3619          166 :   if (mode)
    3620          166 :     *mode = GET_MODE (*dst_loc);
    3621          166 : }
    3622              : 
    3623              : /* Returns true when moving through JUMP will result in bookkeeping
    3624              :    creation.  */
    3625              : bool
    3626          902 : bookkeeping_can_be_created_if_moved_through_p (insn_t jump)
    3627              : {
    3628          902 :   insn_t succ;
    3629          902 :   succ_iterator si;
    3630              : 
    3631         1793 :   FOR_EACH_SUCC (succ, si, jump)
    3632          917 :     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         2529 : insn_is_the_only_one_in_bb_p (insn_t insn)
    3641              : {
    3642         2529 :   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         2871 : verify_backedges (void)
    3649              : {
    3650         2871 :   if (pipelining_p)
    3651              :     {
    3652              :       int i, n = 0;
    3653              :       edge e;
    3654              :       edge_iterator ei;
    3655              : 
    3656        18959 :       for (i = 0; i < current_nr_blocks; i++)
    3657        43604 :         FOR_EACH_EDGE (e, ei, BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i))->succs)
    3658        26287 :           if (in_current_region_p (e->dest)
    3659        26287 :               && BLOCK_TO_BB (e->dest->index) < i)
    3660         1432 :             n++;
    3661              : 
    3662         1642 :       gcc_assert (n <= 1);
    3663              :     }
    3664         2871 : }
    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         8406 : maybe_tidy_empty_bb (basic_block bb)
    3699              : {
    3700         8406 :   basic_block succ_bb, pred_bb, note_bb;
    3701         8406 :   vec<basic_block> dom_bbs;
    3702         8406 :   edge e;
    3703         8406 :   edge_iterator ei;
    3704         8406 :   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         8406 :   if (!sel_bb_empty_p (bb)
    3710           63 :       || (single_succ_p (bb)
    3711           63 :           && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)
    3712         8345 :           && (!single_pred_p (bb)
    3713            1 :               || !(single_pred_edge (bb)->flags & EDGE_FALLTHRU)))
    3714           63 :       || EDGE_COUNT (bb->preds) == 0
    3715         8470 :       || EDGE_COUNT (bb->succs) == 0)
    3716              :     return false;
    3717              : 
    3718              :   /* Do not attempt to redirect complex edges.  */
    3719          148 :   FOR_EACH_EDGE (e, ei, bb->preds)
    3720           86 :     if (e->flags & EDGE_COMPLEX)
    3721              :       return false;
    3722           86 :     else if (e->flags & EDGE_FALLTHRU)
    3723              :       {
    3724           53 :         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           53 :         if (JUMP_P (BB_END (e->src))
    3729           53 :             && (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           62 :   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           62 :   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           62 :   succ_bb = single_succ (bb);
    3751           62 :   rescan_p = true;
    3752           62 :   pred_bb = NULL;
    3753           62 :   dom_bbs.create (0);
    3754              : 
    3755              :   /* Save a pred/succ from the current region to attach the notes to.  */
    3756           62 :   note_bb = NULL;
    3757           62 :   FOR_EACH_EDGE (e, ei, bb->preds)
    3758           62 :     if (in_current_region_p (e->src))
    3759              :       {
    3760           62 :         note_bb = e->src;
    3761           62 :         break;
    3762              :       }
    3763           62 :   if (note_bb == NULL)
    3764            0 :     note_bb = succ_bb;
    3765              : 
    3766              :   /* Redirect all non-fallthru edges to the next bb.  */
    3767          157 :   while (rescan_p)
    3768              :     {
    3769           95 :       rescan_p = false;
    3770              : 
    3771          157 :       FOR_EACH_EDGE (e, ei, bb->preds)
    3772              :         {
    3773           95 :           pred_bb = e->src;
    3774              : 
    3775           95 :           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           33 :               if (e->dest != bb
    3784           33 :                   && single_pred_p (e->dest))
    3785            0 :                 dom_bbs.safe_push (e->dest);
    3786           33 :               sel_redirect_edge_and_branch (e, succ_bb);
    3787           33 :               rescan_p = true;
    3788           33 :               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           62 :           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 (onlyjump_p (BB_END (pred_bb))
    3797            0 :                   && INSN_SCHED_TIMES (BB_END (pred_bb)) == 0
    3798            0 :                   && !IN_CURRENT_FENCE_P (BB_END (pred_bb)))
    3799              :                 {
    3800            0 :                   if (!sel_remove_insn (BB_END (pred_bb), false, false))
    3801            0 :                     tidy_fallthru_edge (e);
    3802              :                 }
    3803              :               else
    3804            0 :                 sel_redirect_edge_and_branch (e, succ_bb);
    3805           95 :               rescan_p = true;
    3806              :               break;
    3807              :             }
    3808              :         }
    3809              :     }
    3810              : 
    3811           62 :   if (can_merge_blocks_p (bb->prev_bb, bb))
    3812           51 :     sel_merge_blocks (bb->prev_bb, bb);
    3813              :   else
    3814              :     {
    3815              :       /* This is a block without fallthru predecessor.  Just delete it.  */
    3816           11 :       gcc_assert (note_bb);
    3817           11 :       move_bb_info (note_bb, bb);
    3818           11 :       remove_empty_bb (bb, true);
    3819              :     }
    3820              : 
    3821           62 :   if (!dom_bbs.is_empty ())
    3822              :     {
    3823            0 :       dom_bbs.safe_push (succ_bb);
    3824            0 :       iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false);
    3825            0 :       dom_bbs.release ();
    3826              :     }
    3827              : 
    3828              :   return true;
    3829              : }
    3830              : 
    3831              : /* Tidy the control flow after we have removed original insn from
    3832              :    XBB.  Return true if we have removed some blocks.  When FULL_TIDYING
    3833              :    is true, also try to optimize control flow on non-empty blocks.  */
    3834              : bool
    3835         8126 : tidy_control_flow (basic_block xbb, bool full_tidying)
    3836              : {
    3837         8126 :   bool changed = true;
    3838         8126 :   insn_t first, last;
    3839              : 
    3840              :   /* First check whether XBB is empty.  */
    3841         8126 :   changed = maybe_tidy_empty_bb (xbb);
    3842         8126 :   if (changed || !full_tidying)
    3843              :     return changed;
    3844              : 
    3845              :   /* Check if there is a unnecessary jump after insn left.  */
    3846         2871 :   if (bb_has_removable_jump_to_p (xbb, xbb->next_bb)
    3847            1 :       && INSN_SCHED_TIMES (BB_END (xbb)) == 0
    3848         2872 :       && !IN_CURRENT_FENCE_P (BB_END (xbb)))
    3849              :     {
    3850              :       /* We used to call sel_remove_insn here that can trigger tidy_control_flow
    3851              :          before we fix up the fallthru edge.  Correct that ordering by
    3852              :          explicitly doing the latter before the former.  */
    3853            1 :       clear_expr (INSN_EXPR (BB_END (xbb)));
    3854            1 :       tidy_fallthru_edge (EDGE_SUCC (xbb, 0));
    3855            1 :       if (tidy_control_flow (xbb, false))
    3856              :         return true;
    3857              :     }
    3858              : 
    3859         2871 :   first = sel_bb_head (xbb);
    3860         2871 :   last = sel_bb_end (xbb);
    3861         2871 :   if (MAY_HAVE_DEBUG_INSNS)
    3862              :     {
    3863           79 :       if (first != last && DEBUG_INSN_P (first))
    3864           59 :         do
    3865           59 :           first = NEXT_INSN (first);
    3866           59 :         while (first != last && (DEBUG_INSN_P (first) || NOTE_P (first)));
    3867              : 
    3868           79 :       if (first != last && DEBUG_INSN_P (last))
    3869            1 :         do
    3870            1 :           last = PREV_INSN (last);
    3871            1 :         while (first != last && (DEBUG_INSN_P (last) || NOTE_P (last)));
    3872              :     }
    3873              :   /* Check if there is an unnecessary jump in previous basic block leading
    3874              :      to next basic block left after removing INSN from stream.
    3875              :      If it is so, remove that jump and redirect edge to current
    3876              :      basic block (where there was INSN before deletion).  This way
    3877              :      when NOP will be deleted several instructions later with its
    3878              :      basic block we will not get a jump to next instruction, which
    3879              :      can be harmful.  */
    3880         2871 :   if (first == last
    3881          326 :       && !sel_bb_empty_p (xbb)
    3882          326 :       && INSN_NOP_P (last)
    3883              :       /* Flow goes fallthru from current block to the next.  */
    3884           57 :       && EDGE_COUNT (xbb->succs) == 1
    3885           57 :       && (EDGE_SUCC (xbb, 0)->flags & EDGE_FALLTHRU)
    3886              :       /* When successor is an EXIT block, it may not be the next block.  */
    3887           57 :       && single_succ (xbb) != EXIT_BLOCK_PTR_FOR_FN (cfun)
    3888              :       /* And unconditional jump in previous basic block leads to
    3889              :          next basic block of XBB and this jump can be safely removed.  */
    3890           57 :       && in_current_region_p (xbb->prev_bb)
    3891           52 :       && bb_has_removable_jump_to_p (xbb->prev_bb, xbb->next_bb)
    3892           13 :       && INSN_SCHED_TIMES (BB_END (xbb->prev_bb)) == 0
    3893              :       /* Also this jump is not at the scheduling boundary.  */
    3894         2884 :       && !IN_CURRENT_FENCE_P (BB_END (xbb->prev_bb)))
    3895              :     {
    3896           13 :       bool recompute_toporder_p;
    3897              :       /* Clear data structures of jump - jump itself will be removed
    3898              :          by sel_redirect_edge_and_branch.  */
    3899           13 :       clear_expr (INSN_EXPR (BB_END (xbb->prev_bb)));
    3900           13 :       recompute_toporder_p
    3901           13 :         = sel_redirect_edge_and_branch (EDGE_SUCC (xbb->prev_bb, 0), xbb);
    3902              : 
    3903           13 :       gcc_assert (EDGE_SUCC (xbb->prev_bb, 0)->flags & EDGE_FALLTHRU);
    3904              : 
    3905              :       /* We could have skipped some debug insns which did not get removed with the block,
    3906              :          and the seqnos could become incorrect.  Fix them up here.  */
    3907           13 :       if (MAY_HAVE_DEBUG_INSNS && (sel_bb_head (xbb) != first || sel_bb_end (xbb) != last))
    3908              :        {
    3909            0 :          if (!sel_bb_empty_p (xbb->prev_bb))
    3910              :            {
    3911            0 :              int prev_seqno = INSN_SEQNO (sel_bb_end (xbb->prev_bb));
    3912            0 :              if (prev_seqno > INSN_SEQNO (sel_bb_head (xbb)))
    3913            0 :                for (insn_t insn = sel_bb_head (xbb); insn != first; insn = NEXT_INSN (insn))
    3914            0 :                  INSN_SEQNO (insn) = prev_seqno + 1;
    3915              :            }
    3916              :        }
    3917              : 
    3918              :       /* It can turn out that after removing unused jump, basic block
    3919              :          that contained that jump, becomes empty too.  In such case
    3920              :          remove it too.  */
    3921           13 :       if (sel_bb_empty_p (xbb->prev_bb))
    3922            0 :         changed = maybe_tidy_empty_bb (xbb->prev_bb);
    3923           13 :       if (recompute_toporder_p)
    3924            0 :         sel_recompute_toporder ();
    3925              :     }
    3926              : 
    3927              :   /* TODO: use separate flag for CFG checking.  */
    3928         2871 :   if (flag_checking)
    3929              :     {
    3930         2871 :       verify_backedges ();
    3931         2871 :       verify_dominators (CDI_DOMINATORS);
    3932              :     }
    3933              : 
    3934              :   return changed;
    3935              : }
    3936              : 
    3937              : /* Purge meaningless empty blocks in the middle of a region.  */
    3938              : void
    3939          770 : purge_empty_blocks (void)
    3940              : {
    3941          770 :   int i;
    3942              : 
    3943              :   /* Do not attempt to delete the first basic block in the region.  */
    3944         1050 :   for (i = 1; i < current_nr_blocks; )
    3945              :     {
    3946          280 :       basic_block b = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i));
    3947              : 
    3948          280 :       if (maybe_tidy_empty_bb (b))
    3949            5 :         continue;
    3950              : 
    3951          275 :       i++;
    3952              :     }
    3953          770 : }
    3954              : 
    3955              : /* Rip-off INSN from the insn stream.  When ONLY_DISCONNECT is true,
    3956              :    do not delete insn's data, because it will be later re-emitted.
    3957              :    Return true if we have removed some blocks afterwards.  */
    3958              : bool
    3959         7220 : sel_remove_insn (insn_t insn, bool only_disconnect, bool full_tidying)
    3960              : {
    3961         7220 :   basic_block bb = BLOCK_FOR_INSN (insn);
    3962              : 
    3963        14440 :   gcc_assert (INSN_IN_STREAM_P (insn));
    3964              : 
    3965         7220 :   if (DEBUG_INSN_P (insn) && BB_AV_SET_VALID_P (bb))
    3966              :     {
    3967           43 :       expr_t expr;
    3968           43 :       av_set_iterator i;
    3969              : 
    3970              :       /* When we remove a debug insn that is head of a BB, it remains
    3971              :          in the AV_SET of the block, but it shouldn't.  */
    3972          128 :       FOR_EACH_EXPR_1 (expr, i, &BB_AV_SET (bb))
    3973           85 :         if (EXPR_INSN_RTX (expr) == insn)
    3974              :           {
    3975           28 :             av_set_iter_remove (&i);
    3976           28 :             break;
    3977              :           }
    3978              :     }
    3979              : 
    3980         7220 :   if (only_disconnect)
    3981         4871 :     remove_insn (insn);
    3982              :   else
    3983              :     {
    3984         2349 :       delete_insn (insn);
    3985         2349 :       clear_expr (INSN_EXPR (insn));
    3986              :     }
    3987              : 
    3988              :   /* It is necessary to NULL these fields in case we are going to re-insert
    3989              :      INSN into the insns stream, as will usually happen in the ONLY_DISCONNECT
    3990              :      case, but also for NOPs that we will return to the nop pool.  */
    3991         7220 :   SET_PREV_INSN (insn) = NULL_RTX;
    3992         7220 :   SET_NEXT_INSN (insn) = NULL_RTX;
    3993         7220 :   set_block_for_insn (insn, NULL);
    3994              : 
    3995         7220 :   return tidy_control_flow (bb, full_tidying);
    3996              : }
    3997              : 
    3998              : /* Estimate number of the insns in BB.  */
    3999              : static int
    4000          101 : sel_estimate_number_of_insns (basic_block bb)
    4001              : {
    4002          101 :   int res = 0;
    4003          101 :   insn_t insn = NEXT_INSN (BB_HEAD (bb)), next_tail = NEXT_INSN (BB_END (bb));
    4004              : 
    4005          968 :   for (; insn != next_tail; insn = NEXT_INSN (insn))
    4006          766 :     if (NONDEBUG_INSN_P (insn))
    4007          623 :       res++;
    4008              : 
    4009          101 :   return res;
    4010              : }
    4011              : 
    4012              : /* We don't need separate luids for notes or labels.  */
    4013              : static int
    4014         1561 : sel_luid_for_non_insn (rtx x)
    4015              : {
    4016         1561 :   gcc_assert (NOTE_P (x) || LABEL_P (x));
    4017              : 
    4018         1561 :   return -1;
    4019              : }
    4020              : 
    4021              : /*  Find the proper seqno for inserting at INSN by successors.
    4022              :     Return -1 if no successors with positive seqno exist.  */
    4023              : static int
    4024            0 : get_seqno_by_succs (rtx_insn *insn)
    4025              : {
    4026            0 :   basic_block bb = BLOCK_FOR_INSN (insn);
    4027            0 :   rtx_insn *tmp = insn, *end = BB_END (bb);
    4028            0 :   int seqno;
    4029            0 :   insn_t succ = NULL;
    4030            0 :   succ_iterator si;
    4031              : 
    4032            0 :   while (tmp != end)
    4033              :     {
    4034            0 :       tmp = NEXT_INSN (tmp);
    4035            0 :       if (INSN_P (tmp))
    4036            0 :         return INSN_SEQNO (tmp);
    4037              :     }
    4038              : 
    4039            0 :   seqno = INT_MAX;
    4040              : 
    4041            0 :   FOR_EACH_SUCC_1 (succ, si, end, SUCCS_NORMAL)
    4042            0 :     if (INSN_SEQNO (succ) > 0)
    4043            0 :       seqno = MIN (seqno, INSN_SEQNO (succ));
    4044              : 
    4045            0 :   if (seqno == INT_MAX)
    4046            0 :     return -1;
    4047              : 
    4048              :   return seqno;
    4049              : }
    4050              : 
    4051              : /* Compute seqno for INSN by its preds or succs.  Use OLD_SEQNO to compute
    4052              :    seqno in corner cases.  */
    4053              : static int
    4054           16 : get_seqno_for_a_jump (insn_t insn, int old_seqno)
    4055              : {
    4056           16 :   int seqno;
    4057              : 
    4058           16 :   gcc_assert (INSN_SIMPLEJUMP_P (insn));
    4059              : 
    4060           16 :   if (!sel_bb_head_p (insn))
    4061           15 :     seqno = INSN_SEQNO (PREV_INSN (insn));
    4062              :   else
    4063              :     {
    4064            1 :       basic_block bb = BLOCK_FOR_INSN (insn);
    4065              : 
    4066            1 :       if (single_pred_p (bb)
    4067            2 :           && !in_current_region_p (single_pred (bb)))
    4068              :         {
    4069              :           /* We can have preds outside a region when splitting edges
    4070              :              for pipelining of an outer loop.  Use succ instead.
    4071              :              There should be only one of them.  */
    4072            0 :           insn_t succ = NULL;
    4073            0 :           succ_iterator si;
    4074            0 :           bool first = true;
    4075              : 
    4076            0 :           gcc_assert (flag_sel_sched_pipelining_outer_loops
    4077              :                       && current_loop_nest);
    4078            0 :           FOR_EACH_SUCC_1 (succ, si, insn,
    4079              :                            SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS)
    4080              :             {
    4081            0 :               gcc_assert (first);
    4082            0 :               first = false;
    4083              :             }
    4084              : 
    4085            0 :           gcc_assert (succ != NULL);
    4086            0 :           seqno = INSN_SEQNO (succ);
    4087              :         }
    4088              :       else
    4089              :         {
    4090            1 :           insn_t *preds;
    4091            1 :           int n;
    4092              : 
    4093            2 :           cfg_preds (BLOCK_FOR_INSN (insn), &preds, &n);
    4094              : 
    4095            1 :           gcc_assert (n > 0);
    4096              :           /* For one predecessor, use simple method.  */
    4097            1 :           if (n == 1)
    4098            1 :             seqno = INSN_SEQNO (preds[0]);
    4099              :           else
    4100            0 :             seqno = get_seqno_by_preds (insn);
    4101              : 
    4102            1 :           free (preds);
    4103              :         }
    4104              :     }
    4105              : 
    4106              :   /* We were unable to find a good seqno among preds.  */
    4107           16 :   if (seqno < 0)
    4108            0 :     seqno = get_seqno_by_succs (insn);
    4109              : 
    4110            0 :   if (seqno < 0)
    4111              :     {
    4112              :       /* The only case where this could be here legally is that the only
    4113              :          unscheduled insn was a conditional jump that got removed and turned
    4114              :          into this unconditional one.  Initialize from the old seqno
    4115              :          of that jump passed down to here.  */
    4116            0 :       seqno = old_seqno;
    4117              :     }
    4118              : 
    4119            0 :   gcc_assert (seqno >= 0);
    4120           16 :   return seqno;
    4121              : }
    4122              : 
    4123              : /*  Find the proper seqno for inserting at INSN.  Returns -1 if no predecessors
    4124              :     with positive seqno exist.  */
    4125              : int
    4126            0 : get_seqno_by_preds (rtx_insn *insn)
    4127              : {
    4128            0 :   basic_block bb = BLOCK_FOR_INSN (insn);
    4129            0 :   rtx_insn *tmp = insn, *head = BB_HEAD (bb);
    4130            0 :   insn_t *preds;
    4131            0 :   int n, i, seqno;
    4132              : 
    4133              :   /* Loop backwards from INSN to HEAD including both.  */
    4134            0 :   while (1)
    4135              :     {
    4136            0 :       if (INSN_P (tmp))
    4137            0 :         return INSN_SEQNO (tmp);
    4138            0 :       if (tmp == head)
    4139              :         break;
    4140            0 :       tmp = PREV_INSN (tmp);
    4141              :     }
    4142              : 
    4143            0 :   cfg_preds (bb, &preds, &n);
    4144            0 :   for (i = 0, seqno = -1; i < n; i++)
    4145            0 :     seqno = MAX (seqno, INSN_SEQNO (preds[i]));
    4146              : 
    4147              :   return seqno;
    4148              : }
    4149              : 
    4150              : 
    4151              : 
    4152              : /* Extend pass-scope data structures for basic blocks.  */
    4153              : void
    4154         1053 : sel_extend_global_bb_info (void)
    4155              : {
    4156         1053 :   sel_global_bb_info.safe_grow_cleared (last_basic_block_for_fn (cfun), true);
    4157         1053 : }
    4158              : 
    4159              : /* Extend region-scope data structures for basic blocks.  */
    4160              : static void
    4161          922 : extend_region_bb_info (void)
    4162              : {
    4163          922 :   sel_region_bb_info.safe_grow_cleared (last_basic_block_for_fn (cfun), true);
    4164          922 : }
    4165              : 
    4166              : /* Extend all data structures to fit for all basic blocks.  */
    4167              : static void
    4168          922 : extend_bb_info (void)
    4169              : {
    4170          845 :   sel_extend_global_bb_info ();
    4171          922 :   extend_region_bb_info ();
    4172          845 : }
    4173              : 
    4174              : /* Finalize pass-scope data structures for basic blocks.  */
    4175              : void
    4176          131 : sel_finish_global_bb_info (void)
    4177              : {
    4178          131 :   sel_global_bb_info.release ();
    4179          131 : }
    4180              : 
    4181              : /* Finalize region-scope data structures for basic blocks.  */
    4182              : static void
    4183          770 : finish_region_bb_info (void)
    4184              : {
    4185            0 :   sel_region_bb_info.release ();
    4186            0 : }
    4187              : 
    4188              : 
    4189              : /* Data for each insn in current region.  */
    4190              : vec<sel_insn_data_def> s_i_d;
    4191              : 
    4192              : /* Extend data structures for insns from current region.  */
    4193              : static void
    4194         3299 : extend_insn_data (void)
    4195              : {
    4196         3299 :   int reserve;
    4197              : 
    4198         3299 :   sched_extend_target ();
    4199         3299 :   sched_deps_init (false);
    4200              : 
    4201              :   /* Extend data structures for insns from current region.  */
    4202         3299 :   reserve = (sched_max_luid + 1 - s_i_d.length ());
    4203         4473 :   if (reserve > 0 && ! s_i_d.space (reserve))
    4204              :     {
    4205         1174 :       int size;
    4206              : 
    4207         1174 :       if (sched_max_luid / 2 > 1024)
    4208            0 :         size = sched_max_luid + 1024;
    4209              :       else
    4210         1174 :         size = 3 * sched_max_luid / 2;
    4211              : 
    4212              : 
    4213         1174 :       s_i_d.safe_grow_cleared (size, true);
    4214              :     }
    4215         3299 : }
    4216              : 
    4217              : /* Finalize data structures for insns from current region.  */
    4218              : static void
    4219          770 : finish_insns (void)
    4220              : {
    4221          770 :   unsigned i;
    4222              : 
    4223              :   /* Clear here all dependence contexts that may have left from insns that were
    4224              :      removed during the scheduling.  */
    4225         9546 :   for (i = 0; i < s_i_d.length (); i++)
    4226              :     {
    4227         8776 :       sel_insn_data_def *sid_entry = &s_i_d[i];
    4228              : 
    4229         8776 :       if (sid_entry->live)
    4230         1165 :         return_regset_to_pool (sid_entry->live);
    4231         8776 :       if (sid_entry->analyzed_deps)
    4232              :         {
    4233          298 :           BITMAP_FREE (sid_entry->analyzed_deps);
    4234          298 :           BITMAP_FREE (sid_entry->found_deps);
    4235          298 :           htab_delete (sid_entry->transformed_insns);
    4236          298 :           free_deps (&sid_entry->deps_context);
    4237              :         }
    4238         8776 :       if (EXPR_VINSN (&sid_entry->expr))
    4239              :         {
    4240            0 :           clear_expr (&sid_entry->expr);
    4241              : 
    4242              :           /* Also, clear CANT_MOVE bit here, because we really don't want it
    4243              :              to be passed to the next region.  */
    4244            0 :           CANT_MOVE_BY_LUID (i) = 0;
    4245              :         }
    4246              :     }
    4247              : 
    4248          770 :   s_i_d.release ();
    4249          770 : }
    4250              : 
    4251              : /* A proxy to pass initialization data to init_insn ().  */
    4252              : static sel_insn_data_def _insn_init_ssid;
    4253              : static sel_insn_data_t insn_init_ssid = &_insn_init_ssid;
    4254              : 
    4255              : /* If true create a new vinsn.  Otherwise use the one from EXPR.  */
    4256              : static bool insn_init_create_new_vinsn_p;
    4257              : 
    4258              : /* Set all necessary data for initialization of the new insn[s].  */
    4259              : static expr_t
    4260         2513 : set_insn_init (expr_t expr, vinsn_t vi, int seqno)
    4261              : {
    4262         2513 :   expr_t x = &insn_init_ssid->expr;
    4263              : 
    4264         2513 :   copy_expr_onside (x, expr);
    4265         2513 :   if (vi != NULL)
    4266              :     {
    4267         2484 :       insn_init_create_new_vinsn_p = false;
    4268         2484 :       change_vinsn_in_expr (x, vi);
    4269              :     }
    4270              :   else
    4271           29 :     insn_init_create_new_vinsn_p = true;
    4272              : 
    4273         2513 :   insn_init_ssid->seqno = seqno;
    4274         2513 :   return x;
    4275              : }
    4276              : 
    4277              : /* Init data for INSN.  */
    4278              : static void
    4279         2513 : init_insn_data (insn_t insn)
    4280              : {
    4281         2513 :   expr_t expr;
    4282         2513 :   sel_insn_data_t ssid = insn_init_ssid;
    4283              : 
    4284              :   /* The fields mentioned below are special and hence are not being
    4285              :      propagated to the new insns.  */
    4286         2513 :   gcc_assert (!ssid->asm_p && ssid->sched_next == NULL
    4287              :               && !ssid->after_stall_p && ssid->sched_cycle == 0);
    4288         2513 :   gcc_assert (INSN_P (insn) && INSN_LUID (insn) > 0);
    4289              : 
    4290         2513 :   expr = INSN_EXPR (insn);
    4291         2513 :   copy_expr (expr, &ssid->expr);
    4292         2513 :   prepare_insn_expr (insn, ssid->seqno);
    4293              : 
    4294         2513 :   if (insn_init_create_new_vinsn_p)
    4295           29 :     change_vinsn_in_expr (expr, vinsn_create (insn, init_insn_force_unique_p));
    4296              : 
    4297         2513 :   if (first_time_insn_init (insn))
    4298         1315 :     init_first_time_insn_data (insn);
    4299         2513 : }
    4300              : 
    4301              : /* This is used to initialize spurious jumps generated by
    4302              :    sel_redirect_edge ().  OLD_SEQNO is used for initializing seqnos
    4303              :    in corner cases within get_seqno_for_a_jump.  */
    4304              : static void
    4305           16 : init_simplejump_data (insn_t insn, int old_seqno)
    4306              : {
    4307           16 :   init_expr (INSN_EXPR (insn), vinsn_create (insn, false), 0,
    4308              :              REG_BR_PROB_BASE, 0, 0, 0, 0, 0, 0,
    4309           16 :              vNULL, true, false, false,
    4310              :              false, true);
    4311           16 :   INSN_SEQNO (insn) = get_seqno_for_a_jump (insn, old_seqno);
    4312           16 :   init_first_time_insn_data (insn);
    4313           16 : }
    4314              : 
    4315              : /* Perform deferred initialization of insns.  This is used to process
    4316              :    a new jump that may be created by redirect_edge.  OLD_SEQNO is used
    4317              :    for initializing simplejumps in init_simplejump_data.  */
    4318              : static void
    4319         2529 : sel_init_new_insn (insn_t insn, int flags, int old_seqno)
    4320              : {
    4321              :   /* We create data structures for bb when the first insn is emitted in it.  */
    4322         2529 :   if (INSN_P (insn)
    4323         5058 :       && INSN_IN_STREAM_P (insn)
    4324         5058 :       && insn_is_the_only_one_in_bb_p (insn))
    4325              :     {
    4326           77 :       extend_bb_info ();
    4327           77 :       create_initial_data_sets (BLOCK_FOR_INSN (insn));
    4328              :     }
    4329              : 
    4330         2529 :   if (flags & INSN_INIT_TODO_LUID)
    4331              :     {
    4332         1331 :       sched_extend_luids ();
    4333         1331 :       sched_init_insn_luid (insn);
    4334              :     }
    4335              : 
    4336         2529 :   if (flags & INSN_INIT_TODO_SSID)
    4337              :     {
    4338         2513 :       extend_insn_data ();
    4339         2513 :       init_insn_data (insn);
    4340         2513 :       clear_expr (&insn_init_ssid->expr);
    4341              :     }
    4342              : 
    4343         2529 :   if (flags & INSN_INIT_TODO_SIMPLEJUMP)
    4344              :     {
    4345           16 :       extend_insn_data ();
    4346           16 :       init_simplejump_data (insn, old_seqno);
    4347              :     }
    4348              : 
    4349         2529 :   gcc_assert (CONTAINING_RGN (BLOCK_NUM (insn))
    4350              :               == CONTAINING_RGN (BB_TO_BLOCK (0)));
    4351         2529 : }
    4352              : 
    4353              : 
    4354              : /* Functions to init/finish work with lv sets.  */
    4355              : 
    4356              : /* Init BB_LV_SET of BB from DF_LR_IN set of BB.  */
    4357              : static void
    4358         1148 : init_lv_set (basic_block bb)
    4359              : {
    4360         1148 :   gcc_assert (!BB_LV_SET_VALID_P (bb));
    4361              : 
    4362         1148 :   BB_LV_SET (bb) = get_regset_from_pool ();
    4363         2296 :   COPY_REG_SET (BB_LV_SET (bb), DF_LR_IN (bb));
    4364         1148 :   BB_LV_SET_VALID_P (bb) = true;
    4365         1148 : }
    4366              : 
    4367              : /* Copy liveness information to BB from FROM_BB.  */
    4368              : static void
    4369            0 : copy_lv_set_from (basic_block bb, basic_block from_bb)
    4370              : {
    4371            0 :   gcc_assert (!BB_LV_SET_VALID_P (bb));
    4372              : 
    4373            0 :   COPY_REG_SET (BB_LV_SET (bb), BB_LV_SET (from_bb));
    4374            0 :   BB_LV_SET_VALID_P (bb) = true;
    4375            0 : }
    4376              : 
    4377              : /* Initialize lv set of all bb headers.  */
    4378              : void
    4379          131 : init_lv_sets (void)
    4380              : {
    4381          131 :   basic_block bb;
    4382              : 
    4383              :   /* Initialize of LV sets.  */
    4384         1148 :   FOR_EACH_BB_FN (bb, cfun)
    4385         1017 :     init_lv_set (bb);
    4386              : 
    4387              :   /* Don't forget EXIT_BLOCK.  */
    4388          131 :   init_lv_set (EXIT_BLOCK_PTR_FOR_FN (cfun));
    4389          131 : }
    4390              : 
    4391              : /* Release lv set of HEAD.  */
    4392              : static void
    4393         1283 : free_lv_set (basic_block bb)
    4394              : {
    4395         1283 :   gcc_assert (BB_LV_SET (bb) != NULL);
    4396              : 
    4397         1283 :   return_regset_to_pool (BB_LV_SET (bb));
    4398         1283 :   BB_LV_SET (bb) = NULL;
    4399         1283 :   BB_LV_SET_VALID_P (bb) = false;
    4400         1283 : }
    4401              : 
    4402              : /* Finalize lv sets of all bb headers.  */
    4403              : void
    4404          131 : free_lv_sets (void)
    4405              : {
    4406          131 :   basic_block bb;
    4407              : 
    4408              :   /* Don't forget EXIT_BLOCK.  */
    4409          131 :   free_lv_set (EXIT_BLOCK_PTR_FOR_FN (cfun));
    4410              : 
    4411              :   /* Free LV sets.  */
    4412         1143 :   FOR_EACH_BB_FN (bb, cfun)
    4413         1012 :     if (BB_LV_SET (bb))
    4414         1012 :       free_lv_set (bb);
    4415          131 : }
    4416              : 
    4417              : /* Mark AV_SET for BB as invalid, so this set will be updated the next time
    4418              :    compute_av() processes BB.  This function is called when creating new basic
    4419              :    blocks, as well as for blocks (either new or existing) where new jumps are
    4420              :    created when the control flow is being updated.  */
    4421              : static void
    4422         1164 : invalidate_av_set (basic_block bb)
    4423              : {
    4424         1164 :   BB_AV_LEVEL (bb) = -1;
    4425         1164 : }
    4426              : 
    4427              : /* Create initial data sets for BB (they will be invalid).  */
    4428              : static void
    4429          145 : create_initial_data_sets (basic_block bb)
    4430              : {
    4431          145 :   if (BB_LV_SET (bb))
    4432           10 :     BB_LV_SET_VALID_P (bb) = false;
    4433              :   else
    4434          135 :     BB_LV_SET (bb) = get_regset_from_pool ();
    4435          145 :   invalidate_av_set (bb);
    4436          145 : }
    4437              : 
    4438              : /* Free av set of BB.  */
    4439              : static void
    4440          129 : free_av_set (basic_block bb)
    4441              : {
    4442          129 :   av_set_clear (&BB_AV_SET (bb));
    4443          129 :   BB_AV_LEVEL (bb) = 0;
    4444          129 : }
    4445              : 
    4446              : /* Free data sets of BB.  */
    4447              : void
    4448          129 : free_data_sets (basic_block bb)
    4449              : {
    4450          129 :   free_lv_set (bb);
    4451          129 :   free_av_set (bb);
    4452          129 : }
    4453              : 
    4454              : /* Exchange data sets of TO and FROM.  */
    4455              : void
    4456          143 : exchange_data_sets (basic_block to, basic_block from)
    4457              : {
    4458              :   /* Exchange lv sets of TO and FROM.  */
    4459          143 :   std::swap (BB_LV_SET (from), BB_LV_SET (to));
    4460          143 :   std::swap (BB_LV_SET_VALID_P (from), BB_LV_SET_VALID_P (to));
    4461              : 
    4462              :   /* Exchange av sets of TO and FROM.  */
    4463          143 :   std::swap (BB_AV_SET (from), BB_AV_SET (to));
    4464          143 :   std::swap (BB_AV_LEVEL (from), BB_AV_LEVEL (to));
    4465          143 : }
    4466              : 
    4467              : /* Copy data sets of FROM to TO.  */
    4468              : void
    4469            0 : copy_data_sets (basic_block to, basic_block from)
    4470              : {
    4471            0 :   gcc_assert (!BB_LV_SET_VALID_P (to) && !BB_AV_SET_VALID_P (to));
    4472            0 :   gcc_assert (BB_AV_SET (to) == NULL);
    4473              : 
    4474            0 :   BB_AV_LEVEL (to) = BB_AV_LEVEL (from);
    4475            0 :   BB_LV_SET_VALID_P (to) = BB_LV_SET_VALID_P (from);
    4476              : 
    4477            0 :   if (BB_AV_SET_VALID_P (from))
    4478              :     {
    4479            0 :       BB_AV_SET (to) = av_set_copy (BB_AV_SET (from));
    4480              :     }
    4481            0 :   if (BB_LV_SET_VALID_P (from))
    4482              :     {
    4483            0 :       gcc_assert (BB_LV_SET (to) != NULL);
    4484            0 :       COPY_REG_SET (BB_LV_SET (to), BB_LV_SET (from));
    4485              :     }
    4486            0 : }
    4487              : 
    4488              : /* Return an av set for INSN, if any.  */
    4489              : av_set_t
    4490         8424 : get_av_set (insn_t insn)
    4491              : {
    4492         8424 :   av_set_t av_set;
    4493              : 
    4494         8424 :   gcc_assert (AV_SET_VALID_P (insn));
    4495              : 
    4496         8424 :   if (sel_bb_head_p (insn))
    4497         8424 :     av_set = BB_AV_SET (BLOCK_FOR_INSN (insn));
    4498              :   else
    4499              :     av_set = NULL;
    4500              : 
    4501         8424 :   return av_set;
    4502              : }
    4503              : 
    4504              : /* Implementation of AV_LEVEL () macro.  Return AV_LEVEL () of INSN.  */
    4505              : int
    4506       108971 : get_av_level (insn_t insn)
    4507              : {
    4508       108971 :   int av_level;
    4509              : 
    4510       108971 :   gcc_assert (INSN_P (insn));
    4511              : 
    4512       108971 :   if (sel_bb_head_p (insn))
    4513        47523 :     av_level = BB_AV_LEVEL (BLOCK_FOR_INSN (insn));
    4514              :   else
    4515        61448 :     av_level = INSN_WS_LEVEL (insn);
    4516              : 
    4517       108971 :   return av_level;
    4518              : }
    4519              : 
    4520              : 
    4521              : 
    4522              : /* Variables to work with control-flow graph.  */
    4523              : 
    4524              : /* The basic block that already has been processed by the sched_data_update (),
    4525              :    but hasn't been in sel_add_bb () yet.  */
    4526              : static vec<basic_block> last_added_blocks;
    4527              : 
    4528              : /* A pool for allocating successor infos.  */
    4529              : static struct
    4530              : {
    4531              :   /* A stack for saving succs_info structures.  */
    4532              :   struct succs_info *stack;
    4533              : 
    4534              :   /* Its size.  */
    4535              :   int size;
    4536              : 
    4537              :   /* Top of the stack.  */
    4538              :   int top;
    4539              : 
    4540              :   /* Maximal value of the top.  */
    4541              :   int max_top;
    4542              : }  succs_info_pool;
    4543              : 
    4544              : /* Functions to work with control-flow graph.  */
    4545              : 
    4546              : /* Return basic block note of BB.  */
    4547              : rtx_insn *
    4548       371932 : sel_bb_head (basic_block bb)
    4549              : {
    4550       371932 :   rtx_insn *head;
    4551              : 
    4552       371932 :   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    4553              :     {
    4554         2274 :       gcc_assert (exit_insn != NULL_RTX);
    4555              :       head = exit_insn;
    4556              :     }
    4557              :   else
    4558              :     {
    4559       369658 :       rtx_note *note = bb_note (bb);
    4560       369658 :       head = next_nonnote_insn (note);
    4561              : 
    4562       369658 :       if (head && (BARRIER_P (head) || BLOCK_FOR_INSN (head) != bb))
    4563              :         head = NULL;
    4564              :     }
    4565              : 
    4566       371932 :   return head;
    4567              : }
    4568              : 
    4569              : /* Return true if INSN is a basic block header.  */
    4570              : bool
    4571       194172 : sel_bb_head_p (insn_t insn)
    4572              : {
    4573       194172 :   return sel_bb_head (BLOCK_FOR_INSN (insn)) == insn;
    4574              : }
    4575              : 
    4576              : /* Return last insn of BB.  */
    4577              : rtx_insn *
    4578        66529 : sel_bb_end (basic_block bb)
    4579              : {
    4580        66529 :   if (sel_bb_empty_p (bb))
    4581              :     return NULL;
    4582              : 
    4583        66529 :   gcc_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
    4584              : 
    4585        66529 :   return BB_END (bb);
    4586              : }
    4587              : 
    4588              : /* Return true if INSN is the last insn in its basic block.  */
    4589              : bool
    4590        23932 : sel_bb_end_p (insn_t insn)
    4591              : {
    4592        23932 :   return insn == sel_bb_end (BLOCK_FOR_INSN (insn));
    4593              : }
    4594              : 
    4595              : /* Return true if BB consist of single NOTE_INSN_BASIC_BLOCK.  */
    4596              : bool
    4597       110684 : sel_bb_empty_p (basic_block bb)
    4598              : {
    4599       110684 :   return sel_bb_head (bb) == NULL;
    4600              : }
    4601              : 
    4602              : /* True when BB belongs to the current scheduling region.  */
    4603              : bool
    4604        99789 : in_current_region_p (basic_block bb)
    4605              : {
    4606        99789 :   if (bb->index < NUM_FIXED_BLOCKS)
    4607              :     return false;
    4608              : 
    4609        98669 :   return CONTAINING_RGN (bb->index) == CONTAINING_RGN (BB_TO_BLOCK (0));
    4610              : }
    4611              : 
    4612              : /* Return the block which is a fallthru bb of a conditional jump JUMP.  */
    4613              : basic_block
    4614          817 : fallthru_bb_of_jump (const rtx_insn *jump)
    4615              : {
    4616          817 :   if (!JUMP_P (jump))
    4617              :     return NULL;
    4618              : 
    4619          800 :   if (!any_condjump_p (jump))
    4620              :     return NULL;
    4621              : 
    4622              :   /* A basic block that ends with a conditional jump may still have one successor
    4623              :      (and be followed by a barrier), we are not interested.  */
    4624          541 :   if (single_succ_p (BLOCK_FOR_INSN (jump)))
    4625              :     return NULL;
    4626              : 
    4627          541 :   return FALLTHRU_EDGE (BLOCK_FOR_INSN (jump))->dest;
    4628              : }
    4629              : 
    4630              : /* Remove all notes from BB.  */
    4631              : static void
    4632         1118 : init_bb (basic_block bb)
    4633              : {
    4634         1118 :   remove_notes (bb_note (bb), BB_END (bb));
    4635         1118 :   BB_NOTE_LIST (bb) = note_list;
    4636         1118 : }
    4637              : 
    4638              : void
    4639          845 : sel_init_bbs (bb_vec_t bbs)
    4640              : {
    4641          845 :   const struct sched_scan_info_def ssi =
    4642              :     {
    4643              :       extend_bb_info, /* extend_bb */
    4644              :       init_bb, /* init_bb */
    4645              :       NULL, /* extend_insn */
    4646              :       NULL /* init_insn */
    4647              :     };
    4648              : 
    4649          845 :   sched_scan (&ssi, bbs);
    4650          845 : }
    4651              : 
    4652              : /* Restore notes for the whole region.  */
    4653              : static void
    4654          770 : sel_restore_notes (void)
    4655              : {
    4656          770 :   int bb;
    4657          770 :   insn_t insn;
    4658              : 
    4659         1826 :   for (bb = 0; bb < current_nr_blocks; bb++)
    4660              :     {
    4661         1056 :       basic_block first, last;
    4662              : 
    4663         1056 :       first = EBB_FIRST_BB (bb);
    4664         1056 :       last = EBB_LAST_BB (bb)->next_bb;
    4665              : 
    4666         1056 :       do
    4667              :         {
    4668         1056 :           note_list = BB_NOTE_LIST (first);
    4669         1056 :           restore_other_notes (NULL, first);
    4670         1056 :           BB_NOTE_LIST (first) = NULL;
    4671              : 
    4672         7997 :           FOR_BB_INSNS (first, insn)
    4673         6941 :             if (NONDEBUG_INSN_P (insn))
    4674         4601 :               reemit_notes (insn);
    4675              : 
    4676         1056 :           first = first->next_bb;
    4677              :         }
    4678         1056 :       while (first != last);
    4679              :     }
    4680          770 : }
    4681              : 
    4682              : /* Free per-bb data structures.  */
    4683              : void
    4684          770 : sel_finish_bbs (void)
    4685              : {
    4686          770 :   sel_restore_notes ();
    4687              : 
    4688              :   /* Remove current loop preheader from this loop.  */
    4689          770 :   if (current_loop_nest)
    4690           56 :     sel_remove_loop_preheader ();
    4691              : 
    4692          770 :   finish_region_bb_info ();
    4693          770 : }
    4694              : 
    4695              : /* Return true if INSN has a single successor of type FLAGS.  */
    4696              : bool
    4697         1460 : sel_insn_has_single_succ_p (insn_t insn, int flags)
    4698              : {
    4699         1460 :   insn_t succ;
    4700         1460 :   succ_iterator si;
    4701         1460 :   bool first_p = true;
    4702              : 
    4703         2920 :   FOR_EACH_SUCC_1 (succ, si, insn, flags)
    4704              :     {
    4705         1463 :       if (first_p)
    4706         1460 :         first_p = false;
    4707              :       else
    4708              :         return false;
    4709              :     }
    4710              : 
    4711              :   return true;
    4712              : }
    4713              : 
    4714              : /* Allocate successor's info.  */
    4715              : static struct succs_info *
    4716         8544 : alloc_succs_info (void)
    4717              : {
    4718         8544 :   if (succs_info_pool.top == succs_info_pool.max_top)
    4719              :     {
    4720          299 :       int i;
    4721              : 
    4722          299 :       if (++succs_info_pool.max_top >= succs_info_pool.size)
    4723            0 :         gcc_unreachable ();
    4724              : 
    4725          299 :       i = ++succs_info_pool.top;
    4726          299 :       succs_info_pool.stack[i].succs_ok.create (10);
    4727          299 :       succs_info_pool.stack[i].succs_other.create (10);
    4728          299 :       succs_info_pool.stack[i].probs_ok.create (10);
    4729              :     }
    4730              :   else
    4731         8245 :     succs_info_pool.top++;
    4732              : 
    4733         8544 :   return &succs_info_pool.stack[succs_info_pool.top];
    4734              : }
    4735              : 
    4736              : /* Free successor's info.  */
    4737              : void
    4738         8544 : free_succs_info (struct succs_info * sinfo)
    4739              : {
    4740         8544 :   gcc_assert (succs_info_pool.top >= 0
    4741              :               && &succs_info_pool.stack[succs_info_pool.top] == sinfo);
    4742         8544 :   succs_info_pool.top--;
    4743              : 
    4744              :   /* Clear stale info.  */
    4745        17088 :   sinfo->succs_ok.block_remove (0, sinfo->succs_ok.length ());
    4746        17088 :   sinfo->succs_other.block_remove (0, sinfo->succs_other.length ());
    4747        17088 :   sinfo->probs_ok.block_remove (0, sinfo->probs_ok.length ());
    4748         8544 :   sinfo->all_prob = 0;
    4749         8544 :   sinfo->succs_ok_n = 0;
    4750         8544 :   sinfo->all_succs_n = 0;
    4751         8544 : }
    4752              : 
    4753              : /* Compute successor info for INSN.  FLAGS are the flags passed
    4754              :    to the FOR_EACH_SUCC_1 iterator.  */
    4755              : struct succs_info *
    4756         8544 : compute_succs_info (insn_t insn, short flags)
    4757              : {
    4758         8544 :   succ_iterator si;
    4759         8544 :   insn_t succ;
    4760         8544 :   struct succs_info *sinfo = alloc_succs_info ();
    4761              : 
    4762              :   /* Traverse *all* successors and decide what to do with each.  */
    4763        22125 :   FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_ALL)
    4764              :     {
    4765              :       /* FIXME: this doesn't work for skipping to loop exits, as we don't
    4766              :          perform code motion through inner loops.  */
    4767        13581 :       short current_flags = si.current_flags & ~SUCCS_SKIP_TO_LOOP_EXITS;
    4768              : 
    4769        13581 :       if (current_flags & flags)
    4770              :         {
    4771         6291 :           sinfo->succs_ok.safe_push (succ);
    4772        12582 :           sinfo->probs_ok.safe_push (
    4773              :                     /* FIXME: Improve calculation when skipping
    4774              :                        inner loop to exits.  */
    4775         6291 :                     si.bb_end
    4776        11994 :                     ? (si.e1->probability.initialized_p ()
    4777         6291 :                        ? si.e1->probability.to_reg_br_prob_base ()
    4778              :                        : 0)
    4779              :                     : REG_BR_PROB_BASE);
    4780         6291 :           sinfo->succs_ok_n++;
    4781              :         }
    4782              :       else
    4783         7290 :         sinfo->succs_other.safe_push (succ);
    4784              : 
    4785              :       /* Compute all_prob.  */
    4786        13581 :       if (!si.bb_end)
    4787            0 :         sinfo->all_prob = REG_BR_PROB_BASE;
    4788        13581 :       else if (si.e1->probability.initialized_p ())
    4789        12697 :         sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
    4790              : 
    4791        13581 :       sinfo->all_succs_n++;
    4792              :     }
    4793              : 
    4794         8544 :   return sinfo;
    4795              : }
    4796              : 
    4797              : /* Return the predecessors of BB in PREDS and their number in N.
    4798              :    Empty blocks are skipped.  SIZE is used to allocate PREDS.  */
    4799              : static void
    4800            1 : cfg_preds_1 (basic_block bb, insn_t **preds, int *n, int *size)
    4801              : {
    4802            1 :   edge e;
    4803            1 :   edge_iterator ei;
    4804              : 
    4805            1 :   gcc_assert (BLOCK_TO_BB (bb->index) != 0);
    4806              : 
    4807            2 :   FOR_EACH_EDGE (e, ei, bb->preds)
    4808              :     {
    4809            1 :       basic_block pred_bb = e->src;
    4810            1 :       insn_t bb_end = BB_END (pred_bb);
    4811              : 
    4812            1 :       if (!in_current_region_p (pred_bb))
    4813              :         {
    4814            0 :           gcc_assert (flag_sel_sched_pipelining_outer_loops
    4815              :                       && current_loop_nest);
    4816            0 :           continue;
    4817              :         }
    4818              : 
    4819            1 :       if (sel_bb_empty_p (pred_bb))
    4820            0 :         cfg_preds_1 (pred_bb, preds, n, size);
    4821              :       else
    4822              :         {
    4823            1 :           if (*n == *size)
    4824            1 :             *preds = XRESIZEVEC (insn_t, *preds,
    4825              :                                  (*size = 2 * *size + 1));
    4826            1 :           (*preds)[(*n)++] = bb_end;
    4827              :         }
    4828              :     }
    4829              : 
    4830            1 :   gcc_assert (*n != 0
    4831              :               || (flag_sel_sched_pipelining_outer_loops
    4832              :                   && current_loop_nest));
    4833            1 : }
    4834              : 
    4835              : /* Find all predecessors of BB and record them in PREDS and their number
    4836              :    in N.  Empty blocks are skipped, and only normal (forward in-region)
    4837              :    edges are processed.  */
    4838              : static void
    4839            1 : cfg_preds (basic_block bb, insn_t **preds, int *n)
    4840              : {
    4841            1 :   int size = 0;
    4842              : 
    4843            1 :   *preds = NULL;
    4844            1 :   *n = 0;
    4845            1 :   cfg_preds_1 (bb, preds, n, &size);
    4846            0 : }
    4847              : 
    4848              : /* Returns true if we are moving INSN through join point.  */
    4849              : bool
    4850         1822 : sel_num_cfg_preds_gt_1 (insn_t insn)
    4851              : {
    4852         1822 :   basic_block bb;
    4853              : 
    4854         1822 :   if (!sel_bb_head_p (insn) || INSN_BB (insn) == 0)
    4855              :     return false;
    4856              : 
    4857              :   bb = BLOCK_FOR_INSN (insn);
    4858              : 
    4859          963 :   while (1)
    4860              :     {
    4861          963 :       if (EDGE_COUNT (bb->preds) > 1)
    4862              :         return true;
    4863              : 
    4864          548 :       gcc_assert (EDGE_PRED (bb, 0)->dest == bb);
    4865          548 :       bb = EDGE_PRED (bb, 0)->src;
    4866              : 
    4867          548 :       if (!sel_bb_empty_p (bb))
    4868              :         break;
    4869              :     }
    4870              : 
    4871              :   return false;
    4872              : }
    4873              : 
    4874              : /* Returns true when BB should be the end of an ebb.  Adapted from the
    4875              :    code in sched-ebb.cc.  */
    4876              : bool
    4877         1163 : bb_ends_ebb_p (basic_block bb)
    4878              : {
    4879         1163 :   basic_block next_bb = bb_next_bb (bb);
    4880         1163 :   edge e;
    4881              : 
    4882         1163 :   if (next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
    4883         1047 :       || bitmap_bit_p (forced_ebb_heads, next_bb->index)
    4884         2119 :       || (LABEL_P (BB_HEAD (next_bb))
    4885              :           /* NB: LABEL_NUSES () is not maintained outside of jump.cc.
    4886              :              Work around that.  */
    4887          374 :           && !single_pred_p (next_bb)))
    4888          556 :     return true;
    4889              : 
    4890          607 :   if (!in_current_region_p (next_bb))
    4891              :     return true;
    4892              : 
    4893          401 :   e = find_fallthru_edge (bb->succs);
    4894          401 :   if (e)
    4895              :     {
    4896          399 :       gcc_assert (e->dest == next_bb);
    4897              : 
    4898              :       return false;
    4899              :     }
    4900              : 
    4901              :   return true;
    4902              : }
    4903              : 
    4904              : /* Returns true when INSN and SUCC are in the same EBB, given that SUCC is a
    4905              :    successor of INSN.  */
    4906              : bool
    4907          269 : in_same_ebb_p (insn_t insn, insn_t succ)
    4908              : {
    4909          269 :   basic_block ptr = BLOCK_FOR_INSN (insn);
    4910              : 
    4911          765 :   for (;;)
    4912              :     {
    4913          517 :       if (ptr == BLOCK_FOR_INSN (succ))
    4914              :         return true;
    4915              : 
    4916          356 :       if (bb_ends_ebb_p (ptr))
    4917              :         return false;
    4918              : 
    4919          248 :       ptr = bb_next_bb (ptr);
    4920              :     }
    4921              : }
    4922              : 
    4923              : /* Recomputes the reverse topological order for the function and
    4924              :    saves it in REV_TOP_ORDER_INDEX.  REV_TOP_ORDER_INDEX_LEN is also
    4925              :    modified appropriately.  */
    4926              : static void
    4927           44 : recompute_rev_top_order (void)
    4928              : {
    4929           44 :   int *postorder;
    4930           44 :   int n_blocks, i;
    4931              : 
    4932           44 :   if (!rev_top_order_index
    4933            1 :       || rev_top_order_index_len < last_basic_block_for_fn (cfun))
    4934              :     {
    4935           43 :       rev_top_order_index_len = last_basic_block_for_fn (cfun);
    4936           43 :       rev_top_order_index = XRESIZEVEC (int, rev_top_order_index,
    4937              :                                         rev_top_order_index_len);
    4938              :     }
    4939              : 
    4940           44 :   postorder = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
    4941              : 
    4942           44 :   n_blocks = post_order_compute (postorder, true, false);
    4943           44 :   gcc_assert (n_basic_blocks_for_fn (cfun) == n_blocks);
    4944              : 
    4945              :   /* Build reverse function: for each basic block with BB->INDEX == K
    4946              :      rev_top_order_index[K] is it's reverse topological sort number.  */
    4947          691 :   for (i = 0; i < n_blocks; i++)
    4948              :     {
    4949          647 :       gcc_assert (postorder[i] < rev_top_order_index_len);
    4950          647 :       rev_top_order_index[postorder[i]] = i;
    4951              :     }
    4952              : 
    4953           44 :   free (postorder);
    4954           44 : }
    4955              : 
    4956              : /* Clear all flags from insns in BB that could spoil its rescheduling.  */
    4957              : void
    4958          148 : clear_outdated_rtx_info (basic_block bb)
    4959              : {
    4960          148 :   rtx_insn *insn;
    4961              : 
    4962         1200 :   FOR_BB_INSNS (bb, insn)
    4963         1052 :     if (INSN_P (insn))
    4964              :       {
    4965          828 :         SCHED_GROUP_P (insn) = 0;
    4966          828 :         INSN_AFTER_STALL_P (insn) = 0;
    4967          828 :         INSN_SCHED_TIMES (insn) = 0;
    4968          828 :         EXPR_PRIORITY_ADJ (INSN_EXPR (insn)) = 0;
    4969              : 
    4970              :         /* We cannot use the changed caches, as previously we could ignore
    4971              :            the LHS dependence due to enabled renaming and transform
    4972              :            the expression, and currently we'll be unable to do this.  */
    4973          828 :         htab_empty (INSN_TRANSFORMED_INSNS (insn));
    4974              :       }
    4975          148 : }
    4976              : 
    4977              : /* Add BB_NOTE to the pool of available basic block notes.  */
    4978              : static void
    4979          118 : return_bb_to_pool (basic_block bb)
    4980              : {
    4981          118 :   rtx_note *note = bb_note (bb);
    4982              : 
    4983          118 :   gcc_assert (NOTE_BASIC_BLOCK (note) == bb
    4984              :               && bb->aux == NULL);
    4985              : 
    4986              :   /* It turns out that current cfg infrastructure does not support
    4987              :      reuse of basic blocks.  Don't bother for now.  */
    4988              :   /*bb_note_pool.safe_push (note);*/
    4989          118 : }
    4990              : 
    4991              : /* Get a bb_note from pool or return NULL_RTX if pool is empty.  */
    4992              : static rtx_note *
    4993           68 : get_bb_note_from_pool (void)
    4994              : {
    4995           68 :   if (bb_note_pool.is_empty ())
    4996              :     return NULL;
    4997              :   else
    4998              :     {
    4999            0 :       rtx_note *note = bb_note_pool.pop ();
    5000              : 
    5001            0 :       SET_PREV_INSN (note) = NULL_RTX;
    5002            0 :       SET_NEXT_INSN (note) = NULL_RTX;
    5003              : 
    5004            0 :       return note;
    5005              :     }
    5006              : }
    5007              : 
    5008              : /* Free bb_note_pool.  */
    5009              : void
    5010          131 : free_bb_note_pool (void)
    5011              : {
    5012          131 :   bb_note_pool.release ();
    5013          131 : }
    5014              : 
    5015              : /* Setup scheduler pool and successor structure.  */
    5016              : void
    5017          131 : alloc_sched_pools (void)
    5018              : {
    5019          131 :   int succs_size;
    5020              : 
    5021          131 :   succs_size = MAX_WS + 1;
    5022          131 :   succs_info_pool.stack = XCNEWVEC (struct succs_info, succs_size);
    5023          131 :   succs_info_pool.size = succs_size;
    5024          131 :   succs_info_pool.top = -1;
    5025          131 :   succs_info_pool.max_top = -1;
    5026          131 : }
    5027              : 
    5028              : /* Free the pools.  */
    5029              : void
    5030          131 : free_sched_pools (void)
    5031              : {
    5032          131 :   int i;
    5033              : 
    5034          131 :   sched_lists_pool.release ();
    5035          131 :   gcc_assert (succs_info_pool.top == -1);
    5036          430 :   for (i = 0; i <= succs_info_pool.max_top; i++)
    5037              :     {
    5038          299 :       succs_info_pool.stack[i].succs_ok.release ();
    5039          299 :       succs_info_pool.stack[i].succs_other.release ();
    5040          299 :       succs_info_pool.stack[i].probs_ok.release ();
    5041              :     }
    5042          131 :   free (succs_info_pool.stack);
    5043          131 : }
    5044              : 
    5045              : 
    5046              : /* Returns a position in RGN where BB can be inserted retaining
    5047              :    topological order.  */
    5048              : static int
    5049           75 : find_place_to_insert_bb (basic_block bb, int rgn)
    5050              : {
    5051           75 :   bool has_preds_outside_rgn = false;
    5052           75 :   edge e;
    5053           75 :   edge_iterator ei;
    5054              : 
    5055              :   /* Find whether we have preds outside the region.  */
    5056          151 :   FOR_EACH_EDGE (e, ei, bb->preds)
    5057           76 :     if (!in_current_region_p (e->src))
    5058              :       {
    5059              :         has_preds_outside_rgn = true;
    5060              :         break;
    5061              :       }
    5062              : 
    5063              :   /* Recompute the top order -- needed when we have > 1 pred
    5064              :      and in case we don't have preds outside.  */
    5065           75 :   if (flag_sel_sched_pipelining_outer_loops
    5066           75 :       && (has_preds_outside_rgn || EDGE_COUNT (bb->preds) > 1))
    5067              :     {
    5068            1 :       int i, bbi = bb->index, cur_bbi;
    5069              : 
    5070            1 :       recompute_rev_top_order ();
    5071            2 :       for (i = RGN_NR_BLOCKS (rgn) - 1; i >= 0; i--)
    5072              :         {
    5073            2 :           cur_bbi = BB_TO_BLOCK (i);
    5074            2 :           if (rev_top_order_index[bbi]
    5075            2 :               < rev_top_order_index[cur_bbi])
    5076              :             break;
    5077              :         }
    5078              : 
    5079              :       /* We skipped the right block, so we increase i.  We accommodate
    5080              :          it for increasing by step later, so we decrease i.  */
    5081              :       return (i + 1) - 1;
    5082              :     }
    5083           74 :   else if (has_preds_outside_rgn)
    5084              :     {
    5085              :       /* This is the case when we generate an extra empty block
    5086              :          to serve as region head during pipelining.  */
    5087            0 :       e = EDGE_SUCC (bb, 0);
    5088            0 :       gcc_assert (EDGE_COUNT (bb->succs) == 1
    5089              :                   && in_current_region_p (EDGE_SUCC (bb, 0)->dest)
    5090              :                   && (BLOCK_TO_BB (e->dest->index) == 0));
    5091              :       return -1;
    5092              :     }
    5093              : 
    5094              :   /* We don't have preds outside the region.  We should have
    5095              :      the only pred, because the multiple preds case comes from
    5096              :      the pipelining of outer loops, and that is handled above.
    5097              :      Just take the bbi of this single pred.  */
    5098           74 :   if (EDGE_COUNT (bb->succs) > 0)
    5099              :     {
    5100           74 :       int pred_bbi;
    5101              : 
    5102           74 :       gcc_assert (EDGE_COUNT (bb->preds) == 1);
    5103              : 
    5104           74 :       pred_bbi = EDGE_PRED (bb, 0)->src->index;
    5105           74 :       return BLOCK_TO_BB (pred_bbi);
    5106              :     }
    5107              :   else
    5108              :     /* BB has no successors.  It is safe to put it in the end.  */
    5109            0 :     return current_nr_blocks - 1;
    5110              : }
    5111              : 
    5112              : /* Deletes an empty basic block freeing its data.  */
    5113              : static void
    5114           22 : delete_and_free_basic_block (basic_block bb)
    5115              : {
    5116           22 :   gcc_assert (sel_bb_empty_p (bb));
    5117              : 
    5118           22 :   if (BB_LV_SET (bb))
    5119           11 :     free_lv_set (bb);
    5120              : 
    5121           22 :   bitmap_clear_bit (blocks_to_reschedule, bb->index);
    5122              : 
    5123              :   /* Can't assert av_set properties because we use sel_aremove_bb
    5124              :      when removing loop preheader from the region.  At the point of
    5125              :      removing the preheader we already have deallocated sel_region_bb_info.  */
    5126           22 :   gcc_assert (BB_LV_SET (bb) == NULL
    5127              :               && !BB_LV_SET_VALID_P (bb)
    5128              :               && BB_AV_LEVEL (bb) == 0
    5129              :               && BB_AV_SET (bb) == NULL);
    5130              : 
    5131           22 :   delete_basic_block (bb);
    5132           22 : }
    5133              : 
    5134              : /* Add BB to the current region and update the region data.  */
    5135              : static void
    5136           75 : add_block_to_current_region (basic_block bb)
    5137              : {
    5138           75 :   int i, pos, bbi = -2, rgn;
    5139              : 
    5140           75 :   rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    5141           75 :   bbi = find_place_to_insert_bb (bb, rgn);
    5142           75 :   bbi += 1;
    5143           75 :   pos = RGN_BLOCKS (rgn) + bbi;
    5144              : 
    5145           75 :   gcc_assert (RGN_HAS_REAL_EBB (rgn) == 0
    5146              :               && ebb_head[bbi] == pos);
    5147              : 
    5148              :   /* Make a place for the new block.  */
    5149           75 :   extend_regions ();
    5150              : 
    5151          463 :   for (i = RGN_BLOCKS (rgn + 1) - 1; i >= pos; i--)
    5152          388 :     BLOCK_TO_BB (rgn_bb_table[i])++;
    5153              : 
    5154           75 :   memmove (rgn_bb_table + pos + 1,
    5155           75 :            rgn_bb_table + pos,
    5156           75 :            (RGN_BLOCKS (nr_regions) - pos) * sizeof (*rgn_bb_table));
    5157              : 
    5158              :   /* Initialize data for BB.  */
    5159           75 :   rgn_bb_table[pos] = bb->index;
    5160           75 :   BLOCK_TO_BB (bb->index) = bbi;
    5161           75 :   CONTAINING_RGN (bb->index) = rgn;
    5162              : 
    5163           75 :   RGN_NR_BLOCKS (rgn)++;
    5164              : 
    5165          447 :   for (i = rgn + 1; i <= nr_regions; i++)
    5166          372 :     RGN_BLOCKS (i)++;
    5167           75 : }
    5168              : 
    5169              : /* Remove BB from the current region and update the region data.  */
    5170              : static void
    5171          118 : remove_bb_from_region (basic_block bb)
    5172              : {
    5173          118 :   int i, pos, bbi = -2, rgn;
    5174              : 
    5175          118 :   rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    5176          118 :   bbi = BLOCK_TO_BB (bb->index);
    5177          118 :   pos = RGN_BLOCKS (rgn) + bbi;
    5178              : 
    5179          118 :   gcc_assert (RGN_HAS_REAL_EBB (rgn) == 0
    5180              :               && ebb_head[bbi] == pos);
    5181              : 
    5182          876 :   for (i = RGN_BLOCKS (rgn + 1) - 1; i >= pos; i--)
    5183          758 :     BLOCK_TO_BB (rgn_bb_table[i])--;
    5184              : 
    5185          118 :   memmove (rgn_bb_table + pos,
    5186          118 :            rgn_bb_table + pos + 1,
    5187          118 :            (RGN_BLOCKS (nr_regions) - pos) * sizeof (*rgn_bb_table));
    5188              : 
    5189          118 :   RGN_NR_BLOCKS (rgn)--;
    5190          843 :   for (i = rgn + 1; i <= nr_regions; i++)
    5191          725 :     RGN_BLOCKS (i)--;
    5192          118 : }
    5193              : 
    5194              : /* Add BB to the current region  and update all data.  If BB is NULL, add all
    5195              :    blocks from last_added_blocks vector.  */
    5196              : static void
    5197           75 : sel_add_bb (basic_block bb)
    5198              : {
    5199              :   /* Extend luids so that new notes will receive zero luids.  */
    5200           75 :   sched_extend_luids ();
    5201           75 :   sched_init_bbs ();
    5202           75 :   sel_init_bbs (last_added_blocks);
    5203              : 
    5204              :   /* When bb is passed explicitly, the vector should contain
    5205              :      the only element that equals to bb; otherwise, the vector
    5206              :      should not be NULL.  */
    5207           75 :   gcc_assert (last_added_blocks.exists ());
    5208              : 
    5209           75 :   if (bb != NULL)
    5210              :     {
    5211          150 :       gcc_assert (last_added_blocks.length () == 1
    5212              :                   && last_added_blocks[0] == bb);
    5213           75 :       add_block_to_current_region (bb);
    5214              : 
    5215              :       /* We associate creating/deleting data sets with the first insn
    5216              :          appearing / disappearing in the bb.  */
    5217           75 :       if (!sel_bb_empty_p (bb) && BB_LV_SET (bb) == NULL)
    5218           68 :         create_initial_data_sets (bb);
    5219              : 
    5220           75 :       last_added_blocks.release ();
    5221              :     }
    5222              :   else
    5223              :     /* BB is NULL - process LAST_ADDED_BLOCKS instead.  */
    5224              :     {
    5225              :       int i;
    5226              :       basic_block temp_bb = NULL;
    5227              : 
    5228            0 :       for (i = 0;
    5229            0 :            last_added_blocks.iterate (i, &bb); i++)
    5230              :         {
    5231            0 :           add_block_to_current_region (bb);
    5232            0 :           temp_bb = bb;
    5233              :         }
    5234              : 
    5235              :       /* We need to fetch at least one bb so we know the region
    5236              :          to update.  */
    5237            0 :       gcc_assert (temp_bb != NULL);
    5238            0 :       bb = temp_bb;
    5239              : 
    5240            0 :       last_added_blocks.release ();
    5241              :     }
    5242              : 
    5243           75 :   rgn_setup_region (CONTAINING_RGN (bb->index));
    5244           75 : }
    5245              : 
    5246              : /* Remove BB from the current region and update all data.
    5247              :    If REMOVE_FROM_CFG_PBB is true, also remove the block cfom cfg.  */
    5248              : static void
    5249          118 : sel_remove_bb (basic_block bb, bool remove_from_cfg_p)
    5250              : {
    5251          118 :   unsigned idx = bb->index;
    5252              : 
    5253          118 :   gcc_assert (bb != NULL && BB_NOTE_LIST (bb) == NULL_RTX);
    5254              : 
    5255          118 :   remove_bb_from_region (bb);
    5256          118 :   return_bb_to_pool (bb);
    5257          118 :   bitmap_clear_bit (blocks_to_reschedule, idx);
    5258              : 
    5259          118 :   if (remove_from_cfg_p)
    5260              :     {
    5261           11 :       basic_block succ = single_succ (bb);
    5262           11 :       delete_and_free_basic_block (bb);
    5263           11 :       set_immediate_dominator (CDI_DOMINATORS, succ,
    5264              :                                recompute_dominator (CDI_DOMINATORS, succ));
    5265              :     }
    5266              : 
    5267          118 :   rgn_setup_region (CONTAINING_RGN (idx));
    5268          118 : }
    5269              : 
    5270              : /* Concatenate info of EMPTY_BB to info of MERGE_BB.  */
    5271              : static void
    5272           62 : move_bb_info (basic_block merge_bb, basic_block empty_bb)
    5273              : {
    5274           62 :   if (in_current_region_p (merge_bb))
    5275           62 :     concat_note_lists (BB_NOTE_LIST (empty_bb),
    5276           62 :                        &BB_NOTE_LIST (merge_bb));
    5277           62 :   BB_NOTE_LIST (empty_bb) = NULL;
    5278              : 
    5279           62 : }
    5280              : 
    5281              : /* Remove EMPTY_BB.  If REMOVE_FROM_CFG_P is false, remove EMPTY_BB from
    5282              :    region, but keep it in CFG.  */
    5283              : static void
    5284           62 : remove_empty_bb (basic_block empty_bb, bool remove_from_cfg_p)
    5285              : {
    5286              :   /* The block should contain just a note or a label.
    5287              :      We try to check whether it is unused below.  */
    5288           62 :   gcc_assert (BB_HEAD (empty_bb) == BB_END (empty_bb)
    5289              :               || LABEL_P (BB_HEAD (empty_bb)));
    5290              : 
    5291              :   /* If basic block has predecessors or successors, redirect them.  */
    5292           62 :   if (remove_from_cfg_p
    5293           62 :       && (EDGE_COUNT (empty_bb->preds) > 0
    5294           10 :           || EDGE_COUNT (empty_bb->succs) > 0))
    5295              :     {
    5296           11 :       basic_block pred;
    5297           11 :       basic_block succ;
    5298              : 
    5299              :       /* We need to init PRED and SUCC before redirecting edges.  */
    5300           11 :       if (EDGE_COUNT (empty_bb->preds) > 0)
    5301              :         {
    5302            1 :           edge e;
    5303              : 
    5304            1 :           gcc_assert (EDGE_COUNT (empty_bb->preds) == 1);
    5305              : 
    5306            1 :           e = EDGE_PRED (empty_bb, 0);
    5307            1 :           gcc_assert (e->src == empty_bb->prev_bb
    5308              :                       && (e->flags & EDGE_FALLTHRU));
    5309              : 
    5310              :           pred = empty_bb->prev_bb;
    5311              :         }
    5312              :       else
    5313              :         pred = NULL;
    5314              : 
    5315           11 :       if (EDGE_COUNT (empty_bb->succs) > 0)
    5316              :         {
    5317              :           /* We do not check fallthruness here as above, because
    5318              :              after removing a jump the edge may actually be not fallthru.  */
    5319           11 :           gcc_assert (EDGE_COUNT (empty_bb->succs) == 1);
    5320           11 :           succ = EDGE_SUCC (empty_bb, 0)->dest;
    5321              :         }
    5322              :       else
    5323              :         succ = NULL;
    5324              : 
    5325           11 :       if (EDGE_COUNT (empty_bb->preds) > 0 && succ != NULL)
    5326              :         {
    5327            1 :           edge e = EDGE_PRED (empty_bb, 0);
    5328              : 
    5329            1 :           if (e->flags & EDGE_FALLTHRU)
    5330            1 :             redirect_edge_succ_nodup (e, succ);
    5331              :           else
    5332            0 :             sel_redirect_edge_and_branch (EDGE_PRED (empty_bb, 0), succ);
    5333              :         }
    5334              : 
    5335           11 :       if (EDGE_COUNT (empty_bb->succs) > 0 && pred != NULL)
    5336              :         {
    5337            1 :           edge e = EDGE_SUCC (empty_bb, 0);
    5338              : 
    5339            1 :           if (find_edge (pred, e->dest) == NULL)
    5340            0 :             redirect_edge_pred (e, pred);
    5341              :         }
    5342              :     }
    5343              : 
    5344              :   /* Finish removing.  */
    5345           62 :   sel_remove_bb (empty_bb, remove_from_cfg_p);
    5346           62 : }
    5347              : 
    5348              : /* An implementation of create_basic_block hook, which additionally updates
    5349              :    per-bb data structures.  */
    5350              : static basic_block
    5351           68 : sel_create_basic_block (void *headp, void *endp, basic_block after)
    5352              : {
    5353           68 :   basic_block new_bb;
    5354           68 :   rtx_note *new_bb_note;
    5355              : 
    5356           68 :   gcc_assert (flag_sel_sched_pipelining_outer_loops
    5357              :               || !last_added_blocks.exists ());
    5358              : 
    5359           68 :   new_bb_note = get_bb_note_from_pool ();
    5360              : 
    5361           68 :   if (new_bb_note == NULL_RTX)
    5362           68 :     new_bb = orig_cfg_hooks.create_basic_block (headp, endp, after);
    5363              :   else
    5364              :     {
    5365            0 :       new_bb = create_basic_block_structure ((rtx_insn *) headp,
    5366              :                                              (rtx_insn *) endp,
    5367              :                                              new_bb_note, after);
    5368            0 :       new_bb->aux = NULL;
    5369              :     }
    5370              : 
    5371           68 :   last_added_blocks.safe_push (new_bb);
    5372              : 
    5373           68 :   return new_bb;
    5374              : }
    5375              : 
    5376              : /* Implement sched_init_only_bb ().  */
    5377              : static void
    5378            0 : sel_init_only_bb (basic_block bb, basic_block after)
    5379              : {
    5380            0 :   gcc_assert (after == NULL);
    5381              : 
    5382            0 :   extend_regions ();
    5383            0 :   rgn_make_new_region_out_of_new_block (bb);
    5384            0 : }
    5385              : 
    5386              : /* Update the latch when we've splitted or merged it from FROM block to TO.
    5387              :    This should be checked for all outer loops, too.  */
    5388              : static void
    5389          118 : change_loops_latches (basic_block from, basic_block to)
    5390              : {
    5391          118 :   gcc_assert (from != to);
    5392              : 
    5393          118 :   if (current_loop_nest)
    5394              :     {
    5395              :       class loop *loop;
    5396              : 
    5397          321 :       for (loop = current_loop_nest; loop; loop = loop_outer (loop))
    5398          214 :         if (considered_for_pipelining_p (loop) && loop->latch == from)
    5399              :           {
    5400            0 :             gcc_assert (loop == current_loop_nest);
    5401            0 :             loop->latch = to;
    5402            0 :             gcc_assert (loop_latch_edge (loop));
    5403              :           }
    5404              :     }
    5405          118 : }
    5406              : 
    5407              : /* Splits BB on two basic blocks, adding it to the region and extending
    5408              :    per-bb data structures.  Returns the newly created bb.  */
    5409              : static basic_block
    5410           67 : sel_split_block (basic_block bb, rtx after)
    5411              : {
    5412           67 :   basic_block new_bb;
    5413           67 :   insn_t insn;
    5414              : 
    5415           67 :   new_bb = sched_split_block_1 (bb, after);
    5416           67 :   sel_add_bb (new_bb);
    5417              : 
    5418              :   /* This should be called after sel_add_bb, because this uses
    5419              :      CONTAINING_RGN for the new block, which is not yet initialized.
    5420              :      FIXME: this function may be a no-op now.  */
    5421           67 :   change_loops_latches (bb, new_bb);
    5422              : 
    5423              :   /* Update ORIG_BB_INDEX for insns moved into the new block.  */
    5424          498 :   FOR_BB_INSNS (new_bb, insn)
    5425          431 :    if (INSN_P (insn))
    5426          364 :      EXPR_ORIG_BB_INDEX (INSN_EXPR (insn)) = new_bb->index;
    5427              : 
    5428           67 :   if (sel_bb_empty_p (bb))
    5429              :     {
    5430           67 :       gcc_assert (!sel_bb_empty_p (new_bb));
    5431              : 
    5432              :       /* NEW_BB has data sets that need to be updated and BB holds
    5433              :          data sets that should be removed.  Exchange these data sets
    5434              :          so that we won't lose BB's valid data sets.  */
    5435           67 :       exchange_data_sets (new_bb, bb);
    5436           67 :       free_data_sets (bb);
    5437              :     }
    5438              : 
    5439           67 :   if (!sel_bb_empty_p (new_bb)
    5440           67 :       && bitmap_bit_p (blocks_to_reschedule, bb->index))
    5441           31 :     bitmap_set_bit (blocks_to_reschedule, new_bb->index);
    5442              : 
    5443           67 :   return new_bb;
    5444              : }
    5445              : 
    5446              : /* If BB ends with a jump insn whose ID is bigger then PREV_MAX_UID, return it.
    5447              :    Otherwise returns NULL.  */
    5448              : static rtx_insn *
    5449           68 : check_for_new_jump (basic_block bb, int prev_max_uid)
    5450              : {
    5451           68 :   rtx_insn *end;
    5452              : 
    5453           68 :   end = sel_bb_end (bb);
    5454           68 :   if (end && INSN_UID (end) >= prev_max_uid)
    5455           16 :     return end;
    5456              :   return NULL;
    5457              : }
    5458              : 
    5459              : /* Look for a new jump either in FROM_BB block or in newly created JUMP_BB block.
    5460              :    New means having UID at least equal to PREV_MAX_UID.  */
    5461              : static rtx_insn *
    5462          113 : find_new_jump (basic_block from, basic_block jump_bb, int prev_max_uid)
    5463              : {
    5464          113 :   rtx_insn *jump;
    5465              : 
    5466              :   /* Return immediately if no new insns were emitted.  */
    5467          113 :   if (get_max_uid () == prev_max_uid)
    5468              :     return NULL;
    5469              : 
    5470              :   /* Now check both blocks for new jumps.  It will ever be only one.  */
    5471           67 :   if ((jump = check_for_new_jump (from, prev_max_uid)))
    5472              :     return jump;
    5473              : 
    5474           52 :   if (jump_bb != NULL
    5475           52 :       && (jump = check_for_new_jump (jump_bb, prev_max_uid)))
    5476              :     return jump;
    5477              :   return NULL;
    5478              : }
    5479              : 
    5480              : /* Splits E and adds the newly created basic block to the current region.
    5481              :    Returns this basic block.  */
    5482              : basic_block
    5483            0 : sel_split_edge (edge e)
    5484              : {
    5485            0 :   basic_block new_bb, src, other_bb = NULL;
    5486            0 :   int prev_max_uid;
    5487            0 :   rtx_insn *jump;
    5488              : 
    5489            0 :   src = e->src;
    5490            0 :   prev_max_uid = get_max_uid ();
    5491            0 :   new_bb = split_edge (e);
    5492              : 
    5493            0 :   if (flag_sel_sched_pipelining_outer_loops
    5494            0 :       && current_loop_nest)
    5495              :     {
    5496              :       int i;
    5497              :       basic_block bb;
    5498              : 
    5499              :       /* Some of the basic blocks might not have been added to the loop.
    5500              :          Add them here, until this is fixed in force_fallthru.  */
    5501            0 :       for (i = 0;
    5502            0 :            last_added_blocks.iterate (i, &bb); i++)
    5503            0 :         if (!bb->loop_father)
    5504              :           {
    5505            0 :             add_bb_to_loop (bb, e->dest->loop_father);
    5506              : 
    5507            0 :             gcc_assert (!other_bb && (new_bb->index != bb->index));
    5508              :             other_bb = bb;
    5509              :           }
    5510              :     }
    5511              : 
    5512              :   /* Add all last_added_blocks to the region.  */
    5513            0 :   sel_add_bb (NULL);
    5514              : 
    5515            0 :   jump = find_new_jump (src, new_bb, prev_max_uid);
    5516            0 :   if (jump)
    5517            0 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
    5518              : 
    5519              :   /* Put the correct lv set on this block.  */
    5520            0 :   if (other_bb && !sel_bb_empty_p (other_bb))
    5521            0 :     compute_live (sel_bb_head (other_bb));
    5522              : 
    5523            0 :   return new_bb;
    5524              : }
    5525              : 
    5526              : /* Implement sched_create_empty_bb ().  */
    5527              : static basic_block
    5528            0 : sel_create_empty_bb (basic_block after)
    5529              : {
    5530            0 :   basic_block new_bb;
    5531              : 
    5532            0 :   new_bb = sched_create_empty_bb_1 (after);
    5533              : 
    5534              :   /* We'll explicitly initialize NEW_BB via sel_init_only_bb () a bit
    5535              :      later.  */
    5536            0 :   gcc_assert (last_added_blocks.length () == 1
    5537              :               && last_added_blocks[0] == new_bb);
    5538              : 
    5539            0 :   last_added_blocks.release ();
    5540            0 :   return new_bb;
    5541              : }
    5542              : 
    5543              : /* Implement sched_create_recovery_block.  ORIG_INSN is where block
    5544              :    will be splitted to insert a check.  */
    5545              : basic_block
    5546            0 : sel_create_recovery_block (insn_t orig_insn)
    5547              : {
    5548            0 :   basic_block first_bb, second_bb, recovery_block;
    5549            0 :   basic_block before_recovery = NULL;
    5550            0 :   rtx_insn *jump;
    5551              : 
    5552            0 :   first_bb = BLOCK_FOR_INSN (orig_insn);
    5553            0 :   if (sel_bb_end_p (orig_insn))
    5554              :     {
    5555              :       /* Avoid introducing an empty block while splitting.  */
    5556            0 :       gcc_assert (single_succ_p (first_bb));
    5557            0 :       second_bb = single_succ (first_bb);
    5558              :     }
    5559              :   else
    5560            0 :     second_bb = sched_split_block (first_bb, orig_insn);
    5561              : 
    5562            0 :   recovery_block = sched_create_recovery_block (&before_recovery);
    5563            0 :   if (before_recovery)
    5564            0 :     copy_lv_set_from (before_recovery, EXIT_BLOCK_PTR_FOR_FN (cfun));
    5565              : 
    5566            0 :   gcc_assert (sel_bb_empty_p (recovery_block));
    5567            0 :   sched_create_recovery_edges (first_bb, recovery_block, second_bb);
    5568            0 :   if (current_loops != NULL)
    5569            0 :     add_bb_to_loop (recovery_block, first_bb->loop_father);
    5570              : 
    5571            0 :   sel_add_bb (recovery_block);
    5572              : 
    5573            0 :   jump = BB_END (recovery_block);
    5574            0 :   gcc_assert (sel_bb_head (recovery_block) == jump);
    5575            0 :   sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
    5576              : 
    5577            0 :   return recovery_block;
    5578              : }
    5579              : 
    5580              : /* Merge basic block B into basic block A.  */
    5581              : static void
    5582           51 : sel_merge_blocks (basic_block a, basic_block b)
    5583              : {
    5584           51 :   gcc_assert (sel_bb_empty_p (b)
    5585              :               && EDGE_COUNT (b->preds) == 1
    5586              :               && EDGE_PRED (b, 0)->src == b->prev_bb);
    5587              : 
    5588           51 :   move_bb_info (b->prev_bb, b);
    5589           51 :   remove_empty_bb (b, false);
    5590           51 :   merge_blocks (a, b);
    5591           51 :   change_loops_latches (b, a);
    5592           51 : }
    5593              : 
    5594              : /* A wrapper for redirect_edge_and_branch_force, which also initializes
    5595              :    data structures for possibly created bb and insns.  */
    5596              : void
    5597           16 : sel_redirect_edge_and_branch_force (edge e, basic_block to)
    5598              : {
    5599           16 :   basic_block jump_bb, src, orig_dest = e->dest;
    5600           16 :   int prev_max_uid;
    5601           16 :   rtx_insn *jump;
    5602           16 :   int old_seqno = -1;
    5603              : 
    5604              :   /* This function is now used only for bookkeeping code creation, where
    5605              :      we'll never get the single pred of orig_dest block and thus will not
    5606              :      hit unreachable blocks when updating dominator info.  */
    5607           32 :   gcc_assert (!sel_bb_empty_p (e->src)
    5608              :               && !single_pred_p (orig_dest));
    5609           16 :   src = e->src;
    5610           16 :   prev_max_uid = get_max_uid ();
    5611              :   /* Compute and pass old_seqno down to sel_init_new_insn only for the case
    5612              :      when the conditional jump being redirected may become unconditional.  */
    5613           16 :   if (any_condjump_p (BB_END (src))
    5614           16 :       && INSN_SEQNO (BB_END (src)) >= 0)
    5615              :     old_seqno = INSN_SEQNO (BB_END (src));
    5616              : 
    5617           16 :   jump_bb = redirect_edge_and_branch_force (e, to);
    5618           16 :   if (jump_bb != NULL)
    5619            1 :     sel_add_bb (jump_bb);
    5620              : 
    5621              :   /* This function could not be used to spoil the loop structure by now,
    5622              :      thus we don't care to update anything.  But check it to be sure.  */
    5623           16 :   if (current_loop_nest
    5624           11 :       && pipelining_p)
    5625           11 :     gcc_assert (loop_latch_edge (current_loop_nest));
    5626              : 
    5627           16 :   jump = find_new_jump (src, jump_bb, prev_max_uid);
    5628           16 :   if (jump)
    5629           16 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP,
    5630              :                        old_seqno);
    5631           16 :   set_immediate_dominator (CDI_DOMINATORS, to,
    5632              :                            recompute_dominator (CDI_DOMINATORS, to));
    5633           16 :   set_immediate_dominator (CDI_DOMINATORS, orig_dest,
    5634              :                            recompute_dominator (CDI_DOMINATORS, orig_dest));
    5635           16 :   if (jump && sel_bb_head_p (jump))
    5636            1 :     compute_live (jump);
    5637           16 : }
    5638              : 
    5639              : /* A wrapper for redirect_edge_and_branch.  Return TRUE if blocks connected by
    5640              :    redirected edge are in reverse topological order.  */
    5641              : bool
    5642           97 : sel_redirect_edge_and_branch (edge e, basic_block to)
    5643              : {
    5644           97 :   bool latch_edge_p;
    5645           97 :   basic_block src, orig_dest = e->dest;
    5646           97 :   int prev_max_uid;
    5647           97 :   rtx_insn *jump;
    5648           97 :   edge redirected;
    5649           97 :   bool recompute_toporder_p = false;
    5650           97 :   bool maybe_unreachable = single_pred_p (orig_dest);
    5651           97 :   int old_seqno = -1;
    5652              : 
    5653          194 :   latch_edge_p = (pipelining_p
    5654           86 :                   && current_loop_nest
    5655          183 :                   && e == loop_latch_edge (current_loop_nest));
    5656              : 
    5657           97 :   src = e->src;
    5658           97 :   prev_max_uid = get_max_uid ();
    5659              : 
    5660              :   /* Compute and pass old_seqno down to sel_init_new_insn only for the case
    5661              :      when the conditional jump being redirected may become unconditional.  */
    5662           97 :   if (any_condjump_p (BB_END (src))
    5663           97 :       && INSN_SEQNO (BB_END (src)) >= 0)
    5664              :     old_seqno = INSN_SEQNO (BB_END (src));
    5665              : 
    5666           97 :   redirected = redirect_edge_and_branch (e, to);
    5667              : 
    5668           97 :   gcc_assert (redirected && !last_added_blocks.exists ());
    5669              : 
    5670              :   /* When we've redirected a latch edge, update the header.  */
    5671           97 :   if (latch_edge_p)
    5672              :     {
    5673            0 :       current_loop_nest->header = to;
    5674            0 :       gcc_assert (loop_latch_edge (current_loop_nest));
    5675              :     }
    5676              : 
    5677              :   /* In rare situations, the topological relation between the blocks connected
    5678              :      by the redirected edge can change (see PR42245 for an example).  Update
    5679              :      block_to_bb/bb_to_block.  */
    5680           97 :   if (CONTAINING_RGN (e->src->index) == CONTAINING_RGN (to->index)
    5681           93 :       && BLOCK_TO_BB (e->src->index) > BLOCK_TO_BB (to->index))
    5682           97 :     recompute_toporder_p = true;
    5683              : 
    5684           97 :   jump = find_new_jump (src, NULL, prev_max_uid);
    5685           97 :   if (jump)
    5686            0 :     sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP, old_seqno);
    5687              : 
    5688              :   /* Only update dominator info when we don't have unreachable blocks.
    5689              :      Otherwise we'll update in maybe_tidy_empty_bb.  */
    5690           97 :   if (!maybe_unreachable)
    5691              :     {
    5692           87 :       set_immediate_dominator (CDI_DOMINATORS, to,
    5693              :                                recompute_dominator (CDI_DOMINATORS, to));
    5694           87 :       set_immediate_dominator (CDI_DOMINATORS, orig_dest,
    5695              :                                recompute_dominator (CDI_DOMINATORS, orig_dest));
    5696              :     }
    5697           97 :   if (jump && sel_bb_head_p (jump))
    5698            0 :     compute_live (jump);
    5699           97 :   return recompute_toporder_p;
    5700              : }
    5701              : 
    5702              : /* This variable holds the cfg hooks used by the selective scheduler.  */
    5703              : static struct cfg_hooks sel_cfg_hooks;
    5704              : 
    5705              : /* Register sel-sched cfg hooks.  */
    5706              : void
    5707          770 : sel_register_cfg_hooks (void)
    5708              : {
    5709          770 :   sched_split_block = sel_split_block;
    5710              : 
    5711          770 :   orig_cfg_hooks = get_cfg_hooks ();
    5712          770 :   sel_cfg_hooks = orig_cfg_hooks;
    5713              : 
    5714          770 :   sel_cfg_hooks.create_basic_block = sel_create_basic_block;
    5715              : 
    5716          770 :   set_cfg_hooks (sel_cfg_hooks);
    5717              : 
    5718          770 :   sched_init_only_bb = sel_init_only_bb;
    5719          770 :   sched_split_block = sel_split_block;
    5720          770 :   sched_create_empty_bb = sel_create_empty_bb;
    5721          770 : }
    5722              : 
    5723              : /* Unregister sel-sched cfg hooks.  */
    5724              : void
    5725          770 : sel_unregister_cfg_hooks (void)
    5726              : {
    5727          770 :   sched_create_empty_bb = NULL;
    5728          770 :   sched_split_block = NULL;
    5729          770 :   sched_init_only_bb = NULL;
    5730              : 
    5731          770 :   set_cfg_hooks (orig_cfg_hooks);
    5732          770 : }
    5733              : 
    5734              : 
    5735              : /* Emit an insn rtx based on PATTERN.  If a jump insn is wanted,
    5736              :    LABEL is where this jump should be directed.  */
    5737              : rtx_insn *
    5738          718 : create_insn_rtx_from_pattern (rtx pattern, rtx label)
    5739              : {
    5740          718 :   rtx_insn *insn_rtx;
    5741              : 
    5742          718 :   gcc_assert (!INSN_P (pattern));
    5743              : 
    5744          718 :   start_sequence ();
    5745              : 
    5746          718 :   if (label == NULL_RTX)
    5747          714 :     insn_rtx = emit_insn (pattern);
    5748            4 :   else if (DEBUG_INSN_P (label))
    5749            4 :     insn_rtx = emit_debug_insn (pattern);
    5750              :   else
    5751              :     {
    5752            0 :       insn_rtx = emit_jump_insn (pattern);
    5753            0 :       JUMP_LABEL (insn_rtx) = label;
    5754            0 :       ++LABEL_NUSES (label);
    5755              :     }
    5756              : 
    5757          718 :   end_sequence ();
    5758              : 
    5759          718 :   sched_extend_luids ();
    5760          718 :   sched_extend_target ();
    5761          718 :   sched_deps_init (false);
    5762              : 
    5763              :   /* Initialize INSN_CODE now.  */
    5764          718 :   recog_memoized (insn_rtx);
    5765          718 :   return insn_rtx;
    5766              : }
    5767              : 
    5768              : /* Create a new vinsn for INSN_RTX.  FORCE_UNIQUE_P is true when the vinsn
    5769              :    must not be clonable.  */
    5770              : vinsn_t
    5771          665 : create_vinsn_from_insn_rtx (rtx_insn *insn_rtx, bool force_unique_p)
    5772              : {
    5773         1330 :   gcc_assert (INSN_P (insn_rtx) && !INSN_IN_STREAM_P (insn_rtx));
    5774              : 
    5775              :   /* If VINSN_TYPE is not USE, retain its uniqueness.  */
    5776          665 :   return vinsn_create (insn_rtx, force_unique_p);
    5777              : }
    5778              : 
    5779              : /* Create a copy of INSN_RTX.  */
    5780              : rtx_insn *
    5781          479 : create_copy_of_insn_rtx (rtx insn_rtx)
    5782              : {
    5783          479 :   rtx_insn *res;
    5784          479 :   rtx link;
    5785              : 
    5786          479 :   if (DEBUG_INSN_P (insn_rtx))
    5787            4 :     return create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
    5788            4 :                                          insn_rtx);
    5789              : 
    5790          475 :   gcc_assert (NONJUMP_INSN_P (insn_rtx));
    5791              : 
    5792          475 :   res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
    5793              :                                       NULL_RTX);
    5794              : 
    5795              :   /* Locate the end of existing REG_NOTES in NEW_RTX.  */
    5796          475 :   rtx *ptail = &REG_NOTES (res);
    5797          475 :   while (*ptail != NULL_RTX)
    5798            0 :     ptail = &XEXP (*ptail, 1);
    5799              : 
    5800              :   /* Copy all REG_NOTES except REG_EQUAL/REG_EQUIV and REG_LABEL_OPERAND
    5801              :      since mark_jump_label will make them.  REG_LABEL_TARGETs are created
    5802              :      there too, but are supposed to be sticky, so we copy them.  */
    5803          834 :   for (link = REG_NOTES (insn_rtx); link; link = XEXP (link, 1))
    5804          359 :     if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND
    5805              :         && REG_NOTE_KIND (link) != REG_EQUAL
    5806              :         && REG_NOTE_KIND (link) != REG_EQUIV)
    5807              :       {
    5808          348 :         *ptail = duplicate_reg_note (link);
    5809          348 :         ptail = &XEXP (*ptail, 1);
    5810              :       }
    5811              : 
    5812              :   return res;
    5813              : }
    5814              : 
    5815              : /* Change vinsn field of EXPR to hold NEW_VINSN.  */
    5816              : void
    5817         3315 : change_vinsn_in_expr (expr_t expr, vinsn_t new_vinsn)
    5818              : {
    5819         3315 :   vinsn_detach (EXPR_VINSN (expr));
    5820              : 
    5821         3315 :   EXPR_VINSN (expr) = new_vinsn;
    5822         3315 :   vinsn_attach (new_vinsn);
    5823         3315 : }
    5824              : 
    5825              : /* Helpers for global init.  */
    5826              : /* This structure is used to be able to call existing bundling mechanism
    5827              :    and calculate insn priorities.  */
    5828              : static struct haifa_sched_info sched_sel_haifa_sched_info =
    5829              : {
    5830              :   NULL, /* init_ready_list */
    5831              :   NULL, /* can_schedule_ready_p */
    5832              :   NULL, /* schedule_more_p */
    5833              :   NULL, /* new_ready */
    5834              :   NULL, /* rgn_rank */
    5835              :   sel_print_insn, /* rgn_print_insn */
    5836              :   contributes_to_priority,
    5837              :   NULL, /* insn_finishes_block_p */
    5838              : 
    5839              :   NULL, NULL,
    5840              :   NULL, NULL,
    5841              :   0, 0,
    5842              : 
    5843              :   NULL, /* add_remove_insn */
    5844              :   NULL, /* begin_schedule_ready */
    5845              :   NULL, /* begin_move_insn */
    5846              :   NULL, /* advance_target_bb */
    5847              : 
    5848              :   NULL,
    5849              :   NULL,
    5850              : 
    5851              :   SEL_SCHED | NEW_BBS
    5852              : };
    5853              : 
    5854              : /* Setup special insns used in the scheduler.  */
    5855              : void
    5856          131 : setup_nop_and_exit_insns (void)
    5857              : {
    5858          131 :   gcc_assert (nop_pattern == NULL_RTX
    5859              :               && exit_insn == NULL_RTX);
    5860              : 
    5861          131 :   nop_pattern = constm1_rtx;
    5862              : 
    5863          131 :   start_sequence ();
    5864          131 :   emit_insn (nop_pattern);
    5865          131 :   exit_insn = end_sequence ();
    5866          131 :   set_block_for_insn (exit_insn, EXIT_BLOCK_PTR_FOR_FN (cfun));
    5867          131 : }
    5868              : 
    5869              : /* Free special insns used in the scheduler.  */
    5870              : void
    5871          131 : free_nop_and_exit_insns (void)
    5872              : {
    5873          131 :   exit_insn = NULL;
    5874          131 :   nop_pattern = NULL_RTX;
    5875          131 : }
    5876              : 
    5877              : /* Setup a special vinsn used in new insns initialization.  */
    5878              : void
    5879          770 : setup_nop_vinsn (void)
    5880              : {
    5881          770 :   nop_vinsn = vinsn_create (exit_insn, false);
    5882          770 :   vinsn_attach (nop_vinsn);
    5883          770 : }
    5884              : 
    5885              : /* Free a special vinsn used in new insns initialization.  */
    5886              : void
    5887          770 : free_nop_vinsn (void)
    5888              : {
    5889          770 :   gcc_assert (VINSN_COUNT (nop_vinsn) == 1);
    5890          770 :   vinsn_detach (nop_vinsn);
    5891          770 :   nop_vinsn = NULL;
    5892          770 : }
    5893              : 
    5894              : /* Call a set_sched_flags hook.  */
    5895              : void
    5896         1671 : sel_set_sched_flags (void)
    5897              : {
    5898              :   /* ??? This means that set_sched_flags were called, and we decided to
    5899              :      support speculation.  However, set_sched_flags also modifies flags
    5900              :      on current_sched_info, doing this only at global init.  And we
    5901              :      sometimes change c_s_i later.  So put the correct flags again.  */
    5902         1671 :   if (spec_info && targetm.sched.set_sched_flags)
    5903            0 :     targetm.sched.set_sched_flags (spec_info);
    5904         1671 : }
    5905              : 
    5906              : /* Setup pointers to global sched info structures.  */
    5907              : void
    5908          901 : sel_setup_sched_infos (void)
    5909              : {
    5910          901 :   rgn_setup_common_sched_info ();
    5911              : 
    5912          901 :   memcpy (&sel_common_sched_info, common_sched_info,
    5913              :           sizeof (sel_common_sched_info));
    5914              : 
    5915          901 :   sel_common_sched_info.fix_recovery_cfg = NULL;
    5916          901 :   sel_common_sched_info.add_block = NULL;
    5917          901 :   sel_common_sched_info.estimate_number_of_insns
    5918          901 :     = sel_estimate_number_of_insns;
    5919          901 :   sel_common_sched_info.luid_for_non_insn = sel_luid_for_non_insn;
    5920          901 :   sel_common_sched_info.sched_pass_id = SCHED_SEL_PASS;
    5921              : 
    5922          901 :   common_sched_info = &sel_common_sched_info;
    5923              : 
    5924          901 :   current_sched_info = &sched_sel_haifa_sched_info;
    5925         1802 :   current_sched_info->sched_max_insns_priority =
    5926          901 :     get_rgn_sched_max_insns_priority ();
    5927              : 
    5928          901 :   sel_set_sched_flags ();
    5929          901 : }
    5930              : 
    5931              : 
    5932              : /* Adds basic block BB to region RGN at the position *BB_ORD_INDEX,
    5933              :    *BB_ORD_INDEX after that is increased.  */
    5934              : static void
    5935          311 : sel_add_block_to_region (basic_block bb, int *bb_ord_index, int rgn)
    5936              : {
    5937          311 :   RGN_NR_BLOCKS (rgn) += 1;
    5938          311 :   RGN_DONT_CALC_DEPS (rgn) = 0;
    5939          311 :   RGN_HAS_REAL_EBB (rgn) = 0;
    5940          311 :   CONTAINING_RGN (bb->index) = rgn;
    5941          311 :   BLOCK_TO_BB (bb->index) = *bb_ord_index;
    5942          311 :   rgn_bb_table[RGN_BLOCKS (rgn) + *bb_ord_index] = bb->index;
    5943          311 :   (*bb_ord_index)++;
    5944              : 
    5945              :   /* FIXME: it is true only when not scheduling ebbs.  */
    5946          311 :   RGN_BLOCKS (rgn + 1) = RGN_BLOCKS (rgn) + RGN_NR_BLOCKS (rgn);
    5947          311 : }
    5948              : 
    5949              : /* Functions to support pipelining of outer loops.  */
    5950              : 
    5951              : /* Creates a new empty region and returns it's number.  */
    5952              : static int
    5953           94 : sel_create_new_region (void)
    5954              : {
    5955           94 :   int new_rgn_number = nr_regions;
    5956              : 
    5957           94 :   RGN_NR_BLOCKS (new_rgn_number) = 0;
    5958              : 
    5959              :   /* FIXME: This will work only when EBBs are not created.  */
    5960           94 :   if (new_rgn_number != 0)
    5961           56 :     RGN_BLOCKS (new_rgn_number) = RGN_BLOCKS (new_rgn_number - 1) +
    5962           56 :       RGN_NR_BLOCKS (new_rgn_number - 1);
    5963              :   else
    5964           38 :     RGN_BLOCKS (new_rgn_number) = 0;
    5965              : 
    5966              :   /* Set the blocks of the next region so the other functions may
    5967              :      calculate the number of blocks in the region.  */
    5968           94 :   RGN_BLOCKS (new_rgn_number + 1) = RGN_BLOCKS (new_rgn_number) +
    5969              :     RGN_NR_BLOCKS (new_rgn_number);
    5970              : 
    5971           94 :   nr_regions++;
    5972              : 
    5973           94 :   return new_rgn_number;
    5974              : }
    5975              : 
    5976              : /* If X has a smaller topological sort number than Y, returns -1;
    5977              :    if greater, returns 1.  */
    5978              : static int
    5979         2155 : bb_top_order_comparator (const void *x, const void *y)
    5980              : {
    5981         2155 :   basic_block bb1 = *(const basic_block *) x;
    5982         2155 :   basic_block bb2 = *(const basic_block *) y;
    5983              : 
    5984         2155 :   gcc_assert (bb1 == bb2
    5985              :               || rev_top_order_index[bb1->index]
    5986              :                  != rev_top_order_index[bb2->index]);
    5987              : 
    5988              :   /* It's a reverse topological order in REV_TOP_ORDER_INDEX, so
    5989              :      bbs with greater number should go earlier.  */
    5990         2155 :   if (rev_top_order_index[bb1->index] > rev_top_order_index[bb2->index])
    5991              :     return -1;
    5992              :   else
    5993          921 :     return 1;
    5994              : }
    5995              : 
    5996              : /* Create a region for LOOP and return its number.  If we don't want
    5997              :    to pipeline LOOP, return -1.  */
    5998              : static int
    5999           59 : make_region_from_loop (class loop *loop)
    6000              : {
    6001           59 :   unsigned int i;
    6002           59 :   int new_rgn_number = -1;
    6003           59 :   class loop *inner;
    6004              : 
    6005              :   /* Basic block index, to be assigned to BLOCK_TO_BB.  */
    6006           59 :   int bb_ord_index = 0;
    6007           59 :   basic_block *loop_blocks;
    6008           59 :   basic_block preheader_block;
    6009              : 
    6010           59 :   if (loop->num_nodes
    6011           59 :       > (unsigned) param_max_pipeline_region_blocks)
    6012              :     return -1;
    6013              : 
    6014              :   /* Don't pipeline loops whose latch belongs to some of its inner loops.  */
    6015           62 :   for (inner = loop->inner; inner; inner = inner->inner)
    6016            6 :     if (flow_bb_inside_loop_p (inner, loop->latch))
    6017              :       return -1;
    6018              : 
    6019           56 :   loop->ninsns = num_loop_insns (loop);
    6020           56 :   if ((int) loop->ninsns > param_max_pipeline_region_insns)
    6021              :     return -1;
    6022              : 
    6023           56 :   loop_blocks = get_loop_body_in_custom_order (loop, bb_top_order_comparator);
    6024              : 
    6025          355 :   for (i = 0; i < loop->num_nodes; i++)
    6026          243 :     if (loop_blocks[i]->flags & BB_IRREDUCIBLE_LOOP)
    6027              :       {
    6028            0 :         free (loop_blocks);
    6029            0 :         return -1;
    6030              :       }
    6031              : 
    6032           56 :   preheader_block = loop_preheader_edge (loop)->src;
    6033           56 :   gcc_assert (preheader_block);
    6034           56 :   gcc_assert (loop_blocks[0] == loop->header);
    6035              : 
    6036           56 :   new_rgn_number = sel_create_new_region ();
    6037              : 
    6038           56 :   sel_add_block_to_region (preheader_block, &bb_ord_index, new_rgn_number);
    6039           56 :   bitmap_set_bit (bbs_in_loop_rgns, preheader_block->index);
    6040              : 
    6041          355 :   for (i = 0; i < loop->num_nodes; i++)
    6042              :     {
    6043              :       /* Add only those blocks that haven't been scheduled in the inner loop.
    6044              :          The exception is the basic blocks with bookkeeping code - they should
    6045              :          be added to the region (and they actually don't belong to the loop
    6046              :          body, but to the region containing that loop body).  */
    6047              : 
    6048          243 :       gcc_assert (new_rgn_number >= 0);
    6049              : 
    6050          243 :       if (! bitmap_bit_p (bbs_in_loop_rgns, loop_blocks[i]->index))
    6051              :         {
    6052          217 :           sel_add_block_to_region (loop_blocks[i], &bb_ord_index,
    6053              :                                    new_rgn_number);
    6054          217 :           bitmap_set_bit (bbs_in_loop_rgns, loop_blocks[i]->index);
    6055              :         }
    6056              :     }
    6057              : 
    6058           56 :   free (loop_blocks);
    6059           56 :   MARK_LOOP_FOR_PIPELINING (loop);
    6060              : 
    6061           56 :   return new_rgn_number;
    6062              : }
    6063              : 
    6064              : /* Create a new region from preheader blocks LOOP_BLOCKS.  */
    6065              : void
    6066           38 : make_region_from_loop_preheader (vec<basic_block> *&loop_blocks)
    6067              : {
    6068           38 :   unsigned int i;
    6069           38 :   int new_rgn_number = -1;
    6070           38 :   basic_block bb;
    6071              : 
    6072              :   /* Basic block index, to be assigned to BLOCK_TO_BB.  */
    6073           38 :   int bb_ord_index = 0;
    6074              : 
    6075           38 :   new_rgn_number = sel_create_new_region ();
    6076              : 
    6077          114 :   FOR_EACH_VEC_ELT (*loop_blocks, i, bb)
    6078              :     {
    6079           38 :       gcc_assert (new_rgn_number >= 0);
    6080              : 
    6081           38 :       sel_add_block_to_region (bb, &bb_ord_index, new_rgn_number);
    6082              :     }
    6083              : 
    6084           38 :   vec_free (loop_blocks);
    6085           38 : }
    6086              : 
    6087              : 
    6088              : /* Create region(s) from loop nest LOOP, such that inner loops will be
    6089              :    pipelined before outer loops.  Returns true when a region for LOOP
    6090              :    is created.  */
    6091              : static bool
    6092           59 : make_regions_from_loop_nest (class loop *loop)
    6093              : {
    6094           59 :   class loop *cur_loop;
    6095           59 :   int rgn_number;
    6096              : 
    6097              :   /* Traverse all inner nodes of the loop.  */
    6098           67 :   for (cur_loop = loop->inner; cur_loop; cur_loop = cur_loop->next)
    6099            8 :     if (! bitmap_bit_p (bbs_in_loop_rgns, cur_loop->header->index))
    6100              :       return false;
    6101              : 
    6102              :   /* At this moment all regular inner loops should have been pipelined.
    6103              :      Try to create a region from this loop.  */
    6104           59 :   rgn_number = make_region_from_loop (loop);
    6105              : 
    6106           59 :   if (rgn_number < 0)
    6107              :     return false;
    6108              : 
    6109           56 :   loop_nests.safe_push (loop);
    6110           56 :   return true;
    6111              : }
    6112              : 
    6113              : /* Initalize data structures needed.  */
    6114              : void
    6115           43 : sel_init_pipelining (void)
    6116              : {
    6117              :   /* Collect loop information to be used in outer loops pipelining.  */
    6118           43 :   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
    6119              :                        | LOOPS_HAVE_FALLTHRU_PREHEADERS
    6120              :                        | LOOPS_HAVE_RECORDED_EXITS
    6121              :                        | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
    6122           43 :   current_loop_nest = NULL;
    6123              : 
    6124           43 :   bbs_in_loop_rgns = sbitmap_alloc (last_basic_block_for_fn (cfun));
    6125           43 :   bitmap_clear (bbs_in_loop_rgns);
    6126              : 
    6127           43 :   recompute_rev_top_order ();
    6128           43 : }
    6129              : 
    6130              : /* Returns a class loop for region RGN.  */
    6131              : loop_p
    6132          387 : get_loop_nest_for_rgn (unsigned int rgn)
    6133              : {
    6134              :   /* Regions created with extend_rgns don't have corresponding loop nests,
    6135              :      because they don't represent loops.  */
    6136          387 :   if (rgn < loop_nests.length ())
    6137           56 :     return loop_nests[rgn];
    6138              :   else
    6139              :     return NULL;
    6140              : }
    6141              : 
    6142              : /* True when LOOP was included into pipelining regions.   */
    6143              : bool
    6144          968 : considered_for_pipelining_p (class loop *loop)
    6145              : {
    6146          968 :   if (loop_depth (loop) == 0)
    6147              :     return false;
    6148              : 
    6149              :   /* Now, the loop could be too large or irreducible.  Check whether its
    6150              :      region is in LOOP_NESTS.
    6151              :      We determine the region number of LOOP as the region number of its
    6152              :      latch.  We can't use header here, because this header could be
    6153              :      just removed preheader and it will give us the wrong region number.
    6154              :      Latch can't be used because it could be in the inner loop too.  */
    6155          211 :   if (LOOP_MARKED_FOR_PIPELINING_P (loop))
    6156              :     {
    6157          163 :       int rgn = CONTAINING_RGN (loop->latch->index);
    6158              : 
    6159          163 :       gcc_assert ((unsigned) rgn < loop_nests.length ());
    6160              :       return true;
    6161              :     }
    6162              : 
    6163              :   return false;
    6164              : }
    6165              : 
    6166              : /* Makes regions from the rest of the blocks, after loops are chosen
    6167              :    for pipelining.  */
    6168              : static void
    6169           43 : make_regions_from_the_rest (void)
    6170              : {
    6171           43 :   int cur_rgn_blocks;
    6172           43 :   int *loop_hdr;
    6173           43 :   int i;
    6174              : 
    6175           43 :   basic_block bb;
    6176           43 :   edge e;
    6177           43 :   edge_iterator ei;
    6178           43 :   int *degree;
    6179              : 
    6180              :   /* Index in rgn_bb_table where to start allocating new regions.  */
    6181           43 :   cur_rgn_blocks = nr_regions ? RGN_BLOCKS (nr_regions) : 0;
    6182              : 
    6183              :   /* Make regions from all the rest basic blocks - those that don't belong to
    6184              :      any loop or belong to irreducible loops.  Prepare the data structures
    6185              :      for extend_rgns.  */
    6186              : 
    6187              :   /* LOOP_HDR[I] == -1 if I-th bb doesn't belong to any loop,
    6188              :      LOOP_HDR[I] == LOOP_HDR[J] iff basic blocks I and J reside within the same
    6189              :      loop.  */
    6190           43 :   loop_hdr = XNEWVEC (int, last_basic_block_for_fn (cfun));
    6191           43 :   degree = XCNEWVEC (int, last_basic_block_for_fn (cfun));
    6192              : 
    6193              : 
    6194              :   /* For each basic block that belongs to some loop assign the number
    6195              :      of innermost loop it belongs to.  */
    6196          726 :   for (i = 0; i < last_basic_block_for_fn (cfun); i++)
    6197          640 :     loop_hdr[i] = -1;
    6198              : 
    6199          596 :   FOR_EACH_BB_FN (bb, cfun)
    6200              :     {
    6201          553 :       if (bb->loop_father && bb->loop_father->num != 0
    6202          309 :           && !(bb->flags & BB_IRREDUCIBLE_LOOP))
    6203          309 :         loop_hdr[bb->index] = bb->loop_father->num;
    6204              :     }
    6205              : 
    6206              :   /* For each basic block degree is calculated as the number of incoming
    6207              :      edges, that are going out of bbs that are not yet scheduled.
    6208              :      The basic blocks that are scheduled have degree value of zero.  */
    6209          596 :   FOR_EACH_BB_FN (bb, cfun)
    6210              :     {
    6211          553 :       degree[bb->index] = 0;
    6212              : 
    6213          553 :       if (!bitmap_bit_p (bbs_in_loop_rgns, bb->index))
    6214              :         {
    6215          697 :           FOR_EACH_EDGE (e, ei, bb->preds)
    6216          417 :             if (!bitmap_bit_p (bbs_in_loop_rgns, e->src->index))
    6217          323 :               degree[bb->index]++;
    6218              :         }
    6219              :       else
    6220          273 :         degree[bb->index] = -1;
    6221              :     }
    6222              : 
    6223           43 :   extend_rgns (degree, &cur_rgn_blocks, bbs_in_loop_rgns, loop_hdr);
    6224              : 
    6225              :   /* Any block that did not end up in a region is placed into a region
    6226              :      by itself.  */
    6227          596 :   FOR_EACH_BB_FN (bb, cfun)
    6228          553 :     if (degree[bb->index] >= 0)
    6229              :       {
    6230          280 :         rgn_bb_table[cur_rgn_blocks] = bb->index;
    6231          280 :         RGN_NR_BLOCKS (nr_regions) = 1;
    6232          280 :         RGN_BLOCKS (nr_regions) = cur_rgn_blocks++;
    6233          280 :         RGN_DONT_CALC_DEPS (nr_regions) = 0;
    6234          280 :         RGN_HAS_REAL_EBB (nr_regions) = 0;
    6235          280 :         CONTAINING_RGN (bb->index) = nr_regions++;
    6236          280 :         BLOCK_TO_BB (bb->index) = 0;
    6237              :       }
    6238              : 
    6239           43 :   free (degree);
    6240           43 :   free (loop_hdr);
    6241           43 : }
    6242              : 
    6243              : /* Free data structures used in pipelining of loops.  */
    6244           43 : void sel_finish_pipelining (void)
    6245              : {
    6246              :   /* Release aux fields so we don't free them later by mistake.  */
    6247          194 :   for (auto loop : loops_list (cfun, 0))
    6248           65 :     loop->aux = NULL;
    6249              : 
    6250           43 :   loop_optimizer_finalize ();
    6251              : 
    6252           43 :   loop_nests.release ();
    6253              : 
    6254           43 :   free (rev_top_order_index);
    6255           43 :   rev_top_order_index = NULL;
    6256           43 : }
    6257              : 
    6258              : /* This function replaces the find_rgns when
    6259              :    FLAG_SEL_SCHED_PIPELINING_OUTER_LOOPS is set.  */
    6260              : void
    6261           43 : sel_find_rgns (void)
    6262              : {
    6263           43 :   sel_init_pipelining ();
    6264           43 :   extend_regions ();
    6265              : 
    6266           43 :   if (current_loops)
    6267              :     {
    6268           36 :       unsigned flags = flag_sel_sched_pipelining_outer_loops
    6269           43 :                          ? LI_FROM_INNERMOST
    6270              :                          : LI_ONLY_INNERMOST;
    6271              : 
    6272          188 :       for (auto loop : loops_list (cfun, flags))
    6273          102 :         make_regions_from_loop_nest (loop);
    6274              :     }
    6275              : 
    6276              :   /* Make regions from all the rest basic blocks and schedule them.
    6277              :      These blocks include blocks that don't belong to any loop or belong
    6278              :      to irreducible loops.  */
    6279           43 :   make_regions_from_the_rest ();
    6280              : 
    6281              :   /* We don't need bbs_in_loop_rgns anymore.  */
    6282           43 :   sbitmap_free (bbs_in_loop_rgns);
    6283           43 :   bbs_in_loop_rgns = NULL;
    6284           43 : }
    6285              : 
    6286              : /* Add the preheader blocks from previous loop to current region taking
    6287              :    it from LOOP_PREHEADER_BLOCKS (current_loop_nest) and record them in *BBS.
    6288              :    This function is only used with -fsel-sched-pipelining-outer-loops.  */
    6289              : void
    6290           56 : sel_add_loop_preheaders (bb_vec_t *bbs)
    6291              : {
    6292           56 :   int i;
    6293           56 :   basic_block bb;
    6294          112 :   vec<basic_block> *preheader_blocks
    6295           56 :     = LOOP_PREHEADER_BLOCKS (current_loop_nest);
    6296              : 
    6297           56 :   if (!preheader_blocks)
    6298           50 :     return;
    6299              : 
    6300           13 :   for (i = 0; preheader_blocks->iterate (i, &bb); i++)
    6301              :     {
    6302            7 :       bbs->safe_push (bb);
    6303            7 :       last_added_blocks.safe_push (bb);
    6304            7 :       sel_add_bb (bb);
    6305              :     }
    6306              : 
    6307            6 :   vec_free (preheader_blocks);
    6308              : }
    6309              : 
    6310              : /* While pipelining outer loops, returns TRUE if BB is a loop preheader.
    6311              :    Please note that the function should also work when pipelining_p is
    6312              :    false, because it is used when deciding whether we should or should
    6313              :    not reschedule pipelined code.  */
    6314              : bool
    6315         1347 : sel_is_loop_preheader_p (basic_block bb)
    6316              : {
    6317         1347 :   if (current_loop_nest)
    6318              :     {
    6319          843 :       class loop *outer;
    6320              : 
    6321          843 :       if (preheader_removed)
    6322              :         return false;
    6323              : 
    6324              :       /* Preheader is the first block in the region.  */
    6325          843 :       if (BLOCK_TO_BB (bb->index) == 0)
    6326              :         return true;
    6327              : 
    6328              :       /* We used to find a preheader with the topological information.
    6329              :          Check that the above code is equivalent to what we did before.  */
    6330              : 
    6331          606 :       if (in_current_region_p (current_loop_nest->header))
    6332          606 :         gcc_assert (!(BLOCK_TO_BB (bb->index)
    6333              :                       < BLOCK_TO_BB (current_loop_nest->header->index)));
    6334              : 
    6335              :       /* Support the situation when the latch block of outer loop
    6336              :          could be from here.  */
    6337          606 :       for (outer = loop_outer (current_loop_nest);
    6338         1304 :            outer;
    6339          698 :            outer = loop_outer (outer))
    6340          698 :         if (considered_for_pipelining_p (outer) && outer->latch == bb)
    6341            0 :           gcc_unreachable ();
    6342              :     }
    6343              : 
    6344              :   return false;
    6345              : }
    6346              : 
    6347              : /* Check whether JUMP_BB ends with a jump insn that leads only to DEST_BB and
    6348              :    can be removed, making the corresponding edge fallthrough (assuming that
    6349              :    all basic blocks between JUMP_BB and DEST_BB are empty).  */
    6350              : static bool
    6351         2934 : bb_has_removable_jump_to_p (basic_block jump_bb, basic_block dest_bb)
    6352              : {
    6353         2934 :   if (!onlyjump_p (BB_END (jump_bb))
    6354         2934 :       || tablejump_p (BB_END (jump_bb), NULL, NULL))
    6355          878 :     return false;
    6356              : 
    6357              :   /* Several outgoing edges, abnormal edge or destination of jump is
    6358              :      not DEST_BB.  */
    6359         4971 :   if (EDGE_COUNT (jump_bb->succs) != 1
    6360          453 :       || EDGE_SUCC (jump_bb, 0)->flags & (EDGE_ABNORMAL | EDGE_CROSSING)
    6361         2503 :       || EDGE_SUCC (jump_bb, 0)->dest != dest_bb)
    6362              :     return false;
    6363              : 
    6364              :   /* If not anything of the upper.  */
    6365              :   return true;
    6366              : }
    6367              : 
    6368              : /* Removes the loop preheader from the current region and saves it in
    6369              :    PREHEADER_BLOCKS of the father loop, so they will be added later to
    6370              :    region that represents an outer loop.  */
    6371              : static void
    6372           56 : sel_remove_loop_preheader (void)
    6373              : {
    6374           56 :   int i, old_len;
    6375           56 :   int cur_rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
    6376           56 :   basic_block bb;
    6377           56 :   bool all_empty_p = true;
    6378           56 :   vec<basic_block> *preheader_blocks
    6379           56 :     = LOOP_PREHEADER_BLOCKS (loop_outer (current_loop_nest));
    6380              : 
    6381           56 :   vec_check_alloc (preheader_blocks, 0);
    6382              : 
    6383           56 :   gcc_assert (current_loop_nest);
    6384           56 :   old_len = preheader_blocks->length ();
    6385              : 
    6386              :   /* Add blocks that aren't within the current loop to PREHEADER_BLOCKS.  */
    6387          340 :   for (i = 0; i < RGN_NR_BLOCKS (cur_rgn); i++)
    6388              :     {
    6389          284 :       bb = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i));
    6390              : 
    6391              :       /* If the basic block belongs to region, but doesn't belong to
    6392              :          corresponding loop, then it should be a preheader.  */
    6393          284 :       if (sel_is_loop_preheader_p (bb))
    6394              :         {
    6395           56 :           preheader_blocks->safe_push (bb);
    6396           56 :           if (BB_END (bb) != bb_note (bb))
    6397          284 :             all_empty_p = false;
    6398              :         }
    6399              :     }
    6400              : 
    6401              :   /* Remove these blocks only after iterating over the whole region.  */
    6402          168 :   for (i = preheader_blocks->length () - 1; i >= old_len; i--)
    6403              :     {
    6404           56 :       bb =  (*preheader_blocks)[i];
    6405           56 :       sel_remove_bb (bb, false);
    6406              :     }
    6407              : 
    6408           56 :   if (!considered_for_pipelining_p (loop_outer (current_loop_nest)))
    6409              :     {
    6410           49 :       if (!all_empty_p)
    6411              :         /* Immediately create new region from preheader.  */
    6412           38 :         make_region_from_loop_preheader (preheader_blocks);
    6413              :       else
    6414              :         {
    6415              :           /* If all preheader blocks are empty - dont create new empty region.
    6416              :              Instead, remove them completely.  */
    6417           22 :           FOR_EACH_VEC_ELT (*preheader_blocks, i, bb)
    6418              :             {
    6419           11 :               edge e;
    6420           11 :               edge_iterator ei;
    6421           11 :               basic_block prev_bb = bb->prev_bb, next_bb = bb->next_bb;
    6422              : 
    6423              :               /* Redirect all incoming edges to next basic block.  */
    6424           23 :               for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
    6425              :                 {
    6426           12 :                   if (! (e->flags & EDGE_FALLTHRU))
    6427            9 :                     redirect_edge_and_branch (e, bb->next_bb);
    6428              :                   else
    6429            3 :                     redirect_edge_succ (e, bb->next_bb);
    6430              :                 }
    6431           11 :               gcc_assert (BB_NOTE_LIST (bb) == NULL);
    6432           11 :               delete_and_free_basic_block (bb);
    6433              : 
    6434              :               /* Check if after deleting preheader there is a nonconditional
    6435              :                  jump in PREV_BB that leads to the next basic block NEXT_BB.
    6436              :                  If it is so - delete this jump and clear data sets of its
    6437              :                  basic block if it becomes empty.  */
    6438           11 :               if (next_bb->prev_bb == prev_bb
    6439           11 :                   && prev_bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
    6440           22 :                   && bb_has_removable_jump_to_p (prev_bb, next_bb))
    6441              :                 {
    6442            5 :                   redirect_edge_and_branch (EDGE_SUCC (prev_bb, 0), next_bb);
    6443            5 :                   if (BB_END (prev_bb) == bb_note (prev_bb))
    6444            0 :                     free_data_sets (prev_bb);
    6445              :                 }
    6446              : 
    6447           11 :               set_immediate_dominator (CDI_DOMINATORS, next_bb,
    6448              :                                        recompute_dominator (CDI_DOMINATORS,
    6449              :                                                             next_bb));
    6450              :             }
    6451              :         }
    6452           49 :       vec_free (preheader_blocks);
    6453              :     }
    6454              :   else
    6455              :     /* Store preheader within the father's loop structure.  */
    6456            7 :     SET_LOOP_PREHEADER_BLOCKS (loop_outer (current_loop_nest),
    6457              :                                preheader_blocks);
    6458           56 : }
    6459              : 
    6460              : #endif
        

Generated by: LCOV version 2.4-beta

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