[multiple changes]
[platform/upstream/gcc.git] / gcc / resource.c
index dfd10f6..a8b449f 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions for computing resource usage of specific insns.
-   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+   Copyright (C) 1999-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -20,12 +20,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
+#include "backend.h"
 #include "rtl.h"
+#include "df.h"
+#include "diagnostic-core.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
-#include "function.h"
 #include "regs.h"
 #include "flags.h"
 #include "output.h"
@@ -33,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "except.h"
 #include "insn-attr.h"
 #include "params.h"
-#include "df.h"
+#include "emit-rtl.h"
 
 /* This structure is used to record liveness information at the targets or
    fallthrough insns of branches.  We will most likely need the information
@@ -78,11 +77,11 @@ static HARD_REG_SET current_live_regs;
 static HARD_REG_SET pending_dead_regs;
 \f
 static void update_live_status (rtx, const_rtx, void *);
-static int find_basic_block (rtx, int);
-static rtx next_insn_no_annul (rtx);
-static rtx find_dead_or_set_registers (rtx, struct resources*,
-                                      rtx*, int, struct resources,
-                                      struct resources);
+static int find_basic_block (rtx_insn *, int);
+static rtx_insn *next_insn_no_annul (rtx_insn *);
+static rtx_insn *find_dead_or_set_registers (rtx_insn *, struct resources*,
+                                            rtx *, int, struct resources,
+                                            struct resources);
 \f
 /* Utility function called from mark_target_live_regs via note_stores.
    It deadens any CLOBBERed registers and livens any SET registers.  */
@@ -106,7 +105,7 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
   else
     {
       first_regno = REGNO (dest);
-      last_regno = END_HARD_REGNO (dest);
+      last_regno = END_REGNO (dest);
     }
 
   if (GET_CODE (x) == CLOBBER)
@@ -132,7 +131,7 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
    correct.  */
 
 static int
-find_basic_block (rtx insn, int search_limit)
+find_basic_block (rtx_insn *insn, int search_limit)
 {
   /* Scan backwards to the previous BARRIER.  Then see if we can find a
      label that starts a basic block.  Return the basic block number.  */
@@ -163,8 +162,8 @@ find_basic_block (rtx insn, int search_limit)
 /* Similar to next_insn, but ignores insns in the delay slots of
    an annulled branch.  */
 
-static rtx
-next_insn_no_annul (rtx insn)
+static rtx_insn *
+next_insn_no_annul (rtx_insn *insn)
 {
   if (insn)
     {
@@ -187,7 +186,7 @@ next_insn_no_annul (rtx insn)
       insn = NEXT_INSN (insn);
       if (insn && NONJUMP_INSN_P (insn)
          && GET_CODE (PATTERN (insn)) == SEQUENCE)
-       insn = XVECEXP (PATTERN (insn), 0, 0);
+       insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
     }
 
   return insn;
@@ -308,7 +307,7 @@ mark_referenced_resources (rtx x, struct resources *res,
             However, we may have moved some of the parameter loading insns
             into the delay slot of this CALL.  If so, the USE's for them
             don't count and should be skipped.  */
-         rtx_insn *insn = PREV_INSN (x);
+         rtx_insn *insn = PREV_INSN (as_a <rtx_insn *> (x));
          rtx_sequence *sequence = 0;
          int seq_size = 0;
          int i;
@@ -326,9 +325,8 @@ mark_referenced_resources (rtx x, struct resources *res,
          if (frame_pointer_needed)
            {
              SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
-             SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
-#endif
+             if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
+               SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
            }
 
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -384,11 +382,9 @@ mark_referenced_resources (rtx x, struct resources *res,
                          include_delayed_effects
                          ? MARK_SRC_DEST_CALL : MARK_SRC_DEST);
 
-#ifdef INSN_REFERENCES_ARE_DELAYED
       if (! include_delayed_effects
-         && INSN_REFERENCES_ARE_DELAYED (x))
+         && INSN_REFERENCES_ARE_DELAYED (as_a <rtx_insn *> (x)))
        return;
-#endif
 
       /* No special processing, just speed up.  */
       mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
@@ -420,21 +416,22 @@ mark_referenced_resources (rtx x, struct resources *res,
    Stop after passing a few conditional jumps, and/or a small
    number of unconditional branches.  */
 
-static rtx
-find_dead_or_set_registers (rtx target, struct resources *res,
+static rtx_insn *
+find_dead_or_set_registers (rtx_insn *target, struct resources *res,
                            rtx *jump_target, int jump_count,
                            struct resources set, struct resources needed)
 {
   HARD_REG_SET scratch;
-  rtx insn, next;
-  rtx jump_insn = 0;
+  rtx_insn *insn;
+  rtx_insn *next_insn;
+  rtx_insn *jump_insn = 0;
   int i;
 
-  for (insn = target; insn; insn = next)
+  for (insn = target; insn; insn = next_insn)
     {
-      rtx this_jump_insn = insn;
+      rtx_insn *this_insn = insn;
 
-      next = NEXT_INSN (insn);
+      next_insn = NEXT_INSN (insn);
 
       /* If this instruction can throw an exception, then we don't
         know where we might end up next.  That means that we have to
@@ -480,8 +477,8 @@ find_dead_or_set_registers (rtx target, struct resources *res,
                 of a call, so search for a JUMP_INSN in any position.  */
              for (i = 0; i < seq->len (); i++)
                {
-                 this_jump_insn = seq->element (i);
-                 if (JUMP_P (this_jump_insn))
+                 this_insn = seq->insn (i);
+                 if (JUMP_P (this_insn))
                    break;
                }
            }
@@ -490,16 +487,19 @@ find_dead_or_set_registers (rtx target, struct resources *res,
          break;
        }
 
-      if (JUMP_P (this_jump_insn))
+      if (rtx_jump_insn *this_jump_insn =
+           dyn_cast <rtx_jump_insn *> (this_insn))
        {
          if (jump_count++ < 10)
            {
              if (any_uncondjump_p (this_jump_insn)
                  || ANY_RETURN_P (PATTERN (this_jump_insn)))
                {
-                 next = JUMP_LABEL (this_jump_insn);
-                 if (ANY_RETURN_P (next))
-                   next = NULL_RTX;
+                 rtx lab_or_return = this_jump_insn->jump_label ();
+                 if (ANY_RETURN_P (lab_or_return))
+                   next_insn = NULL;
+                 else
+                   next_insn = as_a <rtx_insn *> (lab_or_return);
                  if (jump_insn == 0)
                    {
                      jump_insn = insn;
@@ -568,11 +568,11 @@ find_dead_or_set_registers (rtx target, struct resources *res,
                  AND_COMPL_HARD_REG_SET (scratch, needed.regs);
                  AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
 
-                 if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
-                   find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
-                                               &target_res, 0, jump_count,
-                                               target_set, needed);
-                 find_dead_or_set_registers (next,
+                 if (!ANY_RETURN_P (this_jump_insn->jump_label ()))
+                   find_dead_or_set_registers
+                         (this_jump_insn->jump_target (),
+                          &target_res, 0, jump_count, target_set, needed);
+                 find_dead_or_set_registers (next_insn,
                                              &fallthrough_res, 0, jump_count,
                                              set, needed);
                  IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
@@ -656,15 +656,16 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
 
       if (mark_type == MARK_SRC_DEST_CALL)
        {
+         rtx_call_insn *call_insn = as_a <rtx_call_insn *> (x);
          rtx link;
          HARD_REG_SET regs;
 
          res->cc = res->memory = 1;
 
-         get_call_reg_set_usage (x, &regs, regs_invalidated_by_call);
+         get_call_reg_set_usage (call_insn, &regs, regs_invalidated_by_call);
          IOR_HARD_REG_SET (res->regs, regs);
 
-         for (link = CALL_INSN_FUNCTION_USAGE (x);
+         for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
               link; link = XEXP (link, 1))
            if (GET_CODE (XEXP (link, 0)) == CLOBBER)
              mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
@@ -672,7 +673,7 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
 
          /* Check for a REG_SETJMP.  If it exists, then we must
             assume that this call can clobber any register.  */
-         if (find_reg_note (x, REG_SETJMP, NULL))
+         if (find_reg_note (call_insn, REG_SETJMP, NULL))
            SET_HARD_REG_SET (res->regs);
        }
 
@@ -684,11 +685,9 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
        /* An insn consisting of just a CLOBBER (or USE) is just for flow
           and doesn't actually do anything, so we ignore it.  */
 
-#ifdef INSN_SETS_ARE_DELAYED
       if (mark_type != MARK_SRC_DEST_CALL
-         && INSN_SETS_ARE_DELAYED (x))
+         && INSN_SETS_ARE_DELAYED (as_a <rtx_insn *> (x)))
        return;
-#endif
 
       x = PATTERN (x);
       if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
@@ -880,26 +879,29 @@ return_insn_p (const_rtx insn)
    init_resource_info () was invoked before we are called.  */
 
 void
-mark_target_live_regs (rtx insns, rtx target, struct resources *res)
+mark_target_live_regs (rtx_insn *insns, rtx target_maybe_return, struct resources *res)
 {
   int b = -1;
   unsigned int i;
   struct target_info *tinfo = NULL;
-  rtx insn;
-  rtx jump_insn = 0;
+  rtx_insn *insn;
   rtx jump_target;
   HARD_REG_SET scratch;
   struct resources set, needed;
 
   /* Handle end of function.  */
-  if (target == 0 || ANY_RETURN_P (target))
+  if (target_maybe_return == 0 || ANY_RETURN_P (target_maybe_return))
     {
       *res = end_of_function_needs;
       return;
     }
 
+  /* We've handled the case of RETURN/SIMPLE_RETURN; we should now have an
+     instruction.  */
+  rtx_insn *target = as_a <rtx_insn *> (target_maybe_return);
+
   /* Handle return insn.  */
-  else if (return_insn_p (target))
+  if (return_insn_p (target))
     {
       *res = end_of_function_needs;
       mark_referenced_resources (target, res, false);
@@ -923,8 +925,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
         information, we can get it from there unless the insn at the
         start of the basic block has been deleted.  */
       if (tinfo && tinfo->block != -1
-         && ! INSN_DELETED_P (BB_HEAD (BASIC_BLOCK_FOR_FN (cfun,
-                                                           tinfo->block))))
+         && ! BB_HEAD (BASIC_BLOCK_FOR_FN (cfun, tinfo->block))->deleted ())
        b = tinfo->block;
     }
 
@@ -965,7 +966,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
   if (b != -1)
     {
       regset regs_live = DF_LR_IN (BASIC_BLOCK_FOR_FN (cfun, b));
-      rtx start_insn, stop_insn;
+      rtx_insn *start_insn, *stop_insn;
 
       /* Compute hard regs live at start of block.  */
       REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
@@ -978,7 +979,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
 
       if (NONJUMP_INSN_P (start_insn)
          && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
-       start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
+       start_insn = as_a <rtx_sequence *> (PATTERN (start_insn))->insn (0);
 
       if (NONJUMP_INSN_P (stop_insn)
          && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
@@ -988,7 +989,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
           insn = next_insn_no_annul (insn))
        {
          rtx link;
-         rtx real_insn = insn;
+         rtx_insn *real_insn = insn;
          enum rtx_code code = GET_CODE (insn);
 
          if (DEBUG_INSN_P (insn))
@@ -1006,7 +1007,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
          if (code == INSN
              && GET_CODE (PATTERN (insn)) == USE
              && INSN_P (XEXP (PATTERN (insn), 0)))
-           real_insn = XEXP (PATTERN (insn), 0);
+           real_insn = as_a <rtx_insn *> (XEXP (PATTERN (insn), 0));
 
          if (CALL_P (real_insn))
            {
@@ -1111,8 +1112,8 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
   CLEAR_RESOURCE (&set);
   CLEAR_RESOURCE (&needed);
 
-  jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
-                                         set, needed);
+  rtx_insn *jump_insn = find_dead_or_set_registers (target, res, &jump_target,
+                                                   0, set, needed);
 
   /* If we hit an unconditional branch, we have another way of finding out
      what is live: we can see what is live at the branch target and include
@@ -1122,7 +1123,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
   if (jump_insn)
     {
       struct resources new_resources;
-      rtx stop_insn = next_active_insn (jump_insn);
+      rtx_insn *stop_insn = next_active_insn (jump_insn);
 
       if (!ANY_RETURN_P (jump_target))
        jump_target = next_active_insn (jump_target);
@@ -1155,7 +1156,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
    This should be invoked before the first call to mark_target_live_regs.  */
 
 void
-init_resource_info (rtx epilogue_insn)
+init_resource_info (rtx_insn *epilogue_insn)
 {
   int i;
   basic_block bb;
@@ -1174,9 +1175,9 @@ init_resource_info (rtx epilogue_insn)
   if (frame_pointer_needed)
     {
       SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
-      SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
-#endif
+      if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
+       SET_HARD_REG_BIT (end_of_function_needs.regs,
+                         HARD_FRAME_POINTER_REGNUM);
     }
   if (!(frame_pointer_needed
        && EXIT_IGNORE_STACK
@@ -1189,11 +1190,7 @@ init_resource_info (rtx epilogue_insn)
                               &end_of_function_needs, true);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (global_regs[i]
-#ifdef EPILOGUE_USES
-       || EPILOGUE_USES (i)
-#endif
-       )
+    if (global_regs[i] || EPILOGUE_USES (i))
       SET_HARD_REG_BIT (end_of_function_needs.regs, i);
 
   /* The registers required to be live at the end of the function are
@@ -1275,7 +1272,7 @@ free_resource_info (void)
 /* Clear any hashed information that we have stored for INSN.  */
 
 void
-clear_hashed_info_for_insn (rtx insn)
+clear_hashed_info_for_insn (rtx_insn *insn)
 {
   struct target_info *tinfo;
 
@@ -1294,7 +1291,7 @@ clear_hashed_info_for_insn (rtx insn)
 /* Increment the tick count for the basic block that contains INSN.  */
 
 void
-incr_ticks_for_insn (rtx insn)
+incr_ticks_for_insn (rtx_insn *insn)
 {
   int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH);