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]

[dataflow RFA] Remove DF_SUBREGS scanning flag


As mentioned in Kenny's other e-mail, this patch removes the DF_SUBREGS scanning flag. The flag allows the caller to see all subregs; by default df would only show word-extraction subregs and strip all the others. After this patch, all subregs are visible.

The DF_SUBREGS flag only affects the way the ->reg and ->loc fields are filled, so it is useless on passes that don't look at these fields. These are the schedulers (and ddg.c) and sign-extension elimination. Such passes used to specify DF_SUBREGS, Kenny just removed it because there was no behavioral change. This patch reverts their dataflow info to what it was before Kenny's patch, but again without behavioral changes.

fwprop needed DF_SUBREGS, now it achieves the goal without passing it. Nothing spectacular here, either.

The more interesting ones are loop optimizations, and the dataflow scanning itself. In fact all the passes were more or less ready to handle subregs because *some* subregs were already returned by df, as I said. Therefore, the changes are rather simple there.

web is already distinguishing DF_REF_REG and DF_REF_REAL_REG, so it accepts the new subregs correctly.

For dataflow, I actually found a couple of places where DF_REF_REAL_LOC was "inlined" in the code. In one case, I replaced DF_REF_LOC with DF_REF_REAL_LOC.

In two other cases (when dealing with REG_DEAD/REG_UNUSED notes for multiword hard registers), DF_REF_LOC is used to create the REG_DEAD/REG_UNUSED notes. I believe that in this case we will not see a subreg, but on the other hand I don't see any harm if we see one. So I left DF_REF_LOC there.

For loop optimizations, loop-invariant.c analyzes uses and just needs to always see the REG and never the enclosing SUBREG. This is easily done with DF_REF_REAL_LOC. It was already doing the same -- this patch is just a cleanup for that case.

loop-iv.c dealt with subregs like this:

 rtx reg = DF_REF_REG (def);
 ...
 set = single_set (insn);
 if (!set || SET_DEST (set) != reg)
   return false;

This shows why the old behavior without DF_SUBREGS is pretty much broken. We get the DEF (which is not artificial, it is taken from an insn), and it may not be the SET_DEST of the insn! From my analysis, this actually happened when the SET_DEST was a subreg, but I'm CCing Zdenek in case this rings a bell. After this patch, we have this code which is more clear:

 rtx reg = DF_REF_REG (def);
 ...
 if (!REG_P (reg))
   return false;

 set = single_set (insn);
 if (!set)
    return false;

gcc_assert (SET_DEST (set) == reg);

This simply rejects all subregs, and is able to perform a consistency check on the dataflow info.

I will apply the patch sometime next week (I have to rebootstrap/retest after Kenny's changes) if I don't hear from anybody, and will prepare a backport to mainline when 4.3 opens. I'll bootstrap/test with web enabled at -O2. Does it looks ok?

Paolo
2006-10-20  Paolo Bonzini  <bonzinI@gnu.rg>

	* ddg.c (add_deps_for_def, add_deps_for_use): Use accessor macros.
	* df.h (DF_REF_STRIPPED, DF_SUBREGS): Remove.
	* df-core.c: Don't document scanning flags.
	* df-scan.c (df_ref_record): Always behave as if DF_SUBREGS was set.
	* df-problems.c (df_lr_bb_local_compute): Strip SUBREGs with
	DF_REF_REAL_REG.
	(df_chain_start_dump): Don't dump DF_REF_STRIPPED.
	(df_create_unused_note, df_ri_bb_compute): Don't "inline"
	DF_REF_REAL_LOC.
	* fwprop.c (fwprop_init): Do not pass DF_SUBREGS.
	* loop-invariant.c (record_use): Don't strip SUBREGs.
	(record_uses): Do it here with DF_REF_REAL_LOC.
	* loop-iv.c (iv_analyze_def): Only allow REGs.  Replace previous
	way to check for SUBREGs with an assertion.

Index: fwprop.c
===================================================================
--- fwprop.c	(revision 117899)
+++ fwprop.c	(working copy)
@@ -919,7 +919,7 @@ fwprop_init (void)
 
   /* Now set up the dataflow problem (we only want use-def chains) and
      put the dataflow solver to work.  */
-  df = df_init (DF_SUBREGS + DF_UD_CHAIN, DF_EQ_NOTES);
+  df = df_init (DF_UD_CHAIN, DF_EQ_NOTES);
   df_chain_add_problem (df);
   df_analyze (df);
 }
Index: ddg.c
===================================================================
--- ddg.c	(revision 117899)
+++ ddg.c	(working copy)
@@ -265,7 +265,7 @@ add_deps_for_def (ddg_ptr g, struct df *
 
       /* Check if there are uses after RD.  */
       for (i = src_node->cuid + 1; i < g->num_nodes; i++)
-	 if (df_find_use (df, g->nodes[i].insn, rd->reg))
+	 if (df_find_use (df, g->nodes[i].insn, DF_REF_REG (rd)))
 	   return;
 
       dest_node = get_node_of_insn (g, def->insn);
@@ -298,7 +298,7 @@ add_deps_for_use (ddg_ptr g, struct df *
 
   /* Make sure there are no defs after USE.  */
   for (i = use_node->cuid + 1; i < g->num_nodes; i++)
-     if (df_find_def (df, g->nodes[i].insn, use->reg))
+     if (df_find_def (df, g->nodes[i].insn, DF_REF_REG (use)))
        return;
   /* We must not add ANTI dep when there is an intra-loop TRUE dep in
      the opposite direction. If the first_def reaches the USE then there is
Index: df-scan.c
===================================================================
--- df-scan.c	(revision 117899)
+++ df-scan.c	(working copy)
@@ -1156,22 +1156,6 @@ df_ref_record (struct dataflow *dflow, r
 
   gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
 
-  /* For the reg allocator we are interested in some SUBREG rtx's, but not
-     all.  Notably only those representing a word extraction from a multi-word
-     reg.  As written in the docu those should have the form
-     (subreg:SI (reg:M A) N), with size(SImode) > size(Mmode).
-     XXX Is that true?  We could also use the global word_mode variable.  */
-  if ((df->permanent_flags & DF_SUBREGS) == 0
-      && GET_CODE (reg) == SUBREG
-      && (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode)
-	  || GET_MODE_SIZE (GET_MODE (reg))
-	       >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (reg)))))
-    {
-      loc = &SUBREG_REG (reg);
-      reg = *loc;
-      ref_flags |= DF_REF_STRIPPED;
-    }
-
   regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
   if (regno < FIRST_PSEUDO_REGISTER)
     {
Index: df-core.c
===================================================================
--- df-core.c	(revision 117899)
+++ df-core.c	(working copy)
@@ -63,11 +63,6 @@ DF_INIT simply creates a poor man's obje
 passed to all the dataflow routines.  df_finish destroys this object
 and frees up any allocated memory.
 
-There are three flags that can be passed to df_init, each of these
-flags controls the scanning of the rtl:
-
-DF_SUBREGS return subregs rather than the inner reg.
-
 
 DF_ADD_PROBLEM adds a problem, defined by an instance to struct
 df_problem, to the set of problems solved in this instance of df.  All
Index: df.h
===================================================================
--- df.h	(revision 117899)
+++ df.h	(working copy)
@@ -76,11 +76,6 @@ enum df_ref_flags
        independent.  */
     DF_REF_READ_WRITE = 1,
 
-    /* This flag is set, if we stripped the subreg from the reference.
-       In this case we must make conservative guesses, at what the
-       outer mode was.  */
-    DF_REF_STRIPPED = 2,
-    
     /* If this flag is set, this is not a real definition/use, but an
        artificial one created to model always live registers, eh uses, etc.  */
     DF_REF_ARTIFICIAL = 4,
@@ -311,14 +306,12 @@ struct df_link
 
 enum df_permanent_flags 
 {
-  /* Scanning flags.  */
-  DF_SUBREGS       =  1, /* Return subregs rather than the inner reg.  */
   /* Flags that control the building of chains.  */
-  DF_DU_CHAIN      =  2, /* Build DU chains.  */  
-  DF_UD_CHAIN      =  4, /* Build UD chains.  */
+  DF_DU_CHAIN      =  1, /* Build DU chains.  */  
+  DF_UD_CHAIN      =  2, /* Build UD chains.  */
   /* Flag to control the building of register info.  */
-  DF_RI_LIFE       =  8, /* Build register info.  */
-  DF_RI_SETJMP     = 16  /* Build pseudos that cross setjmp info.  */
+  DF_RI_LIFE       =  4, /* Build register info.  */
+  DF_RI_SETJMP     =  8  /* Build pseudos that cross setjmp info.  */
 };
 
 enum df_changeable_flags 
Index: loop-invariant.c
===================================================================
--- loop-invariant.c	(revision 117899)
+++ loop-invariant.c	(working copy)
@@ -673,8 +673,6 @@ record_use (struct def *def, rtx *use, r
 {
   struct use *u = XNEW (struct use);
 
-  if (GET_CODE (*use) == SUBREG)
-    use = &SUBREG_REG (*use);
   gcc_assert (REG_P (*use));
 
   u->pos = use;
@@ -834,7 +832,7 @@ record_uses (rtx insn)
     {
       inv = invariant_for_use (use);
       if (inv)
-	record_use (inv->def, DF_REF_LOC (use), DF_REF_INSN (use));
+	record_use (inv->def, DF_REF_REAL_LOC (use), DF_REF_INSN (use));
     }
 }
 
Index: loop-iv.c
===================================================================
--- loop-iv.c	(revision 117899)
+++ loop-iv.c	(working copy)
@@ -1043,10 +1043,14 @@ iv_analyze_def (struct df_ref *def, stru
   iv->base = NULL_RTX;
   iv->step = NULL_RTX;
 
+  if (!REG_P (reg))
+    return false;
+
   set = single_set (insn);
-  if (!set || SET_DEST (set) != reg)
+  if (!set)
     return false;
 
+  gcc_assert (SET_DEST (set) == reg);
   rhs = find_reg_equal_equiv_note (insn);
   if (rhs)
     rhs = XEXP (rhs, 0);
Index: df-problems.c
===================================================================
--- df-problems.c	(revision 117899)
+++ df-problems.c	(working copy)
@@ -1577,8 +1577,9 @@ df_lr_bb_local_compute (struct dataflow 
 		  && dregno < FIRST_PSEUDO_REGISTER)
 		{
 		  unsigned int i;
+		  enum machine_mode mode = GET_MODE (DF_REF_REAL_REG (def));
 		  unsigned int end = dregno 
-		    + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1;
+		    + hard_regno_nregs[dregno][mode] - 1;
 		  for (i = dregno; i <= end; ++i)
 		    regs_asm_clobbered[i] = 1;
 		}
@@ -3450,8 +3451,6 @@ df_chain_start_dump (struct dataflow *df
 		       DF_REF_REGNO (use));
 	      if (use->flags & DF_REF_READ_WRITE)
 		fprintf (file, "read/write ");
-	      if (use->flags & DF_REF_STRIPPED)
-		fprintf (file, "stripped ");
 	      if (use->flags & DF_REF_IN_NOTE)
 		fprintf (file, "note ");
 	      df_chain_dump (DF_REF_CHAIN (use), file);
@@ -3845,8 +3844,7 @@ df_create_unused_note (basic_block bb, r
 	    && (!bitmap_bit_p (artificial_uses, dregno)) 
 	    && (!df_ignore_stack_reg (dregno)))
     {
-      rtx reg = GET_CODE (*DF_REF_LOC (def)) == SUBREG ?
-	SUBREG_REG (*DF_REF_LOC (def)) : *DF_REF_LOC (def);
+      rtx reg = *DF_REF_REAL_LOC (def);
       rtx note = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
       REG_NOTES (insn) = note;
 #ifdef REG_DEAD_DEBUGGING
@@ -4053,8 +4051,7 @@ df_ri_bb_compute (struct dataflow *dflow
 		   && (!(DF_REF_FLAGS (use) & DF_REF_READ_WRITE))
 		   && (!df_ignore_stack_reg (uregno)))
 		{
-		  rtx reg = GET_CODE (*DF_REF_LOC (use)) == SUBREG ?
-		    SUBREG_REG (*DF_REF_LOC (use)) : *DF_REF_LOC (use);
+		  rtx reg = *DF_REF_REAL_LOC (use);
 		  rtx note = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
 		  REG_NOTES (insn) = note;
 		  if (df->permanent_flags & DF_RI_LIFE)

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