MAINTAINERS (Write After Approval): Add myself.
[platform/upstream/gcc.git] / gcc / cfgbuild.c
index 6e941bf..c1ec46a 100644 (file)
@@ -1,7 +1,5 @@
 /* Control flow graph building code for GNU compiler.
-   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2016 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -23,18 +21,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
+#include "backend.h"
 #include "rtl.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "regs.h"
-#include "flags.h"
-#include "output.h"
-#include "function.h"
+#include "cfghooks.h"
+#include "emit-rtl.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgbuild.h"
 #include "except.h"
-#include "toplev.h"
-#include "timevar.h"
+#include "stmt.h"
 
 static void make_edges (basic_block, basic_block, int);
 static void make_label_edge (sbitmap, basic_block, rtx, int);
@@ -45,26 +40,22 @@ static void compute_outgoing_frequencies (basic_block);
    block.  */
 
 bool
-inside_basic_block_p (const_rtx insn)
+inside_basic_block_p (const rtx_insn *insn)
 {
   switch (GET_CODE (insn))
     {
     case CODE_LABEL:
       /* Avoid creating of basic block for jumptables.  */
       return (NEXT_INSN (insn) == 0
-             || !JUMP_P (NEXT_INSN (insn))
-             || (GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_VEC
-                 && GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_DIFF_VEC));
+             || ! JUMP_TABLE_DATA_P (NEXT_INSN (insn)));
 
     case JUMP_INSN:
-      return (GET_CODE (PATTERN (insn)) != ADDR_VEC
-             && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
-
     case CALL_INSN:
     case INSN:
     case DEBUG_INSN:
       return true;
 
+    case JUMP_TABLE_DATA:
     case BARRIER:
     case NOTE:
       return false;
@@ -78,10 +69,8 @@ inside_basic_block_p (const_rtx insn)
    the basic block.  */
 
 bool
-control_flow_insn_p (const_rtx insn)
+control_flow_insn_p (const rtx_insn *insn)
 {
-  rtx note;
-
   switch (GET_CODE (insn))
     {
     case NOTE:
@@ -90,9 +79,7 @@ control_flow_insn_p (const_rtx insn)
       return false;
 
     case JUMP_INSN:
-      /* Jump insn always causes control transfer except for tablejumps.  */
-      return (GET_CODE (PATTERN (insn)) != ADDR_VEC
-             && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
+      return true;
 
     case CALL_INSN:
       /* Noreturn and sibling call instructions terminate the basic blocks
@@ -101,24 +88,24 @@ control_flow_insn_p (const_rtx insn)
           || find_reg_note (insn, REG_NORETURN, 0))
          && GET_CODE (PATTERN (insn)) != COND_EXEC)
        return true;
+
       /* Call insn may return to the nonlocal goto handler.  */
-      return ((nonlocal_goto_handler_labels
-              && (0 == (note = find_reg_note (insn, REG_EH_REGION,
-                                              NULL_RTX))
-                  || INTVAL (XEXP (note, 0)) >= 0))
-             /* Or may trap.  */
-             || can_throw_internal (insn));
+      if (can_nonlocal_goto (insn))
+       return true;
+      break;
 
     case INSN:
       /* Treat trap instructions like noreturn calls (same provision).  */
       if (GET_CODE (PATTERN (insn)) == TRAP_IF
          && XEXP (PATTERN (insn), 0) == const1_rtx)
        return true;
+      if (!cfun->can_throw_non_call_exceptions)
+       return false;
+      break;
 
-      return (flag_non_call_exceptions && can_throw_internal (insn));
-
+    case JUMP_TABLE_DATA:
     case BARRIER:
-      /* It is nonsense to reach barrier when looking for the
+      /* It is nonsense to reach this when looking for the
         end of basic block, but before dead code is eliminated
         this may happen.  */
       return false;
@@ -126,6 +113,8 @@ control_flow_insn_p (const_rtx insn)
     default:
       gcc_unreachable ();
     }
+
+  return can_throw_internal (insn);
 }
 
 \f
@@ -155,16 +144,23 @@ make_label_edge (sbitmap edge_cache, basic_block src, rtx label, int flags)
 void
 rtl_make_eh_edge (sbitmap edge_cache, basic_block src, rtx insn)
 {
-  int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0;
-  rtx handlers, i;
+  eh_landing_pad lp = get_eh_landing_pad_from_rtx (insn);
 
-  handlers = reachable_handlers (insn);
+  if (lp)
+    {
+      rtx_insn *label = lp->landing_pad;
 
-  for (i = handlers; i; i = XEXP (i, 1))
-    make_label_edge (edge_cache, src, XEXP (i, 0),
-                    EDGE_ABNORMAL | EDGE_EH | is_call);
+      /* During initial rtl generation, use the post_landing_pad.  */
+      if (label == NULL)
+       {
+         gcc_assert (lp->post_landing_pad);
+         label = label_rtx (lp->post_landing_pad);
+       }
 
-  free_INSN_LIST_list (&handlers);
+      make_label_edge (edge_cache, src, label,
+                      EDGE_ABNORMAL | EDGE_EH
+                      | (CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0));
+    }
 }
 
 /* States of basic block as seen by find_many_sub_basic_blocks.  */
@@ -209,16 +205,16 @@ make_edges (basic_block min, basic_block max, int update_p)
      nearly fully-connected CFGs.  In that case we spend a significant
      amount of time searching the edge lists for duplicates.  */
   if (forced_labels || cfun->cfg->max_jumptable_ents > 100)
-    edge_cache = sbitmap_alloc (last_basic_block);
+    edge_cache = sbitmap_alloc (last_basic_block_for_fn (cfun));
 
   /* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
      is always the entry.  */
-  if (min == ENTRY_BLOCK_PTR->next_bb)
-    make_edge (ENTRY_BLOCK_PTR, min, EDGE_FALLTHRU);
+  if (min == ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb)
+    make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), min, EDGE_FALLTHRU);
 
   FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
     {
-      rtx insn, x;
+      rtx_insn *insn;
       enum rtx_code code;
       edge e;
       edge_iterator ei;
@@ -229,18 +225,18 @@ make_edges (basic_block min, basic_block max, int update_p)
       /* If we have an edge cache, cache edges going out of BB.  */
       if (edge_cache)
        {
-         sbitmap_zero (edge_cache);
+         bitmap_clear (edge_cache);
          if (update_p)
            {
              FOR_EACH_EDGE (e, ei, bb->succs)
-               if (e->dest != EXIT_BLOCK_PTR)
-                 SET_BIT (edge_cache, e->dest->index);
+               if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+                 bitmap_set_bit (edge_cache, e->dest->index);
            }
        }
 
       if (LABEL_P (BB_HEAD (bb))
          && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
-       cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
+       cached_make_edge (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, 0);
 
       /* Examine the last instruction of the block, and discover the
         ways we can leave the block.  */
@@ -252,27 +248,19 @@ make_edges (basic_block min, basic_block max, int update_p)
       if (code == JUMP_INSN)
        {
          rtx tmp;
-
-         /* Recognize exception handling placeholders.  */
-         if (GET_CODE (PATTERN (insn)) == RESX)
-           rtl_make_eh_edge (edge_cache, bb, insn);
+         rtx_jump_table_data *table;
 
          /* Recognize a non-local goto as a branch outside the
             current function.  */
-         else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+         if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
            ;
 
          /* Recognize a tablejump and do the right thing.  */
-         else if (tablejump_p (insn, NULL, &tmp))
+         else if (tablejump_p (insn, NULL, &table))
            {
-             rtvec vec;
+             rtvec vec = table->get_labels ();
              int j;
 
-             if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
-               vec = XVEC (PATTERN (tmp), 0);
-             else
-               vec = XVEC (PATTERN (tmp), 1);
-
              for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
                make_label_edge (edge_cache, bb,
                                 XEXP (RTVEC_ELT (vec, j), 0), 0);
@@ -285,20 +273,29 @@ make_edges (basic_block min, basic_block max, int update_p)
                  && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
                  && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
                make_label_edge (edge_cache, bb,
-                                XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
+                                LABEL_REF_LABEL (XEXP (SET_SRC (tmp), 2)), 0);
            }
 
          /* If this is a computed jump, then mark it as reaching
             everything on the forced_labels list.  */
          else if (computed_jump_p (insn))
            {
-             for (x = forced_labels; x; x = XEXP (x, 1))
-               make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
+             for (rtx_insn_list *x = forced_labels; x; x = x->next ())
+               make_label_edge (edge_cache, bb, x->insn (), EDGE_ABNORMAL);
            }
 
          /* Returns create an exit out.  */
          else if (returnjump_p (insn))
-           cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0);
+           cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+
+         /* Recognize asm goto and do the right thing.  */
+         else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
+           {
+             int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
+             for (i = 0; i < n; ++i)
+               make_label_edge (edge_cache, bb,
+                                XEXP (ASM_OPERANDS_LABEL (tmp, i), 0), 0);
+           }
 
          /* Otherwise, we have a plain conditional or unconditional jump.  */
          else
@@ -313,41 +310,50 @@ make_edges (basic_block min, basic_block max, int update_p)
         worry about EH edges, since we wouldn't have created the sibling call
         in the first place.  */
       if (code == CALL_INSN && SIBLING_CALL_P (insn))
-       cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR,
+       cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR_FOR_FN (cfun),
                          EDGE_SIBCALL | EDGE_ABNORMAL);
 
       /* If this is a CALL_INSN, then mark it as reaching the active EH
         handler for this CALL_INSN.  If we're handling non-call
         exceptions then any insn can reach any of the active handlers.
         Also mark the CALL_INSN as reaching any nonlocal goto handler.  */
-      else if (code == CALL_INSN || flag_non_call_exceptions)
+      else if (code == CALL_INSN || cfun->can_throw_non_call_exceptions)
        {
          /* Add any appropriate EH edges.  */
          rtl_make_eh_edge (edge_cache, bb, insn);
 
-         if (code == CALL_INSN && nonlocal_goto_handler_labels)
+         if (code == CALL_INSN)
            {
-             /* ??? This could be made smarter: in some cases it's possible
-                to tell that certain calls will not do a nonlocal goto.
-                For example, if the nested functions that do the nonlocal
-                gotos do not have their addresses taken, then only calls to
-                those functions or to other nested functions that use them
-                could possibly do nonlocal gotos.  */
-
-             /* We do know that a REG_EH_REGION note with a value less
-                than 0 is guaranteed not to perform a non-local goto.  */
-             rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-
-             if (!note || INTVAL (XEXP (note, 0)) >=  0)
-               for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
-                 make_label_edge (edge_cache, bb, XEXP (x, 0),
-                                  EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+             if (can_nonlocal_goto (insn))
+               {
+                 /* ??? This could be made smarter: in some cases it's
+                    possible to tell that certain calls will not do a
+                    nonlocal goto.  For example, if the nested functions
+                    that do the nonlocal gotos do not have their addresses
+                    taken, then only calls to those functions or to other
+                    nested functions that use them could possibly do
+                    nonlocal gotos.  */
+                 for (rtx_insn_list *x = nonlocal_goto_handler_labels;
+                      x;
+                      x = x->next ())
+                   make_label_edge (edge_cache, bb, x->insn (),
+                                    EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+               }
+
+             if (flag_tm)
+               {
+                 rtx note;
+                 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+                   if (REG_NOTE_KIND (note) == REG_TM)
+                     make_label_edge (edge_cache, bb, XEXP (note, 0),
+                                      EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+               }
            }
        }
 
       /* Find out if we can drop through to the next block.  */
       insn = NEXT_INSN (insn);
-      e = find_edge (bb, EXIT_BLOCK_PTR);
+      e = find_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun));
       if (e && e->flags & EDGE_FALLTHRU)
        insn = NULL;
 
@@ -357,8 +363,9 @@ make_edges (basic_block min, basic_block max, int update_p)
        insn = NEXT_INSN (insn);
 
       if (!insn)
-       cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
-      else if (bb->next_bb != EXIT_BLOCK_PTR)
+       cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR_FOR_FN (cfun),
+                         EDGE_FALLTHRU);
+      else if (bb->next_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
        {
          if (insn == BB_HEAD (bb->next_bb))
            cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
@@ -366,7 +373,7 @@ make_edges (basic_block min, basic_block max, int update_p)
     }
 
   if (edge_cache)
-    sbitmap_vector_free (edge_cache);
+    sbitmap_free (edge_cache);
 }
 \f
 static void
@@ -383,18 +390,16 @@ mark_tablejump_edge (rtx label)
 }
 
 static void
-purge_dead_tablejump_edges (basic_block bb, rtx table)
+purge_dead_tablejump_edges (basic_block bb, rtx_jump_table_data *table)
 {
-  rtx insn = BB_END (bb), tmp;
+  rtx_insn *insn = BB_END (bb);
+  rtx tmp;
   rtvec vec;
   int j;
   edge_iterator ei;
   edge e;
 
-  if (GET_CODE (PATTERN (table)) == ADDR_VEC)
-    vec = XVEC (PATTERN (table), 0);
-  else
-    vec = XVEC (PATTERN (table), 1);
+  vec = table->get_labels ();
 
   for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
     mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
@@ -406,7 +411,7 @@ purge_dead_tablejump_edges (basic_block bb, rtx table)
        && SET_DEST (tmp) == pc_rtx
        && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
        && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
-    mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
+    mark_tablejump_edge (LABEL_REF_LABEL (XEXP (SET_SRC (tmp), 2)));
 
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
@@ -429,10 +434,10 @@ static void
 find_bb_boundaries (basic_block bb)
 {
   basic_block orig_bb = bb;
-  rtx insn = BB_HEAD (bb);
-  rtx end = BB_END (bb), x;
-  rtx table;
-  rtx flow_transfer_insn = NULL_RTX;
+  rtx_insn *insn = BB_HEAD (bb);
+  rtx_insn *end = BB_END (bb), *x;
+  rtx_jump_table_data *table;
+  rtx_insn *flow_transfer_insn = NULL;
   edge fallthru = NULL;
 
   if (insn == BB_END (bb))
@@ -446,8 +451,10 @@ find_bb_boundaries (basic_block bb)
     {
       enum rtx_code code = GET_CODE (insn);
 
-      /* On code label, split current basic block.  */
-      if (code == CODE_LABEL)
+      /* In case we've previously seen an insn that effects a control
+        flow transfer, split the block.  */
+      if ((flow_transfer_insn || code == CODE_LABEL)
+         && inside_basic_block_p (insn))
        {
          fallthru = split_block (bb, PREV_INSN (insn));
          if (flow_transfer_insn)
@@ -464,35 +471,17 @@ find_bb_boundaries (basic_block bb)
 
          bb = fallthru->dest;
          remove_edge (fallthru);
-         flow_transfer_insn = NULL_RTX;
-         if (LABEL_ALT_ENTRY_P (insn))
-           make_edge (ENTRY_BLOCK_PTR, bb, 0);
+         flow_transfer_insn = NULL;
+         if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn))
+           make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, 0);
        }
-
-      /* __builtin_unreachable () may cause a barrier to be emitted in
-        the middle of a BB.  We need to split it in the same manner
-        as if the barrier were preceded by a control_flow_insn_p
-        insn.  */
-      if (code == BARRIER && !flow_transfer_insn)
-       flow_transfer_insn = prev_nonnote_insn_bb (insn);
-
-      /* In case we've previously seen an insn that effects a control
-        flow transfer, split the block.  */
-      if (flow_transfer_insn && inside_basic_block_p (insn))
+      else if (code == BARRIER)
        {
-         fallthru = split_block (bb, PREV_INSN (insn));
-         BB_END (bb) = flow_transfer_insn;
-
-         /* Clean up the bb field for the insns between the blocks.  */
-         for (x = NEXT_INSN (flow_transfer_insn);
-              x != BB_HEAD (fallthru->dest);
-              x = NEXT_INSN (x))
-           if (!BARRIER_P (x))
-             set_block_for_insn (x, NULL);
-
-         bb = fallthru->dest;
-         remove_edge (fallthru);
-         flow_transfer_insn = NULL_RTX;
+         /* __builtin_unreachable () may cause a barrier to be emitted in
+            the middle of a BB.  We need to split it in the same manner as
+            if the barrier were preceded by a control_flow_insn_p insn.  */
+         if (!flow_transfer_insn)
+           flow_transfer_insn = prev_nonnote_insn_bb (insn);
        }
 
       if (control_flow_insn_p (insn))
@@ -546,30 +535,47 @@ compute_outgoing_frequencies (basic_block b)
 
       if (note)
        {
-         probability = INTVAL (XEXP (note, 0));
+         probability = XINT (note, 0);
          e = BRANCH_EDGE (b);
          e->probability = probability;
-         e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
-                     / REG_BR_PROB_BASE);
+         e->count = apply_probability (b->count, probability);
          f = FALLTHRU_EDGE (b);
          f->probability = REG_BR_PROB_BASE - probability;
          f->count = b->count - e->count;
          return;
        }
