This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug fix for optimize_mode_switching / NORMAL_MODE


Richard Henderson wrote:
> Well, hmm.  This is pre-reload, thus return insns can't exist yet.
> Therefore there are only two ways to have an edge to the exit block:
> the last block fallthru and sibcalls.  But sibcalls are calls, and
> so we must return to normal mode before the call, so there is only
> one exit predecessor to concern ourselves with -- the fallthru block.
> 
> At which point the problem seems much reduced, since we can simply
> split that one edge.
> 
> > At the end, you'd have to remove the edge between exit block and fake block,
> > redirect the fake block predecessors back to the exit block, and deallocate.
> 
> Actually, you wouldn't have to do anything of the sort.  One, it would
> seem that it's possible that code might have been dropped into the block
> to return to normal mode.  Two, if the block is really empty, then a
> subsequent call to cleanup_cfg should remove the block.
	
I have attached a patch that fixes the discussed problems by useing split_edge
to split the edge from the entry block and the fallthrough edge to the exit
block.

-- 
--------------------------
SuperH
2430 Aztec West / Almondsbury / BRISTOL / BS32 4AQ
T:+44 1454 462330
Thu May 30 11:58:48 2002  J"orn Rennecke <joern.rennecke@superh.com>

	* lcm.c (output.h): #include.
	(compute_earliest): Remove hack to treat renumbered EXIT_BLOCK
	as an ordinary block.
	(optimize_mode_switching): Don't pretend that the exit block is
	an ordinary block, or handle sucessors of entry block specially.
	Instead, split edges from entry block and to exit block, and
	put a computing definition on the thus gained post-entry-block,
	and a need on the pre-exit-block.

Index: lcm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/lcm.c,v
retrieving revision 1.46
diff -p -u -r1.46 lcm.c
--- lcm.c	28 May 2002 12:53:44 -0000	1.46
+++ lcm.c	29 May 2002 23:27:45 -0000
@@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - S
 #include "insn-config.h"
 #include "recog.h"
 #include "basic-block.h"
+#include "output.h"
 #include "tm_p.h"
 
 /* We want target macros for the mode switching code to be able to refer
@@ -207,11 +208,7 @@ compute_earliest (edge_list, n_exprs, an
 	sbitmap_copy (earliest[x], antin[succ->index]);
       else
         {
-	  /* We refer to the EXIT_BLOCK index, instead of testing for
-	     EXIT_BLOCK_PTR, so that EXIT_BLOCK_PTR's index can be
-	     changed so as to pretend it's a regular block, so that
-	     its antin can be taken into account.  */
-	  if (succ->index == EXIT_BLOCK)
+	  if (succ == EXIT_BLOCK_PTR)
 	    sbitmap_zero (earliest[x]);
 	  else
 	    {
@@ -1027,43 +1024,54 @@ optimize_mode_switching (file)
   int n_entities;
   int max_num_modes = 0;
   bool emited = false;
+  basic_block post_entry, pre_exit ATTRIBUTE_UNUSED;
 
   clear_bb_flags ();
-#ifdef NORMAL_MODE
-  /* Increment last_basic_block before allocating bb_info.  */
-  last_basic_block++;
-#endif
 
   for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
     if (OPTIMIZE_MODE_SWITCHING (e))
       {
-	/* Create the list of segments within each basic block.  */
+	int entry_exit_extra = 0;
+
+	/* Create the list of segments within each basic block.
+	   If NORMAL_MODE is defined, allow for two extra
+	   blocks split from the entry and exit block. */
+#ifdef NORMAL_MODE
+	entry_exit_extra = 2;
+#endif
 	bb_info[n_entities]
-	  = (struct bb_info *) xcalloc (last_basic_block, sizeof **bb_info);
+	  = (struct bb_info *) xcalloc (last_basic_block + entry_exit_extra,
+					sizeof **bb_info);
 	entity_map[n_entities++] = e;
 	if (num_modes[e] > max_num_modes)
 	  max_num_modes = num_modes[e];
       }
 
-#ifdef NORMAL_MODE
-  /* Decrement it back in case we return below.  */
-  last_basic_block--;
-#endif
-
   if (! n_entities)
     return 0;
 
 #ifdef NORMAL_MODE
-  /* We're going to pretend the EXIT_BLOCK is a regular basic block,
-     so that switching back to normal mode when entering the
-     EXIT_BLOCK isn't optimized away.  We do this by incrementing the
-     basic block count, growing the VARRAY of basic_block_info and
-     appending the EXIT_BLOCK_PTR to it.  */
-  last_basic_block++;
-  if (VARRAY_SIZE (basic_block_info) < last_basic_block)
-    VARRAY_GROW (basic_block_info, last_basic_block);
-  BASIC_BLOCK (last_basic_block - 1) = EXIT_BLOCK_PTR;
-  EXIT_BLOCK_PTR->index = last_basic_block - 1;
+  {
+    /* Split the edge from the entry block and the fallthrough edge to the
+       exit block, so that we can note that there NORMAL_MODE is supplied /
+       required.  */
+    edge eg;
+    post_entry = split_edge (ENTRY_BLOCK_PTR->succ);
+    /* The only non-call predecessor at this stage is a block with a
+       fallthrough edge; there can be at most one, but there could be
+       none at all, e.g. when exit is called.  */
+    for (pre_exit = 0, eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
+      if (eg->flags & EDGE_FALLTHRU)
+	{
+	  regset live_at_end = eg->src->global_live_at_end;
+
+	  if (pre_exit)
+	    abort ();
+	  pre_exit = split_edge (eg);
+	  COPY_REG_SET (pre_exit->global_live_at_start, live_at_end);
+	  COPY_REG_SET (pre_exit->global_live_at_end, live_at_end);
+	}
+  }
 #endif
 
   /* Create the bitmap vectors.  */
@@ -1124,7 +1132,7 @@ optimize_mode_switching (file)
 	  /* Check for blocks without ANY mode requirements.  */
 	  if (last_mode == no_mode)
 	    {
-	      ptr = new_seginfo (no_mode, insn, bb->index, live_now);
+	      ptr = new_seginfo (no_mode, bb->end, bb->index, live_now);
 	      add_seginfo (info + bb->index, ptr);
 	    }
 	}
@@ -1134,36 +1142,21 @@ optimize_mode_switching (file)
 
 	if (mode != no_mode)
 	  {
-	    edge eg;
-
-	    for (eg = ENTRY_BLOCK_PTR->succ; eg; eg = eg->succ_next)
-	      {
-		bb = eg->dest;
+	    bb = post_entry;
 
-	        /* By always making this nontransparent, we save
-		   an extra check in make_preds_opaque.  We also
-		   need this to avoid confusing pre_edge_lcm when
-		   antic is cleared but transp and comp are set.  */
-		RESET_BIT (transp[bb->index], j);
-
-		/* If the block already has MODE, pretend it
-		   has none (because we don't need to set it),
-		   but retain whatever mode it computes.  */
-		if (info[bb->index].seginfo->mode == mode)
-		  info[bb->index].seginfo->mode = no_mode;
-
-		/* Insert a fake computing definition of MODE into entry
-		   blocks which compute no mode. This represents the mode on
-		   entry.  */
-		else if (info[bb->index].computing == no_mode)
-		  {
-		    info[bb->index].computing = mode;
-		    info[bb->index].seginfo->mode = no_mode;
-		  }
-	      }
+	    /* By always making this nontransparent, we save
+	       an extra check in make_preds_opaque.  We also
+	       need this to avoid confusing pre_edge_lcm when
+	       antic is cleared but transp and comp are set.  */
+	    RESET_BIT (transp[bb->index], j);
+
+	    /* Insert a fake computing definition of MODE into entry
+	       blocks which compute no mode. This represents the mode on
+	       entry.  */
+	    info[bb->index].computing = mode;
 
-	    bb = EXIT_BLOCK_PTR;
-	    info[bb->index].seginfo->mode = mode;
+	    if (pre_exit)
+	      info[pre_exit->index].seginfo->mode = mode;
 	  }
       }
 #endif /* NORMAL_MODE */
