diff gcc/cfgbuild.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/cfgbuild.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/cfgbuild.c	Fri Oct 27 22:46:09 2017 +0900
@@ -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, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -23,20 +21,16 @@
 #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 "memmodel.h"
+#include "emit-rtl.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgbuild.h"
 #include "except.h"
-#include "expr.h"
-#include "diagnostic-core.h"
-#include "timevar.h"
-#include "sbitmap.h"
+#include "stmt.h"
 
 static void make_edges (basic_block, basic_block, int);
 static void make_label_edge (sbitmap, basic_block, rtx, int);
@@ -47,26 +41,22 @@
    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;
@@ -80,7 +70,7 @@
    the basic block.  */
 
 bool
-control_flow_insn_p (const_rtx insn)
+control_flow_insn_p (const rtx_insn *insn)
 {
   switch (GET_CODE (insn))
     {
@@ -90,9 +80,7 @@
       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
@@ -116,8 +104,9 @@
 	return false;
       break;
 
+    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;
@@ -160,7 +149,7 @@
 
   if (lp)
     {
-      rtx label = lp->landing_pad;
+      rtx_insn *label = lp->landing_pad;
 
       /* During initial rtl generation, use the post_landing_pad.  */
       if (label == NULL)
@@ -216,17 +205,18 @@
   /* Heavy use of computed goto in machine-generated code can lead to
      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);
+  if (!vec_safe_is_empty (forced_labels)
+      || cfun->cfg->max_jumptable_ents > 100)
+    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;
@@ -237,18 +227,18 @@
       /* 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.  */
@@ -260,6 +250,7 @@
       if (code == JUMP_INSN)
 	{
 	  rtx tmp;
+	  rtx_jump_table_data *table;
 
 	  /* Recognize a non-local goto as a branch outside the
 	     current function.  */
@@ -267,16 +258,11 @@
 	    ;
 
 	  /* 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);
@@ -289,20 +275,22 @@
 		  && 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);
+	      rtx_insn *insn;
+	      unsigned int i;
+	      FOR_EACH_VEC_SAFE_ELT (forced_labels, i, insn)
+		make_label_edge (edge_cache, bb, 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)
@@ -326,7 +314,7 @@
 	 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
@@ -338,24 +326,38 @@
 	  /* 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.  */
 	      if (can_nonlocal_goto (insn))
-		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);
+		{
+		  /* ??? 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;
 
@@ -365,8 +367,9 @@
 	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);
@@ -374,7 +377,7 @@
     }
 
   if (edge_cache)
-    sbitmap_vector_free (edge_cache);
+    sbitmap_free (edge_cache);
 }
 
 static void
@@ -391,18 +394,16 @@
 }
 
 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));
@@ -414,7 +415,7 @@
        && 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)); )
     {
@@ -437,13 +438,14 @@
 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;
+  rtx_insn *debug_insn = NULL;
   edge fallthru = NULL;
 
-  if (insn == BB_END (bb))
+  if (insn == end)
     return;
 
   if (LABEL_P (insn))
@@ -454,29 +456,55 @@
     {
       enum rtx_code code = GET_CODE (insn);
 
+      if (code == DEBUG_INSN)
+	{
+	  if (flow_transfer_insn && !debug_insn)
+	    debug_insn = insn;
+	}
       /* 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))
+      else if ((flow_transfer_insn || code == CODE_LABEL)
+	       && inside_basic_block_p (insn))
 	{
-	  fallthru = split_block (bb, PREV_INSN (insn));
+	  rtx_insn *prev = PREV_INSN (insn);
+
+	  /* If the first non-debug inside_basic_block_p insn after a control
+	     flow transfer is not a label, split the block before the debug
+	     insn instead of before the non-debug insn, so that the debug
+	     insns are not lost.  */
+	  if (debug_insn && code != CODE_LABEL && code != BARRIER)
+	    prev = PREV_INSN (debug_insn);
+	  fallthru = split_block (bb, prev);
 	  if (flow_transfer_insn)
 	    {
 	      BB_END (bb) = flow_transfer_insn;
 
+	      rtx_insn *next;
 	      /* 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);
+		   x = next)
+		{
+		  next = NEXT_INSN (x);
+		  /* Debug insns should not be in between basic blocks,
+		     drop them on the floor.  */
+		  if (DEBUG_INSN_P (x))
+		    delete_insn (x);
+		  else if (!BARRIER_P (x))
+		    set_block_for_insn (x, NULL);
+		}
 	    }
 
 	  bb = fallthru->dest;
 	  remove_edge (fallthru);
-	  flow_transfer_insn = NULL_RTX;
+	  /* BB is unreachable at this point - we need to determine its profile
+	     once edges are built.  */
+	  bb->frequency = 0;
+	  bb->count = profile_count::uninitialized ();
+	  flow_transfer_insn = NULL;
+	  debug_insn = NULL;
 	  if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn))
-	    make_edge (ENTRY_BLOCK_PTR, bb, 0);
+	    make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, 0);
 	}
       else if (code == BARRIER)
 	{
@@ -497,17 +525,23 @@
   /* In case expander replaced normal insn by sequence terminating by
      return and barrier, or possibly other sequence not behaving like
      ordinary jump, we need to take care and move basic block boundary.  */
-  if (flow_transfer_insn)
+  if (flow_transfer_insn && flow_transfer_insn != end)
     {
       BB_END (bb) = flow_transfer_insn;
 
       /* Clean up the bb field for the insns that do not belong to BB.  */
-      x = flow_transfer_insn;
-      while (x != end)
+      rtx_insn *next;
+      for (x = NEXT_INSN (flow_transfer_insn); ; x = next)
 	{
-	  x = NEXT_INSN (x);
-	  if (!BARRIER_P (x))
+	  next = NEXT_INSN (x);
+	  /* Debug insns should not be in between basic blocks,
+	     drop them on the floor.  */
+	  if (DEBUG_INSN_P (x))
+	    delete_insn (x);
+	  else if (!BARRIER_P (x))
 	    set_block_for_insn (x, NULL);
+	  if (x == end)
+	    break;
 	}
     }
 
@@ -538,30 +572,41 @@
 
       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->probability
+		 = profile_probability::from_reg_br_prob_note (probability);
 	  f = FALLTHRU_EDGE (b);
-	  f->probability = REG_BR_PROB_BASE - probability;
-	  f->count = b->count - e->count;
+	  f->probability = e->probability.invert ();
 	  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;
+      e->probability = profile_probability::always ();
       return;
     }