+      else
+        {
+          guess_outgoing_edge_probabilities (b);
+        }
     }
-
-  if (single_succ_p (b))
+  else if (single_succ_p (b))
     {
       e = single_succ_edge (b);
       e->probability = REG_BR_PROB_BASE;
       e->count = b->count;
       return;
     }
-  guess_outgoing_edge_probabilities (b);
+  else
+    {
+      /* We rely on BBs with more than two successors to have sane probabilities
+         and do not guess them here. For BBs terminated by switch statements
+         expanded to jump-table jump, we have done the right thing during
+         expansion. For EH edges, we still guess the probabilities here.  */
+      bool complex_edge = false;
+      FOR_EACH_EDGE (e, ei, b->succs)
+        if (e->flags & EDGE_COMPLEX)
+          {
+            complex_edge = true;
+            break;
+          }
+      if (complex_edge)
+        guess_outgoing_edge_probabilities (b);
+    }
+
   if (b->count)
     FOR_EACH_EDGE (e, ei, b->succs)
-      e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
-                 / REG_BR_PROB_BASE);
+      e->count = apply_probability (b->count, e->probability);
 }
 
 /* Assume that some pass has inserted labels or control flow
@@ -581,20 +587,20 @@ find_many_sub_basic_blocks (sbitmap blocks)
 {
   basic_block bb, min, max;
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     SET_STATE (bb,
-              TEST_BIT (blocks, bb->index) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
+              bitmap_bit_p (blocks, bb->index) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (STATE (bb) == BLOCK_TO_SPLIT)
       find_bb_boundaries (bb);
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (STATE (bb) != BLOCK_ORIGINAL)
       break;
 
   min = max = bb;
-  for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
+  for (; bb != EXIT_BLOCK_PTR_FOR_FN (cfun); bb = bb->next_bb)
     if (STATE (bb) != BLOCK_ORIGINAL)
       max = bb;
 
@@ -604,7 +610,7 @@ find_many_sub_basic_blocks (sbitmap blocks)
 
   /* Update branch probabilities.  Expect only (un)conditional jumps
      to be created with only the forward edges.  */
-  if (profile_status != PROFILE_ABSENT)
+  if (profile_status_for_fn (cfun) != PROFILE_ABSENT)
     FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
       {
        edge e;
@@ -626,6 +632,6 @@ find_many_sub_basic_blocks (sbitmap blocks)
        compute_outgoing_frequencies (bb);
       }
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     SET_STATE (bb, 0);
 }