Remove bt-load.c
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 9 Sep 2019 16:52:12 +0000 (16:52 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 9 Sep 2019 16:52:12 +0000 (16:52 +0000)
bt-load.c has AFAIK been dead code since the removal of the SH5 port
in 2016.  I have a patch series that would need to update the liveness
tracking in a nontrivial way, so it seemed better to remove the pass
rather than install an untested and probably bogus change.

2019-09-09  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* Makefile.in (OBJS): Remove bt-load.o.
* doc/invoke.texi (fbranch-target-load-optimize): Delete.
(fbranch-target-load-optimize2, fbtr-bb-exclusive): Likewise.
* common.opt (fbranch-target-load-optimize): Mark as Ignore and
document that the option no longer does anything.
(fbranch-target-load-optimize2, fbtr-bb-exclusive): Likewise.
* target.def (branch_target_register_class): Delete.
(branch_target_register_callee_saved): Likewise.
* doc/tm.texi.in (TARGET_BRANCH_TARGET_REGISTER_CLASS): Likewise.
(TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED): Likewise.
* doc/tm.texi: Regenerate.
* tree-pass.h (make_pass_branch_target_load_optimize1): Delete.
(make_pass_branch_target_load_optimize2): Likewise.
* passes.def (pass_branch_target_load_optimize1): Likewise.
(pass_branch_target_load_optimize2): Likewise.
* targhooks.h (default_branch_target_register_class): Likewise.
* targhooks.c (default_branch_target_register_class): Likewise.
* opt-suggestions.c (test_completion_valid_options): Remove
-fbtr-bb-exclusive from the list of test options.
* bt-load.c: Remove.

From-SVN: r275521

13 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/bt-load.c [deleted file]
gcc/common.opt
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/opt-suggestions.c
gcc/passes.def
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-pass.h

index b58b92ad114524f61f71be10032c4bbd2fce03a8..f640d89ac3e6dd9c8ed9d543331b29e422233830 100644 (file)
@@ -1,3 +1,26 @@
+2019-09-09  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * Makefile.in (OBJS): Remove bt-load.o.
+       * doc/invoke.texi (fbranch-target-load-optimize): Delete.
+       (fbranch-target-load-optimize2, fbtr-bb-exclusive): Likewise.
+       * common.opt (fbranch-target-load-optimize): Mark as Ignore and
+       document that the option no longer does anything.
+       (fbranch-target-load-optimize2, fbtr-bb-exclusive): Likewise.
+       * target.def (branch_target_register_class): Delete.
+       (branch_target_register_callee_saved): Likewise.
+       * doc/tm.texi.in (TARGET_BRANCH_TARGET_REGISTER_CLASS): Likewise.
+       (TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED): Likewise.
+       * doc/tm.texi: Regenerate.
+       * tree-pass.h (make_pass_branch_target_load_optimize1): Delete.
+       (make_pass_branch_target_load_optimize2): Likewise.
+       * passes.def (pass_branch_target_load_optimize1): Likewise.
+       (pass_branch_target_load_optimize2): Likewise.
+       * targhooks.h (default_branch_target_register_class): Likewise.
+       * targhooks.c (default_branch_target_register_class): Likewise.
+       * opt-suggestions.c (test_completion_valid_options): Remove
+       -fbtr-bb-exclusive from the list of test options.
+       * bt-load.c: Remove.
+
 2019-09-09  Barnaby Wilks  <barnaby.wilks@arm.com>
 
        * match.pd: Add flag_unsafe_math_optimizations check
index 99d88a46f1d2be6ea8c8d2de82caf4a3c7bd0633..0fe02fb27a106266f3b53dcafc76bca5ddda2476 100644 (file)
@@ -1241,7 +1241,6 @@ OBJS = \
        auto-profile.o \
        bb-reorder.o \
        bitmap.o \
-       bt-load.o \
        builtins.o \
        caller-save.o \
        calls.o \
diff --git a/gcc/bt-load.c b/gcc/bt-load.c
deleted file mode 100644 (file)
index f68879c..0000000
+++ /dev/null
@@ -1,1577 +0,0 @@
-/* Perform branch target register load optimizations.
-   Copyright (C) 2001-2019 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "backend.h"
-#include "target.h"
-#include "rtl.h"
-#include "tree.h"
-#include "df.h"
-#include "insn-config.h"
-#include "regs.h"
-#include "memmodel.h"
-#include "emit-rtl.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "expr.h"
-#include "insn-attr.h"
-#include "tree-pass.h"
-#include "cfgrtl.h"
-#include "cfganal.h"
-#include "cfgcleanup.h"
-#include "cfgloop.h"
-#include "rtl-iter.h"
-#include "fibonacci_heap.h"
-
-struct btr_def;
-
-/* Target register optimizations - these are performed after reload.  */
-
-struct btr_def_group
-{
-  btr_def_group *next;
-  rtx src;
-  btr_def *members;
-};
-
-struct btr_user
-{
-  btr_user *next;
-  basic_block bb;
-  int luid;
-  rtx_insn *insn;
-  /* If INSN has a single use of a single branch register, then
-     USE points to it within INSN.  If there is more than
-     one branch register use, or the use is in some way ambiguous,
-     then USE is NULL.  */
-  rtx use;
-  int n_reaching_defs;
-  int first_reaching_def;
-  char other_use_this_block;
-};
-
-/* btr_def structs appear on three lists:
-     1. A list of all btr_def structures (head is
-       ALL_BTR_DEFS, linked by the NEXT field).
-     2. A list of branch reg definitions per basic block (head is
-       BB_BTR_DEFS[i], linked by the NEXT_THIS_BB field).
-     3. A list of all branch reg definitions belonging to the same
-       group (head is in a BTR_DEF_GROUP struct, linked by
-       NEXT_THIS_GROUP field).  */
-
-struct btr_def
-{
-  btr_def *next_this_bb;
-  btr_def *next_this_group;
-  basic_block bb;
-  int luid;
-  rtx_insn *insn;
-  int btr;
-  int cost;
-  /* For a branch register setting insn that has a constant
-     source (i.e. a label), group links together all the
-     insns with the same source.  For other branch register
-     setting insns, group is NULL.  */
-  btr_def_group *group;
-  btr_user *uses;
-  /* If this def has a reaching use which is not a simple use
-     in a branch instruction, then has_ambiguous_use will be true,
-     and we will not attempt to migrate this definition.  */
-  char has_ambiguous_use;
-  /* live_range is an approximation to the true live range for this
-     def/use web, because it records the set of blocks that contain
-     the live range.  There could be other live ranges for the same
-     branch register in that set of blocks, either in the block
-     containing the def (before the def), or in a block containing
-     a use (after the use).  If there are such other live ranges, then
-     other_btr_uses_before_def or other_btr_uses_after_use must be set true
-     as appropriate.  */
-  char other_btr_uses_before_def;
-  char other_btr_uses_after_use;
-  /* We set own_end when we have moved a definition into a dominator.
-     Thus, when a later combination removes this definition again, we know
-     to clear out trs_live_at_end again.  */
-  char own_end;
-  bitmap live_range;
-};
-
-typedef fibonacci_heap <long, btr_def> btr_heap_t;
-typedef fibonacci_node <long, btr_def> btr_heap_node_t;
-
-static int issue_rate;
-
-static int basic_block_freq (const_basic_block);
-static int insn_sets_btr_p (const rtx_insn *, int, int *);
-static void find_btr_def_group (btr_def_group **, btr_def *);
-static btr_def *add_btr_def (btr_heap_t *, basic_block, int, rtx_insn *,
-                           unsigned int, int, btr_def_group **);
-static btr_user *new_btr_user (basic_block, int, rtx_insn *);
-static void dump_hard_reg_set (HARD_REG_SET);
-static void dump_btrs_live (int);
-static void note_other_use_this_block (unsigned int, btr_user *);
-static void compute_defs_uses_and_gen (btr_heap_t *, btr_def **, btr_user **,
-                                      sbitmap *, sbitmap *, HARD_REG_SET *);
-static void compute_kill (sbitmap *, sbitmap *, HARD_REG_SET *);
-static void compute_out (sbitmap *bb_out, sbitmap *, sbitmap *, int);
-static void link_btr_uses (btr_def **, btr_user **, sbitmap *, sbitmap *, int);
-static void build_btr_def_use_webs (btr_heap_t *);
-static int block_at_edge_of_live_range_p (int, btr_def *);
-static void clear_btr_from_live_range (btr_def *def);
-static void add_btr_to_live_range (btr_def *, int);
-static void augment_live_range (bitmap, HARD_REG_SET *, basic_block,
-                               basic_block, int);
-static int choose_btr (HARD_REG_SET);
-static void combine_btr_defs (btr_def *, HARD_REG_SET *);
-static void btr_def_live_range (btr_def *, HARD_REG_SET *);
-static void move_btr_def (basic_block, int, btr_def *, bitmap, HARD_REG_SET *);
-static int migrate_btr_def (btr_def *, int);
-static void migrate_btr_defs (enum reg_class, int);
-static int can_move_up (const_basic_block, const rtx_insn *, int);
-static void note_btr_set (rtx, const_rtx, void *);
-\f
-/* The following code performs code motion of target load instructions
-   (instructions that set branch target registers), to move them
-   forward away from the branch instructions and out of loops (or,
-   more generally, from a more frequently executed place to a less
-   frequently executed place).
-   Moving target load instructions further in front of the branch
-   instruction that uses the target register value means that the hardware
-   has a better chance of preloading the instructions at the branch
-   target by the time the branch is reached.  This avoids bubbles
-   when a taken branch needs to flush out the pipeline.
-   Moving target load instructions out of loops means they are executed
-   less frequently.  */
-
-/* An obstack to hold the def-use web data structures built up for
-   migrating branch target load instructions.  */
-static struct obstack migrate_btrl_obstack;
-
-/* Array indexed by basic block number, giving the set of registers
-   live in that block.  */
-static HARD_REG_SET *btrs_live;
-
-/* Array indexed by basic block number, giving the set of registers live at
-  the end of that block, including any uses by a final jump insn, if any.  */
-static HARD_REG_SET *btrs_live_at_end;
-
-/* Set of all target registers that we are willing to allocate.  */
-static HARD_REG_SET all_btrs;
-
-/* Provide lower and upper bounds for target register numbers, so that
-   we don't need to search through all the hard registers all the time.  */
-static int first_btr, last_btr;
-
-
-
-/* Return an estimate of the frequency of execution of block bb.  */
-static int
-basic_block_freq (const_basic_block bb)
-{
-  return bb->count.to_frequency (cfun);
-}
-
-/* If the rtx at *XP references (sets or reads) any branch target
-   register, return one such register.  If EXCLUDEP is set, disregard
-   any references within that location.  */
-static rtx *
-find_btr_use (rtx *xp, rtx *excludep = 0)
-{
-  subrtx_ptr_iterator::array_type array;
-  FOR_EACH_SUBRTX_PTR (iter, array, xp, NONCONST)
-    {
-      rtx *loc = *iter;
-      if (loc == excludep)
-       iter.skip_subrtxes ();
-      else
-       {
-         const_rtx x = *loc;
-         if (REG_P (x)
-             && overlaps_hard_reg_set_p (all_btrs, GET_MODE (x), REGNO (x)))
-           return loc;
-       }
-    }
-  return 0;
-}
-
-/* Return true if insn is an instruction that sets a target register.
-   if CHECK_CONST is true, only return true if the source is constant.
-   If such a set is found and REGNO is nonzero, assign the register number
-   of the destination register to *REGNO.  */
-static int
-insn_sets_btr_p (const rtx_insn *insn, int check_const, int *regno)
-{
-  rtx set;
-
-  if (NONJUMP_INSN_P (insn)
-      && (set = single_set (insn)))
-    {
-      rtx dest = SET_DEST (set);
-      rtx src = SET_SRC (set);
-
-      if (GET_CODE (dest) == SUBREG)
-       dest = XEXP (dest, 0);
-
-      if (REG_P (dest)
-         && TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
-       {
-         gcc_assert (!find_btr_use (&src));
-
-         if (!check_const || CONSTANT_P (src))
-           {
-             if (regno)
-               *regno = REGNO (dest);
-             return 1;
-           }
-       }
-    }
-  return 0;
-}
-
-/* Find the group that the target register definition DEF belongs
-   to in the list starting with *ALL_BTR_DEF_GROUPS.  If no such
-   group exists, create one.  Add def to the group.  */
-static void
-find_btr_def_group (btr_def_group **all_btr_def_groups, btr_def *def)
-{
-  if (insn_sets_btr_p (def->insn, 1, NULL))
-    {
-      btr_def_group *this_group;
-      rtx def_src = SET_SRC (single_set (def->insn));
-
-      /* ?? This linear search is an efficiency concern, particularly
-        as the search will almost always fail to find a match.  */
-      for (this_group = *all_btr_def_groups;
-          this_group != NULL;
-          this_group = this_group->next)
-       if (rtx_equal_p (def_src, this_group->src))
-         break;
-
-      if (!this_group)
-       {
-         this_group = XOBNEW (&migrate_btrl_obstack, btr_def_group);
-         this_group->src = def_src;
-         this_group->members = NULL;
-         this_group->next = *all_btr_def_groups;
-         *all_btr_def_groups = this_group;
-       }
-      def->group = this_group;
-      def->next_this_group = this_group->members;
-      this_group->members = def;
-    }
-  else
-    def->group = NULL;
-}
-
-/* Create a new target register definition structure, for a definition in
-   block BB, instruction INSN, and insert it into ALL_BTR_DEFS.  Return
-   the new definition.  */
-static btr_def *
-add_btr_def (btr_heap_t *all_btr_defs, basic_block bb, int insn_luid,
-            rtx_insn *insn,
-            unsigned int dest_reg, int other_btr_uses_before_def,
-            btr_def_group **all_btr_def_groups)
-{
-  btr_def *this_def = XOBNEW (&migrate_btrl_obstack, btr_def);
-  this_def->bb = bb;
-  this_def->luid = insn_luid;
-  this_def->insn = insn;
-  this_def->btr = dest_reg;
-  this_def->cost = basic_block_freq (bb);
-  this_def->has_ambiguous_use = 0;
-  this_def->other_btr_uses_before_def = other_btr_uses_before_def;
-  this_def->other_btr_uses_after_use = 0;
-  this_def->next_this_bb = NULL;
-  this_def->next_this_group = NULL;
-  this_def->uses = NULL;
-  this_def->live_range = NULL;
-  find_btr_def_group (all_btr_def_groups, this_def);
-
-  all_btr_defs->insert (-this_def->cost, this_def);
-
-  if (dump_file)
-    fprintf (dump_file,
-      "Found target reg definition: sets %u { bb %d, insn %d }%s priority %d\n",
-            dest_reg, bb->index, INSN_UID (insn),
-            (this_def->group ? "" : ":not const"), this_def->cost);
-
-  return this_def;
-}
-
-/* Create a new target register user structure, for a use in block BB,
-   instruction INSN.  Return the new user.  */
-static btr_user *
-new_btr_user (basic_block bb, int insn_luid, rtx_insn *insn)
-{
-  /* This instruction reads target registers.  We need
-     to decide whether we can replace all target register
-     uses easily.
-   */
-  rtx *usep = find_btr_use (&PATTERN (insn));
-  rtx use;
-  btr_user *user = NULL;
-
-  if (usep)
-    {
-      int unambiguous_single_use;
-
-      /* We want to ensure that USE is the only use of a target
-        register in INSN, so that we know that to rewrite INSN to use
-        a different target register, all we have to do is replace USE.  */
-      unambiguous_single_use = !find_btr_use (&PATTERN (insn), usep);
-      if (!unambiguous_single_use)
-       usep = NULL;
-    }
-  use = usep ? *usep : NULL_RTX;
-  user = XOBNEW (&migrate_btrl_obstack, btr_user);
-  user->bb = bb;
-  user->luid = insn_luid;
-  user->insn = insn;
-  user->use = use;
-  user->other_use_this_block = 0;
-  user->next = NULL;
-  user->n_reaching_defs = 0;
-  user->first_reaching_def = -1;
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "Uses target reg: { bb %d, insn %d }",
-              bb->index, INSN_UID (insn));
-
-      if (user->use)
-       fprintf (dump_file, ": unambiguous use of reg %d\n",
-                REGNO (user->use));
-    }
-
-  return user;
-}
-
-/* Write the contents of S to the dump file.  */
-static void
-dump_hard_reg_set (HARD_REG_SET s)
-{
-  int reg;
-  for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
-    if (TEST_HARD_REG_BIT (s, reg))
-      fprintf (dump_file, " %d", reg);
-}
-
-/* Write the set of target regs live in block BB to the dump file.  */
-static void
-dump_btrs_live (int bb)
-{
-  fprintf (dump_file, "BB%d live:", bb);
-  dump_hard_reg_set (btrs_live[bb]);
-  fprintf (dump_file, "\n");
-}
-
-/* REGNO is the number of a branch target register that is being used or
-   set.  USERS_THIS_BB is a list of preceding branch target register users;
-   If any of them use the same register, set their other_use_this_block
-   flag.  */
-static void
-note_other_use_this_block (unsigned int regno, btr_user *users_this_bb)
-{
-  btr_user *user;
-
-  for (user = users_this_bb; user != NULL; user = user->next)
-    if (user->use && REGNO (user->use) == regno)
-      user->other_use_this_block = 1;
-}
-
-struct defs_uses_info {
-  btr_user *users_this_bb;
-  HARD_REG_SET btrs_written_in_block;
-  HARD_REG_SET btrs_live_in_block;
-  sbitmap bb_gen;
-  sbitmap *btr_defset;
-};
-
-/* Called via note_stores or directly to register stores into /
-   clobbers of a branch target register DEST that are not recognized as
-   straightforward definitions.  DATA points to information about the
-   current basic block that needs updating.  */
-static void
-note_btr_set (rtx dest, const_rtx set ATTRIBUTE_UNUSED, void *data)
-{
-  defs_uses_info *info = (defs_uses_info *) data;
-  int regno, end_regno;
-
-  if (!REG_P (dest))
-    return;
-  regno = REGNO (dest);
-  end_regno = END_REGNO (dest);
-  for (; regno < end_regno; regno++)
-    if (TEST_HARD_REG_BIT (all_btrs, regno))
-      {
-       note_other_use_this_block (regno, info->users_this_bb);
-       SET_HARD_REG_BIT (info->btrs_written_in_block, regno);
-       SET_HARD_REG_BIT (info->btrs_live_in_block, regno);
-       bitmap_and_compl (info->bb_gen, info->bb_gen,
-                           info->btr_defset[regno - first_btr]);
-      }
-}
-
-static void
-compute_defs_uses_and_gen (btr_heap_t *all_btr_defs, btr_def **def_array,
-                          btr_user **use_array, sbitmap *btr_defset,
-                          sbitmap *bb_gen, HARD_REG_SET *btrs_written)
-{
-  /* Scan the code building up the set of all defs and all uses.
-     For each target register, build the set of defs of that register.
-     For each block, calculate the set of target registers
-     written in that block.
-     Also calculate the set of btrs ever live in that block.
-  */
-  int i;
-  int insn_luid = 0;
-  btr_def_group *all_btr_def_groups = NULL;
-  defs_uses_info info;
-
-  bitmap_vector_clear (bb_gen, last_basic_block_for_fn (cfun));
-  for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-    {
-      basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
-      int reg;
-      btr_def *defs_this_bb = NULL;
-      rtx_insn *insn;
-      rtx_insn *last;
-      int can_throw = 0;
-
-      info.users_this_bb = NULL;
-      info.bb_gen = bb_gen[i];
-      info.btr_defset = btr_defset;
-
-      CLEAR_HARD_REG_SET (info.btrs_live_in_block);
-      CLEAR_HARD_REG_SET (info.btrs_written_in_block);
-      for (reg = first_btr; reg <= last_btr; reg++)
-       if (TEST_HARD_REG_BIT (all_btrs, reg)
-           && REGNO_REG_SET_P (df_get_live_in (bb), reg))
-         SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
-
-      for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
-          insn != last;
-          insn = NEXT_INSN (insn), insn_luid++)
-       {
-         if (INSN_P (insn))
-           {
-             int regno;
-             int insn_uid = INSN_UID (insn);
-
-             if (insn_sets_btr_p (insn, 0, &regno))
-               {
-                 btr_def *def = add_btr_def (
-                     all_btr_defs, bb, insn_luid, insn, regno,
-                     TEST_HARD_REG_BIT (info.btrs_live_in_block, regno),
-                     &all_btr_def_groups);
-
-                 def_array[insn_uid] = def;
-                 SET_HARD_REG_BIT (info.btrs_written_in_block, regno);
-                 SET_HARD_REG_BIT (info.btrs_live_in_block, regno);
-                 bitmap_and_compl (bb_gen[i], bb_gen[i],
-                                     btr_defset[regno - first_btr]);
-                 bitmap_set_bit (bb_gen[i], insn_uid);
-                 def->next_this_bb = defs_this_bb;
-                 defs_this_bb = def;
-                 bitmap_set_bit (btr_defset[regno - first_btr], insn_uid);
-                 note_other_use_this_block (regno, info.users_this_bb);
-               }
-             /* Check for the blockage emitted by expand_nl_goto_receiver.  */
-             else if (cfun->has_nonlocal_label
-                      && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE)
-               {
-                 btr_user *user;
-
-                 /* Do the equivalent of calling note_other_use_this_block
-                    for every target register.  */
-                 for (user = info.users_this_bb; user != NULL;
-                      user = user->next)
-                   if (user->use)
-                     user->other_use_this_block = 1;
-                 IOR_HARD_REG_SET (info.btrs_written_in_block, all_btrs);
-                 IOR_HARD_REG_SET (info.btrs_live_in_block, all_btrs);
-                 bitmap_clear (info.bb_gen);
-               }
-             else
-               {
-                 if (find_btr_use (&PATTERN (insn)))
-                   {
-                     btr_user *user = new_btr_user (bb, insn_luid, insn);
-
-                     use_array[insn_uid] = user;
-                     if (user->use)
-                       SET_HARD_REG_BIT (info.btrs_live_in_block,
-                                         REGNO (user->use));
-                     else
-                       {
-                         int reg;
-                         for (reg = first_btr; reg <= last_btr; reg++)
-                           if (TEST_HARD_REG_BIT (all_btrs, reg)
-                               && refers_to_regno_p (reg, user->insn))
-                             {
-                               note_other_use_this_block (reg,
-                                                          info.users_this_bb);
-                               SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
-                             }
-                         note_stores (PATTERN (insn), note_btr_set, &info);
-                       }
-                     user->next = info.users_this_bb;
-                     info.users_this_bb = user;
-                   }
-                 if (CALL_P (insn))
-                   {
-                     HARD_REG_SET *clobbered = &call_used_reg_set;
-                     HARD_REG_SET call_saved;
-                     rtx pat = PATTERN (insn);
-                     int i;
-
-                     /* Check for sibcall.  */
-                     if (GET_CODE (pat) == PARALLEL)
-                       for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
-                         if (ANY_RETURN_P (XVECEXP (pat, 0, i)))
-                           {
-                             COMPL_HARD_REG_SET (call_saved,
-                                                 call_used_reg_set);
-                             clobbered = &call_saved;
-                           }
-
-                     for (regno = first_btr; regno <= last_btr; regno++)
-                       if (TEST_HARD_REG_BIT (*clobbered, regno))
-                         note_btr_set (regno_reg_rtx[regno], NULL_RTX, &info);
-                   }
-               }
-           }
-       }
-
-      COPY_HARD_REG_SET (btrs_live[i], info.btrs_live_in_block);
-      COPY_HARD_REG_SET (btrs_written[i], info.btrs_written_in_block);
-
-      REG_SET_TO_HARD_REG_SET (btrs_live_at_end[i], df_get_live_out (bb));
-      /* If this block ends in a jump insn, add any uses or even clobbers
-        of branch target registers that it might have.  */
-      for (insn = BB_END (bb); insn != BB_HEAD (bb) && ! INSN_P (insn); )
-       insn = PREV_INSN (insn);
-      /* ??? for the fall-through edge, it would make sense to insert the
-        btr set on the edge, but that would require to split the block
-        early on so that we can distinguish between dominance from the fall
-        through edge - which can use the call-clobbered registers - from
-        dominance by the throw edge.  */
-      if (can_throw_internal (insn))
-       {
-         HARD_REG_SET tmp;
-
-         COPY_HARD_REG_SET (tmp, call_used_reg_set);
-         AND_HARD_REG_SET (tmp, all_btrs);
-         IOR_HARD_REG_SET (btrs_live_at_end[i], tmp);
-         can_throw = 1;
-       }
-      if (can_throw || JUMP_P (insn))
-       {
-         int regno;
-
-         for (regno = first_btr; regno <= last_btr; regno++)
-           if (refers_to_regno_p (regno, insn))
-             SET_HARD_REG_BIT (btrs_live_at_end[i], regno);
-       }
-
-      if (dump_file)
-       dump_btrs_live (i);
-    }
-}
-
-static void
-compute_kill (sbitmap *bb_kill, sbitmap *btr_defset,
-             HARD_REG_SET *btrs_written)
-{
-  int i;
-  int regno;
-
-  /* For each basic block, form the set BB_KILL - the set
-     of definitions that the block kills.  */
-  bitmap_vector_clear (bb_kill, last_basic_block_for_fn (cfun));
-  for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-    {
-      for (regno = first_btr; regno <= last_btr; regno++)
-       if (TEST_HARD_REG_BIT (all_btrs, regno)
-           && TEST_HARD_REG_BIT (btrs_written[i], regno))
-         bitmap_ior (bb_kill[i], bb_kill[i],
-                         btr_defset[regno - first_btr]);
-    }
-}
-
-static void
-compute_out (sbitmap *bb_out, sbitmap *bb_gen, sbitmap *bb_kill, int max_uid)
-{
-  /* Perform iterative dataflow:
-      Initially, for all blocks, BB_OUT = BB_GEN.
-      For each block,
-       BB_IN  = union over predecessors of BB_OUT(pred)
-       BB_OUT = (BB_IN - BB_KILL) + BB_GEN
-     Iterate until the bb_out sets stop growing.  */
-  int i;
-  int changed;
-  auto_sbitmap bb_in (max_uid);
-
-  for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-    bitmap_copy (bb_out[i], bb_gen[i]);
-
-  changed = 1;
-  while (changed)
-    {
-      changed = 0;
-      for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-       {
-         bitmap_union_of_preds (bb_in, bb_out, BASIC_BLOCK_FOR_FN (cfun, i));
-         changed |= bitmap_ior_and_compl (bb_out[i], bb_gen[i],
-                                              bb_in, bb_kill[i]);
-       }
-    }
-}
-
-static void
-link_btr_uses (btr_def **def_array, btr_user **use_array, sbitmap *bb_out,
-              sbitmap *btr_defset, int max_uid)
-{
-  int i;
-  auto_sbitmap reaching_defs (max_uid);
-
-  /* Link uses to the uses lists of all of their reaching defs.
-     Count up the number of reaching defs of each use.  */
-  for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-    {
-      basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
-      rtx_insn *insn;
-      rtx_insn *last;
-
-      bitmap_union_of_preds (reaching_defs, bb_out, BASIC_BLOCK_FOR_FN (cfun, i));
-      for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
-          insn != last;
-          insn = NEXT_INSN (insn))
-       {
-         if (INSN_P (insn))
-           {
-             int insn_uid = INSN_UID (insn);
-
-             btr_def *def   = def_array[insn_uid];
-             btr_user *user = use_array[insn_uid];
-             if (def != NULL)
-               {
-                 /* Remove all reaching defs of regno except
-                    for this one.  */
-                 bitmap_and_compl (reaching_defs, reaching_defs,
-                                     btr_defset[def->btr - first_btr]);
-                 bitmap_set_bit (reaching_defs, insn_uid);
-               }
-
-             if (user != NULL)
-               {
-                 /* Find all the reaching defs for this use.  */
-                 auto_sbitmap reaching_defs_of_reg (max_uid);
-                 unsigned int uid = 0;
-                 sbitmap_iterator sbi;
-
-                 if (user->use)
-                   bitmap_and (
-                     reaching_defs_of_reg,
-                     reaching_defs,
-                     btr_defset[REGNO (user->use) - first_btr]);
-                 else
-                   {
-                     int reg;
-
-                     bitmap_clear (reaching_defs_of_reg);
-                     for (reg = first_btr; reg <= last_btr; reg++)
-                       if (TEST_HARD_REG_BIT (all_btrs, reg)
-                           && refers_to_regno_p (reg, user->insn))
-                         bitmap_or_and (reaching_defs_of_reg,
-                           reaching_defs_of_reg,
-                           reaching_defs,
-                           btr_defset[reg - first_btr]);
-                   }
-                 EXECUTE_IF_SET_IN_BITMAP (reaching_defs_of_reg, 0, uid, sbi)
-                   {
-                     btr_def *def = def_array[uid];
-
-                     /* We now know that def reaches user.  */
-
-                     if (dump_file)
-                       fprintf (dump_file,
-                         "Def in insn %d reaches use in insn %d\n",
-                         uid, insn_uid);
-
-                     user->n_reaching_defs++;
-                     if (!user->use)
-                       def->has_ambiguous_use = 1;
-                     if (user->first_reaching_def != -1)
-                       { /* There is more than one reaching def.  This is
-                            a rare case, so just give up on this def/use
-                            web when it occurs.  */
-                         def->has_ambiguous_use = 1;
-                         def_array[user->first_reaching_def]
-                           ->has_ambiguous_use = 1;
-                         if (dump_file)
-                           fprintf (dump_file,
-                                    "(use %d has multiple reaching defs)\n",
-                                    insn_uid);
-                       }
-                     else
-                       user->first_reaching_def = uid;
-                     if (user->other_use_this_block)
-                       def->other_btr_uses_after_use = 1;
-                     user->next = def->uses;
-                     def->uses = user;
-                   }
-               }
-
-             if (CALL_P (insn))
-               {
-                 int regno;
-
-                 for (regno = first_btr; regno <= last_btr; regno++)
-                   if (TEST_HARD_REG_BIT (all_btrs, regno)
-                       && TEST_HARD_REG_BIT (call_used_reg_set, regno))
-                     bitmap_and_compl (reaching_defs, reaching_defs,
-                                         btr_defset[regno - first_btr]);
-               }
-           }
-       }
-    }
-}
-
-static void
-build_btr_def_use_webs (btr_heap_t *all_btr_defs)
-{
-  const int max_uid = get_max_uid ();
-  btr_def  **def_array   = XCNEWVEC (btr_def *, max_uid);
-  btr_user **use_array   = XCNEWVEC (btr_user *, max_uid);
-  sbitmap *btr_defset   = sbitmap_vector_alloc (
-                          (last_btr - first_btr) + 1, max_uid);
-  sbitmap *bb_gen = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
-                                         max_uid);
-  HARD_REG_SET *btrs_written = XCNEWVEC (HARD_REG_SET,
-                                        last_basic_block_for_fn (cfun));
-  sbitmap *bb_kill;
-  sbitmap *bb_out;
-
-  bitmap_vector_clear (btr_defset, (last_btr - first_btr) + 1);
-
-  compute_defs_uses_and_gen (all_btr_defs, def_array, use_array, btr_defset,
-                            bb_gen, btrs_written);
-
-  bb_kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), max_uid);
-  compute_kill (bb_kill, btr_defset, btrs_written);
-  free (btrs_written);
-
-  bb_out = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), max_uid);
-  compute_out (bb_out, bb_gen, bb_kill, max_uid);
-
-  sbitmap_vector_free (bb_gen);
-  sbitmap_vector_free (bb_kill);
-
-  link_btr_uses (def_array, use_array, bb_out, btr_defset, max_uid);
-
-  sbitmap_vector_free (bb_out);
-  sbitmap_vector_free (btr_defset);
-  free (use_array);
-  free (def_array);
-}
-
-/* Return true if basic block BB contains the start or end of the
-   live range of the definition DEF, AND there are other live
-   ranges of the same target register that include BB.  */
-static int
-block_at_edge_of_live_range_p (int bb, btr_def *def)
-{
-  if (def->other_btr_uses_before_def
-      && BASIC_BLOCK_FOR_FN (cfun, bb) == def->bb)
-    return 1;
-  else if (def->other_btr_uses_after_use)
-    {
-      btr_user *user;
-      for (user = def->uses; user != NULL; user = user->next)
-       if (BASIC_BLOCK_FOR_FN (cfun, bb) == user->bb)
-         return 1;
-    }
-  return 0;
-}
-
-/* We are removing the def/use web DEF.  The target register
-   used in this web is therefore no longer live in the live range
-   of this web, so remove it from the live set of all basic blocks
-   in the live range of the web.
-   Blocks at the boundary of the live range may contain other live
-   ranges for the same target register, so we have to be careful
-   to remove the target register from the live set of these blocks
-   only if they do not contain other live ranges for the same register.  */
-static void
-clear_btr_from_live_range (btr_def *def)
-{
-  unsigned bb;
-  bitmap_iterator bi;
-
-  EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
-    {
-      if ((!def->other_btr_uses_before_def
-          && !def->other_btr_uses_after_use)
-         || !block_at_edge_of_live_range_p (bb, def))
-       {
-         CLEAR_HARD_REG_BIT (btrs_live[bb], def->btr);
-         CLEAR_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
-         if (dump_file)
-           dump_btrs_live (bb);
-       }
-    }
- if (def->own_end)
-   CLEAR_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
-}
-
-
-/* We are adding the def/use web DEF.  Add the target register used
-   in this web to the live set of all of the basic blocks that contain
-   the live range of the web.
-   If OWN_END is set, also show that the register is live from our
-   definitions at the end of the basic block where it is defined.  */
-static void
-add_btr_to_live_range (btr_def *def, int own_end)
-{
-  unsigned bb;
-  bitmap_iterator bi;
-
-  EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
-    {
-      SET_HARD_REG_BIT (btrs_live[bb], def->btr);
-      SET_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
-      if (dump_file)
-       dump_btrs_live (bb);
-    }
-  if (own_end)
-    {
-      SET_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
-      def->own_end = 1;
-    }
-}
-
-/* Update a live range to contain the basic block NEW_BLOCK, and all
-   blocks on paths between the existing live range and NEW_BLOCK.
-   HEAD is a block contained in the existing live range that dominates
-   all other blocks in the existing live range.
-   Also add to the set BTRS_LIVE_IN_RANGE all target registers that
-   are live in the blocks that we add to the live range.
-   If FULL_RANGE is set, include the full live range of NEW_BB;
-   otherwise, if NEW_BB dominates HEAD_BB, only add registers that
-   are life at the end of NEW_BB for NEW_BB itself.
-   It is a precondition that either NEW_BLOCK dominates HEAD,or
-   HEAD dom NEW_BLOCK.  This is used to speed up the
-   implementation of this function.  */
-static void
-augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range,
-                   basic_block head_bb, basic_block new_bb, int full_range)
-{
-  basic_block *worklist, *tos;
-
-  tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
-
-  if (dominated_by_p (CDI_DOMINATORS, new_bb, head_bb))
-    {
-      if (new_bb == head_bb)
-       {
-         if (full_range)
-           IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_bb->index]);
-         free (tos);
-         return;
-       }
-      *tos++ = new_bb;
-    }
-  else
-    {
-      edge e;
-      edge_iterator ei;
-      int new_block = new_bb->index;
-
-      gcc_assert (dominated_by_p (CDI_DOMINATORS, head_bb, new_bb));
-
-      IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[head_bb->index]);
-      bitmap_set_bit (live_range, new_block);
-      /* A previous btr migration could have caused a register to be
-       live just at the end of new_block which we need in full, so
-       use trs_live_at_end even if full_range is set.  */
-      IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live_at_end[new_block]);
-      if (full_range)
-       IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]);
-      if (dump_file)
-       {
-         fprintf (dump_file,
-                  "Adding end of block %d and rest of %d to live range\n",
-                  new_block, head_bb->index);
-         fprintf (dump_file,"Now live btrs are ");
-         dump_hard_reg_set (*btrs_live_in_range);
-         fprintf (dump_file, "\n");
-       }
-      FOR_EACH_EDGE (e, ei, head_bb->preds)
-       *tos++ = e->src;
-    }
-
-  while (tos != worklist)
-    {
-      basic_block bb = *--tos;
-      if (!bitmap_bit_p (live_range, bb->index))
-       {
-         edge e;
-         edge_iterator ei;
-
-         bitmap_set_bit (live_range, bb->index);
-         IOR_HARD_REG_SET (*btrs_live_in_range,
-           btrs_live[bb->index]);
-         /* A previous btr migration could have caused a register to be
-            live just at the end of a block which we need in full.  */
-         IOR_HARD_REG_SET (*btrs_live_in_range,
-           btrs_live_at_end[bb->index]);
-         if (dump_file)
-           {
-             fprintf (dump_file,
-               "Adding block %d to live range\n", bb->index);
-             fprintf (dump_file,"Now live btrs are ");
-             dump_hard_reg_set (*btrs_live_in_range);
-             fprintf (dump_file, "\n");
-           }
-
-         FOR_EACH_EDGE (e, ei, bb->preds)
-           {
-             basic_block pred = e->src;
-             if (!bitmap_bit_p (live_range, pred->index))
-               *tos++ = pred;
-           }
-       }
-    }
-
-  free (worklist);
-}
-
-/*  Return the most desirable target register that is not in
-    the set USED_BTRS.  */
-static int
-choose_btr (HARD_REG_SET used_btrs)
-{
-  int i;
-
-  if (!hard_reg_set_subset_p (all_btrs, used_btrs))
-    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-      {
-#ifdef REG_ALLOC_ORDER
-       int regno = reg_alloc_order[i];
-#else
-       int regno = i;
-#endif
-       if (TEST_HARD_REG_BIT (all_btrs, regno)
-           && !TEST_HARD_REG_BIT (used_btrs, regno))
-         return regno;
-      }
-  return -1;
-}
-
-/* Calculate the set of basic blocks that contain the live range of
-   the def/use web DEF.
-   Also calculate the set of target registers that are live at time
-   in this live range, but ignore the live range represented by DEF
-   when calculating this set.  */
-static void
-btr_def_live_range (btr_def *def, HARD_REG_SET *btrs_live_in_range)
-{
-  if (!def->live_range)
-    {
-      btr_user *user;
-
-      def->live_range = BITMAP_ALLOC (NULL);
-
-      bitmap_set_bit (def->live_range, def->bb->index);
-      COPY_HARD_REG_SET (*btrs_live_in_range,
-                        (flag_btr_bb_exclusive
-                         ? btrs_live : btrs_live_at_end)[def->bb->index]);
-
-      for (user = def->uses; user != NULL; user = user->next)
-       augment_live_range (def->live_range, btrs_live_in_range,
-                           def->bb, user->bb,
-                           (flag_btr_bb_exclusive
-                            || user->insn != BB_END (def->bb)
-                            || !JUMP_P (user->insn)));
-    }
-  else
-    {
-      /* def->live_range is accurate, but we need to recompute
-        the set of target registers live over it, because migration
-        of other PT instructions may have affected it.
-      */
-      unsigned bb;
-      unsigned def_bb = flag_btr_bb_exclusive ? -1 : def->bb->index;
-      bitmap_iterator bi;
-
-      CLEAR_HARD_REG_SET (*btrs_live_in_range);
-      EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
-       {
-         IOR_HARD_REG_SET (*btrs_live_in_range,
-                           (def_bb == bb
-                            ? btrs_live_at_end : btrs_live) [bb]);
-       }
-    }
-  if (!def->other_btr_uses_before_def &&
-      !def->other_btr_uses_after_use)
-    CLEAR_HARD_REG_BIT (*btrs_live_in_range, def->btr);
-}
-
-/* Merge into the def/use web DEF any other def/use webs in the same
-   group that are dominated by DEF, provided that there is a target
-   register available to allocate to the merged web.  */
-static void
-combine_btr_defs (btr_def *def, HARD_REG_SET *btrs_live_in_range)
-{
-  btr_def *other_def;
-
-  for (other_def = def->group->members;
-       other_def != NULL;
-       other_def = other_def->next_this_group)
-    {
-      if (other_def != def
-         && other_def->uses != NULL
-         && ! other_def->has_ambiguous_use
-         && dominated_by_p (CDI_DOMINATORS, other_def->bb, def->bb))
-       {
-         /* def->bb dominates the other def, so def and other_def could
-            be combined.  */
-         /* Merge their live ranges, and get the set of
-            target registers live over the merged range.  */
-         int btr;
-         HARD_REG_SET combined_btrs_live;
-         auto_bitmap combined_live_range;
-         btr_user *user;
-
-         if (other_def->live_range == NULL)
-           {
-             HARD_REG_SET dummy_btrs_live_in_range;
-             btr_def_live_range (other_def, &dummy_btrs_live_in_range);
-           }
-         COPY_HARD_REG_SET (combined_btrs_live, *btrs_live_in_range);
-         bitmap_copy (combined_live_range, def->live_range);
-
-         for (user = other_def->uses; user != NULL; user = user->next)
-           augment_live_range (combined_live_range, &combined_btrs_live,
-                               def->bb, user->bb,
-                               (flag_btr_bb_exclusive
-                                || user->insn != BB_END (def->bb)
-                                || !JUMP_P (user->insn)));
-
-         btr = choose_btr (combined_btrs_live);
-         if (btr != -1)
-           {
-             /* We can combine them.  */
-             if (dump_file)
-               fprintf (dump_file,
-                        "Combining def in insn %d with def in insn %d\n",
-                        INSN_UID (other_def->insn), INSN_UID (def->insn));
-
-             def->btr = btr;
-             user = other_def->uses;
-             while (user != NULL)
-               {
-                 btr_user *next = user->next;
-
-                 user->next = def->uses;
-                 def->uses = user;
-                 user = next;
-               }
-             /* Combining def/use webs can make target registers live
-                after uses where they previously were not.  This means
-                some REG_DEAD notes may no longer be correct.  We could
-                be more precise about this if we looked at the combined
-                live range, but here I just delete any REG_DEAD notes
-                in case they are no longer correct.  */
-             for (user = def->uses; user != NULL; user = user->next)
-               remove_note (user->insn,
-                            find_regno_note (user->insn, REG_DEAD,
-                                             REGNO (user->use)));
-             clear_btr_from_live_range (other_def);
-             other_def->uses = NULL;
-             bitmap_copy (def->live_range, combined_live_range);
-             if (other_def->btr == btr && other_def->other_btr_uses_after_use)
-               def->other_btr_uses_after_use = 1;
-             COPY_HARD_REG_SET (*btrs_live_in_range, combined_btrs_live);
-
-             /* Delete the old target register initialization.  */
-             delete_insn (other_def->insn);
-
-           }
-       }
-    }
-}
-
-/* Move the definition DEF from its current position to basic
-   block NEW_DEF_BB, and modify it to use branch target register BTR.
-   Delete the old defining insn, and insert a new one in NEW_DEF_BB.
-   Update all reaching uses of DEF in the RTL to use BTR.
-   If this new position means that other defs in the
-   same group can be combined with DEF then combine them.  */
-static void
-move_btr_def (basic_block new_def_bb, int btr, btr_def *def, bitmap live_range,
-            HARD_REG_SET *btrs_live_in_range)
-{
-  /* We can move the instruction.
-     Set a target register in block NEW_DEF_BB to the value
-     needed for this target register definition.
-     Replace all uses of the old target register definition by
-     uses of the new definition.  Delete the old definition.  */
-  basic_block b = new_def_bb;
-  rtx_insn *insp = BB_HEAD (b);
-  rtx_insn *old_insn = def->insn;
-  rtx src;
-  rtx btr_rtx;
-  rtx_insn *new_insn;
-  machine_mode btr_mode;
-  btr_user *user;
-  rtx set;
-
-  if (dump_file)
-    fprintf(dump_file, "migrating to basic block %d, using reg %d\n",
-           new_def_bb->index, btr);
-
-  clear_btr_from_live_range (def);
-  def->btr = btr;
-  def->bb = new_def_bb;
-  def->luid = 0;
-  def->cost = basic_block_freq (new_def_bb);
-  bitmap_copy (def->live_range, live_range);
-  combine_btr_defs (def, btrs_live_in_range);
-  btr = def->btr;
-  def->other_btr_uses_before_def
-    = TEST_HARD_REG_BIT (btrs_live[b->index], btr) ? 1 : 0;
-  add_btr_to_live_range (def, 1);
-  if (LABEL_P (insp))
-    insp = NEXT_INSN (insp);
-  /* N.B.: insp is expected to be NOTE_INSN_BASIC_BLOCK now.  Some
-     optimizations can result in insp being both first and last insn of
-     its basic block.  */
-  /* ?? some assertions to check that insp is sensible? */
-
-  if (def->other_btr_uses_before_def)
-    {
-      for (insp = BB_END (b); ! INSN_P (insp); insp = PREV_INSN (insp))
-       gcc_assert (insp != BB_HEAD (b));
-
-      if (JUMP_P (insp) || can_throw_internal (insp))
-       insp = PREV_INSN (insp);
-    }
-
-  set = single_set (old_insn);
-  src = SET_SRC (set);
-  btr_mode = GET_MODE (SET_DEST (set));
-  btr_rtx = gen_rtx_REG (btr_mode, btr);
-
-  new_insn = gen_move_insn (btr_rtx, src);
-
-  /* Insert target register initialization at head of basic block.  */
-  def->insn = emit_insn_after (new_insn, insp);
-
-  df_set_regs_ever_live (btr, true);
-
-  if (dump_file)
-    fprintf (dump_file, "New pt is insn %d, inserted after insn %d\n",
-            INSN_UID (def->insn), INSN_UID (insp));
-
-  /* Delete the old target register initialization.  */
-  delete_insn (old_insn);
-
-  /* Replace each use of the old target register by a use of the new target
-     register.  */
-  for (user = def->uses; user != NULL; user = user->next)
-    {
-      /* Some extra work here to ensure consistent modes, because
-        it seems that a target register REG rtx can be given a different
-        mode depending on the context (surely that should not be
-        the case?).  */
-      rtx replacement_rtx;
-      if (GET_MODE (user->use) == GET_MODE (btr_rtx)
-         || GET_MODE (user->use) == VOIDmode)
-       replacement_rtx = btr_rtx;
-      else
-       replacement_rtx = gen_rtx_REG (GET_MODE (user->use), btr);
-      validate_replace_rtx (user->use, replacement_rtx, user->insn);
-      user->use = replacement_rtx;
-    }
-}
-
-/* We anticipate intra-block scheduling to be done.  See if INSN could move
-   up within BB by N_INSNS.  */
-static int
-can_move_up (const_basic_block bb, const rtx_insn *insn, int n_insns)
-{
-  while (insn != BB_HEAD (bb) && n_insns > 0)
-    {
-      insn = PREV_INSN (insn);
-      /* ??? What if we have an anti-dependency that actually prevents the
-        scheduler from doing the move?  We'd like to re-allocate the register,
-        but not necessarily put the load into another basic block.  */
-      if (INSN_P (insn))
-       n_insns--;
-    }
-  return n_insns <= 0;
-}
-
-/* Attempt to migrate the target register definition DEF to an
-   earlier point in the flowgraph.
-
-   It is a precondition of this function that DEF is migratable:
-   i.e. it has a constant source, and all uses are unambiguous.
-
-   Only migrations that reduce the cost of DEF will be made.
-   MIN_COST is the lower bound on the cost of the DEF after migration.
-   If we migrate DEF so that its cost falls below MIN_COST,
-   then we do not attempt to migrate further.  The idea is that
-   we migrate definitions in a priority order based on their cost,
-   when the cost of this definition falls below MIN_COST, then
-   there is another definition with cost == MIN_COST which now
-   has a higher priority than this definition.
-
-   Return nonzero if there may be benefit from attempting to
-   migrate this DEF further (i.e. we have reduced the cost below
-   MIN_COST, but we may be able to reduce it further).
-   Return zero if no further migration is possible.  */
-static int
-migrate_btr_def (btr_def *def, int min_cost)
-{
-  HARD_REG_SET btrs_live_in_range;
-  int btr_used_near_def = 0;
-  int def_basic_block_freq;
-  basic_block attempt;
-  int give_up = 0;
-  int def_moved = 0;
-  btr_user *user;
-  int def_latency;
-
-  if (dump_file)
-    fprintf (dump_file,
-            "Attempting to migrate pt from insn %d (cost = %d, min_cost = %d) ... ",
-            INSN_UID (def->insn), def->cost, min_cost);
-
-  if (!def->group || def->has_ambiguous_use)
-    /* These defs are not migratable.  */
-    {
-      if (dump_file)
-       fprintf (dump_file, "it's not migratable\n");
-      return 0;
-    }
-
-  if (!def->uses)
-    /* We have combined this def with another in the same group, so
-       no need to consider it further.
-    */
-    {
-      if (dump_file)
-       fprintf (dump_file, "it's already combined with another pt\n");
-      return 0;
-    }
-
-  btr_def_live_range (def, &btrs_live_in_range);
-  auto_bitmap live_range;
-  bitmap_copy (live_range, def->live_range);
-
-#ifdef INSN_SCHEDULING
-  def_latency = insn_default_latency (def->insn) * issue_rate;
-#else
-  def_latency = issue_rate;
-#endif
-
-  for (user = def->uses; user != NULL; user = user->next)
-    {
-      if (user->bb == def->bb
-         && user->luid > def->luid
-         && (def->luid + def_latency) > user->luid
-         && ! can_move_up (def->bb, def->insn,
-                           (def->luid + def_latency) - user->luid))
-       {
-         btr_used_near_def = 1;
-         break;
-       }
-    }
-
-  def_basic_block_freq = basic_block_freq (def->bb);
-
-  for (attempt = get_immediate_dominator (CDI_DOMINATORS, def->bb);
-       !give_up && attempt && attempt != ENTRY_BLOCK_PTR_FOR_FN (cfun)
-       && def->cost >= min_cost;
-       attempt = get_immediate_dominator (CDI_DOMINATORS, attempt))
-    {
-      /* Try to move the instruction that sets the target register into
-        basic block ATTEMPT.  */
-      int try_freq = basic_block_freq (attempt);
-      edge_iterator ei;
-      edge e;
-
-      /* If ATTEMPT has abnormal edges, skip it.  */
-      FOR_EACH_EDGE (e, ei, attempt->succs)
-       if (e->flags & EDGE_COMPLEX)
-         break;
-      if (e)
-       continue;
-
-      if (dump_file)
-       fprintf (dump_file, "trying block %d ...", attempt->index);
-
-      if (try_freq < def_basic_block_freq
-         || (try_freq == def_basic_block_freq && btr_used_near_def))
-       {
-         int btr;
-         augment_live_range (live_range, &btrs_live_in_range, def->bb, attempt,
-                             flag_btr_bb_exclusive);
-         if (dump_file)
-           {
-             fprintf (dump_file, "Now btrs live in range are: ");
-             dump_hard_reg_set (btrs_live_in_range);
-             fprintf (dump_file, "\n");
-           }
-         btr = choose_btr (btrs_live_in_range);
-         if (btr != -1)
-           {
-             move_btr_def (attempt, btr, def, live_range, &btrs_live_in_range);
-             bitmap_copy (live_range, def->live_range);
-             btr_used_near_def = 0;
-             def_moved = 1;
-             def_basic_block_freq = basic_block_freq (def->bb);
-           }
-         else
-           {
-             /* There are no free target registers available to move
-                this far forward, so give up */
-             give_up = 1;
-             if (dump_file)
-               fprintf (dump_file,
-                        "giving up because there are no free target registers\n");
-           }
-
-       }
-    }
-  if (!def_moved)
-    {
-      give_up = 1;
-      if (dump_file)
-       fprintf (dump_file, "failed to move\n");
-    }
-
-  return !give_up;
-}
-
-/* Attempt to move instructions that set target registers earlier
-   in the flowgraph, away from their corresponding uses.  */
-static void
-migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
-{
-  btr_heap_t all_btr_defs (LONG_MIN);
-  int reg;
-
-  gcc_obstack_init (&migrate_btrl_obstack);
-  if (dump_file)
-    {
-      int i;
-
-      for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
-       {
-         basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
-         fprintf (dump_file, "Basic block %d: count = ", i);
-         bb->count.dump (dump_file);
-         fprintf (dump_file, " loop-depth = %d idom = %d\n",
-                  bb_loop_depth (bb),
-                  get_immediate_dominator (CDI_DOMINATORS, bb)->index);
-       }
-    }
-
-  CLEAR_HARD_REG_SET (all_btrs);
-  for (first_btr = -1, reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[(int) btr_class], reg)
-       && (allow_callee_save || call_used_regs[reg]
-           || df_regs_ever_live_p (reg)))
-      {
-       SET_HARD_REG_BIT (all_btrs, reg);
-       last_btr = reg;
-       if (first_btr < 0)
-         first_btr = reg;
-      }
-
-  btrs_live = XCNEWVEC (HARD_REG_SET, last_basic_block_for_fn (cfun));
-  btrs_live_at_end = XCNEWVEC (HARD_REG_SET, last_basic_block_for_fn (cfun));
-
-  build_btr_def_use_webs (&all_btr_defs);
-
-  while (!all_btr_defs.empty ())
-    {
-      int min_cost = -all_btr_defs.min_key ();
-      btr_def *def = all_btr_defs.extract_min ();
-      if (migrate_btr_def (def, min_cost))
-       {
-         all_btr_defs.insert (-def->cost, def);
-         if (dump_file)
-           {
-             fprintf (dump_file,
-               "Putting insn %d back on queue with priority %d\n",
-               INSN_UID (def->insn), def->cost);
-           }
-       }
-      else
-       BITMAP_FREE (def->live_range);
-    }
-
-  free (btrs_live);
-  free (btrs_live_at_end);
-  obstack_free (&migrate_btrl_obstack, NULL);
-}
-
-static void
-branch_target_load_optimize (bool after_prologue_epilogue_gen)
-{
-  enum reg_class klass
-    = (enum reg_class) targetm.branch_target_register_class ();
-  if (klass != NO_REGS)
-    {
-      /* Initialize issue_rate.  */
-      if (targetm.sched.issue_rate)
-       issue_rate = targetm.sched.issue_rate ();
-      else
-       issue_rate = 1;
-
-      if (!after_prologue_epilogue_gen)
-       {
-         /* Build the CFG for migrate_btr_defs.  */
-#if 1
-         /* This may or may not be needed, depending on where we
-            run this phase.  */
-         cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
-#endif
-       }
-      df_analyze ();
-
-
-      /* Dominator info is also needed for migrate_btr_def.  */
-      calculate_dominance_info (CDI_DOMINATORS);
-      migrate_btr_defs (klass,
-                      (targetm.branch_target_register_callee_saved
-                       (after_prologue_epilogue_gen)));
-
-      free_dominance_info (CDI_DOMINATORS);
-    }
-}
-\f
-namespace {
-
-const pass_data pass_data_branch_target_load_optimize1 =
-{
-  RTL_PASS, /* type */
-  "btl1", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  TV_NONE, /* tv_id */
-  0, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_branch_target_load_optimize1 : public rtl_opt_pass
-{
-public:
-  pass_branch_target_load_optimize1 (gcc::context *ctxt)
-    : rtl_opt_pass (pass_data_branch_target_load_optimize1, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  virtual bool gate (function *) { return flag_branch_target_load_optimize; }
-  virtual unsigned int execute (function *)
-    {
-      branch_target_load_optimize (epilogue_completed);
-      return 0;
-    }
-
-}; // class pass_branch_target_load_optimize1
-
-} // anon namespace
-
-rtl_opt_pass *
-make_pass_branch_target_load_optimize1 (gcc::context *ctxt)
-{
-  return new pass_branch_target_load_optimize1 (ctxt);
-}
-
-
-namespace {
-
-const pass_data pass_data_branch_target_load_optimize2 =
-{
-  RTL_PASS, /* type */
-  "btl2", /* name */
-  OPTGROUP_NONE, /* optinfo_flags */
-  TV_NONE, /* tv_id */
-  0, /* properties_required */
-  0, /* properties_provided */
-  0, /* properties_destroyed */
-  0, /* todo_flags_start */
-  0, /* todo_flags_finish */
-};
-
-class pass_branch_target_load_optimize2 : public rtl_opt_pass
-{
-public:
-  pass_branch_target_load_optimize2 (gcc::context *ctxt)
-    : rtl_opt_pass (pass_data_branch_target_load_optimize2, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  virtual bool gate (function *)
-    {
-      return (optimize > 0 && flag_branch_target_load_optimize2);
-    }
-
-  virtual unsigned int execute (function *);
-
-}; // class pass_branch_target_load_optimize2
-
-unsigned int
-pass_branch_target_load_optimize2::execute (function *)
-{
-  static int warned = 0;
-
-  /* Leave this a warning for now so that it is possible to experiment
-     with running this pass twice.  In 3.6, we should either make this
-     an error, or use separate dump files.  */
-  if (flag_branch_target_load_optimize
-      && flag_branch_target_load_optimize2
-      && !warned)
-    {
-      warning (0, "branch target register load optimization is not intended "
-              "to be run twice");
-
-      warned = 1;
-    }
-
-  branch_target_load_optimize (epilogue_completed);
-  return 0;
-}
-
-} // anon namespace
-
-rtl_opt_pass *
-make_pass_branch_target_load_optimize2 (gcc::context *ctxt)
-{
-  return new pass_branch_target_load_optimize2 (ctxt);
-}
index f2214ed93ad857775e092d8baf61ffc2aabff7b7..0d165f5018ad59c1723f121b1851262504895a42 100644 (file)
@@ -1076,16 +1076,16 @@ Common Report Var(flag_branch_probabilities) Optimization
 Use profiling information for branch probabilities.
 
 fbranch-target-load-optimize
-Common Report Var(flag_branch_target_load_optimize) Optimization
-Perform branch target load optimization before prologue / epilogue threading.
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 fbranch-target-load-optimize2
-Common Report Var(flag_branch_target_load_optimize2) Optimization
-Perform branch target load optimization after prologue / epilogue threading.
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 fbtr-bb-exclusive
-Common Report Var(flag_btr_bb_exclusive) Optimization
-Restrict target load migration not to re-use registers in any basic block.
+Common Ignore
+Does nothing.  Preserved for backward compatibility.
 
 fcall-saved-
 Common Joined RejectNegative Var(common_deferred_options) Defer
index 7bcdfcbca15715a7844ad2f85e7e29cde4d10faf..ef23a7d89334086adb2663b83bfc2cce994d5caa 100644 (file)
@@ -406,8 +406,7 @@ Objective-C and Objective-C++ Dialects}.
 -falign-loops[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol
 -fassociative-math  -fauto-profile  -fauto-profile[=@var{path}] @gol
 -fauto-inc-dec  -fbranch-probabilities @gol
--fbranch-target-load-optimize  -fbranch-target-load-optimize2 @gol
--fbtr-bb-exclusive  -fcaller-saves @gol
+-fcaller-saves @gol
 -fcombine-stack-adjustments  -fconserve-stack @gol
 -fcompare-elim  -fcprop-registers  -fcrossjumping @gol
 -fcse-follow-jumps  -fcse-skip-blocks  -fcx-fortran-rules @gol
@@ -11025,24 +11024,6 @@ locations inside a translation unit since the locations are unknown until
 link time.  An example of such an optimization is relaxing calls to short call
 instructions.
 
-@item -fbranch-target-load-optimize
-@opindex fbranch-target-load-optimize
-Perform branch target register load optimization before prologue / epilogue
-threading.
-The use of target registers can typically be exposed only during reload,
-thus hoisting loads out of loops and doing inter-block scheduling needs
-a separate optimization pass.
-
-@item -fbranch-target-load-optimize2
-@opindex fbranch-target-load-optimize2
-Perform branch target register load optimization after prologue / epilogue
-threading.
-
-@item -fbtr-bb-exclusive
-@opindex fbtr-bb-exclusive
-When performing branch target register load optimization, don't reuse
-branch target registers within any basic block.
-
 @item -fstdarg-opt
 @opindex fstdarg-opt
 Optimize the prologue of variadic argument functions with respect to usage of
index 0b5a08d490ec998f143845c48bd5190aed146664..7bb8157df6eb7b79825a19d3bd8b6b1df8566e53 100644 (file)
@@ -11755,28 +11755,6 @@ cannot_modify_jumps_past_reload_p ()
 @end smallexample
 @end deftypefn
 
-@deftypefn {Target Hook} reg_class_t TARGET_BRANCH_TARGET_REGISTER_CLASS (void)
-This target hook returns a register class for which branch target register
-optimizations should be applied.  All registers in this class should be
-usable interchangeably.  After reload, registers in this class will be
-re-allocated and loads will be hoisted out of loops and be subjected
-to inter-block scheduling.
-@end deftypefn
-
-@deftypefn {Target Hook} bool TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED (bool @var{after_prologue_epilogue_gen})
-Branch target register optimization will by default exclude callee-saved
-registers
-that are not already live during the current function; if this target hook
-returns true, they will be included.  The target code must than make sure
-that all target registers in the class returned by
-@samp{TARGET_BRANCH_TARGET_REGISTER_CLASS} that might need saving are
-saved.  @var{after_prologue_epilogue_gen} indicates if prologues and
-epilogues have already been generated.  Note, even if you only return
-true when @var{after_prologue_epilogue_gen} is false, you still are likely
-to have to make special provisions in @code{INITIAL_ELIMINATION_OFFSET}
-to reserve space for caller-saved target registers.
-@end deftypefn
-
 @deftypefn {Target Hook} bool TARGET_HAVE_CONDITIONAL_EXECUTION (void)
 This target hook returns true if the target supports conditional execution.
 This target hook is required only when the target has several different
index a9200551ed484b78ebbf963b3127279c3d166b63..e926c10d197f003d503a808e6b9ddf48dd8faf1e 100644 (file)
@@ -8001,10 +8001,6 @@ build_type_attribute_variant (@var{mdecl},
 
 @hook TARGET_CANNOT_MODIFY_JUMPS_P
 
-@hook TARGET_BRANCH_TARGET_REGISTER_CLASS
-
-@hook TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED
-
 @hook TARGET_HAVE_CONDITIONAL_EXECUTION
 
 @hook TARGET_GEN_CCMP_FIRST
index a820c78ff56fe985dc53e3d9edc16f64297cc650..1ec94203c81e871c7a395ce874f53e2ea3ce701b 100644 (file)
@@ -307,7 +307,6 @@ test_completion_valid_options (option_proposer &proposer)
     "-Wassign-intercept",
     "-Wno-format-security",
     "-fno-sched-stalled-insns",
-    "-fbtr-bb-exclusive",
     "-fno-tree-tail-merge",
     "-Wlong-long",
     "-Wno-unused-but-set-parameter",
index e50cf62657c8797848fa7c9ae838a5f3f1d1e44c..93879223a8bc12c3d7b07af0b3c99542d936db4b 100644 (file)
@@ -461,7 +461,6 @@ along with GCC; see the file COPYING3.  If not see
          NEXT_PASS (pass_split_after_reload);
          NEXT_PASS (pass_ree);
          NEXT_PASS (pass_compare_elim_after_reload);
-         NEXT_PASS (pass_branch_target_load_optimize1);
          NEXT_PASS (pass_thread_prologue_and_epilogue);
          NEXT_PASS (pass_rtl_dse2);
          NEXT_PASS (pass_stack_adjustments);
@@ -474,7 +473,6 @@ along with GCC; see the file COPYING3.  If not see
          NEXT_PASS (pass_cprop_hardreg);
          NEXT_PASS (pass_fast_rtl_dce);
          NEXT_PASS (pass_reorder_blocks);
-         NEXT_PASS (pass_branch_target_load_optimize2);
          NEXT_PASS (pass_leaf_regs);
          NEXT_PASS (pass_split_before_sched2);
          NEXT_PASS (pass_sched2);
index ca7e7ad96b418cdc5fd8b3d49472e706161a7d7c..825c1e6d307501bf2da631a0ab85ae081d0fe532 100644 (file)
@@ -2597,38 +2597,6 @@ DEFHOOK
  bool, (const rtx_insn *follower, const rtx_insn *followee),
  hook_bool_const_rtx_insn_const_rtx_insn_true)
 
-/* Return a register class for which branch target register
-   optimizations should be applied.  */
-DEFHOOK
-(branch_target_register_class,
- "This target hook returns a register class for which branch target register\n\
-optimizations should be applied.  All registers in this class should be\n\
-usable interchangeably.  After reload, registers in this class will be\n\
-re-allocated and loads will be hoisted out of loops and be subjected\n\
-to inter-block scheduling.",
- reg_class_t, (void),
- default_branch_target_register_class)
-
-/* Return true if branch target register optimizations should include
-   callee-saved registers that are not already live during the current
-   function.  AFTER_PE_GEN is true if prologues and epilogues have
-   already been generated.  */
-DEFHOOK
-(branch_target_register_callee_saved,
- "Branch target register optimization will by default exclude callee-saved\n\
-registers\n\
-that are not already live during the current function; if this target hook\n\
-returns true, they will be included.  The target code must than make sure\n\
-that all target registers in the class returned by\n\
-@samp{TARGET_BRANCH_TARGET_REGISTER_CLASS} that might need saving are\n\
-saved.  @var{after_prologue_epilogue_gen} indicates if prologues and\n\
-epilogues have already been generated.  Note, even if you only return\n\
-true when @var{after_prologue_epilogue_gen} is false, you still are likely\n\
-to have to make special provisions in @code{INITIAL_ELIMINATION_OFFSET}\n\
-to reserve space for caller-saved target registers.",
- bool, (bool after_prologue_epilogue_gen),
- hook_bool_bool_false)
-
 /* Return true if the target supports conditional execution.  */
 DEFHOOK
 (have_conditional_execution,
index 1d12ec547047df1d71b57dcb27dcd467d7989cc6..ed77afb1da57e59bc0725dc0d6fac477391bae03 100644 (file)
@@ -1053,12 +1053,6 @@ default_return_pops_args (tree, tree, poly_int64)
   return 0;
 }
 
-reg_class_t
-default_branch_target_register_class (void)
-{
-  return NO_REGS;
-}
-
 reg_class_t
 default_ira_change_pseudo_allocno_class (int regno ATTRIBUTE_UNUSED,
                                         reg_class_t cl,
index 20a6e79d2d23b2899c523612433f5a3458ef475e..5aba67660f85406b9fd475e75a3cc65b0d1952f5 100644 (file)
@@ -164,7 +164,6 @@ extern rtx default_internal_arg_pointer (void);
 extern rtx default_static_chain (const_tree, bool);
 extern void default_trampoline_init (rtx, tree, rtx);
 extern poly_int64 default_return_pops_args (tree, tree, poly_int64);
-extern reg_class_t default_branch_target_register_class (void);
 extern reg_class_t default_ira_change_pseudo_allocno_class (int, reg_class_t,
                                                            reg_class_t);
 extern bool default_lra_p (void);
index be7603a4c72dd18413aa7045a9e09408bd6a9e8d..7106eba54af1dcf85a434f0a7ac94a41ddd85f25 100644 (file)
@@ -585,8 +585,6 @@ extern rtl_opt_pass *make_pass_postreload_jump (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_postreload_cse (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_gcse2 (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt);
-extern rtl_opt_pass *make_pass_branch_target_load_optimize1 (gcc::context
-                                                            *ctxt);
 extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context
                                                             *ctxt);
 extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt);
@@ -596,8 +594,6 @@ extern rtl_opt_pass *make_pass_if_after_reload (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_regrename (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_cprop_hardreg (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_reorder_blocks (gcc::context *ctxt);
-extern rtl_opt_pass *make_pass_branch_target_load_optimize2 (gcc::context
-                                                            *ctxt);
 extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt);