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: CANNOT_CHANGE_MODE changes for df/ra*


Hi,

On Mon, 3 Feb 2003, Michael Matz wrote:

> > the logic is wrong.  Consider when word_mode is SImode:
> >
> > (set (subreg:HI (reg:DI ...)) ...)
> > (set (subreg:SI (reg:DI ...)) ...)
> > (set (subreg:DI (reg:TI ...)) ...)
>
> I've deactivated that function at all.  Hmm, I guess for other users of
> df.c that don't do that, the definition of read_modify_subreg_p() is now
> wrong indeed.  OK, I'll change the function to do, what you suggested, and
> introduce a flag for df_flags, which can be set by the new RA to not call
> that function.

Hmm, it seems I never got to committing this patch.  I retested it for
current mainline on i686-linux, and am going to commit it now.  I'll
bootstrap/regtest also the 3.3 branch with it, and commit it there too.

> > return (isize > osize && isize > UNITS_PER_WORD)
> >
> > rather than using double negatives.


Ciao,
Michael.
-- 
        * df.h (enum df_ref_flags.DF_REF_STRIPPED): New.
        (DF_FOR_REGALLOC): New.
        * df.c (df_ref_record): Set DF_REF_STRIPPED.
        (read_modify_subreg_p): Simplify.
        (df_def_record_1, df_uses_record): Set DF_REF_MODE_CHANGE more often.
        Use DF_FOR_REGALLOC.
        * ra.h (struct web): New member subreg_stripped.
        (invalid_mode_change_regs): Declare.
        * ra.c (invalid_mode_change_regs): New.
        (init_ra): Initialize it.
        * ra-build.c (init_one_web_common, remember_web_was_spilled): Use it.
        Use CANNOT_CHANGE_MODE_CLASS as ifdef guard.
        (reinit_one_web, parts_to_web_1): Deal with subreg_stripped.
        * ra-colorize.c (colorize_one_web): Use invalid_mode_change_regs.
        Use CANNOT_CHANGE_MODE_CLASS as ifdef guard.

Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.46
diff -u -p -r1.46 df.c
--- df.c	31 Jan 2003 23:34:12 -0000	1.46
+++ df.c	7 Mar 2003 16:54:04 -0000
@@ -849,6 +849,7 @@ df_ref_record (df, reg, loc, insn, ref_t
     {
       loc = &SUBREG_REG (reg);
       reg = *loc;
+      ref_flags |= DF_REF_STRIPPED;
     }

   regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
@@ -893,13 +894,8 @@ read_modify_subreg_p (x)
     return false;
   isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
   osize = GET_MODE_SIZE (GET_MODE (x));
-  if (isize <= osize)
-    return true;
-  if (isize <= UNITS_PER_WORD)
-    return false;
-  if (osize > UNITS_PER_WORD)
-    return false;
-  return true;
+  /* Paradoxical subreg writes don't leave a trace of the old content.  */
+  return (isize > osize && isize > UNITS_PER_WORD);
 }


@@ -927,9 +923,7 @@ df_def_record_1 (df, x, bb, insn)
     }

 #ifdef CLASS_CANNOT_CHANGE_MODE
-  if (GET_CODE (dst) == SUBREG
-      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
-				     GET_MODE (dst)))
+  if (GET_CODE (dst) == SUBREG)
     flags |= DF_REF_MODE_CHANGE;
 #endif

@@ -938,7 +932,8 @@ df_def_record_1 (df, x, bb, insn)
   while (GET_CODE (dst) == STRICT_LOW_PART
 	 || GET_CODE (dst) == ZERO_EXTRACT
 	 || GET_CODE (dst) == SIGN_EXTRACT
-	 || read_modify_subreg_p (dst))
+	 || ((df->flags & DF_FOR_REGALLOC) == 0
+             && read_modify_subreg_p (dst)))
     {
       /* Strict low part always contains SUBREG, but we do not want to make
 	 it appear outside, as whole register is always considered.  */
@@ -948,9 +943,7 @@ df_def_record_1 (df, x, bb, insn)
 	  dst = *loc;
 	}
 #ifdef CLASS_CANNOT_CHANGE_MODE
-      if (GET_CODE (dst) == SUBREG
-	  && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
-				         GET_MODE (dst)))
+      if (GET_CODE (dst) == SUBREG)
         flags |= DF_REF_MODE_CHANGE;
 #endif
       loc = &XEXP (dst, 0);
@@ -1050,9 +1043,7 @@ df_uses_record (df, loc, ref_type, bb, i
 	  return;
 	}
 #ifdef CLASS_CANNOT_CHANGE_MODE
-      if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
-				      GET_MODE (SUBREG_REG (x))))
-        flags |= DF_REF_MODE_CHANGE;
+      flags |= DF_REF_MODE_CHANGE;
 #endif

       /* ... Fall through ...  */