@@ -1288,63 +1281,11 @@ optimize_mode_switching (file)
       free_edge_list (edge_list);
     }
 
-#ifdef NORMAL_MODE
-  /* Restore the special status of EXIT_BLOCK.  */
-  last_basic_block--;
-  VARRAY_POP (basic_block_info);
-  EXIT_BLOCK_PTR->index = EXIT_BLOCK;
-#endif
-
   /* Now output the remaining mode sets in all the segments.  */
   for (j = n_entities - 1; j >= 0; j--)
     {
       int no_mode = num_modes[entity_map[j]];
 
-#ifdef NORMAL_MODE
-      if (bb_info[j][last_basic_block].seginfo->mode != no_mode)
-	{
-	  edge eg;
-	  struct seginfo *ptr = bb_info[j][last_basic_block].seginfo;
-
-	  for (eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
-	    {
-	      rtx mode_set;
-
-	      if (bb_info[j][eg->src->index].computing == ptr->mode)
-		continue;
-
-	      start_sequence ();
-	      EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
-	      mode_set = gen_sequence ();
-	      end_sequence ();
-
-	      /* Do not bother to insert empty sequence.  */
-	      if (GET_CODE (mode_set) == SEQUENCE
-		  && !XVECLEN (mode_set, 0))
-		continue;
-
-	      /* If this is an abnormal edge, we'll insert at the end of the
-		 previous block.  */
-	      if (eg->flags & EDGE_ABNORMAL)
-		{
-		  emited = true;
-		  if (GET_CODE (eg->src->end) == JUMP_INSN)
-		    emit_insn_before (mode_set, eg->src->end);
-		  else if (GET_CODE (eg->src->end) == INSN)
-		    emit_insn_after (mode_set, eg->src->end);
-		  else
-		    abort ();
-		}
-	      else
-		{
-		  need_commit = 1;
-		  insert_insn_on_edge (mode_set, eg);
-		}
-	    }
-
-	}
-#endif
-
       FOR_EACH_BB_REVERSE (bb)
 	{
 	  struct seginfo *ptr, *next;
@@ -1393,8 +1334,12 @@ optimize_mode_switching (file)
   if (need_commit)
     commit_edge_insertions ();
 
+#ifdef NORMAL_MODE
+  cleanup_cfg (CLEANUP_NO_INSN_DEL);
+#else
   if (!need_commit && !emited)
     return 0;
+#endif
 
   max_regno = max_reg_num ();
   allocate_reg_info (max_regno, FALSE, FALSE);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]