-  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);
+  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);
+    }
 }
 
 /* Assume that some pass has inserted labels or control flow
@@ -572,21 +617,37 @@
 find_many_sub_basic_blocks (sbitmap blocks)
 {
   basic_block bb, min, max;
+  bool found = false;
+  auto_vec<unsigned int> n_succs;
+  n_succs.safe_grow_cleared (last_basic_block_for_fn (cfun));
 
-  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_FN (bb, cfun)
+    if (STATE (bb) == BLOCK_TO_SPLIT)
+      {
+	int n = last_basic_block_for_fn (cfun);
+	unsigned int ns = EDGE_COUNT (bb->succs);
 
-  FOR_EACH_BB (bb)
-    if (STATE (bb) == BLOCK_TO_SPLIT)
-      find_bb_boundaries (bb);
+        find_bb_boundaries (bb);
+	if (n == last_basic_block_for_fn (cfun) && ns == EDGE_COUNT (bb->succs))
+	  n_succs[bb->index] = EDGE_COUNT (bb->succs);
+      }
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (STATE (bb) != BLOCK_ORIGINAL)
-      break;
+      {
+	found = true;
+        break;
+      }
+
+  if (!found)
+    return;
 
   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;
 
@@ -596,7 +657,7 @@
 
   /* 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;
@@ -606,18 +667,50 @@
 	  continue;
 	if (STATE (bb) == BLOCK_NEW)
 	  {
-	    bb->count = 0;
+	    bool initialized_src = false, uninitialized_src = false;
+	    bb->count = profile_count::zero ();
 	    bb->frequency = 0;
 	    FOR_EACH_EDGE (e, ei, bb->preds)
 	      {
-		bb->count += e->count;
-		bb->frequency += EDGE_FREQUENCY (e);
+		if (e->count ().initialized_p ())
+		  {
+		    bb->count += e->count ();
+		    initialized_src = true;
+		  }
+		else
+		  uninitialized_src = true;
+		if (e->probability.initialized_p ())
+		  bb->frequency += EDGE_FREQUENCY (e);
 	      }
+	    /* When some edges are missing with read profile, this is
+	       most likely because RTL expansion introduced loop.
+	       When profile is guessed we may have BB that is reachable
+	       from unlikely path as well as from normal path.
+
+	       TODO: We should handle loops created during BB expansion
+	       correctly here.  For now we assume all those loop to cycle
+	       precisely once.  */
+	    if (!initialized_src
+		|| (uninitialized_src
+		     && profile_status_for_fn (cfun) != PROFILE_READ))
+	      bb->count = profile_count::uninitialized ();
+	  }
+ 	/* If nothing changed, there is no need to create new BBs.  */
+	else if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+	  {
+	    /* In rare occassions RTL expansion might have mistakely assigned
+	       a probabilities different from what is in CFG.  This happens
+	       when we try to split branch to two but optimize out the
+	       second branch during the way. See PR81030.  */
+	    if (JUMP_P (BB_END (bb)) && any_condjump_p (BB_END (bb))
+		&& EDGE_COUNT (bb->succs) >= 2)
+	      update_br_prob_note (bb);
+	    continue;
 	  }
 
 	compute_outgoing_frequencies (bb);
       }
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     SET_STATE (bb, 0);
 }