LCOV - code coverage report
Current view: top level - gcc - reorg.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 1.0 % 1538 16
Test Date: 2026-09-19 16:22:48 Functions: 9.8 % 51 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Perform instruction reorganizations for delay slot filling.
       2              :    Copyright (C) 1992-2026 Free Software Foundation, Inc.
       3              :    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
       4              :    Hacked by Michael Tiemann (tiemann@cygnus.com).
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it under
       9              : the terms of the GNU General Public License as published by the Free
      10              : Software Foundation; either version 3, or (at your option) any later
      11              : version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : /* Instruction reorganization pass.
      23              : 
      24              :    This pass runs after register allocation and final jump
      25              :    optimization.  It should be the last pass to run before peephole.
      26              :    It serves primarily to fill delay slots of insns, typically branch
      27              :    and call insns.  Other insns typically involve more complicated
      28              :    interactions of data dependencies and resource constraints, and
      29              :    are better handled by scheduling before register allocation (by the
      30              :    function `schedule_insns').
      31              : 
      32              :    The Branch Penalty is the number of extra cycles that are needed to
      33              :    execute a branch insn.  On an ideal machine, branches take a single
      34              :    cycle, and the Branch Penalty is 0.  Several RISC machines approach
      35              :    branch delays differently:
      36              : 
      37              :    The MIPS has a single branch delay slot.  Most insns
      38              :    (except other branches) can be used to fill this slot.  When the
      39              :    slot is filled, two insns execute in two cycles, reducing the
      40              :    branch penalty to zero.
      41              : 
      42              :    The SPARC always has a branch delay slot, but its effects can be
      43              :    annulled when the branch is not taken.  This means that failing to
      44              :    find other sources of insns, we can hoist an insn from the branch
      45              :    target that would only be safe to execute knowing that the branch
      46              :    is taken.
      47              : 
      48              :    The HP-PA always has a branch delay slot.  For unconditional branches
      49              :    its effects can be annulled when the branch is taken.  The effects
      50              :    of the delay slot in a conditional branch can be nullified for forward
      51              :    taken branches, or for untaken backward branches.  This means
      52              :    we can hoist insns from the fall-through path for forward branches or
      53              :    steal insns from the target of backward branches.
      54              : 
      55              :    The TMS320C3x and C4x have three branch delay slots.  When the three
      56              :    slots are filled, the branch penalty is zero.  Most insns can fill the
      57              :    delay slots except jump insns.
      58              : 
      59              :    Three techniques for filling delay slots have been implemented so far:
      60              : 
      61              :    (1) `fill_simple_delay_slots' is the simplest, most efficient way
      62              :    to fill delay slots.  This pass first looks for insns which come
      63              :    from before the branch and which are safe to execute after the
      64              :    branch.  Then it searches after the insn requiring delay slots or,
      65              :    in the case of a branch, for insns that are after the point at
      66              :    which the branch merges into the fallthrough code, if such a point
      67              :    exists.  When such insns are found, the branch penalty decreases
      68              :    and no code expansion takes place.
      69              : 
      70              :    (2) `fill_eager_delay_slots' is more complicated: it is used for
      71              :    scheduling conditional jumps, or for scheduling jumps which cannot
      72              :    be filled using (1).  A machine need not have annulled jumps to use
      73              :    this strategy, but it helps (by keeping more options open).
      74              :    `fill_eager_delay_slots' tries to guess the direction the branch
      75              :    will go; if it guesses right 100% of the time, it can reduce the
      76              :    branch penalty as much as `fill_simple_delay_slots' does.  If it
      77              :    guesses wrong 100% of the time, it might as well schedule nops.  When
      78              :    `fill_eager_delay_slots' takes insns from the fall-through path of
      79              :    the jump, usually there is no code expansion; when it takes insns
      80              :    from the branch target, there is code expansion if it is not the
      81              :    only way to reach that target.
      82              : 
      83              :    (3) `relax_delay_slots' uses a set of rules to simplify code that
      84              :    has been reorganized by (1) and (2).  It finds cases where
      85              :    conditional test can be eliminated, jumps can be threaded, extra
      86              :    insns can be eliminated, etc.  It is the job of (1) and (2) to do a
      87              :    good job of scheduling locally; `relax_delay_slots' takes care of
      88              :    making the various individual schedules work well together.  It is
      89              :    especially tuned to handle the control flow interactions of branch
      90              :    insns.  It does nothing for insns with delay slots that do not
      91              :    branch.  */
      92              : 
      93              : #include "config.h"
      94              : #include "system.h"
      95              : #include "coretypes.h"
      96              : #include "backend.h"
      97              : #include "target.h"
      98              : #include "rtl.h"
      99              : #include "tree.h"
     100              : #include "predict.h"
     101              : #include "memmodel.h"
     102              : #include "tm_p.h"
     103              : #include "expmed.h"
     104              : #include "insn-config.h"
     105              : #include "emit-rtl.h"
     106              : #include "recog.h"
     107              : #include "insn-attr.h"
     108              : #include "resource.h"
     109              : #include "tree-pass.h"
     110              : 
     111              : 
     112              : /* First, some functions that were used before GCC got a control flow graph.
     113              :    These functions are now only used here in reorg.cc, and have therefore
     114              :    been moved here to avoid inadvertent misuse elsewhere in the compiler.  */
     115              : 
     116              : /* Return the last label to mark the same position as LABEL.  Return LABEL
     117              :    itself if it is null or any return rtx.  */
     118              : 
     119              : static rtx
     120            0 : skip_consecutive_labels (rtx label_or_return)
     121              : {
     122            0 :   rtx_insn *insn;
     123              : 
     124            0 :   if (label_or_return && ANY_RETURN_P (label_or_return))
     125              :     return label_or_return;
     126              : 
     127            0 :   rtx_insn *label = as_a <rtx_insn *> (label_or_return);
     128              : 
     129              :   /* __builtin_unreachable can create a CODE_LABEL followed by a BARRIER.
     130              : 
     131              :      Since reaching the CODE_LABEL is undefined behavior, we can return
     132              :      any code label and we're OK at run time.
     133              : 
     134              :      However, if we return a CODE_LABEL which leads to a shrink-wrapped
     135              :      epilogue, but the path does not have a prologue, then we will trip
     136              :      a sanity check in the dwarf2 cfi code which wants to verify that
     137              :      the CFIs are all the same on the traces leading to the epilogue.
     138              : 
     139              :      So we explicitly disallow looking through BARRIERS here.  */
     140            0 :   for (insn = label;
     141            0 :        insn != 0 && !INSN_P (insn) && !BARRIER_P (insn);
     142            0 :        insn = NEXT_INSN (insn))
     143            0 :     if (LABEL_P (insn))
     144            0 :       label = insn;
     145              : 
     146              :   return label;
     147              : }
     148              : 
     149              : /* Insns which have delay slots that have not yet been filled.  */
     150              : 
     151              : static struct obstack unfilled_slots_obstack;
     152              : static rtx *unfilled_firstobj;
     153              : 
     154              : /* Define macros to refer to the first and last slot containing unfilled
     155              :    insns.  These are used because the list may move and its address
     156              :    should be recomputed at each use.  */
     157              : 
     158              : #define unfilled_slots_base     \
     159              :   ((rtx_insn **) obstack_base (&unfilled_slots_obstack))
     160              : 
     161              : #define unfilled_slots_next     \
     162              :   ((rtx_insn **) obstack_next_free (&unfilled_slots_obstack))
     163              : 
     164              : /* Points to the label before the end of the function, or before a
     165              :    return insn.  */
     166              : static rtx_code_label *function_return_label;
     167              : /* Likewise for a simple_return.  */
     168              : static rtx_code_label *function_simple_return_label;
     169              : 
     170              : /* Mapping between INSN_UID's and position in the code since INSN_UID's do
     171              :    not always monotonically increase.  */
     172              : static int *uid_to_ruid;
     173              : 
     174              : /* Highest valid index in `uid_to_ruid'.  */
     175              : static int max_uid;
     176              : 
     177              : static bool stop_search_p (rtx_insn *, bool);
     178              : static bool resource_conflicts_p (struct resources *, struct resources *);
     179              : static bool insn_references_resource_p (rtx, struct resources *, bool);
     180              : static bool insn_sets_resource_p (rtx, struct resources *, bool);
     181              : static rtx_code_label *find_end_label (rtx);
     182              : static rtx_insn *emit_delay_sequence (rtx_insn *, const vec<rtx_insn *> &,
     183              :                                       int);
     184              : static void add_to_delay_list (rtx_insn *, vec<rtx_insn *> *);
     185              : static rtx_insn *delete_from_delay_slot (rtx_insn *);
     186              : static void delete_scheduled_jump (rtx_insn *);
     187              : static void note_delay_statistics (int, int);
     188              : static int get_jump_flags (const rtx_insn *, rtx);
     189              : static int mostly_true_jump (rtx);
     190              : static rtx get_branch_condition (const rtx_insn *, rtx);
     191              : static bool condition_dominates_p (rtx, const rtx_insn *);
     192              : static bool redirect_with_delay_slots_safe_p (rtx_insn *, rtx, rtx);
     193              : static bool redirect_with_delay_list_safe_p (rtx_insn *, rtx,
     194              :                                              const vec<rtx_insn *> &);
     195              : static bool check_annul_list_true_false (bool, const vec<rtx_insn *> &);
     196              : static void steal_delay_list_from_target (rtx_insn *, rtx, rtx_sequence *,
     197              :                                           vec<rtx_insn *> *,
     198              :                                           struct resources *,
     199              :                                           struct resources *,
     200              :                                           struct resources *,
     201              :                                           int, int *, bool *,
     202              :                                           rtx *);
     203              : static void steal_delay_list_from_fallthrough (rtx_insn *, rtx, rtx_sequence *,
     204              :                                                vec<rtx_insn *> *,
     205              :                                                struct resources *,
     206              :                                                struct resources *,
     207              :                                                struct resources *,
     208              :                                                int, int *, bool *);
     209              : static void try_merge_delay_insns (rtx_insn *, rtx_insn *);
     210              : static rtx_insn *redundant_insn (rtx, rtx_insn *, const vec<rtx_insn *> &);
     211              : static bool own_thread_p (rtx, rtx, bool);
     212              : static void update_block (rtx_insn *, rtx_insn *);
     213              : static bool reorg_redirect_jump (rtx_jump_insn *, rtx);
     214              : static void update_reg_dead_notes (rtx_insn *, rtx_insn *);
     215              : static void fix_reg_dead_note (rtx_insn *, rtx);
     216              : static void update_reg_unused_notes (rtx_insn *, rtx);
     217              : static void fill_simple_delay_slots (bool);
     218              : static void fill_slots_from_thread (rtx_jump_insn *, rtx, rtx, rtx,
     219              :                                     bool, bool, bool, int,
     220              :                                     int *, vec<rtx_insn *> *);
     221              : static void fill_eager_delay_slots (void);
     222              : static void relax_delay_slots (rtx_insn *);
     223              : static void make_return_insns (rtx_insn *);
     224              : 
     225              : /* A wrapper around next_active_insn which takes care to return ret_rtx
     226              :    unchanged.  */
     227              : 
     228              : static rtx
     229            0 : first_active_target_insn (rtx insn)
     230              : {
     231            0 :   if (ANY_RETURN_P (insn))
     232              :     return insn;
     233            0 :   return next_active_insn (as_a <rtx_insn *> (insn));
     234              : }
     235              : 
     236              : /* Return true iff INSN is a simplejump, or any kind of return insn.  */
     237              : 
     238              : static bool
     239            0 : simplejump_or_return_p (rtx insn)
     240              : {
     241            0 :   return (JUMP_P (insn)
     242            0 :           && (simplejump_p (as_a <rtx_insn *> (insn))
     243            0 :               || ANY_RETURN_P (PATTERN (insn))));
     244              : }
     245              : 
     246              : /* Return TRUE if this insn should stop the search for insn to fill delay
     247              :    slots.  LABELS_P indicates that labels should terminate the search.
     248              :    In all cases, jumps terminate the search.  */
     249              : 
     250              : static bool
     251            0 : stop_search_p (rtx_insn *insn, bool labels_p)
     252              : {
     253            0 :   if (insn == 0)
     254              :     return true;
     255              : 
     256              :   /* If the insn can throw an exception that is caught within the function,
     257              :      it may effectively perform a jump from the viewpoint of the function.
     258              :      Therefore act like for a jump.  */
     259            0 :   if (can_throw_internal (insn))
     260              :     return true;
     261              : 
     262            0 :   switch (GET_CODE (insn))
     263              :     {
     264              :     case NOTE:
     265              :     case CALL_INSN:
     266              :     case DEBUG_INSN:
     267              :       return false;
     268              : 
     269              :     case CODE_LABEL:
     270              :       return labels_p;
     271              : 
     272              :     case JUMP_INSN:
     273              :     case BARRIER:
     274              :       return true;
     275              : 
     276            0 :     case INSN:
     277              :       /* OK unless it contains a delay slot or is an `asm' insn of some type.
     278              :          We don't know anything about these.  */
     279            0 :       return (GET_CODE (PATTERN (insn)) == SEQUENCE
     280            0 :               || GET_CODE (PATTERN (insn)) == ASM_INPUT
     281            0 :               || asm_noperands (PATTERN (insn)) >= 0);
     282              : 
     283            0 :     default:
     284            0 :       gcc_unreachable ();
     285              :     }
     286              : }
     287              : 
     288              : /* Return TRUE if any resources are marked in both RES1 and RES2 or if either
     289              :    resource set contains a volatile memory reference.  Otherwise, return FALSE.  */
     290              : 
     291              : static bool
     292            0 : resource_conflicts_p (struct resources *res1, struct resources *res2)
     293              : {
     294            0 :   if ((res1->cc && res2->cc) || (res1->memory && res2->memory)
     295            0 :       || res1->volatil || res2->volatil)
     296              :     return true;
     297              : 
     298            0 :   return hard_reg_set_intersect_p (res1->regs, res2->regs);
     299              : }
     300              : 
     301              : /* Return TRUE if any resource marked in RES, a `struct resources', is
     302              :    referenced by INSN.  If INCLUDE_DELAYED_EFFECTS is set, return if the called
     303              :    routine is using those resources.
     304              : 
     305              :    We compute this by computing all the resources referenced by INSN and
     306              :    seeing if this conflicts with RES.  It might be faster to directly check
     307              :    ourselves, and this is the way it used to work, but it means duplicating
     308              :    a large block of complex code.  */
     309              : 
     310              : static bool
     311            0 : insn_references_resource_p (rtx insn, struct resources *res,
     312              :                             bool include_delayed_effects)
     313              : {
     314            0 :   struct resources insn_res;
     315              : 
     316            0 :   CLEAR_RESOURCE (&insn_res);
     317            0 :   mark_referenced_resources (insn, &insn_res, include_delayed_effects);
     318            0 :   return resource_conflicts_p (&insn_res, res);
     319              : }
     320              : 
     321              : /* Return TRUE if INSN modifies resources that are marked in RES.
     322              :    INCLUDE_DELAYED_EFFECTS is set if the actions of that routine should be
     323              :    included.   */
     324              : 
     325              : static bool
     326            0 : insn_sets_resource_p (rtx insn, struct resources *res,
     327              :                       bool include_delayed_effects)
     328              : {
     329            0 :   struct resources insn_sets;
     330              : 
     331            0 :   CLEAR_RESOURCE (&insn_sets);
     332            0 :   mark_set_resources (insn, &insn_sets, 0,
     333              :                       (include_delayed_effects
     334              :                        ? MARK_SRC_DEST_CALL
     335              :                        : MARK_SRC_DEST));
     336            0 :   return resource_conflicts_p (&insn_sets, res);
     337              : }
     338              : 
     339              : /* Find a label before a RETURN.  If there is none, try to make one; if this
     340              :    fails, return 0.  KIND is either ret_rtx or simple_return_rtx, indicating
     341              :    which type of RETURN we're looking for.
     342              : 
     343              :    The property of the label is that it is placed just before a bare RETURN
     344              :    insn, so that another bare RETURN can be turned into a jump to the label
     345              :    unconditionally.  In particular, the label cannot be placed before a
     346              :    RETURN insn with a filled delay slot.
     347              : 
     348              :    ??? There may be a problem with the current implementation.  Suppose
     349              :    we start with a bare RETURN insn and call find_end_label.  It may set
     350              :    function_return_label just before the RETURN.  Suppose the machinery
     351              :    is able to fill the delay slot of the RETURN insn afterwards.  Then
     352              :    function_return_label is no longer valid according to the property
     353              :    described above and find_end_label will still return it unmodified.
     354              :    Note that this is probably mitigated by the following observation:
     355              :    once function_return_label is made, it is very likely the target of
     356              :    a jump, so filling the delay slot of the RETURN will be much more
     357              :    difficult.  */
     358              : 
     359              : static rtx_code_label *
     360            0 : find_end_label (rtx kind)
     361              : {
     362            0 :   rtx_insn *insn;
     363            0 :   rtx_code_label **plabel;
     364              : 
     365            0 :   if (kind == ret_rtx)
     366            0 :     plabel = &function_return_label;
     367              :   else
     368              :     {
     369            0 :       gcc_assert (kind == simple_return_rtx);
     370            0 :       plabel = &function_simple_return_label;
     371              :     }
     372              : 
     373              :   /* If we found one previously, return it.  */
     374            0 :   if (*plabel)
     375              :     return *plabel;
     376              : 
     377              :   /* Otherwise, scan the insns backward from the end of the function.  */
     378            0 :   insn = get_last_insn ();
     379            0 :   while (NOTE_P (insn)
     380            0 :          || (NONJUMP_INSN_P (insn)
     381            0 :              && (GET_CODE (PATTERN (insn)) == USE
     382            0 :                  || GET_CODE (PATTERN (insn)) == CLOBBER)))
     383            0 :     insn = PREV_INSN (insn);
     384              : 
     385              :   /* First, see if there is a RETURN at the end of the function.  If so,
     386              :      put the label before it.  */
     387            0 :   if (BARRIER_P (insn)
     388            0 :       && JUMP_P (PREV_INSN (insn))
     389            0 :       && PATTERN (PREV_INSN (insn)) == kind)
     390              :     {
     391            0 :       rtx_insn *temp = PREV_INSN (PREV_INSN (insn));
     392            0 :       rtx_code_label *label = gen_label_rtx ();
     393            0 :       LABEL_NUSES (label) = 0;
     394              : 
     395              :       /* Put the label before any USE insns that may precede the
     396              :          RETURN insn.  */
     397            0 :       while (GET_CODE (temp) == USE)
     398            0 :         temp = PREV_INSN (temp);
     399              : 
     400            0 :       emit_label_after (label, temp);
     401            0 :       *plabel = label;
     402              :     }
     403              : 
     404              :   /* If the basic block reordering pass has moved the return insn to some
     405              :      other place, try to locate it again and put the label there.  */
     406              :   else
     407              :     {
     408            0 :       rtx_code_label *label = gen_label_rtx ();
     409            0 :       LABEL_NUSES (label) = 0;
     410            0 :       while (insn && ! (JUMP_P (insn) && (PATTERN (insn) == kind)))
     411            0 :         insn = PREV_INSN (insn);
     412            0 :       if (insn)
     413              :         {
     414            0 :           insn = PREV_INSN (insn);
     415              : 
     416              :           /* Put the label before any USE insns that may precede the
     417              :              RETURN insn.  */
     418            0 :           while (GET_CODE (insn) == USE)
     419            0 :             insn = PREV_INSN (insn);
     420              : 
     421            0 :           emit_label_after (label, insn);
     422              :         }
     423              :       else
     424              :         {
     425            0 :           if (targetm.have_epilogue () && ! targetm.have_return ())
     426              :             /* The RETURN insn has its delay slot filled so we cannot
     427              :                emit the label just before it.  Since we already have
     428              :                an epilogue and cannot emit a new RETURN, we cannot
     429              :                emit the label at all.  */
     430              :             return NULL;
     431              : 
     432              :           /* Otherwise, make a new label and emit a RETURN and BARRIER,
     433              :              if needed.  */
     434            0 :           emit_label (label);
     435            0 :           if (targetm.have_return ())
     436              :             {
     437              :               /* The return we make may have delay slots too.  */
     438            0 :               rtx_insn *pat = targetm.gen_return ();
     439            0 :               rtx_insn *insn = emit_jump_insn (pat);
     440            0 :               set_return_jump_label (insn);
     441            0 :               emit_barrier ();
     442            0 :               if (num_delay_slots (insn) > 0)
     443            0 :                 obstack_ptr_grow (&unfilled_slots_obstack, insn);
     444              :             }
     445              :         }
     446            0 :       *plabel = label;
     447              :     }
     448              : 
     449              :   /* Show one additional use for this label so it won't go away until
     450              :      we are done.  */
     451            0 :   ++LABEL_NUSES (*plabel);
     452              : 
     453            0 :   return *plabel;
     454              : }
     455              : 
     456              : /* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace
     457              :    the pattern of INSN with the SEQUENCE.
     458              : 
     459              :    Returns the insn containing the SEQUENCE that replaces INSN.  */
     460              : 
     461              : static rtx_insn *
     462            0 : emit_delay_sequence (rtx_insn *insn, const vec<rtx_insn *> &list, int length)
     463              : {
     464              :   /* Allocate the rtvec to hold the insns and the SEQUENCE.  */
     465            0 :   rtvec seqv = rtvec_alloc (length + 1);
     466            0 :   rtx seq = gen_rtx_SEQUENCE (VOIDmode, seqv);
     467            0 :   rtx_insn *seq_insn = make_insn_raw (seq);
     468              : 
     469              :   /* If DELAY_INSN has a location, use it for SEQ_INSN.  If DELAY_INSN does
     470              :      not have a location, but one of the delayed insns does, we pick up a
     471              :      location from there later.  */
     472            0 :   INSN_LOCATION (seq_insn) = INSN_LOCATION (insn);
     473              : 
     474              :   /* Unlink INSN from the insn chain, so that we can put it into
     475              :      the SEQUENCE.   Remember where we want to emit SEQUENCE in AFTER.  */
     476            0 :   rtx_insn *after = PREV_INSN (insn);
     477            0 :   remove_insn (insn);
     478            0 :   SET_NEXT_INSN (insn) = SET_PREV_INSN (insn) = NULL;
     479              : 
     480              :   /* Build our SEQUENCE and rebuild the insn chain.  */
     481            0 :   start_sequence ();
     482            0 :   XVECEXP (seq, 0, 0) = emit_insn (insn);
     483              : 
     484            0 :   unsigned int delay_insns = list.length ();
     485            0 :   gcc_assert (delay_insns == (unsigned int) length);
     486            0 :   for (unsigned int i = 0; i < delay_insns; i++)
     487              :     {
     488            0 :       rtx_insn *tem = list[i];
     489            0 :       rtx note, next;
     490              : 
     491              :       /* Show that this copy of the insn isn't deleted.  */
     492            0 :       tem->set_undeleted ();
     493              : 
     494              :       /* Unlink insn from its original place, and re-emit it into
     495              :          the sequence.  */
     496            0 :       SET_NEXT_INSN (tem) = SET_PREV_INSN (tem) = NULL;
     497            0 :       XVECEXP (seq, 0, i + 1) = emit_insn (tem);
     498              : 
     499              :       /* SPARC assembler, for instance, emit warning when debug info is output
     500              :          into the delay slot.  */
     501            0 :       if (INSN_LOCATION (tem) && !INSN_LOCATION (seq_insn))
     502            0 :         INSN_LOCATION (seq_insn) = INSN_LOCATION (tem);
     503            0 :       INSN_LOCATION (tem) = 0;
     504              : 
     505            0 :       for (note = REG_NOTES (tem); note; note = next)
     506              :         {
     507            0 :           next = XEXP (note, 1);
     508            0 :           switch (REG_NOTE_KIND (note))
     509              :             {
     510            0 :             case REG_DEAD:
     511              :               /* Remove any REG_DEAD notes because we can't rely on them now
     512              :                  that the insn has been moved.  */
     513            0 :               remove_note (tem, note);
     514            0 :               break;
     515              : 
     516            0 :             case REG_LABEL_OPERAND:
     517            0 :             case REG_LABEL_TARGET:
     518              :               /* Keep the label reference count up to date.  */
     519            0 :               if (LABEL_P (XEXP (note, 0)))
     520            0 :                 LABEL_NUSES (XEXP (note, 0)) ++;
     521              :               break;
     522              : 
     523              :             default:
     524              :               break;
     525              :             }
     526              :         }
     527              :     }
     528            0 :   end_sequence ();
     529              : 
     530              :   /* Splice our SEQUENCE into the insn stream where INSN used to be.  */
     531            0 :   add_insn_after (seq_insn, after, NULL);
     532              : 
     533            0 :   return seq_insn;
     534              : }
     535              : 
     536              : /* Add INSN to DELAY_LIST and return the head of the new list.  The list must
     537              :    be in the order in which the insns are to be executed.  */
     538              : 
     539              : static void
     540            0 : add_to_delay_list (rtx_insn *insn, vec<rtx_insn *> *delay_list)
     541              : {
     542              :   /* If INSN has its block number recorded, clear it since we may
     543              :      be moving the insn to a new block.  */
     544            0 :   clear_hashed_info_for_insn (insn);
     545              : 
     546            0 :   delay_list->safe_push (insn);
     547            0 : }
     548              : 
     549              : /* Delete INSN from the delay slot of the insn that it is in, which may
     550              :    produce an insn with no delay slots.  Return the new insn.  */
     551              : 
     552              : static rtx_insn *
     553            0 : delete_from_delay_slot (rtx_insn *insn)
     554              : {
     555            0 :   rtx_insn *trial, *seq_insn, *prev;
     556            0 :   rtx_sequence *seq;
     557            0 :   bool had_barrier = false;
     558            0 :   int i;
     559              : 
     560              :   /* We first must find the insn containing the SEQUENCE with INSN in its
     561              :      delay slot.  Do this by finding an insn, TRIAL, where
     562              :      PREV_INSN (NEXT_INSN (TRIAL)) != TRIAL.  */
     563              : 
     564            0 :   for (trial = insn;
     565            0 :        PREV_INSN (NEXT_INSN (trial)) == trial;
     566              :        trial = NEXT_INSN (trial))
     567              :     ;
     568              : 
     569            0 :   seq_insn = PREV_INSN (NEXT_INSN (trial));
     570            0 :   seq = as_a <rtx_sequence *> (PATTERN (seq_insn));
     571              : 
     572            0 :   if (NEXT_INSN (seq_insn) && BARRIER_P (NEXT_INSN (seq_insn)))
     573              :     had_barrier = true;
     574              : 
     575              :   /* Create a delay list consisting of all the insns other than the one
     576              :      we are deleting (unless we were the only one).  */
     577            0 :   auto_vec<rtx_insn *, 5> delay_list;
     578            0 :   if (seq->len () > 2)
     579            0 :     for (i = 1; i < seq->len (); i++)
     580            0 :       if (seq->insn (i) != insn)
     581            0 :         add_to_delay_list (seq->insn (i), &delay_list);
     582              : 
     583              :   /* Delete the old SEQUENCE, re-emit the insn that used to have the delay
     584              :      list, and rebuild the delay list if non-empty.  */
     585            0 :   prev = PREV_INSN (seq_insn);
     586            0 :   trial = seq->insn (0);
     587            0 :   delete_related_insns (seq_insn);
     588            0 :   add_insn_after (trial, prev, NULL);
     589              : 
     590              :   /* If there was a barrier after the old SEQUENCE, remit it.  */
     591            0 :   if (had_barrier)
     592            0 :     emit_barrier_after (trial);
     593              : 
     594              :   /* If there are any delay insns, remit them.  Otherwise clear the
     595              :      annul flag.  */
     596            0 :   if (!delay_list.is_empty ())
     597            0 :     trial = emit_delay_sequence (trial, delay_list, XVECLEN (seq, 0) - 2);
     598            0 :   else if (JUMP_P (trial))
     599            0 :     INSN_ANNULLED_BRANCH_P (trial) = 0;
     600              : 
     601            0 :   INSN_FROM_TARGET_P (insn) = 0;
     602              : 
     603              :   /* Show we need to fill this insn again.  */
     604            0 :   obstack_ptr_grow (&unfilled_slots_obstack, trial);
     605              : 
     606            0 :   return trial;
     607            0 : }
     608              : 
     609              : /* Delete INSN, a JUMP_INSN.  */
     610              : 
     611              : static void
     612            0 : delete_scheduled_jump (rtx_insn *insn)
     613              : {
     614            0 :   delete_related_insns (insn);
     615            0 : }
     616              : 
     617              : /* Counters for delay-slot filling.  */
     618              : 
     619              : #define NUM_REORG_FUNCTIONS 2
     620              : #define MAX_DELAY_HISTOGRAM 3
     621              : #define MAX_REORG_PASSES 2
     622              : 
     623              : static int num_insns_needing_delays[NUM_REORG_FUNCTIONS][MAX_REORG_PASSES];
     624              : 
     625              : static int num_filled_delays[NUM_REORG_FUNCTIONS][MAX_DELAY_HISTOGRAM+1][MAX_REORG_PASSES];
     626              : 
     627              : static int reorg_pass_number;
     628              : 
     629              : static void
     630            0 : note_delay_statistics (int slots_filled, int index)
     631              : {
     632            0 :   num_insns_needing_delays[index][reorg_pass_number]++;
     633            0 :   if (slots_filled > MAX_DELAY_HISTOGRAM)
     634              :     slots_filled = MAX_DELAY_HISTOGRAM;
     635            0 :   num_filled_delays[index][slots_filled][reorg_pass_number]++;
     636            0 : }
     637              : 
     638              : /* Optimize the following cases:
     639              : 
     640              :    1.  When a conditional branch skips over only one instruction,
     641              :        use an annulling branch and put that insn in the delay slot.
     642              :        Use either a branch that annuls when the condition if true or
     643              :        invert the test with a branch that annuls when the condition is
     644              :        false.  This saves insns, since otherwise we must copy an insn
     645              :        from the L1 target.
     646              : 
     647              :         (orig)           (skip)         (otherwise)
     648              :         Bcc.n L1        Bcc',a L1       Bcc,a L1'
     649              :         insn            insn            insn2
     650              :       L1:             L1:             L1:
     651              :         insn2           insn2           insn2
     652              :         insn3           insn3         L1':
     653              :                                         insn3
     654              : 
     655              :    2.  When a conditional branch skips over only one instruction,
     656              :        and after that, it unconditionally branches somewhere else,
     657              :        perform the similar optimization. This saves executing the
     658              :        second branch in the case where the inverted condition is true.
     659              : 
     660              :         Bcc.n L1        Bcc',a L2
     661              :         insn            insn
     662              :       L1:             L1:
     663              :         Bra L2          Bra L2
     664              : 
     665              :    INSN is a JUMP_INSN.
     666              : 
     667              :    This should be expanded to skip over N insns, where N is the number
     668              :    of delay slots required.  */
     669              : 
     670              : static void
     671            0 : optimize_skip (rtx_jump_insn *insn, vec<rtx_insn *> *delay_list)
     672              : {
     673            0 :   rtx_insn *trial = next_nonnote_insn (insn);
     674            0 :   rtx_insn *next_trial = next_active_insn (trial);
     675            0 :   int flags;
     676              : 
     677            0 :   flags = get_jump_flags (insn, JUMP_LABEL (insn));
     678              : 
     679            0 :   if (trial == 0
     680            0 :       || !NONJUMP_INSN_P (trial)
     681            0 :       || GET_CODE (PATTERN (trial)) == SEQUENCE
     682            0 :       || recog_memoized (trial) < 0
     683            0 :       || (! eligible_for_annul_false (insn, 0, trial, flags)
     684            0 :           && ! eligible_for_annul_true (insn, 0, trial, flags))
     685            0 :       || RTX_FRAME_RELATED_P (trial)
     686            0 :       || can_throw_internal (trial))
     687              :     return;
     688              : 
     689              :   /* There are two cases where we are just executing one insn (we assume
     690              :      here that a branch requires only one insn; this should be generalized
     691              :      at some point):  Where the branch goes around a single insn or where
     692              :      we have one insn followed by a branch to the same label we branch to.
     693              :      In both of these cases, inverting the jump and annulling the delay
     694              :      slot give the same effect in fewer insns.  */
     695            0 :   if (next_trial == next_active_insn (JUMP_LABEL_AS_INSN (insn))
     696            0 :       || (next_trial != 0
     697            0 :           && simplejump_or_return_p (next_trial)
     698            0 :           && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)))
     699              :     {
     700            0 :       if (eligible_for_annul_false (insn, 0, trial, flags))
     701              :         {
     702            0 :           if (invert_jump (insn, JUMP_LABEL (insn), 1))
     703            0 :             INSN_FROM_TARGET_P (trial) = 1;
     704            0 :           else if (! eligible_for_annul_true (insn, 0, trial, flags))
     705              :             return;
     706              :         }
     707              : 
     708            0 :       add_to_delay_list (trial, delay_list);
     709            0 :       next_trial = next_active_insn (trial);
     710            0 :       update_block (trial, trial);
     711            0 :       delete_related_insns (trial);
     712              : 
     713              :       /* Also, if we are targeting an unconditional
     714              :          branch, thread our jump to the target of that branch.  Don't
     715              :          change this into a RETURN here, because it may not accept what
     716              :          we have in the delay slot.  We'll fix this up later.  */
     717            0 :       if (next_trial && simplejump_or_return_p (next_trial))
     718              :         {
     719            0 :           rtx target_label = JUMP_LABEL (next_trial);
     720            0 :           if (ANY_RETURN_P (target_label))
     721            0 :             target_label = find_end_label (target_label);
     722              : 
     723            0 :           if (target_label)
     724              :             {
     725              :               /* Recompute the flags based on TARGET_LABEL since threading
     726              :                  the jump to TARGET_LABEL may change the direction of the
     727              :                  jump (which may change the circumstances in which the
     728              :                  delay slot is nullified).  */
     729            0 :               flags = get_jump_flags (insn, target_label);
     730            0 :               if (eligible_for_annul_true (insn, 0, trial, flags))
     731            0 :                 reorg_redirect_jump (insn, target_label);
     732              :             }
     733              :         }
     734              : 
     735            0 :       INSN_ANNULLED_BRANCH_P (insn) = 1;
     736              :     }
     737              : }
     738              : 
     739              : /*  Encode and return branch direction and prediction information for
     740              :     INSN assuming it will jump to LABEL.
     741              : 
     742              :     Non conditional branches return no direction information and
     743              :     are predicted as very likely taken.  */
     744              : 
     745              : static int
     746            0 : get_jump_flags (const rtx_insn *insn, rtx label)
     747              : {
     748            0 :   int flags;
     749              : 
     750              :   /* get_jump_flags can be passed any insn with delay slots, these may
     751              :      be INSNs, CALL_INSNs, or JUMP_INSNs.  Only JUMP_INSNs have branch
     752              :      direction information, and only if they are conditional jumps.
     753              : 
     754              :      If LABEL is a return, then there is no way to determine the branch
     755              :      direction.  */
     756            0 :   if (JUMP_P (insn)
     757            0 :       && (condjump_p (insn) || condjump_in_parallel_p (insn))
     758            0 :       && !ANY_RETURN_P (label)
     759            0 :       && INSN_UID (insn) <= max_uid
     760            0 :       && INSN_UID (label) <= max_uid)
     761            0 :     flags
     762            0 :       = (uid_to_ruid[INSN_UID (label)] > uid_to_ruid[INSN_UID (insn)])
     763            0 :          ? ATTR_FLAG_forward : ATTR_FLAG_backward;
     764              :   /* No valid direction information.  */
     765              :   else
     766              :     flags = 0;
     767              : 
     768            0 :   return flags;
     769              : }
     770              : 
     771              : /* Return truth value of the statement that this branch
     772              :    is mostly taken.  If we think that the branch is extremely likely
     773              :    to be taken, we return 2.  If the branch is slightly more likely to be
     774              :    taken, return 1.  If the branch is slightly less likely to be taken,
     775              :    return 0 and if the branch is highly unlikely to be taken, return -1.  */
     776              : 
     777              : static int
     778            0 : mostly_true_jump (rtx jump_insn)
     779              : {
     780              :   /* If branch probabilities are available, then use that number since it
     781              :      always gives a correct answer.  */
     782            0 :   rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
     783            0 :   if (note)
     784              :     {
     785            0 :       int prob = profile_probability::from_reg_br_prob_note (XINT (note, 0))
     786            0 :                         .to_reg_br_prob_base ();
     787              : 
     788            0 :       if (prob >= REG_BR_PROB_BASE * 9 / 10)
     789              :         return 2;
     790            0 :       else if (prob >= REG_BR_PROB_BASE / 2)
     791              :         return 1;
     792            0 :       else if (prob >= REG_BR_PROB_BASE / 10)
     793              :         return 0;
     794              :       else
     795            0 :         return -1;
     796              :     }
     797              : 
     798              :   /* If there is no note, assume branches are not taken.
     799              :      This should be rare.  */
     800              :     return 0;
     801              : }
     802              : 
     803              : /* Return the condition under which INSN will branch to TARGET.  If TARGET
     804              :    is zero, return the condition under which INSN will return.  If INSN is
     805              :    an unconditional branch, return const_true_rtx.  If INSN isn't a simple
     806              :    type of jump, or it doesn't go to TARGET, return 0.  */
     807              : 
     808              : static rtx
     809            0 : get_branch_condition (const rtx_insn *insn, rtx target)
     810              : {
     811            0 :   rtx pat = PATTERN (insn);
     812            0 :   rtx src;
     813              : 
     814            0 :   if (condjump_in_parallel_p (insn))
     815            0 :     pat = XVECEXP (pat, 0, 0);
     816              : 
     817            0 :   if (ANY_RETURN_P (pat) && pat == target)
     818            0 :     return const_true_rtx;
     819              : 
     820            0 :   if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
     821              :     return 0;
     822              : 
     823            0 :   src = SET_SRC (pat);
     824            0 :   if (GET_CODE (src) == LABEL_REF && label_ref_label (src) == target)
     825            0 :     return const_true_rtx;
     826              : 
     827            0 :   else if (GET_CODE (src) == IF_THEN_ELSE
     828            0 :            && XEXP (src, 2) == pc_rtx
     829            0 :            && ((GET_CODE (XEXP (src, 1)) == LABEL_REF
     830            0 :                 && label_ref_label (XEXP (src, 1)) == target)
     831            0 :                || (ANY_RETURN_P (XEXP (src, 1)) && XEXP (src, 1) == target)))
     832            0 :     return XEXP (src, 0);
     833              : 
     834            0 :   else if (GET_CODE (src) == IF_THEN_ELSE
     835            0 :            && XEXP (src, 1) == pc_rtx
     836            0 :            && ((GET_CODE (XEXP (src, 2)) == LABEL_REF
     837            0 :                 && label_ref_label (XEXP (src, 2)) == target)
     838            0 :                || (ANY_RETURN_P (XEXP (src, 2)) && XEXP (src, 2) == target)))
     839              :     {
     840            0 :       enum rtx_code rev;
     841            0 :       rev = reversed_comparison_code (XEXP (src, 0), insn);
     842            0 :       if (rev != UNKNOWN)
     843            0 :         return gen_rtx_fmt_ee (rev, GET_MODE (XEXP (src, 0)),
     844              :                                XEXP (XEXP (src, 0), 0),
     845              :                                XEXP (XEXP (src, 0), 1));
     846              :     }
     847              : 
     848              :   return 0;
     849              : }
     850              : 
     851              : /* Return true if CONDITION is more strict than the condition of
     852              :    INSN, i.e., if INSN will always branch if CONDITION is true.  */
     853              : 
     854              : static bool
     855            0 : condition_dominates_p (rtx condition, const rtx_insn *insn)
     856              : {
     857            0 :   rtx other_condition = get_branch_condition (insn, JUMP_LABEL (insn));
     858            0 :   enum rtx_code code = GET_CODE (condition);
     859            0 :   enum rtx_code other_code;
     860              : 
     861            0 :   if (rtx_equal_p (condition, other_condition)
     862            0 :       || other_condition == const_true_rtx)
     863              :     return true;
     864              : 
     865            0 :   else if (condition == const_true_rtx || other_condition == 0)
     866              :     return false;
     867              : 
     868            0 :   other_code = GET_CODE (other_condition);
     869            0 :   if (GET_RTX_LENGTH (code) != 2 || GET_RTX_LENGTH (other_code) != 2
     870            0 :       || ! rtx_equal_p (XEXP (condition, 0), XEXP (other_condition, 0))
     871            0 :       || ! rtx_equal_p (XEXP (condition, 1), XEXP (other_condition, 1)))
     872              :     return false;
     873              : 
     874            0 :   return comparison_dominates_p (code, other_code);
     875              : }
     876              : 
     877              : /* Return true if redirecting JUMP to NEWLABEL does not invalidate
     878              :    any insns already in the delay slot of JUMP.  */
     879              : 
     880              : static bool
     881            0 : redirect_with_delay_slots_safe_p (rtx_insn *jump, rtx newlabel, rtx seq)
     882              : {
     883            0 :   int flags, i;
     884            0 :   rtx_sequence *pat = as_a <rtx_sequence *> (PATTERN (seq));
     885              : 
     886              :   /* Make sure all the delay slots of this jump would still
     887              :      be valid after threading the jump.  If they are still
     888              :      valid, then return nonzero.  */
     889              : 
     890            0 :   flags = get_jump_flags (jump, newlabel);
     891            0 :   for (i = 1; i < pat->len (); i++)
     892            0 :     if (! (
     893              : #if ANNUL_IFFALSE_SLOTS
     894              :            (INSN_ANNULLED_BRANCH_P (jump)
     895              :             && INSN_FROM_TARGET_P (pat->insn (i)))
     896              :            ? eligible_for_annul_false (jump, i - 1, pat->insn (i), flags) :
     897              : #endif
     898              : #if ANNUL_IFTRUE_SLOTS
     899              :            (INSN_ANNULLED_BRANCH_P (jump)
     900              :             && ! INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)))
     901              :            ? eligible_for_annul_true (jump, i - 1, pat->insn (i), flags) :
     902              : #endif
     903            0 :            eligible_for_delay (jump, i - 1, pat->insn (i), flags)))
     904              :       break;
     905              : 
     906            0 :   return (i == pat->len ());
     907              : }
     908              : 
     909              : /* Return true if redirecting JUMP to NEWLABEL does not invalidate
     910              :    any insns we wish to place in the delay slot of JUMP.  */
     911              : 
     912              : static bool
     913            0 : redirect_with_delay_list_safe_p (rtx_insn *jump, rtx newlabel,
     914              :                                  const vec<rtx_insn *> &delay_list)
     915              : {
     916              :   /* Make sure all the insns in DELAY_LIST would still be
     917              :      valid after threading the jump.  If they are still
     918              :      valid, then return true.  */
     919              : 
     920            0 :   int flags = get_jump_flags (jump, newlabel);
     921            0 :   unsigned int delay_insns = delay_list.length ();
     922            0 :   unsigned int i = 0;
     923            0 :   for (; i < delay_insns; i++)
     924            0 :     if (! (
     925              : #if ANNUL_IFFALSE_SLOTS
     926              :            (INSN_ANNULLED_BRANCH_P (jump)
     927              :             && INSN_FROM_TARGET_P (delay_list[i]))
     928              :            ? eligible_for_annul_false (jump, i, delay_list[i], flags) :
     929              : #endif
     930              : #if ANNUL_IFTRUE_SLOTS
     931              :            (INSN_ANNULLED_BRANCH_P (jump)
     932              :             && ! INSN_FROM_TARGET_P (delay_list[i]))
     933              :            ? eligible_for_annul_true (jump, i, delay_list[i], flags) :
     934              : #endif
     935            0 :            eligible_for_delay (jump, i, delay_list[i], flags)))
     936              :       break;
     937              : 
     938            0 :   return i == delay_insns;
     939              : }
     940              : 
     941              : /* DELAY_LIST is a list of insns that have already been placed into delay
     942              :    slots.  See if all of them have the same annulling status as ANNUL_TRUE_P.
     943              :    If not, return false; otherwise return true.  */
     944              : 
     945              : static bool
     946            0 : check_annul_list_true_false (bool annul_true_p,
     947              :                              const vec<rtx_insn *> &delay_list)
     948              : {
     949            0 :   rtx_insn *trial;
     950            0 :   unsigned int i;
     951            0 :   FOR_EACH_VEC_ELT (delay_list, i, trial)
     952            0 :     if ((annul_true_p && INSN_FROM_TARGET_P (trial))
     953            0 :         || (!annul_true_p && !INSN_FROM_TARGET_P (trial)))
     954              :       return false;
     955              : 
     956              :   return true;
     957              : }
     958              : 
     959              : /* INSN branches to an insn whose pattern SEQ is a SEQUENCE.  Given that
     960              :    the condition tested by INSN is CONDITION and the resources shown in
     961              :    OTHER_NEEDED are needed after INSN, see whether INSN can take all the insns
     962              :    from SEQ's delay list, in addition to whatever insns it may execute
     963              :    (in DELAY_LIST).   SETS and NEEDED are denote resources already set and
     964              :    needed while searching for delay slot insns.  Return the concatenated
     965              :    delay list if possible, otherwise, return 0.
     966              : 
     967              :    SLOTS_TO_FILL is the total number of slots required by INSN, and
     968              :    PSLOTS_FILLED points to the number filled so far (also the number of
     969              :    insns in DELAY_LIST).  It is updated with the number that have been
     970              :    filled from the SEQUENCE, if any.
     971              : 
     972              :    PANNUL_P points to a nonzero value if we already know that we need
     973              :    to annul INSN.  If this routine determines that annulling is needed,
     974              :    it may set that value to true.
     975              : 
     976              :    PNEW_THREAD points to a location that is to receive the place at which
     977              :    execution should continue.  */
     978              : 
     979              : static void
     980            0 : steal_delay_list_from_target (rtx_insn *insn, rtx condition, rtx_sequence *seq,
     981              :                               vec<rtx_insn *> *delay_list,
     982              :                               struct resources *sets,
     983              :                               struct resources *needed,
     984              :                               struct resources *other_needed,
     985              :                               int slots_to_fill, int *pslots_filled,
     986              :                               bool *pannul_p, rtx *pnew_thread)
     987              : {
     988            0 :   int slots_remaining = slots_to_fill - *pslots_filled;
     989            0 :   int total_slots_filled = *pslots_filled;
     990            0 :   auto_vec<rtx_insn *, 5> new_delay_list;
     991            0 :   bool must_annul = *pannul_p;
     992            0 :   bool used_annul = false;
     993            0 :   int i;
     994            0 :   struct resources cc_set;
     995            0 :   rtx_insn **redundant;
     996              : 
     997              :   /* We can't do anything if there are more delay slots in SEQ than we
     998              :      can handle, or if we don't know that it will be a taken branch.
     999              :      We know that it will be a taken branch if it is either an unconditional
    1000              :      branch or a conditional branch with a stricter branch condition.
    1001              : 
    1002              :      Also, exit if the branch has more than one set, since then it is computing
    1003              :      other results that can't be ignored, e.g. the HPPA mov&branch instruction.
    1004              :      ??? It may be possible to move other sets into INSN in addition to
    1005              :      moving the instructions in the delay slots.
    1006              : 
    1007              :      We cannot steal the delay list if one of the instructions in the
    1008              :      current delay_list modifies the condition codes and the jump in the
    1009              :      sequence is a conditional jump. We cannot do this because we cannot
    1010              :      change the direction of the jump because the condition codes
    1011              :      will effect the direction of the jump in the sequence.  */
    1012              : 
    1013            0 :   CLEAR_RESOURCE (&cc_set);
    1014              : 
    1015              :   rtx_insn *trial;
    1016            0 :   FOR_EACH_VEC_ELT (*delay_list, i, trial)
    1017              :     {
    1018            0 :       mark_set_resources (trial, &cc_set, 0, MARK_SRC_DEST_CALL);
    1019            0 :       if (insn_references_resource_p (seq->insn (0), &cc_set, false))
    1020              :         return;
    1021              :     }
    1022              : 
    1023            0 :   if (XVECLEN (seq, 0) - 1 > slots_remaining
    1024            0 :       || ! condition_dominates_p (condition, seq->insn (0))
    1025            0 :       || ! single_set (seq->insn (0)))
    1026              :     return;
    1027              : 
    1028              :   /* On some targets, branches with delay slots can have a limited
    1029              :      displacement.  Give the back end a chance to tell us we can't do
    1030              :      this.  */
    1031            0 :   if (! targetm.can_follow_jump (insn, seq->insn (0)))
    1032              :     return;
    1033              : 
    1034            0 :   redundant = XALLOCAVEC (rtx_insn *, XVECLEN (seq, 0));
    1035            0 :   for (i = 1; i < seq->len (); i++)
    1036              :     {
    1037            0 :       rtx_insn *trial = seq->insn (i);
    1038            0 :       int flags;
    1039              : 
    1040            0 :       if (insn_references_resource_p (trial, sets, false)
    1041            0 :           || insn_sets_resource_p (trial, needed, false)
    1042            0 :           || insn_sets_resource_p (trial, sets, false)
    1043              :           /* If TRIAL is from the fallthrough code of an annulled branch insn
    1044              :              in SEQ, we cannot use it.  */
    1045            0 :           || (INSN_ANNULLED_BRANCH_P (seq->insn (0))
    1046            0 :               && ! INSN_FROM_TARGET_P (trial)))
    1047              :         return;
    1048              : 
    1049              :       /* If this insn was already done (usually in a previous delay slot),
    1050              :          pretend we put it in our delay slot.  */
    1051            0 :       redundant[i] = redundant_insn (trial, insn, new_delay_list);
    1052            0 :       if (redundant[i])
    1053            0 :         continue;
    1054              : 
    1055              :       /* We will end up re-vectoring this branch, so compute flags
    1056              :          based on jumping to the new label.  */
    1057            0 :       flags = get_jump_flags (insn, JUMP_LABEL (seq->insn (0)));
    1058              : 
    1059            0 :       if (! must_annul
    1060            0 :           && ((condition == const_true_rtx
    1061            0 :                || (! insn_sets_resource_p (trial, other_needed, false)
    1062            0 :                    && ! may_trap_or_fault_p (PATTERN (trial)))))
    1063            0 :           ? eligible_for_delay (insn, total_slots_filled, trial, flags)
    1064            0 :           : (must_annul || (delay_list->is_empty () && new_delay_list.is_empty ()))
    1065            0 :              && (must_annul = true,
    1066            0 :                  check_annul_list_true_false (false, *delay_list)
    1067            0 :                  && check_annul_list_true_false (false, new_delay_list)
    1068            0 :                  && eligible_for_annul_false (insn, total_slots_filled,
    1069              :                                               trial, flags)))
    1070              :         {
    1071            0 :           if (must_annul)
    1072              :             {
    1073              :               /* Frame related instructions cannot go into annulled delay
    1074              :                  slots, it messes up the dwarf info.  */
    1075            0 :               if (RTX_FRAME_RELATED_P (trial))
    1076              :                 return;
    1077              :               used_annul = true;
    1078              :             }
    1079            0 :           rtx_insn *temp = copy_delay_slot_insn (trial);
    1080            0 :           INSN_FROM_TARGET_P (temp) = 1;
    1081            0 :           add_to_delay_list (temp, &new_delay_list);
    1082            0 :           total_slots_filled++;
    1083              : 
    1084            0 :           if (--slots_remaining == 0)
    1085              :             break;
    1086              :         }
    1087              :       else
    1088              :         return;
    1089              :     }
    1090              : 
    1091              :   /* Record the effect of the instructions that were redundant and which
    1092              :      we therefore decided not to copy.  */
    1093            0 :   for (i = 1; i < seq->len (); i++)
    1094            0 :     if (redundant[i])
    1095              :       {
    1096            0 :         fix_reg_dead_note (redundant[i], insn);
    1097            0 :         update_block (seq->insn (i), insn);
    1098              :       }
    1099              : 
    1100              :   /* Show the place to which we will be branching.  */
    1101            0 :   *pnew_thread = first_active_target_insn (JUMP_LABEL (seq->insn (0)));
    1102              : 
    1103              :   /* Add any new insns to the delay list and update the count of the
    1104              :      number of slots filled.  */
    1105            0 :   *pslots_filled = total_slots_filled;
    1106            0 :   if (used_annul)
    1107            0 :     *pannul_p = true;
    1108              : 
    1109            0 :   rtx_insn *temp;
    1110            0 :   FOR_EACH_VEC_ELT (new_delay_list, i, temp)
    1111            0 :     add_to_delay_list (temp, delay_list);
    1112            0 : }
    1113              : 
    1114              : /* Similar to steal_delay_list_from_target except that SEQ is on the
    1115              :    fallthrough path of INSN.  Here we only do something if the delay insn
    1116              :    of SEQ is an unconditional branch.  In that case we steal its delay slot
    1117              :    for INSN since unconditional branches are much easier to fill.  */
    1118              : 
    1119              : static void
    1120            0 : steal_delay_list_from_fallthrough (rtx_insn *insn, rtx condition,
    1121              :                                    rtx_sequence *seq,
    1122              :                                    vec<rtx_insn *> *delay_list,
    1123              :                                    struct resources *sets,
    1124              :                                    struct resources *needed,
    1125              :                                    struct resources *other_needed,
    1126              :                                    int slots_to_fill, int *pslots_filled,
    1127              :                                    bool *pannul_p)
    1128              : {
    1129            0 :   int i;
    1130            0 :   int flags;
    1131            0 :   bool must_annul = *pannul_p;
    1132            0 :   bool used_annul = false;
    1133              : 
    1134            0 :   flags = get_jump_flags (insn, JUMP_LABEL (insn));
    1135              : 
    1136              :   /* We can't do anything if SEQ's delay insn isn't an
    1137              :      unconditional branch.  */
    1138              : 
    1139            0 :   if (! simplejump_or_return_p (seq->insn (0)))
    1140              :     return;
    1141              : 
    1142            0 :   for (i = 1; i < seq->len (); i++)
    1143              :     {
    1144            0 :       rtx_insn *trial = seq->insn (i);
    1145            0 :       rtx_insn *prior_insn;
    1146              : 
    1147            0 :       if (insn_references_resource_p (trial, sets, false)
    1148            0 :           || insn_sets_resource_p (trial, needed, false)
    1149            0 :           || insn_sets_resource_p (trial, sets, false))
    1150              :         break;
    1151              : 
    1152              :       /* If this insn was already done, we don't need it.  */
    1153            0 :       if ((prior_insn = redundant_insn (trial, insn, *delay_list)))
    1154              :         {
    1155            0 :           fix_reg_dead_note (prior_insn, insn);
    1156            0 :           update_block (trial, insn);
    1157            0 :           delete_from_delay_slot (trial);
    1158            0 :           continue;
    1159              :         }
    1160              : 
    1161            0 :       if (! must_annul
    1162            0 :           && ((condition == const_true_rtx
    1163            0 :                || (! insn_sets_resource_p (trial, other_needed, false)
    1164            0 :                    && ! may_trap_or_fault_p (PATTERN (trial)))))
    1165            0 :           ? eligible_for_delay (insn, *pslots_filled, trial, flags)
    1166            0 :           : (must_annul || delay_list->is_empty ()) && (must_annul = true,
    1167            0 :              check_annul_list_true_false (true, *delay_list)
    1168            0 :              && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
    1169              :         {
    1170            0 :           if (must_annul)
    1171            0 :             used_annul = true;
    1172            0 :           delete_from_delay_slot (trial);
    1173            0 :           add_to_delay_list (trial, delay_list);
    1174              : 
    1175            0 :           if (++(*pslots_filled) == slots_to_fill)
    1176              :             break;
    1177              :         }
    1178              :       else
    1179              :         break;
    1180              :     }
    1181              : 
    1182            0 :   if (used_annul)
    1183            0 :     *pannul_p = true;
    1184              : }
    1185              : 
    1186              : /* Try merging insns starting at THREAD which match exactly the insns in
    1187              :    INSN's delay list.
    1188              : 
    1189              :    If all insns were matched and the insn was previously annulling, the
    1190              :    annul bit will be cleared.
    1191              : 
    1192              :    For each insn that is merged, if the branch is or will be non-annulling,
    1193              :    we delete the merged insn.  */
    1194              : 
    1195              : static void
    1196            0 : try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
    1197              : {
    1198            0 :   rtx_insn *trial, *next_trial;
    1199            0 :   rtx_insn *delay_insn = as_a <rtx_insn *> (XVECEXP (PATTERN (insn), 0, 0));
    1200            0 :   bool annul_p = JUMP_P (delay_insn) && INSN_ANNULLED_BRANCH_P (delay_insn);
    1201            0 :   int slot_number = 1;
    1202            0 :   int num_slots = XVECLEN (PATTERN (insn), 0);
    1203            0 :   rtx next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
    1204            0 :   struct resources set, needed, modified;
    1205            0 :   auto_vec<std::pair<rtx_insn *, bool>, 10> merged_insns;
    1206            0 :   int flags;
    1207              : 
    1208            0 :   flags = get_jump_flags (delay_insn, JUMP_LABEL (delay_insn));
    1209              : 
    1210            0 :   CLEAR_RESOURCE (&needed);
    1211            0 :   CLEAR_RESOURCE (&set);
    1212              : 
    1213              :   /* If this is not an annulling branch, take into account anything needed in
    1214              :      INSN's delay slot.  This prevents two increments from being incorrectly
    1215              :      folded into one.  If we are annulling, this would be the correct
    1216              :      thing to do.  (The alternative, looking at things set in NEXT_TO_MATCH
    1217              :      will essentially disable this optimization.  This method is somewhat of
    1218              :      a kludge, but I don't see a better way.)  */
    1219            0 :   if (! annul_p)
    1220            0 :     for (int i = 1; i < num_slots; i++)
    1221            0 :       if (XVECEXP (PATTERN (insn), 0, i))
    1222            0 :         mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed,
    1223              :                                    true);
    1224              : 
    1225            0 :   for (trial = thread; !stop_search_p (trial, true); trial = next_trial)
    1226              :     {
    1227            0 :       rtx pat = PATTERN (trial);
    1228            0 :       rtx oldtrial = trial;
    1229              : 
    1230            0 :       next_trial = next_nonnote_insn (trial);
    1231              : 
    1232              :       /* TRIAL must be a CALL_INSN or INSN.  Skip USE and CLOBBER.  */
    1233            0 :       if (NONJUMP_INSN_P (trial)
    1234            0 :           && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER))
    1235            0 :         continue;
    1236              : 
    1237            0 :       if (GET_CODE (next_to_match) == GET_CODE (trial)
    1238            0 :           && ! insn_references_resource_p (trial, &set, true)
    1239            0 :           && ! insn_sets_resource_p (trial, &set, true)
    1240            0 :           && ! insn_sets_resource_p (trial, &needed, true)
    1241            0 :           && (trial = try_split (pat, trial, 0)) != 0
    1242              :           /* Update next_trial, in case try_split succeeded.  */
    1243            0 :           && (next_trial = next_nonnote_insn (trial))
    1244              :           /* Likewise THREAD.  */
    1245            0 :           && (thread = oldtrial == thread ? trial : thread)
    1246            0 :           && rtx_equal_p (PATTERN (next_to_match), PATTERN (trial))
    1247              :           /* Have to test this condition if annul condition is different
    1248              :              from (and less restrictive than) non-annulling one.  */
    1249            0 :           && eligible_for_delay (delay_insn, slot_number - 1, trial, flags))
    1250              :         {
    1251              : 
    1252            0 :           if (! annul_p)
    1253              :             {
    1254            0 :               update_block (trial, thread);
    1255            0 :               if (trial == thread)
    1256            0 :                 thread = next_active_insn (thread);
    1257              : 
    1258            0 :               delete_related_insns (trial);
    1259            0 :               INSN_FROM_TARGET_P (next_to_match) = 0;
    1260              :             }
    1261              :           else
    1262            0 :             merged_insns.safe_push (std::pair<rtx_insn *, bool> (trial, false));
    1263              : 
    1264            0 :           if (++slot_number == num_slots)
    1265              :             break;
    1266              : 
    1267            0 :           next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
    1268              :         }
    1269              : 
    1270            0 :       mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
    1271            0 :       mark_referenced_resources (trial, &needed, true);
    1272              :     }
    1273              : 
    1274              :   /* See if we stopped on a filled insn.  If we did, try to see if its
    1275              :      delay slots match.  */
    1276            0 :   if (slot_number != num_slots
    1277            0 :       && trial && NONJUMP_INSN_P (trial)
    1278            0 :       && GET_CODE (PATTERN (trial)) == SEQUENCE
    1279            0 :       && !(JUMP_P (XVECEXP (PATTERN (trial), 0, 0))
    1280            0 :            && INSN_ANNULLED_BRANCH_P (XVECEXP (PATTERN (trial), 0, 0))))
    1281              :     {
    1282            0 :       rtx_sequence *pat = as_a <rtx_sequence *> (PATTERN (trial));
    1283            0 :       rtx filled_insn = XVECEXP (pat, 0, 0);
    1284              : 
    1285              :       /* Account for resources set/needed by the filled insn.  */
    1286            0 :       mark_set_resources (filled_insn, &set, 0, MARK_SRC_DEST_CALL);
    1287            0 :       mark_referenced_resources (filled_insn, &needed, true);
    1288              : 
    1289            0 :       for (int i = 1; i < pat->len (); i++)
    1290              :         {
    1291            0 :           rtx_insn *dtrial = pat->insn (i);
    1292              : 
    1293            0 :           CLEAR_RESOURCE (&modified);
    1294              :           /* Account for resources set by the insn following NEXT_TO_MATCH
    1295              :              inside INSN's delay list. */
    1296            0 :           for (int j = 1; slot_number + j < num_slots; j++)
    1297            0 :             mark_set_resources (XVECEXP (PATTERN (insn), 0, slot_number + j),
    1298              :                                 &modified, 0, MARK_SRC_DEST_CALL);
    1299              :           /* Account for resources set by the insn before DTRIAL and inside
    1300              :              TRIAL's delay list. */
    1301            0 :           for (int j = 1; j < i; j++)
    1302            0 :             mark_set_resources (XVECEXP (pat, 0, j),
    1303              :                                 &modified, 0, MARK_SRC_DEST_CALL);
    1304            0 :           if (! insn_references_resource_p (dtrial, &set, true)
    1305            0 :               && ! insn_sets_resource_p (dtrial, &set, true)
    1306            0 :               && ! insn_sets_resource_p (dtrial, &needed, true)
    1307            0 :               && rtx_equal_p (PATTERN (next_to_match), PATTERN (dtrial))
    1308              :               /* Check that DTRIAL and NEXT_TO_MATCH does not reference a
    1309              :                  resource modified between them (only dtrial is checked because
    1310              :                  next_to_match and dtrial shall to be equal in order to hit
    1311              :                  this line) */
    1312            0 :               && ! insn_references_resource_p (dtrial, &modified, true)
    1313            0 :               && eligible_for_delay (delay_insn, slot_number - 1, dtrial, flags))
    1314              :             {
    1315            0 :               if (! annul_p)
    1316              :                 {
    1317            0 :                   rtx_insn *new_rtx;
    1318              : 
    1319            0 :                   update_block (dtrial, thread);
    1320            0 :                   new_rtx = delete_from_delay_slot (dtrial);
    1321            0 :                   if (thread->deleted ())
    1322            0 :                     thread = new_rtx;
    1323            0 :                   INSN_FROM_TARGET_P (next_to_match) = 0;
    1324              :                 }
    1325              :               else
    1326            0 :                 merged_insns.safe_push (std::pair<rtx_insn *, bool> (dtrial,
    1327            0 :                                                                      true));
    1328              : 
    1329            0 :               if (++slot_number == num_slots)
    1330              :                 break;
    1331              : 
    1332            0 :               next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
    1333              :             }
    1334              :           else
    1335              :             {
    1336              :               /* Keep track of the set/referenced resources for the delay
    1337              :                  slots of any trial insns we encounter.  */
    1338            0 :               mark_set_resources (dtrial, &set, 0, MARK_SRC_DEST_CALL);
    1339            0 :               mark_referenced_resources (dtrial, &needed, true);
    1340              :             }
    1341              :         }
    1342              :     }
    1343              : 
    1344              :   /* If all insns in the delay slot have been matched and we were previously
    1345              :      annulling the branch, we need not any more.  In that case delete all the
    1346              :      merged insns.  Also clear the INSN_FROM_TARGET_P bit of each insn in
    1347              :      the delay list so that we know that it isn't only being used at the
    1348              :      target.  */
    1349            0 :   if (slot_number == num_slots && annul_p)
    1350              :     {
    1351            0 :       unsigned int len = merged_insns.length ();
    1352            0 :       for (unsigned int i = len - 1; i < len; i--)
    1353            0 :         if (merged_insns[i].second)
    1354              :           {
    1355            0 :             update_block (merged_insns[i].first, thread);
    1356            0 :             rtx_insn *new_rtx = delete_from_delay_slot (merged_insns[i].first);
    1357            0 :             if (thread->deleted ())
    1358            0 :               thread = new_rtx;
    1359              :           }
    1360              :         else
    1361              :           {
    1362            0 :             update_block (merged_insns[i].first, thread);
    1363            0 :             delete_related_insns (merged_insns[i].first);
    1364              :           }
    1365              : 
    1366            0 :       INSN_ANNULLED_BRANCH_P (delay_insn) = 0;
    1367              : 
    1368            0 :       for (int i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
    1369            0 :         INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) = 0;
    1370              :     }
    1371            0 : }
    1372              : 
    1373              : /* See if INSN is redundant with an insn in front of TARGET.  Often this
    1374              :    is called when INSN is a candidate for a delay slot of TARGET.
    1375              :    DELAY_LIST are insns that will be placed in delay slots of TARGET in front
    1376              :    of INSN.  Often INSN will be redundant with an insn in a delay slot of
    1377              :    some previous insn.  This happens when we have a series of branches to the
    1378              :    same label; in that case the first insn at the target might want to go
    1379              :    into each of the delay slots.
    1380              : 
    1381              :    If we are not careful, this routine can take up a significant fraction
    1382              :    of the total compilation time (4%), but only wins rarely.  Hence we
    1383              :    speed this routine up by making two passes.  The first pass goes back
    1384              :    until it hits a label and sees if it finds an insn with an identical
    1385              :    pattern.  Only in this (relatively rare) event does it check for
    1386              :    data conflicts.
    1387              : 
    1388              :    We do not split insns we encounter.  This could cause us not to find a
    1389              :    redundant insn, but the cost of splitting seems greater than the possible
    1390              :    gain in rare cases.  */
    1391              : 
    1392              : static rtx_insn *
    1393            0 : redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
    1394              : {
    1395            0 :   rtx target_main = target;
    1396            0 :   rtx ipat = PATTERN (insn);
    1397            0 :   rtx_insn *trial;
    1398            0 :   rtx pat;
    1399            0 :   struct resources needed, set;
    1400            0 :   int i;
    1401            0 :   unsigned insns_to_search;
    1402              : 
    1403              :   /* If INSN has any REG_UNUSED notes, it can't match anything since we
    1404              :      are allowed to not actually assign to such a register.  */
    1405            0 :   if (find_reg_note (insn, REG_UNUSED, NULL_RTX) != 0)
    1406              :     return 0;
    1407              : 
    1408              :   /* Scan backwards looking for a match.  */
    1409            0 :   for (trial = PREV_INSN (target),
    1410            0 :          insns_to_search = param_max_delay_slot_insn_search;
    1411            0 :        trial && insns_to_search > 0;
    1412            0 :        trial = PREV_INSN (trial))
    1413              :     {
    1414              :       /* (use (insn))s can come immediately after a barrier if the
    1415              :          label that used to precede them has been deleted as dead.
    1416              :          See delete_related_insns.  */
    1417            0 :       if (LABEL_P (trial) || BARRIER_P (trial))
    1418              :         return 0;
    1419              : 
    1420            0 :       if (!NONDEBUG_INSN_P (trial))
    1421            0 :         continue;
    1422            0 :       --insns_to_search;
    1423              : 
    1424            0 :       pat = PATTERN (trial);
    1425            0 :       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
    1426            0 :         continue;
    1427              : 
    1428            0 :       if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
    1429              :         {
    1430              :           /* Stop for a CALL and its delay slots because it is difficult to
    1431              :              track its resource needs correctly.  */
    1432            0 :           if (CALL_P (seq->element (0)))
    1433              :             return 0;
    1434              : 
    1435              :           /* Stop for an INSN or JUMP_INSN with delayed effects and its delay
    1436              :              slots because it is difficult to track its resource needs
    1437              :              correctly.  */
    1438              : 
    1439            0 :           if (INSN_SETS_ARE_DELAYED (seq->insn (0)))
    1440              :             return 0;
    1441              : 
    1442            0 :           if (INSN_REFERENCES_ARE_DELAYED (seq->insn (0)))
    1443              :             return 0;
    1444              : 
    1445              :           /* See if any of the insns in the delay slot match, updating
    1446              :              resource requirements as we go.  */
    1447            0 :           for (i = seq->len () - 1; i > 0; i--)
    1448            0 :             if (GET_CODE (seq->element (i)) == GET_CODE (insn)
    1449            0 :                 && rtx_equal_p (PATTERN (seq->element (i)), ipat)
    1450            0 :                 && ! find_reg_note (seq->element (i), REG_UNUSED, NULL_RTX))
    1451              :               break;
    1452              : 
    1453              :           /* If found a match, exit this loop early.  */
    1454            0 :           if (i > 0)
    1455              :             break;
    1456              :         }
    1457              : 
    1458            0 :       else if (GET_CODE (trial) == GET_CODE (insn) && rtx_equal_p (pat, ipat)
    1459            0 :                && ! find_reg_note (trial, REG_UNUSED, NULL_RTX))
    1460              :         break;
    1461              :     }
    1462              : 
    1463              :   /* If we didn't find an insn that matches, return 0.  */
    1464            0 :   if (trial == 0)
    1465              :     return 0;
    1466              : 
    1467              :   /* See what resources this insn sets and needs.  If they overlap, it
    1468              :      can't be redundant.  */
    1469              : 
    1470            0 :   CLEAR_RESOURCE (&needed);
    1471            0 :   CLEAR_RESOURCE (&set);
    1472            0 :   mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
    1473            0 :   mark_referenced_resources (insn, &needed, true);
    1474              : 
    1475              :   /* If TARGET is a SEQUENCE, get the main insn.  */
    1476            0 :   if (NONJUMP_INSN_P (target) && GET_CODE (PATTERN (target)) == SEQUENCE)
    1477            0 :     target_main = XVECEXP (PATTERN (target), 0, 0);
    1478              : 
    1479            0 :   if (resource_conflicts_p (&needed, &set)
    1480              :       /* The insn requiring the delay may not set anything needed or set by
    1481              :          INSN.  */
    1482            0 :       || insn_sets_resource_p (target_main, &needed, true)
    1483            0 :       || insn_sets_resource_p (target_main, &set, true))
    1484              :     return 0;
    1485              : 
    1486              :   /* Insns we pass may not set either NEEDED or SET, so merge them for
    1487              :      simpler tests.  */
    1488            0 :   needed.memory |= set.memory;
    1489            0 :   needed.regs |= set.regs;
    1490              : 
    1491              :   /* This insn isn't redundant if it conflicts with an insn that either is
    1492              :      or will be in a delay slot of TARGET.  */
    1493              : 
    1494              :   unsigned int j;
    1495              :   rtx_insn *temp;
    1496            0 :   FOR_EACH_VEC_ELT (delay_list, j, temp)
    1497            0 :     if (insn_sets_resource_p (temp, &needed, true))
    1498              :       return 0;
    1499              : 
    1500            0 :   if (NONJUMP_INSN_P (target) && GET_CODE (PATTERN (target)) == SEQUENCE)
    1501            0 :     for (i = 1; i < XVECLEN (PATTERN (target), 0); i++)
    1502            0 :       if (insn_sets_resource_p (XVECEXP (PATTERN (target), 0, i), &needed,
    1503              :                                 true))
    1504              :         return 0;
    1505              : 
    1506              :   /* Scan backwards until we reach a label or an insn that uses something
    1507              :      INSN sets or sets something insn uses or sets.  */
    1508              : 
    1509            0 :   for (trial = PREV_INSN (target),
    1510            0 :          insns_to_search = param_max_delay_slot_insn_search;
    1511            0 :        trial && !LABEL_P (trial) && insns_to_search > 0;
    1512            0 :        trial = PREV_INSN (trial))
    1513              :     {
    1514            0 :       if (!NONDEBUG_INSN_P (trial))
    1515            0 :         continue;
    1516            0 :       --insns_to_search;
    1517              : 
    1518            0 :       pat = PATTERN (trial);
    1519            0 :       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
    1520            0 :         continue;
    1521              : 
    1522            0 :       if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
    1523              :         {
    1524            0 :           bool annul_p = false;
    1525            0 :           rtx_insn *control = seq->insn (0);
    1526              : 
    1527              :           /* If this is a CALL_INSN and its delay slots, it is hard to track
    1528              :              the resource needs properly, so give up.  */
    1529            0 :           if (CALL_P (control))
    1530              :             return 0;
    1531              : 
    1532              :           /* If this is an INSN or JUMP_INSN with delayed effects, it
    1533              :              is hard to track the resource needs properly, so give up.  */
    1534              : 
    1535            0 :           if (INSN_SETS_ARE_DELAYED (control))
    1536              :             return 0;
    1537              : 
    1538            0 :           if (INSN_REFERENCES_ARE_DELAYED (control))
    1539              :             return 0;
    1540              : 
    1541            0 :           if (JUMP_P (control))
    1542            0 :             annul_p = INSN_ANNULLED_BRANCH_P (control);
    1543              : 
    1544              :           /* See if any of the insns in the delay slot match, updating
    1545              :              resource requirements as we go.  */
    1546            0 :           for (i = seq->len () - 1; i > 0; i--)
    1547              :             {
    1548            0 :               rtx_insn *candidate = seq->insn (i);
    1549              : 
    1550              :               /* If an insn will be annulled if the branch is false, it isn't
    1551              :                  considered as a possible duplicate insn.  */
    1552            0 :               if (rtx_equal_p (PATTERN (candidate), ipat)
    1553            0 :                   && ! (annul_p && INSN_FROM_TARGET_P (candidate)))
    1554              :                 {
    1555              :                   /* Show that this insn will be used in the sequel.  */
    1556            0 :                   INSN_FROM_TARGET_P (candidate) = 0;
    1557            0 :                   return candidate;
    1558              :                 }
    1559              : 
    1560              :               /* Unless this is an annulled insn from the target of a branch,
    1561              :                  we must stop if it sets anything needed or set by INSN.  */
    1562            0 :               if ((!annul_p || !INSN_FROM_TARGET_P (candidate))
    1563            0 :                   && insn_sets_resource_p (candidate, &needed, true))
    1564              :                 return 0;
    1565              :             }
    1566              : 
    1567              :           /* If the insn requiring the delay slot conflicts with INSN, we
    1568              :              must stop.  */
    1569            0 :           if (insn_sets_resource_p (control, &needed, true))
    1570              :             return 0;
    1571              :         }
    1572              :       else
    1573              :         {
    1574              :           /* See if TRIAL is the same as INSN.  */
    1575            0 :           pat = PATTERN (trial);
    1576            0 :           if (rtx_equal_p (pat, ipat))
    1577              :             return trial;
    1578              : 
    1579              :           /* Can't go any further if TRIAL conflicts with INSN.  */
    1580            0 :           if (insn_sets_resource_p (trial, &needed, true))
    1581              :             return 0;
    1582              :         }
    1583              :     }
    1584              : 
    1585              :   return 0;
    1586              : }
    1587              : 
    1588              : /* Return true if THREAD can only be executed in one way.  If LABEL is nonzero,
    1589              :    it is the target of the branch insn being scanned.  If ALLOW_FALLTHROUGH
    1590              :    is true, we are allowed to fall into this thread; otherwise, we are not.
    1591              : 
    1592              :    If LABEL is used more than one or we pass a label other than LABEL before
    1593              :    finding an active insn, we do not own this thread.  */
    1594              : 
    1595              : static bool
    1596            0 : own_thread_p (rtx thread, rtx label, bool allow_fallthrough)
    1597              : {
    1598            0 :   rtx_insn *active_insn;
    1599            0 :   rtx_insn *insn;
    1600              : 
    1601              :   /* We don't own the function end.  */
    1602            0 :   if (thread == 0 || ANY_RETURN_P (thread))
    1603              :     return false;
    1604              : 
    1605              :   /* We have a non-NULL insn.  */
    1606            0 :   rtx_insn *thread_insn = as_a <rtx_insn *> (thread);
    1607              : 
    1608              :   /* Get the first active insn, or THREAD_INSN, if it is an active insn.  */
    1609            0 :   active_insn = next_active_insn (PREV_INSN (thread_insn));
    1610              : 
    1611            0 :   for (insn = thread_insn; insn != active_insn; insn = NEXT_INSN (insn))
    1612            0 :     if (LABEL_P (insn)
    1613            0 :         && (insn != label || LABEL_NUSES (insn) != 1))
    1614              :       return false;
    1615              : 
    1616            0 :   if (allow_fallthrough)
    1617              :     return true;
    1618              : 
    1619              :   /* Ensure that we reach a BARRIER before any insn or label.  */
    1620            0 :   for (insn = prev_nonnote_insn (thread_insn);
    1621            0 :        insn == 0 || !BARRIER_P (insn);
    1622            0 :        insn = prev_nonnote_insn (insn))
    1623            0 :     if (insn == 0
    1624            0 :         || LABEL_P (insn)
    1625            0 :         || (NONJUMP_INSN_P (insn)
    1626            0 :             && GET_CODE (PATTERN (insn)) != USE
    1627            0 :             && GET_CODE (PATTERN (insn)) != CLOBBER))
    1628              :       return false;
    1629              : 
    1630              :   return true;
    1631              : }
    1632              : 
    1633              : /* Called when INSN is being moved from a location near the target of a jump.
    1634              :    We leave a marker of the form (use (INSN)) immediately in front of WHERE
    1635              :    for mark_target_live_regs.  These markers will be deleted at the end.
    1636              : 
    1637              :    We used to try to update the live status of registers if WHERE is at
    1638              :    the start of a basic block, but that can't work since we may remove a
    1639              :    BARRIER in relax_delay_slots.  */
    1640              : 
    1641              : static void
    1642            0 : update_block (rtx_insn *insn, rtx_insn *where)
    1643              : {
    1644            0 :   emit_insn_before (gen_rtx_USE (VOIDmode, insn), where);
    1645              : 
    1646              :   /* INSN might be making a value live in a block where it didn't use to
    1647              :      be.  So recompute liveness information for this block.  */
    1648            0 :   incr_ticks_for_insn (insn);
    1649            0 : }
    1650              : 
    1651              : /* Similar to REDIRECT_JUMP except that we update the BB_TICKS entry for
    1652              :    the basic block containing the jump.  */
    1653              : 
    1654              : static bool
    1655            0 : reorg_redirect_jump (rtx_jump_insn *jump, rtx nlabel)
    1656              : {
    1657            0 :   incr_ticks_for_insn (jump);
    1658            0 :   return redirect_jump (jump, nlabel, 1);
    1659              : }
    1660              : 
    1661              : /* Called when INSN is being moved forward into a delay slot of DELAYED_INSN.
    1662              :    We check every instruction between INSN and DELAYED_INSN for REG_DEAD notes
    1663              :    that reference values used in INSN.  If we find one, then we move the
    1664              :    REG_DEAD note to INSN.
    1665              : 
    1666              :    This is needed to handle the case where a later insn (after INSN) has a
    1667              :    REG_DEAD note for a register used by INSN, and this later insn subsequently
    1668              :    gets moved before a CODE_LABEL because it is a redundant insn.  In this
    1669              :    case, mark_target_live_regs may be confused into thinking the register
    1670              :    is dead because it sees a REG_DEAD note immediately before a CODE_LABEL.  */
    1671              : 
    1672              : static void
    1673            0 : update_reg_dead_notes (rtx_insn *insn, rtx_insn *delayed_insn)
    1674              : {
    1675            0 :   rtx link, next;
    1676            0 :   rtx_insn *p;
    1677              : 
    1678            0 :   for (p = next_nonnote_insn (insn); p != delayed_insn;
    1679            0 :        p = next_nonnote_insn (p))
    1680            0 :     for (link = REG_NOTES (p); link; link = next)
    1681              :       {
    1682            0 :         next = XEXP (link, 1);
    1683              : 
    1684            0 :         if (REG_NOTE_KIND (link) != REG_DEAD
    1685            0 :             || !REG_P (XEXP (link, 0)))
    1686            0 :           continue;
    1687              : 
    1688            0 :         if (reg_referenced_p (XEXP (link, 0), PATTERN (insn)))
    1689              :           {
    1690              :             /* Move the REG_DEAD note from P to INSN.  */
    1691            0 :             remove_note (p, link);
    1692            0 :             XEXP (link, 1) = REG_NOTES (insn);
    1693            0 :             REG_NOTES (insn) = link;
    1694              :           }
    1695              :       }
    1696            0 : }
    1697              : 
    1698              : /* Called when an insn redundant with start_insn is deleted.  If there
    1699              :    is a REG_DEAD note for the target of start_insn between start_insn
    1700              :    and stop_insn, then the REG_DEAD note needs to be deleted since the
    1701              :    value no longer dies there.
    1702              : 
    1703              :    If the REG_DEAD note isn't deleted, then mark_target_live_regs may be
    1704              :    confused into thinking the register is dead.  */
    1705              : 
    1706              : static void
    1707            0 : fix_reg_dead_note (rtx_insn *start_insn, rtx stop_insn)
    1708              : {
    1709            0 :   rtx link, next;
    1710            0 :   rtx_insn *p;
    1711              : 
    1712            0 :   for (p = next_nonnote_insn (start_insn); p != stop_insn;
    1713            0 :        p = next_nonnote_insn (p))
    1714            0 :     for (link = REG_NOTES (p); link; link = next)
    1715              :       {
    1716            0 :         next = XEXP (link, 1);
    1717              : 
    1718            0 :         if (REG_NOTE_KIND (link) != REG_DEAD
    1719            0 :             || !REG_P (XEXP (link, 0)))
    1720            0 :           continue;
    1721              : 
    1722            0 :         if (reg_set_p (XEXP (link, 0), PATTERN (start_insn)))
    1723              :           {
    1724            0 :             remove_note (p, link);
    1725            0 :             return;
    1726              :           }
    1727              :       }
    1728              : }
    1729              : 
    1730              : /* Delete any REG_UNUSED notes that exist on INSN but not on OTHER_INSN.
    1731              : 
    1732              :    This handles the case of udivmodXi4 instructions which optimize their
    1733              :    output depending on whether any REG_UNUSED notes are present.  We must
    1734              :    make sure that INSN calculates as many results as OTHER_INSN does.  */
    1735              : 
    1736              : static void
    1737            0 : update_reg_unused_notes (rtx_insn *insn, rtx other_insn)
    1738              : {
    1739            0 :   rtx link, next;
    1740              : 
    1741            0 :   for (link = REG_NOTES (insn); link; link = next)
    1742              :     {
    1743            0 :       next = XEXP (link, 1);
    1744              : 
    1745            0 :       if (REG_NOTE_KIND (link) != REG_UNUSED
    1746            0 :           || !REG_P (XEXP (link, 0)))
    1747            0 :         continue;
    1748              : 
    1749            0 :       if (!find_regno_note (other_insn, REG_UNUSED, REGNO (XEXP (link, 0))))
    1750            0 :         remove_note (insn, link);
    1751              :     }
    1752            0 : }
    1753              : 
    1754              : static vec <rtx> sibling_labels;
    1755              : 
    1756              : /* Return the label before INSN, or put a new label there.  If SIBLING is
    1757              :    non-zero, it is another label associated with the new label (if any),
    1758              :    typically the former target of the jump that will be redirected to
    1759              :    the new label.  */
    1760              : 
    1761              : static rtx_insn *
    1762            0 : get_label_before (rtx_insn *insn, rtx sibling)
    1763              : {
    1764            0 :   rtx_insn *label;
    1765              : 
    1766              :   /* Find an existing label at this point
    1767              :      or make a new one if there is none.  */
    1768            0 :   label = prev_nonnote_insn (insn);
    1769              : 
    1770            0 :   if (label == 0 || !LABEL_P (label))
    1771              :     {
    1772            0 :       rtx_insn *prev = PREV_INSN (insn);
    1773              : 
    1774            0 :       label = gen_label_rtx ();
    1775            0 :       emit_label_after (label, prev);
    1776            0 :       LABEL_NUSES (label) = 0;
    1777            0 :       if (sibling)
    1778              :         {
    1779            0 :           sibling_labels.safe_push (label);
    1780            0 :           sibling_labels.safe_push (sibling);
    1781              :         }
    1782              :     }
    1783            0 :   return label;
    1784              : }
    1785              : 
    1786              : /* Scan a function looking for insns that need a delay slot and find insns to
    1787              :    put into the delay slot.
    1788              : 
    1789              :    NON_JUMPS_P is true if we are to only try to fill non-jump insns (such
    1790              :    as calls).  We do these first since we don't want jump insns (that are
    1791              :    easier to fill) to get the only insns that could be used for non-jump insns.
    1792              :    When it is zero, only try to fill JUMP_INSNs.
    1793              : 
    1794              :    When slots are filled in this manner, the insns (including the
    1795              :    delay_insn) are put together in a SEQUENCE rtx.  In this fashion,
    1796              :    it is possible to tell whether a delay slot has really been filled
    1797              :    or not.  `final' knows how to deal with this, by communicating
    1798              :    through FINAL_SEQUENCE.  */
    1799              : 
    1800              : static void
    1801            0 : fill_simple_delay_slots (bool non_jumps_p)
    1802              : {
    1803            0 :   rtx_insn *insn, *trial, *next_trial;
    1804            0 :   rtx pat;
    1805            0 :   int i;
    1806            0 :   int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base;
    1807            0 :   struct resources needed, set;
    1808            0 :   int slots_to_fill, slots_filled;
    1809            0 :   auto_vec<rtx_insn *, 5> delay_list;
    1810              : 
    1811            0 :   for (i = 0; i < num_unfilled_slots; i++)
    1812              :     {
    1813            0 :       int flags;
    1814              :       /* Get the next insn to fill.  If it has already had any slots assigned,
    1815              :          we can't do anything with it.  Maybe we'll improve this later.  */
    1816              : 
    1817            0 :       insn = unfilled_slots_base[i];
    1818            0 :       if (insn == 0
    1819            0 :           || insn->deleted ()
    1820            0 :           || (NONJUMP_INSN_P (insn)
    1821            0 :               && GET_CODE (PATTERN (insn)) == SEQUENCE)
    1822            0 :           || (JUMP_P (insn) && non_jumps_p)
    1823            0 :           || (!JUMP_P (insn) && ! non_jumps_p))
    1824            0 :         continue;
    1825              : 
    1826              :       /* It may have been that this insn used to need delay slots, but
    1827              :          now doesn't; ignore in that case.  This can happen, for example,
    1828              :          on the HP PA RISC, where the number of delay slots depends on
    1829              :          what insns are nearby.  */
    1830            0 :       slots_to_fill = num_delay_slots (insn);
    1831              : 
    1832              :       /* Some machine description have defined instructions to have
    1833              :          delay slots only in certain circumstances which may depend on
    1834              :          nearby insns (which change due to reorg's actions).
    1835              : 
    1836              :          For example, the PA port normally has delay slots for unconditional
    1837              :          jumps.
    1838              : 
    1839              :          However, the PA port claims such jumps do not have a delay slot
    1840              :          if they are immediate successors of certain CALL_INSNs.  This
    1841              :          allows the port to favor filling the delay slot of the call with
    1842              :          the unconditional jump.  */
    1843            0 :       if (slots_to_fill == 0)
    1844            0 :         continue;
    1845              : 
    1846              :       /* This insn needs, or can use, some delay slots.  SLOTS_TO_FILL
    1847              :          says how many.  After initialization, first try optimizing
    1848              : 
    1849              :          call _foo              call _foo
    1850              :          nop                    add %o7,.-L1,%o7
    1851              :          b,a L1
    1852              :          nop
    1853              : 
    1854              :          If this case applies, the delay slot of the call is filled with
    1855              :          the unconditional jump.  This is done first to avoid having the
    1856              :          delay slot of the call filled in the backward scan.  Also, since
    1857              :          the unconditional jump is likely to also have a delay slot, that
    1858              :          insn must exist when it is subsequently scanned.
    1859              : 
    1860              :          This is tried on each insn with delay slots as some machines
    1861              :          have insns which perform calls, but are not represented as
    1862              :          CALL_INSNs.  */
    1863              : 
    1864            0 :       slots_filled = 0;
    1865            0 :       delay_list.truncate (0);
    1866              : 
    1867            0 :       if (JUMP_P (insn))
    1868            0 :         flags = get_jump_flags (insn, JUMP_LABEL (insn));
    1869              :       else
    1870            0 :         flags = get_jump_flags (insn, NULL_RTX);
    1871              : 
    1872            0 :       if ((trial = next_active_insn (insn))
    1873            0 :           && JUMP_P (trial)
    1874            0 :           && simplejump_p (trial)
    1875            0 :           && eligible_for_delay (insn, slots_filled, trial, flags)
    1876            0 :           && no_labels_between_p (insn, trial)
    1877            0 :           && ! can_throw_internal (trial))
    1878              :         {
    1879            0 :           rtx_insn **tmp;
    1880            0 :           slots_filled++;
    1881            0 :           add_to_delay_list (trial, &delay_list);
    1882              : 
    1883              :           /* TRIAL may have had its delay slot filled, then unfilled.  When
    1884              :              the delay slot is unfilled, TRIAL is placed back on the unfilled
    1885              :              slots obstack.  Unfortunately, it is placed on the end of the
    1886              :              obstack, not in its original location.  Therefore, we must search
    1887              :              from entry i + 1 to the end of the unfilled slots obstack to
    1888              :              try and find TRIAL.  */
    1889            0 :           tmp = &unfilled_slots_base[i + 1];
    1890            0 :           while (*tmp != trial && tmp != unfilled_slots_next)
    1891            0 :             tmp++;
    1892              : 
    1893              :           /* Remove the unconditional jump from consideration for delay slot
    1894              :              filling and unthread it.  */
    1895            0 :           if (*tmp == trial)
    1896            0 :             *tmp = 0;
    1897            0 :           {
    1898            0 :             rtx_insn *next = NEXT_INSN (trial);
    1899            0 :             rtx_insn *prev = PREV_INSN (trial);
    1900            0 :             if (prev)
    1901            0 :               SET_NEXT_INSN (prev) = next;
    1902            0 :             if (next)
    1903            0 :               SET_PREV_INSN (next) = prev;
    1904              :           }
    1905              :         }
    1906              : 
    1907              :       /* Now, scan backwards from the insn to search for a potential
    1908              :          delay-slot candidate.  Stop searching when a label or jump is hit.
    1909              : 
    1910              :          For each candidate, if it is to go into the delay slot (moved
    1911              :          forward in execution sequence), it must not need or set any resources
    1912              :          that were set by later insns and must not set any resources that
    1913              :          are needed for those insns.
    1914              : 
    1915              :          The delay slot insn itself sets resources unless it is a call
    1916              :          (in which case the called routine, not the insn itself, is doing
    1917              :          the setting).  */
    1918              : 
    1919            0 :       if (slots_filled < slots_to_fill)
    1920              :         {
    1921              :           /* If the flags register is dead after the insn, then we want to be
    1922              :              able to accept a candidate that clobbers it.  For this purpose,
    1923              :              we need to filter the flags register during life analysis, so
    1924              :              that it doesn't create RAW and WAW dependencies, while still
    1925              :              creating the necessary WAR dependencies.  */
    1926            0 :           bool filter_flags
    1927              :             = (slots_to_fill == 1
    1928            0 :                && targetm.flags_regnum != INVALID_REGNUM
    1929            0 :                && find_regno_note (insn, REG_DEAD, targetm.flags_regnum));
    1930            0 :           struct resources fset;
    1931            0 :           CLEAR_RESOURCE (&needed);
    1932            0 :           CLEAR_RESOURCE (&set);
    1933            0 :           mark_set_resources (insn, &set, 0, MARK_SRC_DEST);
    1934            0 :           if (filter_flags)
    1935              :             {
    1936            0 :               CLEAR_RESOURCE (&fset);
    1937            0 :               mark_set_resources (insn, &fset, 0, MARK_SRC_DEST);
    1938              :             }
    1939            0 :           mark_referenced_resources (insn, &needed, false);
    1940              : 
    1941            0 :           for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, true);
    1942            0 :                trial = next_trial)
    1943              :             {
    1944            0 :               next_trial = prev_nonnote_insn (trial);
    1945              : 
    1946              :               /* This must be an INSN or CALL_INSN.  */
    1947            0 :               pat = PATTERN (trial);
    1948              : 
    1949              :               /* Stand-alone USE and CLOBBER are just for flow.  */
    1950            0 :               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
    1951            0 :                 continue;
    1952              : 
    1953              :               /* And DEBUG_INSNs never go into delay slots.  */
    1954            0 :               if (GET_CODE (trial) == DEBUG_INSN)
    1955            0 :                 continue;
    1956              : 
    1957              :               /* Check for resource conflict first, to avoid unnecessary
    1958              :                  splitting.  */
    1959            0 :               if (! insn_references_resource_p (trial, &set, true)
    1960            0 :                   && ! insn_sets_resource_p (trial,
    1961              :                                              filter_flags ? &fset : &set,
    1962              :                                              true)
    1963            0 :                   && ! insn_sets_resource_p (trial, &needed, true)
    1964            0 :                   && ! can_throw_internal (trial))
    1965              :                 {
    1966            0 :                   trial = try_split (pat, trial, 1);
    1967            0 :                   next_trial = prev_nonnote_insn (trial);
    1968            0 :                   if (eligible_for_delay (insn, slots_filled, trial, flags))
    1969              :                     {
    1970              :                       /* In this case, we are searching backward, so if we
    1971              :                          find insns to put on the delay list, we want
    1972              :                          to put them at the head, rather than the
    1973              :                          tail, of the list.  */
    1974              : 
    1975            0 :                       update_reg_dead_notes (trial, insn);
    1976            0 :                       delay_list.safe_insert (0, trial);
    1977            0 :                       update_block (trial, trial);
    1978            0 :                       delete_related_insns (trial);
    1979            0 :                       if (slots_to_fill == ++slots_filled)
    1980              :                         break;
    1981            0 :                       continue;
    1982              :                     }
    1983              :                 }
    1984              : 
    1985            0 :               mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
    1986            0 :               if (filter_flags)
    1987              :                 {
    1988            0 :                   mark_set_resources (trial, &fset, 0, MARK_SRC_DEST_CALL);
    1989              :                   /* If the flags register is set, then it doesn't create RAW
    1990              :                      dependencies any longer and it also doesn't create WAW
    1991              :                      dependencies since it's dead after the original insn.  */
    1992            0 :                   if (TEST_HARD_REG_BIT (fset.regs, targetm.flags_regnum))
    1993              :                     {
    1994            0 :                       CLEAR_HARD_REG_BIT (needed.regs, targetm.flags_regnum);
    1995            0 :                       CLEAR_HARD_REG_BIT (fset.regs, targetm.flags_regnum);
    1996              :                     }
    1997              :                 }
    1998            0 :               mark_referenced_resources (trial, &needed, true);
    1999              :             }
    2000              :         }
    2001              : 
    2002              :       /* If all needed slots haven't been filled, we come here.  */
    2003              : 
    2004              :       /* Try to optimize case of jumping around a single insn.  */
    2005            0 :       if ((ANNUL_IFTRUE_SLOTS || ANNUL_IFFALSE_SLOTS)
    2006              :         && slots_filled != slots_to_fill
    2007              :           && delay_list.is_empty ()
    2008              :           && JUMP_P (insn)
    2009              :           && (condjump_p (insn) || condjump_in_parallel_p (insn))
    2010              :           && !ANY_RETURN_P (JUMP_LABEL (insn)))
    2011              :         {
    2012              :           optimize_skip (as_a <rtx_jump_insn *> (insn), &delay_list);
    2013              :           if (!delay_list.is_empty ())
    2014              :             slots_filled += 1;
    2015              :         }
    2016              : 
    2017              :       /* Try to get insns from beyond the insn needing the delay slot.
    2018              :          These insns can neither set or reference resources set in insns being
    2019              :          skipped, cannot set resources in the insn being skipped, and, if this
    2020              :          is a CALL_INSN (or a CALL_INSN is passed), cannot trap (because the
    2021              :          call might not return).
    2022              : 
    2023              :          There used to be code which continued past the target label if
    2024              :          we saw all uses of the target label.  This code did not work,
    2025              :          because it failed to account for some instructions which were
    2026              :          both annulled and marked as from the target.  This can happen as a
    2027              :          result of optimize_skip.  Since this code was redundant with
    2028              :          fill_eager_delay_slots anyways, it was just deleted.  */
    2029              : 
    2030            0 :       if (slots_filled != slots_to_fill
    2031              :           /* If this instruction could throw an exception which is
    2032              :              caught in the same function, then it's not safe to fill
    2033              :              the delay slot with an instruction from beyond this
    2034              :              point.  For example, consider:
    2035              : 
    2036              :                int i = 2;
    2037              : 
    2038              :                try {
    2039              :                  f();
    2040              :                  i = 3;
    2041              :                } catch (...) {}
    2042              : 
    2043              :                return i;
    2044              : 
    2045              :              Even though `i' is a local variable, we must be sure not
    2046              :              to put `i = 3' in the delay slot if `f' might throw an
    2047              :              exception.
    2048              : 
    2049              :              Presumably, we should also check to see if we could get
    2050              :              back to this function via `setjmp'.  */
    2051            0 :           && ! can_throw_internal (insn)
    2052            0 :           && !JUMP_P (insn))
    2053              :         {
    2054            0 :           bool maybe_never = false;
    2055            0 :           rtx pat, trial_delay;
    2056              : 
    2057            0 :           CLEAR_RESOURCE (&needed);
    2058            0 :           CLEAR_RESOURCE (&set);
    2059            0 :           mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
    2060            0 :           mark_referenced_resources (insn, &needed, true);
    2061              : 
    2062            0 :           if (CALL_P (insn))
    2063            0 :             maybe_never = true;
    2064              : 
    2065            0 :           for (trial = next_nonnote_insn (insn); !stop_search_p (trial, true);
    2066            0 :                trial = next_trial)
    2067              :             {
    2068            0 :               next_trial = next_nonnote_insn (trial);
    2069              : 
    2070              :               /* This must be an INSN or CALL_INSN.  */
    2071            0 :               pat = PATTERN (trial);
    2072              : 
    2073              :               /* Stand-alone USE and CLOBBER are just for flow.  */
    2074            0 :               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
    2075            0 :                 continue;
    2076              : 
    2077              :               /* And DEBUG_INSNs do not go in delay slots.  */
    2078            0 :               if (GET_CODE (trial) == DEBUG_INSN)
    2079            0 :                 continue;
    2080              : 
    2081              :               /* If this already has filled delay slots, get the insn needing
    2082              :                  the delay slots.  */
    2083            0 :               if (GET_CODE (pat) == SEQUENCE)
    2084            0 :                 trial_delay = XVECEXP (pat, 0, 0);
    2085              :               else
    2086              :                 trial_delay = trial;
    2087              : 
    2088              :               /* Stop our search when seeing a jump.  */
    2089            0 :               if (JUMP_P (trial_delay))
    2090              :                 break;
    2091              : 
    2092              :               /* See if we have a resource problem before we try to split.  */
    2093            0 :               if (GET_CODE (pat) != SEQUENCE
    2094            0 :                   && ! insn_references_resource_p (trial, &set, true)
    2095            0 :                   && ! insn_sets_resource_p (trial, &set, true)
    2096            0 :                   && ! insn_sets_resource_p (trial, &needed, true)
    2097            0 :                   && ! (maybe_never && may_trap_or_fault_p (pat))
    2098            0 :                   && (trial = try_split (pat, trial, 0))
    2099            0 :                   && eligible_for_delay (insn, slots_filled, trial, flags)
    2100            0 :                   && ! can_throw_internal (trial))
    2101              :                 {
    2102            0 :                   next_trial = next_nonnote_insn (trial);
    2103            0 :                   add_to_delay_list (trial, &delay_list);
    2104              : 
    2105            0 :                   delete_related_insns (trial);
    2106            0 :                   if (slots_to_fill == ++slots_filled)
    2107              :                     break;
    2108            0 :                   continue;
    2109              :                 }
    2110              : 
    2111            0 :               mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
    2112            0 :               mark_referenced_resources (trial, &needed, true);
    2113              : 
    2114              :               /* Ensure we don't put insns between the setting of cc and the
    2115              :                  comparison by moving a setting of cc into an earlier delay
    2116              :                  slot since these insns could clobber the condition code.  */
    2117            0 :               set.cc = 1;
    2118              : 
    2119              :               /* If this is a call, we might not get here.  */
    2120            0 :               if (CALL_P (trial_delay))
    2121            0 :                 maybe_never = true;
    2122              :             }
    2123              : 
    2124              :           /* If there are slots left to fill and our search was stopped by an
    2125              :              unconditional branch, try the insn at the branch target.  We can
    2126              :              redirect the branch if it works.
    2127              : 
    2128              :              Don't do this if the insn at the branch target is a branch.  */
    2129            0 :           if (slots_to_fill != slots_filled
    2130            0 :               && trial
    2131            0 :               && jump_to_label_p (trial)
    2132            0 :               && simplejump_p (trial)
    2133            0 :               && (next_trial = next_active_insn (JUMP_LABEL_AS_INSN (trial))) != 0
    2134            0 :               && ! (NONJUMP_INSN_P (next_trial)
    2135            0 :                     && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
    2136            0 :               && !JUMP_P (next_trial)
    2137            0 :               && ! insn_references_resource_p (next_trial, &set, true)
    2138            0 :               && ! insn_sets_resource_p (next_trial, &set, true)
    2139            0 :               && ! insn_sets_resource_p (next_trial, &needed, true)
    2140            0 :               && ! (maybe_never && may_trap_or_fault_p (PATTERN (next_trial)))
    2141            0 :               && (next_trial = try_split (PATTERN (next_trial), next_trial, 0))
    2142            0 :               && eligible_for_delay (insn, slots_filled, next_trial, flags)
    2143            0 :               && ! can_throw_internal (trial))
    2144              :             {
    2145              :               /* See comment in relax_delay_slots about necessity of using
    2146              :                  next_real_nondebug_insn here.  */
    2147            0 :               rtx_insn *new_label = next_real_nondebug_insn (next_trial);
    2148              : 
    2149            0 :               if (new_label != 0)
    2150            0 :                 new_label = get_label_before (new_label, JUMP_LABEL (trial));
    2151              :               else
    2152            0 :                 new_label = find_end_label (simple_return_rtx);
    2153              : 
    2154            0 :               if (new_label)
    2155              :                 {
    2156            0 :                   add_to_delay_list (copy_delay_slot_insn (next_trial),
    2157              :                                      &delay_list);
    2158            0 :                   slots_filled++;
    2159            0 :                   reorg_redirect_jump (as_a <rtx_jump_insn *> (trial),
    2160              :                                        new_label);
    2161              :                 }
    2162              :             }
    2163              :         }
    2164              : 
    2165              :       /* If this is an unconditional jump, then try to get insns from the
    2166              :          target of the jump.  */
    2167            0 :       rtx_jump_insn *jump_insn;
    2168            0 :       if ((jump_insn = dyn_cast <rtx_jump_insn *> (insn))
    2169            0 :           && simplejump_p (jump_insn)
    2170            0 :           && slots_filled != slots_to_fill)
    2171            0 :         fill_slots_from_thread (jump_insn, const_true_rtx,
    2172            0 :                                 next_active_insn (JUMP_LABEL_AS_INSN (insn)),
    2173              :                                 NULL, 1, 1, own_thread_p (JUMP_LABEL (insn),
    2174              :                                                  JUMP_LABEL (insn), false),
    2175              :                                 slots_to_fill, &slots_filled, &delay_list);
    2176              : 
    2177            0 :       if (!delay_list.is_empty ())
    2178            0 :         unfilled_slots_base[i]
    2179            0 :           = emit_delay_sequence (insn, delay_list, slots_filled);
    2180              : 
    2181            0 :       if (slots_to_fill == slots_filled)
    2182            0 :         unfilled_slots_base[i] = 0;
    2183              : 
    2184            0 :       note_delay_statistics (slots_filled, 0);
    2185              :     }
    2186            0 : }
    2187              : 
    2188              : /* Follow any unconditional jump at LABEL, for the purpose of redirecting JUMP;
    2189              :    return the ultimate label reached by any such chain of jumps.
    2190              :    Return a suitable return rtx if the chain ultimately leads to a
    2191              :    return instruction.
    2192              :    If LABEL is not followed by a jump, return LABEL.
    2193              :    If the chain loops or we can't find end, return LABEL,
    2194              :    since that tells caller to avoid changing the insn.
    2195              :    If the returned label is obtained by following a crossing jump,
    2196              :    set *CROSSING to true, otherwise set it to false.  */
    2197              : 
    2198              : static rtx
    2199            0 : follow_jumps (rtx label, rtx_insn *jump, bool *crossing)
    2200              : {
    2201            0 :   rtx_insn *insn;
    2202            0 :   rtx_insn *next;
    2203            0 :   int depth;
    2204              : 
    2205            0 :   *crossing = false;
    2206            0 :   if (ANY_RETURN_P (label))
    2207              :     return label;
    2208              : 
    2209            0 :   rtx_insn *value = as_a <rtx_insn *> (label);
    2210              : 
    2211            0 :   for (depth = 0;
    2212              :        (depth < 10
    2213            0 :         && (insn = next_active_insn (value)) != 0
    2214            0 :         && JUMP_P (insn)
    2215            0 :         && JUMP_LABEL (insn) != NULL_RTX
    2216            0 :         && ((any_uncondjump_p (insn) && onlyjump_p (insn))
    2217            0 :             || ANY_RETURN_P (PATTERN (insn)))
    2218            0 :         && (next = NEXT_INSN (insn))
    2219            0 :         && BARRIER_P (next));
    2220              :        depth++)
    2221              :     {
    2222            0 :       rtx this_label_or_return = JUMP_LABEL (insn);
    2223              : 
    2224              :       /* If we have found a cycle, make the insn jump to itself.  */
    2225            0 :       if (this_label_or_return == label)
    2226              :         return label;
    2227              : 
    2228              :       /* Cannot follow returns and cannot look through tablejumps.  */
    2229            0 :       if (ANY_RETURN_P (this_label_or_return))
    2230              :         return this_label_or_return;
    2231              : 
    2232            0 :       rtx_insn *this_label = as_a <rtx_insn *> (this_label_or_return);
    2233            0 :       if (NEXT_INSN (this_label)
    2234            0 :           && JUMP_TABLE_DATA_P (NEXT_INSN (this_label)))
    2235              :         break;
    2236              : 
    2237            0 :       if (!targetm.can_follow_jump (jump, insn))
    2238              :         break;
    2239            0 :       if (!*crossing)
    2240            0 :         *crossing = CROSSING_JUMP_P (jump);
    2241            0 :       value = this_label;
    2242              :     }
    2243            0 :   if (depth == 10)
    2244            0 :     return label;
    2245              :   return value;
    2246              : }
    2247              : 
    2248              : /* Try to find insns to place in delay slots.
    2249              : 
    2250              :    INSN is the jump needing SLOTS_TO_FILL delay slots.  It tests CONDITION
    2251              :    or is an unconditional branch if CONDITION is const_true_rtx.
    2252              :    *PSLOTS_FILLED is updated with the number of slots that we have filled.
    2253              : 
    2254              :    THREAD is a flow-of-control, either the insns to be executed if the
    2255              :    branch is true or if the branch is false, THREAD_IF_TRUE says which.
    2256              : 
    2257              :    OPPOSITE_THREAD is the thread in the opposite direction.  It is used
    2258              :    to see if any potential delay slot insns set things needed there.
    2259              : 
    2260              :    LIKELY is true if it is extremely likely that the branch will be
    2261              :    taken and THREAD_IF_TRUE is set.  This is used for the branch at the
    2262              :    end of a loop back up to the top.
    2263              : 
    2264              :    OWN_THREAD is true if we are the only user of the thread, i.e. it is
    2265              :    the target of the jump when we are the only jump going there.
    2266              : 
    2267              :    If OWN_THREAD is false, it must be the "true" thread of a jump.  In that
    2268              :    case, we can only take insns from the head of the thread for our delay
    2269              :    slot.  We then adjust the jump to point after the insns we have taken.  */
    2270              : 
    2271              : static void
    2272            0 : fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
    2273              :                         rtx thread_or_return, rtx opposite_thread, bool likely,
    2274              :                         bool thread_if_true, bool own_thread, int slots_to_fill,
    2275              :                         int *pslots_filled, vec<rtx_insn *> *delay_list)
    2276              : {
    2277            0 :   rtx new_thread;
    2278            0 :   struct resources opposite_needed, set, needed;
    2279            0 :   rtx_insn *trial;
    2280            0 :   bool lose = false;
    2281            0 :   bool must_annul = false;
    2282            0 :   int flags;
    2283              : 
    2284              :   /* Validate our arguments.  */
    2285            0 :   gcc_assert (condition != const_true_rtx || thread_if_true);
    2286            0 :   gcc_assert (own_thread || thread_if_true);
    2287              : 
    2288            0 :   flags = get_jump_flags (insn, JUMP_LABEL (insn));
    2289              : 
    2290              :   /* If our thread is the end of subroutine, we can't get any delay
    2291              :      insns from that.  */
    2292            0 :   if (thread_or_return == NULL_RTX || ANY_RETURN_P (thread_or_return))
    2293            0 :     return;
    2294              : 
    2295            0 :   rtx_insn *thread = as_a <rtx_insn *> (thread_or_return);
    2296              : 
    2297              :   /* If this is an unconditional branch, nothing is needed at the
    2298              :      opposite thread.  Otherwise, compute what is needed there.  */
    2299            0 :   if (condition == const_true_rtx)
    2300            0 :     CLEAR_RESOURCE (&opposite_needed);
    2301              :   else
    2302            0 :     mark_target_live_regs (get_insns (), opposite_thread, &opposite_needed);
    2303              : 
    2304              :   /* If the insn at THREAD can be split, do it here to avoid having to
    2305              :      update THREAD and NEW_THREAD if it is done in the loop below.  Also
    2306              :      initialize NEW_THREAD.  */
    2307              : 
    2308            0 :   new_thread = thread = try_split (PATTERN (thread), thread, 0);
    2309              : 
    2310              :   /* Scan insns at THREAD.  We are looking for an insn that can be removed
    2311              :      from THREAD (it neither sets nor references resources that were set
    2312              :      ahead of it and it doesn't set anything needs by the insns ahead of
    2313              :      it) and that either can be placed in an annulling insn or aren't
    2314              :      needed at OPPOSITE_THREAD.  */
    2315              : 
    2316            0 :   CLEAR_RESOURCE (&needed);
    2317            0 :   CLEAR_RESOURCE (&set);
    2318              : 
    2319              :   /* Handle the flags register specially, to be able to accept a
    2320              :      candidate that clobbers it.  See also fill_simple_delay_slots.  */
    2321            0 :   bool filter_flags
    2322              :     = (slots_to_fill == 1
    2323            0 :        && targetm.flags_regnum != INVALID_REGNUM
    2324            0 :        && find_regno_note (insn, REG_DEAD, targetm.flags_regnum));
    2325            0 :   struct resources fset;
    2326            0 :   struct resources flags_res;
    2327            0 :   if (filter_flags)
    2328              :     {
    2329            0 :       CLEAR_RESOURCE (&fset);
    2330            0 :       CLEAR_RESOURCE (&flags_res);
    2331            0 :       SET_HARD_REG_BIT (flags_res.regs, targetm.flags_regnum);
    2332              :     }
    2333              : 
    2334              :   /* If we do not own this thread, we must stop as soon as we find
    2335              :      something that we can't put in a delay slot, since all we can do
    2336              :      is branch into THREAD at a later point.  Therefore, labels stop
    2337              :      the search if this is not the `true' thread.  */
    2338              : 
    2339            0 :   for (trial = thread;
    2340            0 :        ! stop_search_p (trial, ! thread_if_true) && (! lose || own_thread);
    2341            0 :        trial = next_nonnote_insn (trial))
    2342              :     {
    2343            0 :       rtx pat, old_trial;
    2344              : 
    2345              :       /* If we have passed a label, we no longer own this thread.  */
    2346            0 :       if (LABEL_P (trial))
    2347              :         {
    2348            0 :           own_thread = 0;
    2349            0 :           continue;
    2350              :         }
    2351              : 
    2352            0 :       pat = PATTERN (trial);
    2353            0 :       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
    2354            0 :         continue;
    2355              : 
    2356            0 :       if (GET_CODE (trial) == DEBUG_INSN)
    2357            0 :         continue;
    2358              : 
    2359              :       /* If TRIAL conflicts with the insns ahead of it, we lose.  */
    2360            0 :       if (! insn_references_resource_p (trial, &set, true)
    2361            0 :           && ! insn_sets_resource_p (trial, filter_flags ? &fset : &set, true)
    2362            0 :           && ! insn_sets_resource_p (trial, &needed, true)
    2363              :           /* If we're handling sets to the flags register specially, we
    2364              :              only allow an insn into a delay-slot, if it either:
    2365              :              - doesn't set the flags register,
    2366              :              - the "set" of the flags register isn't used (clobbered),
    2367              :              - insns between the delay-slot insn and the trial-insn
    2368              :              as accounted in "set", have not affected the flags register.  */
    2369            0 :           && (! filter_flags
    2370            0 :               || ! insn_sets_resource_p (trial, &flags_res, true)
    2371            0 :               || find_regno_note (trial, REG_UNUSED, targetm.flags_regnum)
    2372            0 :               || ! TEST_HARD_REG_BIT (set.regs, targetm.flags_regnum))
    2373            0 :           && ! can_throw_internal (trial))
    2374              :         {
    2375            0 :           rtx_insn *prior_insn;
    2376              : 
    2377              :           /* If TRIAL is redundant with some insn before INSN, we don't
    2378              :              actually need to add it to the delay list; we can merely pretend
    2379              :              we did.  */
    2380            0 :           if ((prior_insn = redundant_insn (trial, insn, *delay_list)))
    2381              :             {
    2382            0 :               fix_reg_dead_note (prior_insn, insn);
    2383            0 :               if (own_thread)
    2384              :                 {
    2385            0 :                   update_block (trial, thread);
    2386            0 :                   if (trial == thread)
    2387              :                     {
    2388            0 :                       thread = next_active_insn (thread);
    2389            0 :                       if (new_thread == trial)
    2390            0 :                         new_thread = thread;
    2391              :                     }
    2392              : 
    2393            0 :                   delete_related_insns (trial);
    2394              :                 }
    2395              :               else
    2396              :                 {
    2397            0 :                   update_reg_unused_notes (prior_insn, trial);
    2398            0 :                   new_thread = next_active_insn (trial);
    2399              :                 }
    2400              : 
    2401            0 :               continue;
    2402              :             }
    2403              : 
    2404              :           /* There are two ways we can win:  If TRIAL doesn't set anything
    2405              :              needed at the opposite thread and can't trap, or if it can
    2406              :              go into an annulled delay slot.  But we want neither to copy
    2407              :              nor to speculate frame-related insns.  */
    2408            0 :           if (!must_annul
    2409            0 :               && ((condition == const_true_rtx
    2410            0 :                    && (own_thread || !RTX_FRAME_RELATED_P (trial)))
    2411            0 :                   || (! insn_sets_resource_p (trial, &opposite_needed, true)
    2412            0 :                       && ! may_trap_or_fault_p (pat)
    2413            0 :                       && ! RTX_FRAME_RELATED_P (trial))))
    2414              :             {
    2415            0 :               old_trial = trial;
    2416            0 :               trial = try_split (pat, trial, 0);
    2417            0 :               if (new_thread == old_trial)
    2418            0 :                 new_thread = trial;
    2419            0 :               if (thread == old_trial)
    2420            0 :                 thread = trial;
    2421            0 :               pat = PATTERN (trial);
    2422            0 :               if (eligible_for_delay (insn, *pslots_filled, trial, flags))
    2423            0 :                 goto winner;
    2424              :             }
    2425            0 :           else if (!RTX_FRAME_RELATED_P (trial)
    2426              :                    && ((ANNUL_IFTRUE_SLOTS && ! thread_if_true)
    2427              :                         || (ANNUL_IFFALSE_SLOTS && thread_if_true)))
    2428              :             {
    2429              :               old_trial = trial;
    2430              :               trial = try_split (pat, trial, 0);
    2431              :               if (new_thread == old_trial)
    2432              :                 new_thread = trial;
    2433              :               if (thread == old_trial)
    2434              :                 thread = trial;
    2435              :               pat = PATTERN (trial);
    2436              :               if ((must_annul || delay_list->is_empty ()) && (thread_if_true
    2437              :                    ? check_annul_list_true_false (false, *delay_list)
    2438              :                      && eligible_for_annul_false (insn, *pslots_filled, trial, flags)
    2439              :                    : check_annul_list_true_false (true, *delay_list)
    2440              :                      && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
    2441              :                 {
    2442              :                   rtx_insn *temp;
    2443              : 
    2444              :                   must_annul = true;
    2445            0 :                 winner:
    2446              : 
    2447              :                   /* If we own this thread, delete the insn.  If this is the
    2448              :                      destination of a branch, show that a basic block status
    2449              :                      may have been updated.  In any case, mark the new
    2450              :                      starting point of this thread.  */
    2451            0 :                   if (own_thread)
    2452              :                     {
    2453            0 :                       rtx note;
    2454              : 
    2455            0 :                       update_block (trial, thread);
    2456            0 :                       if (trial == thread)
    2457              :                         {
    2458            0 :                           thread = next_active_insn (thread);
    2459            0 :                           if (new_thread == trial)
    2460            0 :                             new_thread = thread;
    2461              :                         }
    2462              : 
    2463              :                       /* We are moving this insn, not deleting it.  We must
    2464              :                          temporarily increment the use count on any referenced
    2465              :                          label lest it be deleted by delete_related_insns.  */
    2466            0 :                       for (note = REG_NOTES (trial);
    2467            0 :                            note != NULL_RTX;
    2468            0 :                            note = XEXP (note, 1))
    2469            0 :                         if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
    2470            0 :                             || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
    2471              :                           {
    2472              :                             /* REG_LABEL_OPERAND could be
    2473              :                                NOTE_INSN_DELETED_LABEL too.  */
    2474            0 :                             if (LABEL_P (XEXP (note, 0)))
    2475            0 :                               LABEL_NUSES (XEXP (note, 0))++;
    2476              :                             else
    2477            0 :                               gcc_assert (REG_NOTE_KIND (note)
    2478              :                                           == REG_LABEL_OPERAND);
    2479              :                           }
    2480            0 :                       if (jump_to_label_p (trial))
    2481            0 :                         LABEL_NUSES (JUMP_LABEL (trial))++;
    2482              : 
    2483            0 :                       delete_related_insns (trial);
    2484              : 
    2485            0 :                       for (note = REG_NOTES (trial);
    2486            0 :                            note != NULL_RTX;
    2487            0 :                            note = XEXP (note, 1))
    2488            0 :                         if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
    2489            0 :                             || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
    2490              :                           {
    2491              :                             /* REG_LABEL_OPERAND could be
    2492              :                                NOTE_INSN_DELETED_LABEL too.  */
    2493            0 :                             if (LABEL_P (XEXP (note, 0)))
    2494            0 :                               LABEL_NUSES (XEXP (note, 0))--;
    2495              :                             else
    2496            0 :                               gcc_assert (REG_NOTE_KIND (note)
    2497              :                                           == REG_LABEL_OPERAND);
    2498              :                           }
    2499            0 :                       if (jump_to_label_p (trial))
    2500            0 :                         LABEL_NUSES (JUMP_LABEL (trial))--;
    2501              :                     }
    2502              :                   else
    2503            0 :                     new_thread = next_active_insn (trial);
    2504              : 
    2505            0 :                   temp = own_thread ? trial : copy_delay_slot_insn (trial);
    2506            0 :                   if (thread_if_true)
    2507            0 :                     INSN_FROM_TARGET_P (temp) = 1;
    2508              : 
    2509            0 :                   add_to_delay_list (temp, delay_list);
    2510              : 
    2511            0 :                   if (slots_to_fill == ++(*pslots_filled))
    2512              :                     {
    2513              :                       /* Even though we have filled all the slots, we
    2514              :                          may be branching to a location that has a
    2515              :                          redundant insn.  Skip any if so.  */
    2516            0 :                       while (new_thread && ! own_thread
    2517            0 :                              && ! insn_sets_resource_p (new_thread, &set, true)
    2518            0 :                              && ! insn_sets_resource_p (new_thread, &needed,
    2519              :                                                         true)
    2520            0 :                              && ! insn_references_resource_p (new_thread,
    2521              :                                                               &set, true)
    2522            0 :                              && (prior_insn
    2523            0 :                                  = redundant_insn (new_thread, insn,
    2524              :                                                    *delay_list)))
    2525              :                         {
    2526              :                           /* We know we do not own the thread, so no need
    2527              :                              to call update_block and delete_insn.  */
    2528            0 :                           fix_reg_dead_note (prior_insn, insn);
    2529            0 :                           update_reg_unused_notes (prior_insn, new_thread);
    2530            0 :                           new_thread
    2531            0 :                             = next_active_insn (as_a<rtx_insn *> (new_thread));
    2532              :                         }
    2533              :                       break;
    2534              :                     }
    2535              : 
    2536            0 :                   continue;
    2537            0 :                 }
    2538              :             }
    2539              :         }
    2540              : 
    2541              :       /* This insn can't go into a delay slot.  */
    2542            0 :       lose = true;
    2543            0 :       mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
    2544            0 :       mark_referenced_resources (trial, &needed, true);
    2545            0 :       if (filter_flags)
    2546              :         {
    2547            0 :           mark_set_resources (trial, &fset, 0, MARK_SRC_DEST_CALL);
    2548              : 
    2549              :           /* Groups of flags-register setters with users should not
    2550              :              affect opportunities to move flags-register-setting insns
    2551              :              (clobbers) into the delay-slot.  */
    2552            0 :           CLEAR_HARD_REG_BIT (needed.regs, targetm.flags_regnum);
    2553            0 :           CLEAR_HARD_REG_BIT (fset.regs, targetm.flags_regnum);
    2554              :         }
    2555              : 
    2556              :       /* Ensure we don't put insns between the setting of cc and the comparison
    2557              :          by moving a setting of cc into an earlier delay slot since these insns
    2558              :          could clobber the condition code.  */
    2559            0 :       set.cc = 1;
    2560              : 
    2561              :       /* If this insn is a register-register copy and the next insn has
    2562              :          a use of our destination, change it to use our source.  That way,
    2563              :          it will become a candidate for our delay slot the next time
    2564              :          through this loop.  This case occurs commonly in loops that
    2565              :          scan a list.
    2566              : 
    2567              :          We could check for more complex cases than those tested below,
    2568              :          but it doesn't seem worth it.  It might also be a good idea to try
    2569              :          to swap the two insns.  That might do better.
    2570              : 
    2571              :          We can't do this if the next insn modifies our destination, because
    2572              :          that would make the replacement into the insn invalid.  We also can't
    2573              :          do this if it modifies our source, because it might be an earlyclobber
    2574              :          operand.  This latter test also prevents updating the contents of
    2575              :          a PRE_INC.  We also can't do this if there's overlap of source and
    2576              :          destination.  Overlap may happen for larger-than-register-size modes.  */
    2577              : 
    2578            0 :       if (NONJUMP_INSN_P (trial) && GET_CODE (pat) == SET
    2579            0 :           && REG_P (SET_SRC (pat))
    2580            0 :           && REG_P (SET_DEST (pat))
    2581            0 :           && !reg_overlap_mentioned_p (SET_DEST (pat), SET_SRC (pat)))
    2582              :         {
    2583            0 :           rtx_insn *next = next_nonnote_insn (trial);
    2584              : 
    2585            0 :           if (next && NONJUMP_INSN_P (next)
    2586            0 :               && GET_CODE (PATTERN (next)) != USE
    2587            0 :               && ! reg_set_p (SET_DEST (pat), next)
    2588            0 :               && ! reg_set_p (SET_SRC (pat), next)
    2589            0 :               && reg_referenced_p (SET_DEST (pat), PATTERN (next))
    2590            0 :               && ! modified_in_p (SET_DEST (pat), next))
    2591            0 :             validate_replace_rtx (SET_DEST (pat), SET_SRC (pat), next);
    2592              :         }
    2593              :     }
    2594              : 
    2595              :   /* If we stopped on a branch insn that has delay slots, see if we can
    2596              :      steal some of the insns in those slots.  */
    2597            0 :   if (trial && NONJUMP_INSN_P (trial)
    2598            0 :       && GET_CODE (PATTERN (trial)) == SEQUENCE
    2599            0 :       && JUMP_P (XVECEXP (PATTERN (trial), 0, 0)))
    2600              :     {
    2601            0 :       rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (trial));
    2602              :       /* If this is the `true' thread, we will want to follow the jump,
    2603              :          so we can only do this if we have taken everything up to here.  */
    2604            0 :       if (thread_if_true && trial == new_thread)
    2605              :         {
    2606            0 :           steal_delay_list_from_target (insn, condition, sequence,
    2607              :                                         delay_list, &set, &needed,
    2608              :                                         &opposite_needed, slots_to_fill,
    2609              :                                         pslots_filled, &must_annul,
    2610              :                                         &new_thread);
    2611              :           /* If we owned the thread and are told that it branched
    2612              :              elsewhere, make sure we own the thread at the new location.  */
    2613            0 :           if (own_thread && trial != new_thread)
    2614            0 :             own_thread = own_thread_p (new_thread, new_thread, false);
    2615              :         }
    2616              :       else if (! thread_if_true)
    2617            0 :         steal_delay_list_from_fallthrough (insn, condition, sequence,
    2618              :                                            delay_list, &set, &needed,
    2619              :                                            &opposite_needed, slots_to_fill,
    2620              :                                            pslots_filled, &must_annul);
    2621              :     }
    2622              : 
    2623              :   /* If we haven't found anything for this delay slot and it is very
    2624              :      likely that the branch will be taken, see if the insn at our target
    2625              :      increments or decrements a register with an increment that does not
    2626              :      depend on the destination register.  If so, try to place the opposite
    2627              :      arithmetic insn after the jump insn and put the arithmetic insn in the
    2628              :      delay slot.  If we can't do this, return.  */
    2629            0 :   if (delay_list->is_empty () && likely
    2630            0 :       && new_thread
    2631            0 :       && !ANY_RETURN_P (new_thread)
    2632            0 :       && NONJUMP_INSN_P (new_thread)
    2633            0 :       && !RTX_FRAME_RELATED_P (new_thread)
    2634            0 :       && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
    2635            0 :       && asm_noperands (PATTERN (new_thread)) < 0)
    2636              :     {
    2637            0 :       rtx dest;
    2638            0 :       rtx src;
    2639              : 
    2640              :       /* We know "new_thread" is an insn due to NONJUMP_INSN_P (new_thread)
    2641              :          above.  */
    2642            0 :       trial = as_a <rtx_insn *> (new_thread);
    2643            0 :       rtx pat = PATTERN (trial);
    2644              : 
    2645            0 :       if (!NONJUMP_INSN_P (trial)
    2646            0 :           || GET_CODE (pat) != SET
    2647            0 :           || ! eligible_for_delay (insn, 0, trial, flags)
    2648            0 :           || can_throw_internal (trial))
    2649              :         return;
    2650              : 
    2651            0 :       dest = SET_DEST (pat), src = SET_SRC (pat);
    2652            0 :       if ((GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
    2653            0 :           && rtx_equal_p (XEXP (src, 0), dest)
    2654            0 :           && (!FLOAT_MODE_P (GET_MODE (src))
    2655            0 :               || flag_unsafe_math_optimizations)
    2656            0 :           && ! reg_overlap_mentioned_p (dest, XEXP (src, 1))
    2657            0 :           && ! side_effects_p (pat))
    2658              :         {
    2659            0 :           rtx other = XEXP (src, 1);
    2660            0 :           rtx new_arith;
    2661            0 :           rtx_insn *ninsn;
    2662              : 
    2663              :           /* If this is a constant adjustment, use the same code with
    2664              :              the negated constant.  Otherwise, reverse the sense of the
    2665              :              arithmetic.  */
    2666            0 :           if (CONST_INT_P (other))
    2667            0 :             new_arith = gen_rtx_fmt_ee (GET_CODE (src), GET_MODE (src), dest,
    2668              :                                         negate_rtx (GET_MODE (src), other));
    2669              :           else
    2670            0 :             new_arith = gen_rtx_fmt_ee (GET_CODE (src) == PLUS ? MINUS : PLUS,
    2671              :                                         GET_MODE (src), dest, other);
    2672              : 
    2673            0 :           ninsn = emit_insn_after (gen_rtx_SET (dest, new_arith), insn);
    2674              : 
    2675            0 :           if (recog_memoized (ninsn) < 0
    2676            0 :               || (extract_insn (ninsn),
    2677            0 :                   !constrain_operands (1, get_preferred_alternatives (ninsn))))
    2678              :             {
    2679            0 :               delete_related_insns (ninsn);
    2680            0 :               return;
    2681              :             }
    2682              : 
    2683            0 :           if (own_thread)
    2684              :             {
    2685            0 :               update_block (trial, thread);
    2686            0 :               if (trial == thread)
    2687              :                 {
    2688            0 :                   thread = next_active_insn (thread);
    2689            0 :                   if (new_thread == trial)
    2690            0 :                     new_thread = thread;
    2691              :                 }
    2692            0 :               delete_related_insns (trial);
    2693              :             }
    2694              :           else
    2695            0 :             new_thread = next_active_insn (trial);
    2696              : 
    2697            0 :           ninsn = own_thread ? trial : copy_delay_slot_insn (trial);
    2698            0 :           if (thread_if_true)
    2699            0 :             INSN_FROM_TARGET_P (ninsn) = 1;
    2700              : 
    2701            0 :           add_to_delay_list (ninsn, delay_list);
    2702            0 :           (*pslots_filled)++;
    2703              :         }
    2704              :     }
    2705              : 
    2706            0 :   if (!delay_list->is_empty () && must_annul)
    2707            0 :     INSN_ANNULLED_BRANCH_P (insn) = 1;
    2708              : 
    2709              :   /* If we are to branch into the middle of this thread, find an appropriate
    2710              :      label or make a new one if none, and redirect INSN to it.  If we hit the
    2711              :      end of the function, use the end-of-function label.  */
    2712            0 :   if (new_thread != thread)
    2713              :     {
    2714            0 :       rtx label;
    2715            0 :       bool crossing = false;
    2716              : 
    2717            0 :       gcc_assert (thread_if_true);
    2718              : 
    2719            0 :       if (new_thread
    2720            0 :           && simplejump_or_return_p (new_thread)
    2721            0 :           && redirect_with_delay_list_safe_p (insn,
    2722              :                                               JUMP_LABEL (new_thread),
    2723              :                                               *delay_list))
    2724            0 :         new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, &crossing);
    2725              : 
    2726            0 :       if (!new_thread)
    2727            0 :         label = find_end_label (simple_return_rtx);
    2728            0 :       else if (ANY_RETURN_P (new_thread))
    2729            0 :         label = find_end_label (new_thread);
    2730            0 :       else if (LABEL_P (new_thread))
    2731              :         label = new_thread;
    2732              :       else
    2733            0 :         label = get_label_before (as_a <rtx_insn *> (new_thread),
    2734              :                                   JUMP_LABEL (insn));
    2735              : 
    2736            0 :       if (label)
    2737              :         {
    2738            0 :           reorg_redirect_jump (insn, label);
    2739            0 :           if (crossing)
    2740            0 :             CROSSING_JUMP_P (insn) = 1;
    2741              :         }
    2742              :     }
    2743              : }
    2744              : 
    2745              : /* Make another attempt to find insns to place in delay slots.
    2746              : 
    2747              :    We previously looked for insns located in front of the delay insn
    2748              :    and, for non-jump delay insns, located behind the delay insn.
    2749              : 
    2750              :    Here only try to schedule jump insns and try to move insns from either
    2751              :    the target or the following insns into the delay slot.  If annulling is
    2752              :    supported, we will be likely to do this.  Otherwise, we can do this only
    2753              :    if safe.  */
    2754              : 
    2755              : static void
    2756            0 : fill_eager_delay_slots (void)
    2757              : {
    2758            0 :   rtx_insn *insn;
    2759            0 :   int i;
    2760            0 :   int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base;
    2761              : 
    2762            0 :   for (i = 0; i < num_unfilled_slots; i++)
    2763              :     {
    2764            0 :       rtx condition;
    2765            0 :       rtx target_label, insn_at_target;
    2766            0 :       rtx_insn *fallthrough_insn;
    2767            0 :       auto_vec<rtx_insn *, 5> delay_list;
    2768            0 :       rtx_jump_insn *jump_insn;
    2769            0 :       bool own_target;
    2770            0 :       bool own_fallthrough;
    2771            0 :       int prediction, slots_to_fill, slots_filled;
    2772              : 
    2773            0 :       insn = unfilled_slots_base[i];
    2774            0 :       if (insn == 0
    2775            0 :           || insn->deleted ()
    2776            0 :           || ! (jump_insn = dyn_cast <rtx_jump_insn *> (insn))
    2777            0 :           || ! (condjump_p (jump_insn) || condjump_in_parallel_p (jump_insn)))
    2778            0 :         continue;
    2779              : 
    2780            0 :       slots_to_fill = num_delay_slots (jump_insn);
    2781              :       /* Some machine description have defined instructions to have
    2782              :          delay slots only in certain circumstances which may depend on
    2783              :          nearby insns (which change due to reorg's actions).
    2784              : 
    2785              :          For example, the PA port normally has delay slots for unconditional
    2786              :          jumps.
    2787              : 
    2788              :          However, the PA port claims such jumps do not have a delay slot
    2789              :          if they are immediate successors of certain CALL_INSNs.  This
    2790              :          allows the port to favor filling the delay slot of the call with
    2791              :          the unconditional jump.  */
    2792            0 :       if (slots_to_fill == 0)
    2793            0 :         continue;
    2794              : 
    2795            0 :       slots_filled = 0;
    2796            0 :       target_label = JUMP_LABEL (jump_insn);
    2797            0 :       condition = get_branch_condition (jump_insn, target_label);
    2798              : 
    2799            0 :       if (condition == 0)
    2800            0 :         continue;
    2801              : 
    2802              :       /* Get the next active fallthrough and target insns and see if we own
    2803              :          them.  Then see whether the branch is likely true.  We don't need
    2804              :          to do a lot of this for unconditional branches.  */
    2805              : 
    2806            0 :       insn_at_target = first_active_target_insn (target_label);
    2807            0 :       own_target = own_thread_p (target_label, target_label, false);
    2808              : 
    2809            0 :       if (condition == const_true_rtx)
    2810              :         {
    2811              :           own_fallthrough = false;
    2812              :           fallthrough_insn = 0;
    2813              :           prediction = 2;
    2814              :         }
    2815              :       else
    2816              :         {
    2817            0 :           fallthrough_insn = next_active_insn (jump_insn);
    2818            0 :           own_fallthrough = own_thread_p (NEXT_INSN (jump_insn),
    2819              :                                           NULL_RTX, true);
    2820            0 :           prediction = mostly_true_jump (jump_insn);
    2821              :         }
    2822              : 
    2823              :       /* If this insn is expected to branch, first try to get insns from our
    2824              :          target, then our fallthrough insns.  If it is not expected to branch,
    2825              :          try the other order.  */
    2826              : 
    2827            0 :       if (prediction > 0)
    2828              :         {
    2829            0 :           fill_slots_from_thread (jump_insn, condition, insn_at_target,
    2830              :                                   fallthrough_insn, prediction == 2, true,
    2831              :                                   own_target, slots_to_fill,
    2832              :                                   &slots_filled, &delay_list);
    2833              : 
    2834            0 :           if (delay_list.is_empty () && own_fallthrough)
    2835              :             {
    2836              :               /* Even though we didn't find anything for delay slots,
    2837              :                  we might have found a redundant insn which we deleted
    2838              :                  from the thread that was filled.  So we have to recompute
    2839              :                  the next insn at the target.  */
    2840            0 :               target_label = JUMP_LABEL (jump_insn);
    2841            0 :               insn_at_target = first_active_target_insn (target_label);
    2842              : 
    2843            0 :               fill_slots_from_thread (jump_insn, condition, fallthrough_insn,
    2844              :                                       insn_at_target, false, false,
    2845              :                                       own_fallthrough, slots_to_fill,
    2846              :                                       &slots_filled, &delay_list);
    2847              :             }
    2848              :         }
    2849              :       else
    2850              :         {
    2851            0 :           if (own_fallthrough)
    2852            0 :             fill_slots_from_thread (jump_insn, condition, fallthrough_insn,
    2853              :                                     insn_at_target, false, false,
    2854              :                                     own_fallthrough, slots_to_fill,
    2855              :                                     &slots_filled, &delay_list);
    2856              : 
    2857            0 :           if (delay_list.is_empty ())
    2858            0 :             fill_slots_from_thread (jump_insn, condition, insn_at_target,
    2859            0 :                                     next_active_insn (insn), false, true,
    2860              :                                     own_target, slots_to_fill,
    2861              :                                     &slots_filled, &delay_list);
    2862              :         }
    2863              : 
    2864            0 :       if (!delay_list.is_empty ())
    2865            0 :         unfilled_slots_base[i]
    2866            0 :           = emit_delay_sequence (jump_insn, delay_list, slots_filled);
    2867              : 
    2868            0 :       if (slots_to_fill == slots_filled)
    2869            0 :         unfilled_slots_base[i] = 0;
    2870              : 
    2871            0 :       note_delay_statistics (slots_filled, 1);
    2872            0 :     }
    2873            0 : }
    2874              : 
    2875              : static void delete_computation (rtx_insn *insn);
    2876              : 
    2877              : /* Recursively delete prior insns that compute the value (used only by INSN
    2878              :    which the caller is deleting) stored in the register mentioned by NOTE
    2879              :    which is a REG_DEAD note associated with INSN.  */
    2880              : 
    2881              : static void
    2882            0 : delete_prior_computation (rtx note, rtx_insn *insn)
    2883              : {
    2884            0 :   rtx_insn *our_prev;
    2885            0 :   rtx reg = XEXP (note, 0);
    2886              : 
    2887            0 :   for (our_prev = prev_nonnote_insn (insn);
    2888            0 :        our_prev && (NONJUMP_INSN_P (our_prev)
    2889            0 :                     || CALL_P (our_prev));
    2890            0 :        our_prev = prev_nonnote_insn (our_prev))
    2891              :     {
    2892            0 :       rtx pat = PATTERN (our_prev);
    2893              : 
    2894              :       /* If we reach a CALL which is not calling a const function
    2895              :          or the callee pops the arguments, then give up.  */
    2896            0 :       if (CALL_P (our_prev)
    2897            0 :           && (! RTL_CONST_CALL_P (our_prev)
    2898            0 :               || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
    2899              :         break;
    2900              : 
    2901              :       /* If we reach a SEQUENCE, it is too complex to try to
    2902              :          do anything with it, so give up.  We can be run during
    2903              :          and after reorg, so SEQUENCE rtl can legitimately show
    2904              :          up here.  */
    2905            0 :       if (GET_CODE (pat) == SEQUENCE)
    2906              :         break;
    2907              : 
    2908            0 :       if (GET_CODE (pat) == USE
    2909            0 :           && NONJUMP_INSN_P (XEXP (pat, 0)))
    2910              :         /* reorg creates USEs that look like this.  We leave them
    2911              :            alone because reorg needs them for its own purposes.  */
    2912              :         break;
    2913              : 
    2914            0 :       if (reg_set_p (reg, pat))
    2915              :         {
    2916            0 :           if (side_effects_p (pat) && !CALL_P (our_prev))
    2917              :             break;
    2918              : 
    2919            0 :           if (GET_CODE (pat) == PARALLEL)
    2920              :             {
    2921              :               /* If we find a SET of something else, we can't
    2922              :                  delete the insn.  */
    2923              : 
    2924              :               int i;
    2925              : 
    2926            0 :               for (i = 0; i < XVECLEN (pat, 0); i++)
    2927              :                 {
    2928            0 :                   rtx part = XVECEXP (pat, 0, i);
    2929              : 
    2930            0 :                   if (GET_CODE (part) == SET
    2931            0 :                       && SET_DEST (part) != reg)
    2932              :                     break;
    2933              :                 }
    2934              : 
    2935            0 :               if (i == XVECLEN (pat, 0))
    2936            0 :                 delete_computation (our_prev);
    2937              :             }
    2938            0 :           else if (GET_CODE (pat) == SET
    2939            0 :                    && REG_P (SET_DEST (pat)))
    2940              :             {
    2941            0 :               int dest_regno = REGNO (SET_DEST (pat));
    2942            0 :               int dest_endregno = END_REGNO (SET_DEST (pat));
    2943            0 :               int regno = REGNO (reg);
    2944            0 :               int endregno = END_REGNO (reg);
    2945              : 
    2946            0 :               if (dest_regno >= regno
    2947            0 :                   && dest_endregno <= endregno)
    2948            0 :                 delete_computation (our_prev);
    2949              : 
    2950              :               /* We may have a multi-word hard register and some, but not
    2951              :                  all, of the words of the register are needed in subsequent
    2952              :                  insns.  Write REG_UNUSED notes for those parts that were not
    2953              :                  needed.  */
    2954            0 :               else if (dest_regno <= regno
    2955            0 :                        && dest_endregno >= endregno)
    2956              :                 {
    2957            0 :                   int i;
    2958              : 
    2959            0 :                   add_reg_note (our_prev, REG_UNUSED, reg);
    2960              : 
    2961            0 :                   for (i = dest_regno; i < dest_endregno; i++)
    2962            0 :                     if (! find_regno_note (our_prev, REG_UNUSED, i))
    2963              :                       break;
    2964              : 
    2965            0 :                   if (i == dest_endregno)
    2966            0 :                     delete_computation (our_prev);
    2967              :                 }
    2968              :             }
    2969              : 
    2970              :           break;
    2971              :         }
    2972              : 
    2973              :       /* If PAT references the register that dies here, it is an
    2974              :          additional use.  Hence any prior SET isn't dead.  However, this
    2975              :          insn becomes the new place for the REG_DEAD note.  */
    2976            0 :       if (reg_overlap_mentioned_p (reg, pat))
    2977              :         {
    2978            0 :           XEXP (note, 1) = REG_NOTES (our_prev);
    2979            0 :           REG_NOTES (our_prev) = note;
    2980            0 :           break;
    2981              :         }
    2982              :     }
    2983            0 : }
    2984              : 
    2985              : /* Delete INSN and recursively delete insns that compute values used only
    2986              :    by INSN.  This uses the REG_DEAD notes computed during flow analysis.
    2987              : 
    2988              :    Look at all our REG_DEAD notes.  If a previous insn does nothing other
    2989              :    than set a register that dies in this insn, we can delete that insn
    2990              :    as well.  */
    2991              : 
    2992              : static void
    2993            0 : delete_computation (rtx_insn *insn)
    2994              : {
    2995            0 :   rtx note, next;
    2996              : 
    2997            0 :   for (note = REG_NOTES (insn); note; note = next)
    2998              :     {
    2999            0 :       next = XEXP (note, 1);
    3000              : 
    3001            0 :       if (REG_NOTE_KIND (note) != REG_DEAD
    3002              :           /* Verify that the REG_NOTE is legitimate.  */
    3003            0 :           || !REG_P (XEXP (note, 0)))
    3004            0 :         continue;
    3005              : 
    3006            0 :       delete_prior_computation (note, insn);
    3007              :     }
    3008              : 
    3009            0 :   delete_related_insns (insn);
    3010            0 : }
    3011              : 
    3012              : /* If all INSN does is set the pc, delete it,
    3013              :    and delete the insn that set the condition codes for it
    3014              :    if that's what the previous thing was.  */
    3015              : 
    3016              : static void
    3017            0 : delete_jump (rtx_insn *insn)
    3018              : {
    3019            0 :   rtx set = single_set (insn);
    3020              : 
    3021            0 :   if (set && GET_CODE (SET_DEST (set)) == PC)
    3022            0 :     delete_computation (insn);
    3023            0 : }
    3024              : 
    3025              : static rtx_insn *
    3026            0 : label_before_next_insn (rtx_insn *x, rtx scan_limit)
    3027              : {
    3028            0 :   rtx_insn *insn = next_active_insn (x);
    3029            0 :   while (insn)
    3030              :     {
    3031            0 :       insn = PREV_INSN (insn);
    3032            0 :       if (insn == scan_limit || insn == NULL_RTX)
    3033              :         return NULL;
    3034            0 :       if (LABEL_P (insn))
    3035              :         break;
    3036              :     }
    3037              :   return insn;
    3038              : }
    3039              : 
    3040              : /* Return TRUE if there is a NOTE_INSN_SWITCH_TEXT_SECTIONS note in between
    3041              :    BEG and END.  */
    3042              : 
    3043              : static bool
    3044            0 : switch_text_sections_between_p (const rtx_insn *beg, const rtx_insn *end)
    3045              : {
    3046            0 :   const rtx_insn *p;
    3047            0 :   for (p = beg; p != end; p = NEXT_INSN (p))
    3048            0 :     if (NOTE_P (p) && NOTE_KIND (p) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
    3049              :       return true;
    3050              :   return false;
    3051              : }
    3052              : 
    3053              : 
    3054              : /* Once we have tried two ways to fill a delay slot, make a pass over the
    3055              :    code to try to improve the results and to do such things as more jump
    3056              :    threading.  */
    3057              : 
    3058              : static void
    3059            0 : relax_delay_slots (rtx_insn *first)
    3060              : {
    3061            0 :   rtx_insn *insn, *next;
    3062            0 :   rtx_sequence *pat;
    3063            0 :   rtx_insn *delay_insn;
    3064            0 :   rtx target_label;
    3065              : 
    3066              :   /* Look at every JUMP_INSN and see if we can improve it.  */
    3067            0 :   for (insn = first; insn; insn = next)
    3068              :     {
    3069            0 :       rtx_insn *other, *prior_insn;
    3070            0 :       bool crossing;
    3071              : 
    3072            0 :       next = next_active_insn (insn);
    3073              : 
    3074              :       /* If this is a jump insn, see if it now jumps to a jump, jumps to
    3075              :          the next insn, or jumps to a label that is not the last of a
    3076              :          group of consecutive labels.  */
    3077            0 :       if (is_a <rtx_jump_insn *> (insn)
    3078            0 :           && (condjump_p (insn) || condjump_in_parallel_p (insn))
    3079            0 :           && !ANY_RETURN_P (target_label = JUMP_LABEL (insn)))
    3080              :         {
    3081            0 :           rtx_jump_insn *jump_insn = as_a <rtx_jump_insn *> (insn);
    3082            0 :           target_label
    3083            0 :             = skip_consecutive_labels (follow_jumps (target_label, jump_insn,
    3084              :                                                      &crossing));
    3085            0 :           if (ANY_RETURN_P (target_label))
    3086            0 :             target_label = find_end_label (target_label);
    3087              : 
    3088            0 :           if (target_label
    3089            0 :               && next_active_insn (as_a<rtx_insn *> (target_label)) == next
    3090            0 :               && ! condjump_in_parallel_p (jump_insn)
    3091            0 :               && ! (next && switch_text_sections_between_p (jump_insn, next)))
    3092              :             {
    3093            0 :               rtx_insn *direct_label = as_a<rtx_insn *> (JUMP_LABEL (insn));
    3094            0 :               rtx_insn *prev = prev_nonnote_insn (direct_label);
    3095              : 
    3096              :               /* If the insn jumps over a BARRIER and is the only way to reach
    3097              :                  its target, then we need to delete the BARRIER before the jump
    3098              :                  because, otherwise, the target may end up being considered as
    3099              :                  unreachable and thus also deleted.  */
    3100            0 :               if (BARRIER_P (prev) && LABEL_NUSES (direct_label) == 1)
    3101              :                 {
    3102            0 :                   delete_related_insns (prev);
    3103              : 
    3104              :                   /* We have just removed a BARRIER, which means that the block
    3105              :                      number of the next insns has effectively been changed (see
    3106              :                      find_basic_block in resource.cc), so clear it.  */
    3107            0 :                   clear_hashed_info_until_next_barrier (direct_label);
    3108              :                 }
    3109              : 
    3110            0 :               delete_jump (jump_insn);
    3111            0 :               continue;
    3112            0 :             }
    3113              : 
    3114            0 :           if (target_label && target_label != JUMP_LABEL (jump_insn))
    3115              :             {
    3116            0 :               reorg_redirect_jump (jump_insn, target_label);
    3117            0 :               if (crossing)
    3118            0 :                 CROSSING_JUMP_P (jump_insn) = 1;
    3119              :             }
    3120              : 
    3121              :           /* See if this jump conditionally branches around an unconditional
    3122              :              jump.  If so, invert this jump and point it to the target of the
    3123              :              second jump.  Check if it's possible on the target.  */
    3124            0 :           if (next && simplejump_or_return_p (next)
    3125            0 :               && any_condjump_p (jump_insn)
    3126            0 :               && target_label
    3127            0 :               && (next_active_insn (as_a<rtx_insn *> (target_label))
    3128            0 :                   == next_active_insn (next))
    3129            0 :               && no_labels_between_p (jump_insn, next)
    3130            0 :               && targetm.can_follow_jump (jump_insn, next))
    3131              :             {
    3132            0 :               rtx label = JUMP_LABEL (next);
    3133              : 
    3134              :               /* Be careful how we do this to avoid deleting code or
    3135              :                  labels that are momentarily dead.  See similar optimization
    3136              :                  in jump.cc.
    3137              : 
    3138              :                  We also need to ensure we properly handle the case when
    3139              :                  invert_jump fails.  */
    3140              : 
    3141            0 :               ++LABEL_NUSES (target_label);
    3142            0 :               if (!ANY_RETURN_P (label))
    3143            0 :                 ++LABEL_NUSES (label);
    3144              : 
    3145            0 :               if (invert_jump (jump_insn, label, 1))
    3146              :                 {
    3147            0 :                   rtx_insn *from = delete_related_insns (next);
    3148              : 
    3149              :                   /* We have just removed a BARRIER, which means that the block
    3150              :                      number of the next insns has effectively been changed (see
    3151              :                      find_basic_block in resource.cc), so clear it.  */
    3152            0 :                   if (from)
    3153            0 :                     clear_hashed_info_until_next_barrier (from);
    3154              : 
    3155              :                   next = jump_insn;
    3156              :                 }
    3157              : 
    3158            0 :               if (!ANY_RETURN_P (label))
    3159            0 :                 --LABEL_NUSES (label);
    3160              : 
    3161            0 :               if (--LABEL_NUSES (target_label) == 0)
    3162            0 :                 delete_related_insns (target_label);
    3163              : 
    3164            0 :               continue;
    3165            0 :             }
    3166              :         }
    3167              : 
    3168              :       /* If this is an unconditional jump and the previous insn is a
    3169              :          conditional jump, try reversing the condition of the previous
    3170              :          insn and swapping our targets.  The next pass might be able to
    3171              :          fill the slots.
    3172              : 
    3173              :          Don't do this if we expect the conditional branch to be true, because
    3174              :          we would then be making the more common case longer.  */
    3175              : 
    3176            0 :       if (simplejump_or_return_p (insn)
    3177            0 :           && (other = prev_active_insn (insn)) != 0
    3178            0 :           && any_condjump_p (other)
    3179            0 :           && no_labels_between_p (other, insn)
    3180            0 :           && mostly_true_jump (other) < 0)
    3181              :         {
    3182            0 :           rtx other_target = JUMP_LABEL (other);
    3183            0 :           target_label = JUMP_LABEL (insn);
    3184              : 
    3185            0 :           if (invert_jump (as_a <rtx_jump_insn *> (other), target_label, 0))
    3186            0 :             reorg_redirect_jump (as_a <rtx_jump_insn *> (insn), other_target);
    3187              :         }
    3188              : 
    3189              :       /* Now look only at cases where we have a filled delay slot.  */
    3190            0 :       if (!NONJUMP_INSN_P (insn) || GET_CODE (PATTERN (insn)) != SEQUENCE)
    3191            0 :         continue;
    3192              : 
    3193            0 :       pat = as_a <rtx_sequence *> (PATTERN (insn));
    3194            0 :       delay_insn = pat->insn (0);
    3195              : 
    3196              :       /* See if the first insn in the delay slot is redundant with some
    3197              :          previous insn.  Remove it from the delay slot if so; then set up
    3198              :          to reprocess this insn.  */
    3199            0 :       if ((prior_insn = redundant_insn (pat->insn (1), delay_insn, vNULL)))
    3200              :         {
    3201            0 :           fix_reg_dead_note (prior_insn, insn);
    3202            0 :           update_block (pat->insn (1), insn);
    3203            0 :           delete_from_delay_slot (pat->insn (1));
    3204            0 :           next = prev_active_insn (next);
    3205            0 :           continue;
    3206              :         }
    3207              : 
    3208              :       /* See if we have a RETURN insn with a filled delay slot followed
    3209              :          by a RETURN insn with an unfilled a delay slot.  If so, we can delete
    3210              :          the first RETURN (but not its delay insn).  This gives the same
    3211              :          effect in fewer instructions.
    3212              : 
    3213              :          Only do so if optimizing for size since this results in slower, but
    3214              :          smaller code.  */
    3215            0 :       if (optimize_function_for_size_p (cfun)
    3216            0 :           && ANY_RETURN_P (PATTERN (delay_insn))
    3217            0 :           && next
    3218            0 :           && JUMP_P (next)
    3219            0 :           && PATTERN (next) == PATTERN (delay_insn))
    3220              :         {
    3221              :           rtx_insn *after;
    3222              :           int i;
    3223              : 
    3224              :           /* Delete the RETURN and just execute the delay list insns.
    3225              : 
    3226              :              We do this by deleting the INSN containing the SEQUENCE, then
    3227              :              re-emitting the insns separately, and then deleting the RETURN.
    3228              :              This allows the count of the jump target to be properly
    3229              :              decremented.
    3230              : 
    3231              :              Note that we need to change the INSN_UID of the re-emitted insns
    3232              :              since it is used to hash the insns for mark_target_live_regs and
    3233              :              the re-emitted insns will no longer be wrapped up in a SEQUENCE.
    3234              : 
    3235              :              Clear the from target bit, since these insns are no longer
    3236              :              in delay slots.  */
    3237            0 :           for (i = 0; i < XVECLEN (pat, 0); i++)
    3238            0 :             INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
    3239              : 
    3240            0 :           rtx_insn *prev = PREV_INSN (insn);
    3241            0 :           delete_related_insns (insn);
    3242            0 :           gcc_assert (GET_CODE (pat) == SEQUENCE);
    3243            0 :           add_insn_after (delay_insn, prev, NULL);
    3244            0 :           after = delay_insn;
    3245            0 :           for (i = 1; i < pat->len (); i++)
    3246            0 :             after = emit_copy_of_insn_after (pat->insn (i), after);
    3247            0 :           delete_scheduled_jump (delay_insn);
    3248            0 :           continue;
    3249            0 :         }
    3250              : 
    3251              :       /* Now look only at the cases where we have a filled JUMP_INSN.  */
    3252            0 :       rtx_jump_insn *delay_jump_insn =
    3253            0 :                 dyn_cast <rtx_jump_insn *> (delay_insn);
    3254            0 :       if (! delay_jump_insn || !(condjump_p (delay_jump_insn)
    3255            0 :           || condjump_in_parallel_p (delay_jump_insn)))
    3256            0 :         continue;
    3257              : 
    3258            0 :       target_label = JUMP_LABEL (delay_jump_insn);
    3259            0 :       if (target_label && ANY_RETURN_P (target_label))
    3260            0 :         continue;
    3261              : 
    3262              :       /* If this jump goes to another unconditional jump, thread it, but
    3263              :          don't convert a jump into a RETURN here.  */
    3264            0 :       rtx trial = skip_consecutive_labels (follow_jumps (target_label,
    3265              :                                                          delay_jump_insn,
    3266              :                                                          &crossing));
    3267            0 :       if (ANY_RETURN_P (trial))
    3268            0 :         trial = find_end_label (trial);
    3269              : 
    3270            0 :       if (trial && trial != target_label
    3271            0 :           && redirect_with_delay_slots_safe_p (delay_jump_insn, trial, insn))
    3272              :         {
    3273            0 :           reorg_redirect_jump (delay_jump_insn, trial);
    3274            0 :           target_label = trial;
    3275            0 :           if (crossing)
    3276            0 :             CROSSING_JUMP_P (delay_jump_insn) = 1;
    3277              :         }
    3278              : 
    3279              :       /* If the first insn at TARGET_LABEL is redundant with a previous
    3280              :          insn, redirect the jump to the following insn and process again.
    3281              :          We use next_real_nondebug_insn instead of next_active_insn so we
    3282              :          don't skip USE-markers, or we'll end up with incorrect
    3283              :          liveness info.  */
    3284            0 :       trial = next_real_nondebug_insn (target_label);
    3285            0 :       if (trial && GET_CODE (PATTERN (trial)) != SEQUENCE
    3286            0 :           && redundant_insn (trial, insn, vNULL)
    3287            0 :           && ! can_throw_internal (trial))
    3288              :         {
    3289              :           /* Figure out where to emit the special USE insn so we don't
    3290              :              later incorrectly compute register live/death info.  */
    3291            0 :           rtx_insn *tmp = next_active_insn (as_a<rtx_insn *> (trial));
    3292            0 :           if (tmp == 0)
    3293            0 :             tmp = find_end_label (simple_return_rtx);
    3294              : 
    3295            0 :           if (tmp)
    3296              :             {
    3297              :               /* Insert the special USE insn and update dataflow info.
    3298              :                  We know "trial" is an insn here as it is the output of
    3299              :                  next_real_nondebug_insn () above.  */
    3300            0 :               update_block (as_a <rtx_insn *> (trial), tmp);
    3301              : 
    3302              :               /* Now emit a label before the special USE insn, and
    3303              :                  redirect our jump to the new label.  */
    3304            0 :               target_label = get_label_before (PREV_INSN (tmp), target_label);
    3305            0 :               reorg_redirect_jump (delay_jump_insn, target_label);
    3306            0 :               next = insn;
    3307            0 :               continue;
    3308              :             }
    3309              :         }
    3310              : 
    3311              :       /* Similarly, if it is an unconditional jump with one insn in its
    3312              :          delay list and that insn is redundant, thread the jump.  */
    3313            0 :       rtx_sequence *trial_seq =
    3314            0 :         trial ? dyn_cast <rtx_sequence *> (PATTERN (trial)) : NULL;
    3315            0 :       if (trial_seq
    3316            0 :           && trial_seq->len () == 2
    3317            0 :           && JUMP_P (trial_seq->insn (0))
    3318            0 :           && simplejump_or_return_p (trial_seq->insn (0))
    3319            0 :           && redundant_insn (trial_seq->insn (1), insn, vNULL))
    3320              :         {
    3321            0 :           rtx temp_label = JUMP_LABEL (trial_seq->insn (0));
    3322            0 :           if (ANY_RETURN_P (temp_label))
    3323            0 :             temp_label = find_end_label (temp_label);
    3324              : 
    3325            0 :           if (temp_label
    3326            0 :               && redirect_with_delay_slots_safe_p (delay_jump_insn,
    3327              :                                                    temp_label, insn))
    3328              :             {
    3329            0 :               update_block (trial_seq->insn (1), insn);
    3330            0 :               reorg_redirect_jump (delay_jump_insn, temp_label);
    3331            0 :               next = insn;
    3332            0 :               continue;
    3333              :             }
    3334              :         }
    3335              : 
    3336              :       /* See if we have a simple (conditional) jump that is useless.  */
    3337            0 :       if (!CROSSING_JUMP_P (delay_jump_insn)
    3338            0 :           && !INSN_ANNULLED_BRANCH_P (delay_jump_insn)
    3339            0 :           && !condjump_in_parallel_p (delay_jump_insn)
    3340            0 :           && prev_active_insn (as_a<rtx_insn *> (target_label)) == insn
    3341            0 :           && !BARRIER_P (prev_nonnote_insn (as_a<rtx_insn *> (target_label))))
    3342              :         {
    3343              :           rtx_insn *after;
    3344              :           int i;
    3345              : 
    3346              :           /* All this insn does is execute its delay list and jump to the
    3347              :              following insn.  So delete the jump and just execute the delay
    3348              :              list insns.
    3349              : 
    3350              :              We do this by deleting the INSN containing the SEQUENCE, then
    3351              :              re-emitting the insns separately, and then deleting the jump.
    3352              :              This allows the count of the jump target to be properly
    3353              :              decremented.
    3354              : 
    3355              :              Note that we need to change the INSN_UID of the re-emitted insns
    3356              :              since it is used to hash the insns for mark_target_live_regs and
    3357              :              the re-emitted insns will no longer be wrapped up in a SEQUENCE.
    3358              : 
    3359              :              Clear the from target bit, since these insns are no longer
    3360              :              in delay slots.  */
    3361            0 :           for (i = 0; i < XVECLEN (pat, 0); i++)
    3362            0 :             INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
    3363              : 
    3364            0 :           rtx_insn *prev = PREV_INSN (insn);
    3365            0 :           delete_related_insns (insn);
    3366            0 :           gcc_assert (GET_CODE (pat) == SEQUENCE);
    3367            0 :           add_insn_after (delay_jump_insn, prev, NULL);
    3368            0 :           after = delay_jump_insn;
    3369            0 :           for (i = 1; i < pat->len (); i++)
    3370            0 :             after = emit_copy_of_insn_after (pat->insn (i), after);
    3371            0 :           delete_scheduled_jump (delay_jump_insn);
    3372            0 :           continue;
    3373            0 :         }
    3374              : 
    3375              :       /* See if this is an unconditional jump around a single insn which is
    3376              :          identical to the one in its delay slot.  In this case, we can just
    3377              :          delete the branch and the insn in its delay slot.  */
    3378            0 :       if (next && NONJUMP_INSN_P (next)
    3379            0 :           && label_before_next_insn (next, insn) == target_label
    3380            0 :           && simplejump_p (insn)
    3381            0 :           && XVECLEN (pat, 0) == 2
    3382            0 :           && rtx_equal_p (PATTERN (next), PATTERN (pat->insn (1))))
    3383              :         {
    3384            0 :           delete_related_insns (insn);
    3385            0 :           continue;
    3386              :         }
    3387              : 
    3388              :       /* See if this jump (with its delay slots) conditionally branches
    3389              :          around an unconditional jump (without delay slots).  If so, invert
    3390              :          this jump and point it to the target of the second jump.  We cannot
    3391              :          do this for annulled jumps, though.  Again, don't convert a jump to
    3392              :          a RETURN here.  */
    3393            0 :       if (! INSN_ANNULLED_BRANCH_P (delay_jump_insn)
    3394            0 :           && any_condjump_p (delay_jump_insn)
    3395            0 :           && next && simplejump_or_return_p (next)
    3396            0 :           && (next_active_insn (as_a<rtx_insn *> (target_label))
    3397            0 :               == next_active_insn (next))
    3398            0 :           && no_labels_between_p (insn, next)
    3399            0 :           && !switch_text_sections_between_p (insn, next_active_insn (next)))
    3400              :         {
    3401            0 :           rtx label = JUMP_LABEL (next);
    3402            0 :           rtx old_label = JUMP_LABEL (delay_jump_insn);
    3403              : 
    3404            0 :           if (ANY_RETURN_P (label))
    3405            0 :             label = find_end_label (label);
    3406              : 
    3407              :           /* find_end_label can generate a new label. Check this first.  */
    3408            0 :           if (label
    3409            0 :               && no_labels_between_p (insn, next)
    3410            0 :               && redirect_with_delay_slots_safe_p (delay_jump_insn,
    3411              :                                                    label, insn))
    3412              :             {
    3413              :               /* Be careful how we do this to avoid deleting code or labels
    3414              :                  that are momentarily dead.  See similar optimization in
    3415              :                  jump.cc  */
    3416            0 :               if (old_label)
    3417            0 :                 ++LABEL_NUSES (old_label);
    3418              : 
    3419            0 :               if (invert_jump (delay_jump_insn, label, 1))
    3420              :                 {
    3421              :                   /* Must update the INSN_FROM_TARGET_P bits now that
    3422              :                      the branch is reversed, so that mark_target_live_regs
    3423              :                      will handle the delay slot insn correctly.  */
    3424            0 :                   for (int i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
    3425              :                     {
    3426            0 :                       rtx slot = XVECEXP (PATTERN (insn), 0, i);
    3427            0 :                       INSN_FROM_TARGET_P (slot) = ! INSN_FROM_TARGET_P (slot);
    3428              :                     }
    3429              : 
    3430              :                   /* We have just removed a BARRIER, which means that the block
    3431              :                      number of the next insns has effectively been changed (see
    3432              :                      find_basic_block in resource.cc), so clear it.  */
    3433            0 :                   rtx_insn *from = delete_related_insns (next);
    3434            0 :                   if (from)
    3435            0 :                     clear_hashed_info_until_next_barrier (from);
    3436              : 
    3437              :                   next = insn;
    3438              :                 }
    3439              : 
    3440            0 :               if (old_label && --LABEL_NUSES (old_label) == 0)
    3441            0 :                 delete_related_insns (old_label);
    3442            0 :               continue;
    3443            0 :             }
    3444              :         }
    3445              : 
    3446              :       /* If we own the thread opposite the way this insn branches, see if we
    3447              :          can merge its delay slots with following insns.  */
    3448            0 :       if (INSN_FROM_TARGET_P (pat->insn (1))
    3449            0 :           && own_thread_p (NEXT_INSN (insn), 0, true))
    3450            0 :         try_merge_delay_insns (insn, next);
    3451            0 :       else if (! INSN_FROM_TARGET_P (pat->insn (1))
    3452            0 :                && own_thread_p (target_label, target_label, false))
    3453            0 :         try_merge_delay_insns (insn,
    3454              :                                next_active_insn (as_a<rtx_insn *> (target_label)));
    3455              : 
    3456              :       /* If we get here, we haven't deleted INSN.  But we may have deleted
    3457              :          NEXT, so recompute it.  */
    3458            0 :       next = next_active_insn (insn);
    3459              :     }
    3460            0 : }
    3461              : 
    3462              : 
    3463              : /* Look for filled jumps to the end of function label.  We can try to convert
    3464              :    them into RETURN insns if the insns in the delay slot are valid for the
    3465              :    RETURN as well.  */
    3466              : 
    3467              : static void
    3468            0 : make_return_insns (rtx_insn *first)
    3469              : {
    3470            0 :   rtx_insn *insn;
    3471            0 :   rtx_jump_insn *jump_insn;
    3472            0 :   rtx real_return_label = function_return_label;
    3473            0 :   rtx real_simple_return_label = function_simple_return_label;
    3474            0 :   int slots, i;
    3475              : 
    3476              :   /* See if there is a RETURN insn in the function other than the one we
    3477              :      made for END_OF_FUNCTION_LABEL.  If so, set up anything we can't change
    3478              :      into a RETURN to jump to it.  */
    3479            0 :   for (insn = first; insn; insn = NEXT_INSN (insn))
    3480            0 :     if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
    3481              :       {
    3482            0 :         rtx t = get_label_before (insn, NULL_RTX);
    3483            0 :         if (PATTERN (insn) == ret_rtx)
    3484              :           real_return_label = t;
    3485              :         else
    3486              :           real_simple_return_label = t;
    3487              :         break;
    3488              :       }
    3489              : 
    3490              :   /* Show an extra usage of REAL_RETURN_LABEL so it won't go away if it
    3491              :      was equal to END_OF_FUNCTION_LABEL.  */
    3492            0 :   if (real_return_label)
    3493            0 :     LABEL_NUSES (real_return_label)++;
    3494            0 :   if (real_simple_return_label)
    3495            0 :     LABEL_NUSES (real_simple_return_label)++;
    3496              : 
    3497              :   /* Clear the list of insns to fill so we can use it.  */
    3498            0 :   obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
    3499              : 
    3500            0 :   for (insn = first; insn; insn = NEXT_INSN (insn))
    3501              :     {
    3502            0 :       int flags;
    3503            0 :       rtx kind, real_label;
    3504              : 
    3505              :       /* Only look at filled JUMP_INSNs that go to the end of function
    3506              :          label.  */
    3507            0 :       if (!NONJUMP_INSN_P (insn))
    3508            0 :         continue;
    3509              : 
    3510            0 :       if (GET_CODE (PATTERN (insn)) != SEQUENCE)
    3511            0 :         continue;
    3512              : 
    3513            0 :       rtx_sequence *pat = as_a <rtx_sequence *> (PATTERN (insn));
    3514              : 
    3515            0 :       if (!jump_to_label_p (pat->insn (0)))
    3516            0 :         continue;
    3517              : 
    3518            0 :       if (JUMP_LABEL (pat->insn (0)) == function_return_label)
    3519              :         {
    3520            0 :           kind = ret_rtx;
    3521            0 :           real_label = real_return_label;
    3522              :         }
    3523            0 :       else if (JUMP_LABEL (pat->insn (0)) == function_simple_return_label)
    3524              :         {
    3525            0 :           kind = simple_return_rtx;
    3526            0 :           real_label = real_simple_return_label;
    3527              :         }
    3528              :       else
    3529            0 :         continue;
    3530              : 
    3531            0 :       jump_insn = as_a <rtx_jump_insn *> (pat->insn (0));
    3532              : 
    3533              :       /* If we can't make the jump into a RETURN, try to redirect it to the best
    3534              :          RETURN and go on to the next insn.  */
    3535            0 :       if (!reorg_redirect_jump (jump_insn, kind))
    3536              :         {
    3537              :           /* Make sure redirecting the jump will not invalidate the delay
    3538              :              slot insns.  */
    3539            0 :           if (redirect_with_delay_slots_safe_p (jump_insn, real_label, insn))
    3540            0 :             reorg_redirect_jump (jump_insn, real_label);
    3541            0 :           continue;
    3542              :         }
    3543              : 
    3544              :       /* See if this RETURN can accept the insns current in its delay slot.
    3545              :          It can if it has more or an equal number of slots and the contents
    3546              :          of each is valid.  */
    3547              : 
    3548            0 :       flags = get_jump_flags (jump_insn, JUMP_LABEL (jump_insn));
    3549            0 :       slots = num_delay_slots (jump_insn);
    3550            0 :       if (slots >= XVECLEN (pat, 0) - 1)
    3551              :         {
    3552            0 :           for (i = 1; i < XVECLEN (pat, 0); i++)
    3553            0 :             if (! (
    3554              : #if ANNUL_IFFALSE_SLOTS
    3555              :                    (INSN_ANNULLED_BRANCH_P (jump_insn)
    3556              :                     && INSN_FROM_TARGET_P (pat->insn (i)))
    3557              :                    ? eligible_for_annul_false (jump_insn, i - 1,
    3558              :                                                pat->insn (i), flags) :
    3559              : #endif
    3560              : #if ANNUL_IFTRUE_SLOTS
    3561              :                    (INSN_ANNULLED_BRANCH_P (jump_insn)
    3562              :                     && ! INSN_FROM_TARGET_P (pat->insn (i)))
    3563              :                    ? eligible_for_annul_true (jump_insn, i - 1,
    3564              :                                               pat->insn (i), flags) :
    3565              : #endif
    3566            0 :                    eligible_for_delay (jump_insn, i - 1,
    3567              :                                        pat->insn (i), flags)))
    3568              :               break;
    3569              :         }
    3570              :       else
    3571              :         i = 0;
    3572              : 
    3573            0 :       if (i == XVECLEN (pat, 0))
    3574            0 :         continue;
    3575              : 
    3576              :       /* We have to do something with this insn.  If it is an unconditional
    3577              :          RETURN, delete the SEQUENCE and output the individual insns,
    3578              :          followed by the RETURN.  Then set things up so we try to find
    3579              :          insns for its delay slots, if it needs some.  */
    3580            0 :       if (ANY_RETURN_P (PATTERN (jump_insn)))
    3581              :         {
    3582            0 :           rtx_insn *after = PREV_INSN (insn);
    3583              : 
    3584            0 :           delete_related_insns (insn);
    3585            0 :           insn = jump_insn;
    3586            0 :           for (i = 1; i < pat->len (); i++)
    3587            0 :             after = emit_copy_of_insn_after (pat->insn (i), after);
    3588            0 :           add_insn_after (insn, after, NULL);
    3589            0 :           emit_barrier_after (insn);
    3590              : 
    3591            0 :           if (slots)
    3592            0 :             obstack_ptr_grow (&unfilled_slots_obstack, insn);
    3593              :         }
    3594              :       else
    3595              :         /* It is probably more efficient to keep this with its current
    3596              :            delay slot as a branch to a RETURN.  */
    3597            0 :         reorg_redirect_jump (jump_insn, real_label);
    3598              :     }
    3599              : 
    3600              :   /* Now delete REAL_RETURN_LABEL if we never used it.  Then try to fill any
    3601              :      new delay slots we have created.  */
    3602            0 :   if (real_return_label != NULL_RTX && --LABEL_NUSES (real_return_label) == 0)
    3603            0 :     delete_related_insns (real_return_label);
    3604            0 :   if (real_simple_return_label != NULL_RTX
    3605            0 :       && --LABEL_NUSES (real_simple_return_label) == 0)
    3606            0 :     delete_related_insns (real_simple_return_label);
    3607              : 
    3608            0 :   fill_simple_delay_slots (true);
    3609            0 :   fill_simple_delay_slots (false);
    3610            0 : }
    3611              : 
    3612              : /* Try to find insns to place in delay slots.  */
    3613              : 
    3614              : static void
    3615            0 : dbr_schedule (rtx_insn *first)
    3616              : {
    3617            0 :   rtx_insn *insn, *next, *epilogue_insn = 0;
    3618            0 :   bool need_return_insns;
    3619            0 :   int i;
    3620              : 
    3621              :   /* If the current function has no insns other than the prologue and
    3622              :      epilogue, then do not try to fill any delay slots.  */
    3623            0 :   if (n_basic_blocks_for_fn (cfun) == NUM_FIXED_BLOCKS)
    3624              :     return;
    3625              : 
    3626              :   /* Find the highest INSN_UID and allocate and initialize our map from
    3627              :      INSN_UID's to position in code.  */
    3628            0 :   for (max_uid = 0, insn = first; insn; insn = NEXT_INSN (insn))
    3629              :     {
    3630            0 :       if (INSN_UID (insn) > max_uid)
    3631            0 :         max_uid = INSN_UID (insn);
    3632            0 :       if (NOTE_P (insn)
    3633            0 :           && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
    3634            0 :         epilogue_insn = insn;
    3635              :     }
    3636              : 
    3637            0 :   uid_to_ruid = XNEWVEC (int, max_uid + 1);
    3638            0 :   for (i = 0, insn = first; insn; i++, insn = NEXT_INSN (insn))
    3639            0 :     uid_to_ruid[INSN_UID (insn)] = i;
    3640              : 
    3641              :   /* Initialize the list of insns that need filling.  */
    3642            0 :   if (unfilled_firstobj == 0)
    3643              :     {
    3644            0 :       gcc_obstack_init (&unfilled_slots_obstack);
    3645            0 :       unfilled_firstobj = XOBNEWVAR (&unfilled_slots_obstack, rtx, 0);
    3646              :     }
    3647              : 
    3648            0 :   for (insn = next_active_insn (first); insn; insn = next_active_insn (insn))
    3649              :     {
    3650            0 :       rtx target;
    3651              : 
    3652              :       /* Skip vector tables.  We can't get attributes for them.  */
    3653            0 :       if (JUMP_TABLE_DATA_P (insn))
    3654            0 :         continue;
    3655              : 
    3656            0 :       if (JUMP_P (insn))
    3657            0 :         INSN_ANNULLED_BRANCH_P (insn) = 0;
    3658            0 :       INSN_FROM_TARGET_P (insn) = 0;
    3659              : 
    3660            0 :       if (num_delay_slots (insn) > 0)
    3661            0 :         obstack_ptr_grow (&unfilled_slots_obstack, insn);
    3662              : 
    3663              :       /* Ensure all jumps go to the last of a set of consecutive labels.  */
    3664            0 :       if (JUMP_P (insn)
    3665            0 :           && (condjump_p (insn) || condjump_in_parallel_p (insn))
    3666            0 :           && !ANY_RETURN_P (JUMP_LABEL (insn))
    3667            0 :           && ((target = skip_consecutive_labels (JUMP_LABEL (insn)))
    3668              :               != JUMP_LABEL (insn)))
    3669            0 :         redirect_jump (as_a <rtx_jump_insn *> (insn), target, 1);
    3670              :     }
    3671              : 
    3672            0 :   init_resource_info (epilogue_insn);
    3673              : 
    3674              :   /* Show we haven't computed an end-of-function label yet.  */
    3675            0 :   function_return_label = function_simple_return_label = NULL;
    3676              : 
    3677              :   /* Initialize the statistics for this function.  */
    3678            0 :   memset (num_insns_needing_delays, 0, sizeof num_insns_needing_delays);
    3679            0 :   memset (num_filled_delays, 0, sizeof num_filled_delays);
    3680              : 
    3681              :   /* Now do the delay slot filling.  Try everything twice in case earlier
    3682              :      changes make more slots fillable.  */
    3683              : 
    3684            0 :   for (reorg_pass_number = 0;
    3685            0 :        reorg_pass_number < MAX_REORG_PASSES;
    3686              :        reorg_pass_number++)
    3687              :     {
    3688            0 :       fill_simple_delay_slots (true);
    3689            0 :       fill_simple_delay_slots (false);
    3690            0 :       if (!targetm.no_speculation_in_delay_slots_p ())
    3691            0 :         fill_eager_delay_slots ();
    3692            0 :       relax_delay_slots (first);
    3693              :     }
    3694              : 
    3695              :   /* If we made an end of function label, indicate that it is now
    3696              :      safe to delete it by undoing our prior adjustment to LABEL_NUSES.
    3697              :      If it is now unused, delete it.  */
    3698            0 :   if (function_return_label && --LABEL_NUSES (function_return_label) == 0)
    3699            0 :     delete_related_insns (function_return_label);
    3700            0 :   if (function_simple_return_label
    3701            0 :       && --LABEL_NUSES (function_simple_return_label) == 0)
    3702            0 :     delete_related_insns (function_simple_return_label);
    3703              : 
    3704            0 :   need_return_insns = false;
    3705            0 :   need_return_insns |= targetm.have_return () && function_return_label != 0;
    3706            0 :   need_return_insns |= (targetm.have_simple_return ()
    3707            0 :                         && function_simple_return_label != 0);
    3708            0 :   if (need_return_insns)
    3709            0 :     make_return_insns (first);
    3710              : 
    3711              :   /* Delete any USE insns made by update_block; subsequent passes don't need
    3712              :      them or know how to deal with them.  */
    3713            0 :   for (insn = first; insn; insn = next)
    3714              :     {
    3715            0 :       next = NEXT_INSN (insn);
    3716              : 
    3717            0 :       if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
    3718            0 :           && INSN_P (XEXP (PATTERN (insn), 0)))
    3719            0 :         next = delete_related_insns (insn);
    3720              :     }
    3721              : 
    3722            0 :   obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
    3723              : 
    3724              :   /* It is not clear why the line below is needed, but it does seem to be.  */
    3725            0 :   unfilled_firstobj = XOBNEWVAR (&unfilled_slots_obstack, rtx, 0);
    3726              : 
    3727            0 :   if (dump_file)
    3728              :     {
    3729            0 :       int i, j, need_comma;
    3730            0 :       int total_delay_slots[MAX_DELAY_HISTOGRAM + 1];
    3731            0 :       int total_annul_slots[MAX_DELAY_HISTOGRAM + 1];
    3732              : 
    3733            0 :       for (reorg_pass_number = 0;
    3734            0 :            reorg_pass_number < MAX_REORG_PASSES;
    3735              :            reorg_pass_number++)
    3736              :         {
    3737            0 :           fprintf (dump_file, ";; Reorg pass #%d:\n", reorg_pass_number + 1);
    3738            0 :           for (i = 0; i < NUM_REORG_FUNCTIONS; i++)
    3739              :             {
    3740            0 :               need_comma = 0;
    3741            0 :               fprintf (dump_file, ";; Reorg function #%d\n", i);
    3742              : 
    3743            0 :               fprintf (dump_file, ";; %d insns needing delay slots\n;; ",
    3744              :                        num_insns_needing_delays[i][reorg_pass_number]);
    3745              : 
    3746            0 :               for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
    3747            0 :                 if (num_filled_delays[i][j][reorg_pass_number])
    3748              :                   {
    3749            0 :                     if (need_comma)
    3750            0 :                       fprintf (dump_file, ", ");
    3751            0 :                     need_comma = 1;
    3752            0 :                     fprintf (dump_file, "%d got %d delays",
    3753              :                              num_filled_delays[i][j][reorg_pass_number], j);
    3754              :                   }
    3755            0 :               fprintf (dump_file, "\n");
    3756              :             }
    3757              :         }
    3758            0 :       memset (total_delay_slots, 0, sizeof total_delay_slots);
    3759            0 :       memset (total_annul_slots, 0, sizeof total_annul_slots);
    3760            0 :       for (insn = first; insn; insn = NEXT_INSN (insn))
    3761              :         {
    3762            0 :           if (! insn->deleted ()
    3763            0 :               && NONJUMP_INSN_P (insn)
    3764            0 :               && GET_CODE (PATTERN (insn)) != USE
    3765            0 :               && GET_CODE (PATTERN (insn)) != CLOBBER)
    3766              :             {
    3767            0 :               if (GET_CODE (PATTERN (insn)) == SEQUENCE)
    3768              :                 {
    3769            0 :                   rtx control;
    3770            0 :                   j = XVECLEN (PATTERN (insn), 0) - 1;
    3771            0 :                   if (j > MAX_DELAY_HISTOGRAM)
    3772              :                     j = MAX_DELAY_HISTOGRAM;
    3773            0 :                   control = XVECEXP (PATTERN (insn), 0, 0);
    3774            0 :                   if (JUMP_P (control) && INSN_ANNULLED_BRANCH_P (control))
    3775            0 :                     total_annul_slots[j]++;
    3776              :                   else
    3777            0 :                     total_delay_slots[j]++;
    3778              :                 }
    3779            0 :               else if (num_delay_slots (insn) > 0)
    3780            0 :                 total_delay_slots[0]++;
    3781              :             }
    3782              :         }
    3783            0 :       fprintf (dump_file, ";; Reorg totals: ");
    3784            0 :       need_comma = 0;
    3785            0 :       for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
    3786              :         {
    3787            0 :           if (total_delay_slots[j])
    3788              :             {
    3789            0 :               if (need_comma)
    3790            0 :                 fprintf (dump_file, ", ");
    3791            0 :               need_comma = 1;
    3792            0 :               fprintf (dump_file, "%d got %d delays", total_delay_slots[j], j);
    3793              :             }
    3794              :         }
    3795            0 :       fprintf (dump_file, "\n");
    3796              : 
    3797            0 :       if (ANNUL_IFTRUE_SLOTS || ANNUL_IFFALSE_SLOTS)
    3798              :         {
    3799              :           fprintf (dump_file, ";; Reorg annuls: ");
    3800              :           need_comma = 0;
    3801              :           for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
    3802              :             {
    3803              :               if (total_annul_slots[j])
    3804              :                 {
    3805              :                   if (need_comma)
    3806              :                     fprintf (dump_file, ", ");
    3807              :                   need_comma = 1;
    3808              :                   fprintf (dump_file, "%d got %d delays", total_annul_slots[j], j);
    3809              :                 }
    3810              :             }
    3811              :           fprintf (dump_file, "\n");
    3812              :         }
    3813              : 
    3814            0 :       fprintf (dump_file, "\n");
    3815              :     }
    3816              : 
    3817            0 :   if (!sibling_labels.is_empty ())
    3818              :     {
    3819            0 :       update_alignments (sibling_labels);
    3820            0 :       sibling_labels.release ();
    3821              :     }
    3822              : 
    3823            0 :   free_resource_info ();
    3824            0 :   free (uid_to_ruid);
    3825            0 :   crtl->dbr_scheduled_p = true;
    3826              : }
    3827              : 
    3828              : /* Run delay slot optimization.  */
    3829              : static void
    3830            0 : rest_of_handle_delay_slots (void)
    3831              : {
    3832            0 :   if (DELAY_SLOTS)
    3833              :     dbr_schedule (get_insns ());
    3834            0 : }
    3835              : 
    3836              : namespace {
    3837              : 
    3838              : const pass_data pass_data_delay_slots =
    3839              : {
    3840              :   RTL_PASS, /* type */
    3841              :   "dbr", /* name */
    3842              :   OPTGROUP_NONE, /* optinfo_flags */
    3843              :   TV_DBR_SCHED, /* tv_id */
    3844              :   0, /* properties_required */
    3845              :   0, /* properties_provided */
    3846              :   0, /* properties_destroyed */
    3847              :   0, /* todo_flags_start */
    3848              :   0, /* todo_flags_finish */
    3849              : };
    3850              : 
    3851              : class pass_delay_slots : public rtl_opt_pass
    3852              : {
    3853              : public:
    3854       294587 :   pass_delay_slots (gcc::context *ctxt)
    3855       589174 :     : rtl_opt_pass (pass_data_delay_slots, ctxt)
    3856              :   {}
    3857              : 
    3858              :   /* opt_pass methods: */
    3859              :   bool gate (function *) final override;
    3860            0 :   unsigned int execute (function *) final override
    3861              :     {
    3862            0 :       rest_of_handle_delay_slots ();
    3863            0 :       return 0;
    3864              :     }
    3865              : 
    3866              : }; // class pass_delay_slots
    3867              : 
    3868              : bool
    3869      1511392 : pass_delay_slots::gate (function *)
    3870              : {
    3871              :   /* At -O0 dataflow info isn't updated after RA.  */
    3872      1511392 :   if (DELAY_SLOTS)
    3873              :     return optimize > 0 && flag_delayed_branch && !crtl->dbr_scheduled_p;
    3874              : 
    3875      1511392 :   return false;
    3876              : }
    3877              : 
    3878              : } // anon namespace
    3879              : 
    3880              : rtl_opt_pass *
    3881       294587 : make_pass_delay_slots (gcc::context *ctxt)
    3882              : {
    3883       294587 :   return new pass_delay_slots (ctxt);
    3884              : }
    3885              : 
    3886              : /* Machine dependent reorg pass.  */
    3887              : 
    3888              : namespace {
    3889              : 
    3890              : const pass_data pass_data_machine_reorg =
    3891              : {
    3892              :   RTL_PASS, /* type */
    3893              :   "mach", /* name */
    3894              :   OPTGROUP_NONE, /* optinfo_flags */
    3895              :   TV_MACH_DEP, /* tv_id */
    3896              :   0, /* properties_required */
    3897              :   0, /* properties_provided */
    3898              :   0, /* properties_destroyed */
    3899              :   0, /* todo_flags_start */
    3900              :   0, /* todo_flags_finish */
    3901              : };
    3902              : 
    3903              : class pass_machine_reorg : public rtl_opt_pass
    3904              : {
    3905              : public:
    3906       294587 :   pass_machine_reorg (gcc::context *ctxt)
    3907       589174 :     : rtl_opt_pass (pass_data_machine_reorg, ctxt)
    3908              :   {}
    3909              : 
    3910              :   /* opt_pass methods: */
    3911      1511392 :   bool gate (function *) final override
    3912              :     {
    3913      1511392 :       return targetm.machine_dependent_reorg != 0;
    3914              :     }
    3915              : 
    3916      1511385 :   unsigned int execute (function *) final override
    3917              :     {
    3918      1511385 :       targetm.machine_dependent_reorg ();
    3919      1511385 :       return 0;
    3920              :     }
    3921              : 
    3922              : }; // class pass_machine_reorg
    3923              : 
    3924              : } // anon namespace
    3925              : 
    3926              : rtl_opt_pass *
    3927       294587 : make_pass_machine_reorg (gcc::context *ctxt)
    3928              : {
    3929       294587 :   return new pass_machine_reorg (ctxt);
    3930              : }
        

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.