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]

Re: One more optimize_mode_switching() problem


On Feb  7, 2001, Richard Henderson <rth@redhat.com> wrote:

> On Wed, Feb 07, 2001 at 04:13:24PM -0200, Alexandre Oliva wrote:
>> If the last insn of a function is a DFmode store, and prologue and
>> epilogue must run in single mode, the mode switching would be inserted
>> before the store, because there was not NOTE_INSN_BASIC_BLOCK after it
>> that ptr->insn_ptr could be pointed to.

> This doesn't seem right at all.  If you need to change modes
> on exit of a function, you should be using insert_insn_on_edge
> to the EXIT_BLOCK.

Ok.  I bit the bullet and ended up fixing it by implementing the
optimization I had suggested in my previous message too.  I find it a
bit hackish, but I don't see a cleaner way to get the entry mode of
the exit block taken into account.  How do you feel about this?  Ok to
install, if it survives a battery of testing?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* lcm.c (compute_earliest): Let EXIT_BLOCK be handled as a regular
	basic block.
	(optimize_mode_switching) [NORMAL_MODE]: Set up EXIT_BLOCK as a
	regular basic block, and arrange for all edges into it to switch
	to normal mode.

Index: gcc/lcm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/lcm.c,v
retrieving revision 1.22
diff -u -p -r1.22 lcm.c
--- gcc/lcm.c 2001/02/07 17:44:47 1.22
+++ gcc/lcm.c 2001/02/09 16:11:08
@@ -205,7 +205,11 @@ compute_earliest (edge_list, n_exprs, an
 	sbitmap_copy (earliest[x], antin[succ->index]);
       else
         {
-	  if (succ == EXIT_BLOCK_PTR)
+	  /* 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)
 	    sbitmap_zero (earliest[x]);
 	  else
 	    {
@@ -1019,6 +1023,10 @@ optimize_mode_switching (file)
   int n_entities;
   int max_num_modes = 0;
 
+#ifdef NORMAL_MODE
+  n_basic_blocks++;
+#endif
+
   for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
     if (OPTIMIZE_MODE_SWITCHING (e))
       {
@@ -1030,9 +1038,21 @@ optimize_mode_switching (file)
 	  max_num_modes = num_modes[e];
       }
 
+#ifdef NORMAL_MODE
+  n_basic_blocks--;
+#endif
+
   if (! n_entities)
     return 0;
 
+#ifdef NORMAL_MODE
+  n_basic_blocks++;
+  if (VARRAY_SIZE (basic_block_info) < n_basic_blocks)
+    VARRAY_GROW (basic_block_info, n_basic_blocks);
+  BASIC_BLOCK (n_basic_blocks - 1) = EXIT_BLOCK_PTR;
+  EXIT_BLOCK_PTR->index = n_basic_blocks - 1;
+#endif
+
   /* Create the bitmap vectors.  */
 
   antic = sbitmap_vector_alloc (n_basic_blocks, n_entities);
@@ -1087,29 +1107,6 @@ optimize_mode_switching (file)
 		}
 	    }
 
-	  /* If this is a predecessor of the exit block, and we must 
-	     force a mode on exit, make note of that.  */
-#ifdef NORMAL_MODE
-	  if (NORMAL_MODE (e) != no_mode && last_mode != NORMAL_MODE (e))
-	    for (eg = BASIC_BLOCK (bb)->succ; eg; eg = eg->succ_next)
-	      if (eg->dest == EXIT_BLOCK_PTR)
-		{
-		  rtx insn = BLOCK_END (bb);
-
-		  /* Find the last insn before a USE and/or JUMP.  */
-		  while ((GET_CODE (insn) == INSN 
-			      && GET_CODE (PATTERN (insn)) == USE)
-			  || GET_CODE (insn) == JUMP_INSN)
-		    insn = PREV_INSN (insn);
-		  if (insn != BLOCK_END (bb) && NEXT_INSN (insn))
-		    insn = NEXT_INSN (insn);
-		  last_mode = NORMAL_MODE (e);
-		  add_seginfo (info + bb, 
-		      new_seginfo (last_mode, insn, bb, live_now));
-		  RESET_BIT (transp[bb], j);
-		} 
-#endif
-
 	  info[bb].computing = last_mode;
 	  /* Check for blocks without ANY mode requirements.  */
 	  if (last_mode == no_mode)
@@ -1149,6 +1146,9 @@ optimize_mode_switching (file)
 		    info[bb].seginfo->mode = no_mode;
 		  }
 	      }
+
+	    bb = n_basic_blocks - 1;
+	    info[bb].seginfo->mode = mode;
 	  }
       }
 #endif /* NORMAL_MODE */
@@ -1253,10 +1253,41 @@ optimize_mode_switching (file)
       free_edge_list (edge_list);
     }
 
+#ifdef NORMAL_MODE
+  n_basic_blocks--;
+  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][n_basic_blocks].seginfo->mode != no_mode)
+	{
+	  edge eg;
+	  struct seginfo *ptr = bb_info[j][n_basic_blocks].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 ();
+
+	      need_commit = 1;
+	      insert_insn_on_edge (mode_set, eg);
+	    }
+	  
+	}
+#endif
 
       for (bb = n_basic_blocks - 1; bb >= 0; bb--)
 	{

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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