@@ -1072,13 +1063,12 @@ df_uses_record (df, loc, ref_type, bb, i
 	  {
 	    enum df_ref_flags use_flags;
 	    case SUBREG:
-	      if (read_modify_subreg_p (dst))
+	      if ((df->flags & DF_FOR_REGALLOC) == 0
+                  && read_modify_subreg_p (dst))
 		{
 		  use_flags = DF_REF_READ_WRITE;
 #ifdef CLASS_CANNOT_CHANGE_MODE
-		  if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
-						  GET_MODE (SUBREG_REG (dst))))
-		    use_flags |= DF_REF_MODE_CHANGE;
+		  use_flags |= DF_REF_MODE_CHANGE;
 #endif
 		  df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
 				  insn, use_flags);
@@ -1102,9 +1092,7 @@ df_uses_record (df, loc, ref_type, bb, i
 		abort ();
 	      use_flags = DF_REF_READ_WRITE;
 #ifdef CLASS_CANNOT_CHANGE_MODE
-	      if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
-					      GET_MODE (SUBREG_REG (dst))))
-		use_flags |= DF_REF_MODE_CHANGE;
+	      use_flags |= DF_REF_MODE_CHANGE;
 #endif
 	      df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
 			     insn, use_flags);
Index: df.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.h,v
retrieving revision 1.15
diff -u -p -r1.15 df.h
--- df.h	26 Jan 2003 06:10:37 -0000	1.15
+++ df.h	7 Mar 2003 16:54:04 -0000
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - S
 #define DF_ALL	       255
 #define DF_HARD_REGS  1024	/* Mark hard registers.  */
 #define DF_EQUIV_NOTES 2048	/* Mark uses present in EQUIV/EQUAL notes.  */
+#define DF_FOR_REGALLOC 4096    /* If called for the register allocator.  */

 enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD,
 		  DF_REF_REG_MEM_STORE};
@@ -52,13 +53,17 @@ enum df_ref_flags
     DF_REF_READ_WRITE = 1,

     /* This flag is set on register references inside a subreg on
-       machines which have CLASS_CANNOT_CHANGE_MODE and where the mode
-       change of that subreg expression is invalid for this class.
+       machines which have CANNOT_CHANGE_MODE_CLASS.
        Note, that this flag can also be set on df_refs representing
        the REG itself (i.e., one might not see the subreg anyore).
        Also note, that this flag is set also for hardreg refs, i.e.,
        you must check yourself if it's a pseudo.  */
-    DF_REF_MODE_CHANGE = 2
+    DF_REF_MODE_CHANGE = 2,
+
+    /* 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 = 4
   };


Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-build.c,v
retrieving revision 1.16
diff -u -p -r1.16 ra-build.c
--- ra-build.c	11 Feb 2003 20:58:36 -0000	1.16
+++ ra-build.c	7 Mar 2003 16:54:04 -0000
@@ -1305,10 +1305,9 @@ init_one_web_common (web, reg)
       AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
       prune_hardregs_for_mode (&web->usable_regs,
 			       PSEUDO_REGNO_MODE (web->regno));
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       if (web->mode_changed)
-        AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
-			          (int) CLASS_CANNOT_CHANGE_MODE]);
+        AND_COMPL_HARD_REG_SET (web->usable_regs, invalid_mode_change_regs);
 #endif
       web->num_freedom = hard_regs_count (web->usable_regs);
       web->num_freedom -= web->add_hardregs;
@@ -1351,6 +1350,7 @@ reinit_one_web (web, reg)
   web->artificial = 0;
   web->live_over_abnormal = 0;
   web->mode_changed = 0;
+  web->subreg_stripped = 0;
   web->move_related = 0;
   web->in_load = 0;
   web->target_of_spilled_move = 0;
@@ -1912,6 +1912,9 @@ parts_to_webs_1 (df, copy_webs, all_refs
 	  if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
 	      && web->regno >= FIRST_PSEUDO_REGISTER)
 	    web->mode_changed = 1;
+	  if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0
+	      && web->regno >= FIRST_PSEUDO_REGISTER)
+	    web->subreg_stripped = 1;
 	  if (i >= def_id
 	      && TEST_BIT (live_over_abnormal, ref_id))
 	    web->live_over_abnormal = 1;
@@ -1961,6 +1964,9 @@ parts_to_webs_1 (df, copy_webs, all_refs
       if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
 	  && web->regno >= FIRST_PSEUDO_REGISTER)
 	web->mode_changed = 1;
+      if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0
+	  && web->regno >= FIRST_PSEUDO_REGISTER)
+	web->subreg_stripped = 1;

       /* Setup def2web, or use2web, and increment num_defs or num_uses.  */
       if (i < def_id)
@@ -2364,10 +2370,9 @@ remember_web_was_spilled (web)
 		       reg_class_contents[(int) GENERAL_REGS]);
   AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
   prune_hardregs_for_mode (&web->usable_regs, PSEUDO_REGNO_MODE (web->regno));
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
   if (web->mode_changed)
-    AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
-			      (int) CLASS_CANNOT_CHANGE_MODE]);
+    AND_COMPL_HARD_REG_SET (web->usable_regs, invalid_mode_change_regs);
 #endif
   web->num_freedom = hard_regs_count (web->usable_regs);
   if (!web->num_freedom)
Index: ra-colorize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-colorize.c,v
retrieving revision 1.9
diff -u -p -r1.9 ra-colorize.c
--- ra-colorize.c	26 Feb 2003 12:36:18 -0000	1.9
+++ ra-colorize.c	7 Mar 2003 16:54:04 -0000
@@ -1370,10 +1370,9 @@ colorize_one_web (web, hard)
       else
 	COPY_HARD_REG_SET (colors,
 			   usable_regs[reg_preferred_class (web->regno)]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       if (web->mode_changed)
-        AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
-			          (int) CLASS_CANNOT_CHANGE_MODE]);
+        AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs);
 #endif
       COPY_HARD_REG_SET (call_clobbered, colors);
       AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
@@ -1404,10 +1403,9 @@ colorize_one_web (web, hard)
 	  else
 	    IOR_HARD_REG_SET (colors, usable_regs
 			      [reg_alternate_class (web->regno)]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
 	  if (web->mode_changed)
-	    AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
-				      (int) CLASS_CANNOT_CHANGE_MODE]);
+	    AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs);
 #endif
 	  COPY_HARD_REG_SET (call_clobbered, colors);
 	  AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
Index: ra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.c,v
retrieving revision 1.7
diff -u -p -r1.7 ra.c
--- ra.c	17 Jan 2003 03:28:09 -0000	1.7
+++ ra.c	7 Mar 2003 16:54:04 -0000
@@ -148,6 +148,7 @@ HARD_REG_SET never_use_colors;
 HARD_REG_SET usable_regs[N_REG_CLASSES];
 unsigned int num_free_regs[N_REG_CLASSES];
 HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+HARD_REG_SET invalid_mode_change_regs;
 unsigned char byte2bitcount[256];

 unsigned int debug_new_regalloc = -1;
@@ -555,6 +556,23 @@ init_ra ()
       COPY_HARD_REG_SET (hardregs_for_mode[i], rs);
     }

+  CLEAR_HARD_REG_SET (invalid_mode_change_regs);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  if (0)
+  for (i = 0; i < NUM_MACHINE_MODES; i++)
+    {
+      enum machine_mode from = (enum machine_mode) i;
+      enum machine_mode to;
+      for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
+	{
+	  int r;
+	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
+	    if (REG_CANNOT_CHANGE_MODE_P (from, to, r))
+	      SET_HARD_REG_BIT (invalid_mode_change_regs, r);
+	}
+    }
+#endif
+
   for (an_unusable_color = 0; an_unusable_color < FIRST_PSEUDO_REGISTER;
        an_unusable_color++)
     if (TEST_HARD_REG_BIT (never_use_colors, an_unusable_color))
@@ -755,7 +773,7 @@ reg_alloc ()
 	 chains per insn, and per regno.  In later passes only update
          that info from the new and modified insns.  */
       df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1,
-		  DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN);
+		  DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN | DF_FOR_REGALLOC);

       if ((debug_new_regalloc & DUMP_DF) != 0)
 	{
Index: ra.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.h,v
retrieving revision 1.5
diff -u -p -r1.5 ra.h
--- ra.h	17 Jan 2003 03:28:09 -0000	1.5
+++ ra.h	7 Mar 2003 16:54:04 -0000
@@ -168,6 +168,11 @@ struct web
      was illegal for hardregs in CLASS_CANNOT_CHANGE_MODE.  */
   unsigned int mode_changed:1;

+  /* Nonzero if some references of this web, where in subreg context,
+     but the actual subreg is already stripped (i.e. we don't know the
+     outer mode of the actual reference).  */
+  unsigned int subreg_stripped:1;
+
   /* Nonzero, when this web stems from the last pass of the allocator,
      and all info is still valid (i.e. it wasn't spilled).  */
   unsigned int old_web:1;
@@ -497,6 +502,8 @@ extern unsigned int num_free_regs[N_REG_
    represent the possible resources which could be taken away be a value
    in mode M.  */
 extern HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+/* The set of hardregs, for which _any_ mode change is invalid.  */
+extern HARD_REG_SET invalid_mode_change_regs;
 /* For 0 <= I <= 255, the number of bits set in I.  Used to calculate
    the number of set bits in a HARD_REG_SET.  */
 extern unsigned char byte2bitcount[256];


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