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]

[new-ra] Bootstrap on amd64 and pentiumpro


Hi,

the branch as is doesn't bootstrap on amd64 and i386 (if configured as 
pentiumpro).  The main issue is the non-handling of 
CANNOT_CHANGE_MODE_CLASS machines, which somewhen got lost.  Hmpf.

There was also a problem that somewhen it deleted insns which have 
sideeffects.

And a third one regarding the acceptance of certain instruction constraint 
wise.  Denis: I now remember (because I rediscovered the bug ;-)) why we 
can't ignore the character after '*'.  We must accept as reload would 
(which ignores '*').  The actual problem is move patterns.  For amd64 the 
SSE moves are implemented by hiding the 'Y' constraint after '*', so it 
doesn't get accidentially taken up by regclass to influence register 
choices.

But if we ignore them also in pre-reload we have no way anymore to move 
something in or out of SSE registers (because at least the mov insns must 
work).

And a last thing is, that pre-reload sometimes has to create a subreg of 
pseudo as scratch operand, so we have to accept this during newra.

Anyway the branch now bootstraps on amd64 and i386.


Ciao,
Michael.
-- 
        * df.c (df_def_record_1, df_uses_record): Set DF_REF_MODE_CHANGE.
        * pre-reload.c (scan_alternative): Don't ignore characters after '*'.
        (scan_alternative): Use pre_operands_match_p, handle other
        direction too.
        * ra-build.c (select_regclass): Use ALL_REGS for nonreferenced webs.
        Move never_use_colors intersection down.  Handle
        CANNOT_CHANGE_MODE_CLASS machines.
        (calc_pref_class): Use invalid_mode_change_regs instead predicate.
        * ra-rewrite.c (assign_stack_slots_1): Don't delete complicated
        insns.
        (web_class_spill_ref): Handle the case of multiple uses and defs
        in one insns.  Handle defs and uses by the same code.
        * ra.c (init_ra): Calculate invalid_mode_change_regs at all
        and correctly.
        * recog.c (scratch_operand): During register allocation accept

? .ra-build.c.swp
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.1.2.26
diff -u -p -r1.1.2.26 df.c
--- df.c	6 Nov 2003 17:07:02 -0000	1.1.2.26
+++ df.c	5 Apr 2004 08:28:54 -0000
@@ -928,6 +928,9 @@ df_def_record_1 (struct df *df, rtx x, b
       return;
     }
 
+  if (GET_CODE (dst) == SUBREG)
+    flags |= DF_REF_MODE_CHANGE;
+
   /* Maybe, we should flag the use of STRICT_LOW_PART somehow.  It might
      be handy for the reg allocator.  */
   while (GET_CODE (dst) == STRICT_LOW_PART
@@ -943,6 +946,8 @@ df_def_record_1 (struct df *df, rtx x, b
 	  loc = &XEXP (dst, 0);
 	  dst = *loc;
 	}
+      if (GET_CODE (dst) == SUBREG)
+	flags |= DF_REF_MODE_CHANGE;
       loc = &XEXP (dst, 0);
       dst = *loc;
       flags |= DF_REF_READ_WRITE;
@@ -1033,6 +1038,7 @@ df_uses_record (struct df *df, rtx *loc,
 	  df_uses_record (df, loc, ref_type, bb, insn, flags);
 	  return;
 	}
+      flags |= DF_REF_MODE_CHANGE;
       /* ... Fall through ...  */
 
     case REG:
@@ -1053,7 +1059,7 @@ df_uses_record (struct df *df, rtx *loc,
 	      if ((df->flags & DF_FOR_REGALLOC) == 0
                   && read_modify_subreg_p (dst))
 		{
-		  use_flags = DF_REF_READ_WRITE;
+		  use_flags = DF_REF_READ_WRITE | DF_REF_MODE_CHANGE;
 		  df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
 				  insn, use_flags);
 		  break;
@@ -1074,7 +1080,7 @@ df_uses_record (struct df *df, rtx *loc,
 	      dst = XEXP (dst, 0);
 	      if (GET_CODE (dst) != SUBREG)
 		abort ();
-	      use_flags = DF_REF_READ_WRITE;
+	      use_flags = DF_REF_READ_WRITE | DF_REF_MODE_CHANGE;
 	      df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
 			     insn, use_flags);
 	      break;
Index: pre-reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/pre-reload.c,v
retrieving revision 1.1.2.23
diff -u -p -r1.1.2.23 pre-reload.c
--- pre-reload.c	5 Mar 2004 06:05:30 -0000	1.1.2.23
+++ pre-reload.c	5 Apr 2004 08:28:54 -0000
@@ -2366,9 +2366,10 @@ scan_alternative (this_alt, constraints,
 	    c = '\0';
 	    break;
 
-	  case '=':  case '+':
+	  case '=':  case '+':  case '*':
 	    break;
 		
+#if 0
 	  case '*':
           /* Ignore next constraint because it's reloading.
              It's not a regclass.  */
@@ -2377,6 +2378,7 @@ scan_alternative (this_alt, constraints,
           if (c && c != ',')
             len = CONSTRAINT_LEN (c, p);
 	    break;
+#endif
 
 	  case '%':
 	    /* The last operand should not be marked commutative.  */
@@ -2802,8 +2804,13 @@ scan_alternative (this_alt, constraints,
 		/* Don't coutn an input operand that is constrained to match
 		   the early clobber operand.  */
 		&& ! (this_alt[j].matches == i
-		      && rtx_equal_p (recog_data.operand[i],
-				      recog_data.operand[j]))
+		      && pre_operands_match_p (recog_data.operand[i],
+					       recog_data.operand[j]))
+		/* Similarly if the output operand is constrained to match
+		   the input operand.  This can only happen for clobbers.  */
+		&& ! (this_alt[i].matches == j
+		      && pre_operands_match_p (recog_data.operand[i],
+		      			       recog_data.operand[j]))
 		/* Is it altered by storing the earlyclobber operand?  */
 		&& !pre_reload_immune_p (recog_data.operand[j],
 					 recog_data.operand[i],
Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-build.c,v
retrieving revision 1.1.2.27
diff -u -p -r1.1.2.27 ra-build.c
--- ra-build.c	5 Mar 2004 06:05:30 -0000	1.1.2.27
+++ ra-build.c	5 Apr 2004 08:28:54 -0000
@@ -3092,12 +3092,6 @@ select_regclass ()
 				[reg_alternate_class (web->regno)]);
 	    }
 	}
-      /* add_hardregs is wrong in multi-length classes, e.g.
-	 using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
-	 where, if it finally is allocated to GENERAL_REGS it needs two,
-	 if allocated to FLOAT_REGS only one hardreg.  XXX */
-      AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
-
       /* Don't limit usable regs for uninitialized webs too much.
 	 This could make us spill them (when usable_regs becomes empty
 	 if we also remove caller saved regs),
@@ -3110,6 +3104,15 @@ select_regclass ()
       if (!web->num_defs)
 	IOR_HARD_REG_SET (web->usable_regs,
 			  reg_class_contents[(int) GENERAL_REGS]);
+
+      /* XXX A non referenced web sometimes happens when we were able to
+	 remove all references by rematerialization.  We shouldn't even
+	 try to color them or look at them at all, but for now we simply
+	 make sure they can be colored to something.  */
+      if (web->num_defs == 0 && web->num_uses == 0)
+	IOR_HARD_REG_SET (web->usable_regs,
+			  reg_class_contents[(int) ALL_REGS]);
+
       if (web->crosses_call)
 	{
 	  unsigned int num_refs = web->num_uses + web->num_defs;
@@ -3137,12 +3140,13 @@ select_regclass ()
 
       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
 
+      AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
+
       if ((web->spill_temp == 1 || web->spill_temp == 2)
 	  && ! web->changed
 	  && ! flag_ra_pre_reload)
@@ -3171,6 +3175,10 @@ found:
 	    }
 	}
 
+      /* add_hardregs is wrong in multi-length classes, e.g.
+	 using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
+	 where, if it finally is allocated to GENERAL_REGS it needs two,
+	 if allocated to FLOAT_REGS only one hardreg.  XXX */
       web->add_hardregs
 	  = CLASS_MAX_NREGS (web->regclass,
 			     web->parent_web
@@ -4004,8 +4012,8 @@ calc_pref_class (struct costs *p, struct
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
         || (web->mode_changed
-            && invalid_mode_change_p (web->regno, (enum reg_class) class,
-                                      mode))
+            && hard_regs_intersect_p (&invalid_mode_change_regs,
+				      &reg_class_contents[class]))
 #endif
         )
       ;
Index: ra-rewrite.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-rewrite.c,v
retrieving revision 1.1.2.27
diff -u -p -r1.1.2.27 ra-rewrite.c
--- ra-rewrite.c	13 Nov 2003 19:02:01 -0000	1.1.2.27
+++ ra-rewrite.c	5 Apr 2004 08:28:54 -0000
@@ -2674,9 +2674,18 @@ assign_stack_slots_1 ()
 	  unsigned int i;
 	  rtx dead = DF_REF_INSN (web->defs[0]);
 	  struct ra_insn_info *info = &insn_df[INSN_UID (dead)];
+	  rtx set;
 
-	  if (info->num_defs != 1 || GET_CODE (dead) != INSN
-	      || can_throw_internal (dead))
+	  /* This web only has one definition and the insn also only one
+	     def.  But we really have to test if the only set in that insn
+	     indeed sets a reg, because otherwise it could be a clobber and
+	     the real set does change memory.  We can't delete such insns.  */
+	  if (info->num_defs != 1
+	      || !(set = single_set (dead))
+	      || !REG_P (SET_DEST (set))
+	      || volatile_refs_p (SET_SRC (set))
+	      || can_throw_internal (dead)
+	      || (flag_non_call_exceptions && may_trap_p (dead)))
 	    continue;
 	  for (i = 0; i < info->num_uses; ++i)
 	    {
@@ -4063,120 +4072,106 @@ web_class_spill_ref (web, ref)
 {
   rtx insns;
   rtx insn = DF_REF_INSN (ref);
-
-  if (DF_REF_REG_USE_P (ref))
-    {
-      int num_refs;
-      int i, j;
-      rtx source, target;
-      struct ref **refs;
-      rtx def_dst = NULL;
-      rtx def_src = NULL;
-      rtx reg = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
-      basic_block bb = BLOCK_FOR_INSN (insn);
-
-      for (i = 0, refs = web->uses, num_refs = web->num_uses;
-	   i < 2;
-	   refs = web->defs, num_refs = web->num_defs, i++)
-	for (j = 0; j < num_refs; j++)
-	  {
-	    if (DF_REF_INSN (refs[j]) != insn)
-	      continue;
-	      
-	    target = DF_REF_REG (refs[j]);
-	    source = reg;
-
-	    if (GET_CODE (target) == SUBREG)
-	      source = simplify_gen_subreg (GET_MODE (target), source,
-					    GET_MODE (source),
-					    SUBREG_BYTE (target));
-	    ra_validate_change (insn, DF_REF_LOC (refs[j]), source, 1);
-	    if (i == 1) /* This is a def.  */
-	      {
-		if (def_src)
-		  abort ();
-		def_src = source;
-		def_dst = DF_REF_REG (refs[j]);
-	      }
-	  }
-      if (!ra_apply_change_group ())
-	abort ();
-
-      df_insn_modify (df, bb, insn);
-      bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
-
-      start_sequence ();
-      ra_emit_move_insn (reg, web->orig_x);
-      insns = get_insns ();
-      end_sequence ();
-      if (insns)
-	{
-	  rtx pi;
-	  rtx aux_insn = PREV_INSN (insn);
-	  emit_insn_before (insns, insn);
-	  if (bb->head == insn)
-	    bb->head = NEXT_INSN (aux_insn);
-	  for (pi = PREV_INSN (insn); pi != aux_insn;
-	       pi = PREV_INSN (pi))
+  int num_refs;
+  int i, j;
+  struct ref **refs;
+  rtx *new_defs, *new_uses;
+  int ind_defs = 0, ind_uses = 0;
+  rtx reg = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
+  basic_block bb = BLOCK_FOR_INSN (insn);
+
+  new_defs = alloca (2 * (web->num_defs + web->num_uses)
+		     * sizeof (new_defs[0]));
+  new_uses = alloca (2 * (web->num_defs + web->num_uses)
+		     * sizeof (new_uses[0]));
+  for (i = 0, refs = web->uses, num_refs = web->num_uses;
+       i < 2;
+       refs = web->defs, num_refs = web->num_defs, i++)
+    for (j = 0; j < num_refs; j++)
+      if (DF_REF_INSN (refs[j]) == insn)
+	{
+	  rtx target = DF_REF_REG (refs[j]);
+	  rtx source = reg;
+
+	  if (GET_CODE (target) == SUBREG)
+	    source = simplify_gen_subreg (GET_MODE (target), source,
+					  GET_MODE (source),
+					  SUBREG_BYTE (target));
+	  ra_validate_change (insn, DF_REF_LOC (refs[j]), source, 1);
+	  if (i == 0)
+	    /* A use.  */
 	    {
-	      set_block_for_insn (pi, bb);
-	      df_insn_modify (df, bb, pi);
-	      bitmap_set_bit (ra_modified_insns, INSN_UID (pi));
+	      /* Full REGs come first.  */
+	      if (GET_CODE (target) == REG)
+		new_uses[0] = source, new_uses[1] = target, ind_uses = 1;
+	      else if (ind_uses == 0 || GET_CODE (new_uses[0]) == SUBREG)
+		/* Otherwise if we are a SUBREG add us only if there's
+		   not already a full REG in the first position.  */
+		{
+		  new_uses[2 * ind_uses] = copy_rtx (source);
+		  new_uses[2 * ind_uses + 1] = copy_rtx (target);
+		  ind_uses++;
+		}
 	    }
-	}
-
-      if (def_src)
-	{
-	  start_sequence ();
-	  ra_emit_move_insn (def_dst, copy_rtx (def_src));
-	  insns = get_insns ();
-	  end_sequence ();
-	  if (insns)
+	  else
+	    /* A def.  */
 	    {
-	      rtx ni;
-	      rtx aux_insn = NEXT_INSN (insn);
-	      emit_insn_after (insns, insn);
-	      if (bb->end == insn)
-		bb->end = PREV_INSN (aux_insn);
-	      for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
+	      if (GET_CODE (target) == REG)
+		new_defs[0] = source, new_defs[1] = target, ind_defs = 1;
+	      else if (ind_defs == 0 || GET_CODE (new_defs[0]) == SUBREG)
+		/* Otherwise if we are a SUBREG add us only if there's
+		   not already a full REG in the first position.  */
 		{
-		  set_block_for_insn (ni, bb);
-		  df_insn_modify (df, bb, ni);
-		  bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
+		  new_defs[2 * ind_defs] = copy_rtx (source);
+		  new_defs[2 * ind_defs + 1] = copy_rtx (target);
+		  ind_defs++;
 		}
 	    }
 	}
+  if (!ra_apply_change_group ())
+    abort ();
+
+  df_insn_modify (df, bb, insn);
+  bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
+
+  start_sequence ();
+  for (i = 0; i < ind_uses; i++)
+    ra_emit_move_insn (new_uses[2 * i], new_uses[2 * i + 1]);
+  insns = get_insns ();
+  end_sequence ();
+  if (insns)
+    {
+      rtx pi;
+      rtx aux_insn = PREV_INSN (insn);
+      emit_insn_before (insns, insn);
+      if (bb->head == insn)
+	bb->head = NEXT_INSN (aux_insn);
+      for (pi = PREV_INSN (insn); pi != aux_insn;
+	   pi = PREV_INSN (pi))
+	{
+	  set_block_for_insn (pi, bb);
+	  df_insn_modify (df, bb, pi);
+	  bitmap_set_bit (ra_modified_insns, INSN_UID (pi));
+	}
     }
-  else if (DF_REF_REG_DEF_P (ref))
+
+  start_sequence ();
+  for (i = 0; i < ind_defs; i++)
+    ra_emit_move_insn (new_defs[2 * i + 1], new_defs[2 * i]);
+  insns = get_insns ();
+  end_sequence ();
+  if (insns)
     {
+      rtx ni;
       rtx aux_insn = NEXT_INSN (insn);
-      rtx reg = gen_reg_rtx (GET_MODE (DF_REF_REG (ref)));
-      basic_block bb = BLOCK_FOR_INSN (insn);
-      
-      if (ra_validate_change (insn, DF_REF_LOC (ref), reg, 0))
+      emit_insn_after (insns, insn);
+      if (bb->end == insn)
+	bb->end = PREV_INSN (aux_insn);
+      for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
 	{
-	  df_insn_modify (df, bb, insn);
-	  bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
-	}
-      else
-	abort ();
-
-      start_sequence ();
-      ra_emit_move_insn (DF_REF_REG (ref), reg);
-      insns = get_insns ();
-      end_sequence ();
-      if (insns)
-	{
-	  rtx ni;
-	  emit_insn_after (insns, insn);
-	  if (bb->end == insn)
-	    bb->end = PREV_INSN (aux_insn);
-	  for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
-	    {
-	      set_block_for_insn (ni, bb);
-	      df_insn_modify (df, bb, ni);
-	      bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
-	    }
+	  set_block_for_insn (ni, bb);
+	  df_insn_modify (df, bb, ni);
+	  bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
 	}
     }
 }
Index: ra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.c,v
retrieving revision 1.1.2.77
diff -u -p -r1.1.2.77 ra.c
--- ra.c	5 Mar 2004 06:05:30 -0000	1.1.2.77
+++ ra.c	5 Apr 2004 08:28:54 -0000
@@ -233,7 +233,7 @@ hard_regs_count (HARD_REG_SET rs)
 
 /* Basically like emit_move_insn (i.e. validifies constants and such),
    but also handle MODE_CC moves (but then the operands must already
-   be basically valid.  */
+   be basically valid).  */
 
 rtx
 ra_emit_move_insn (rtx x, rtx y)
@@ -634,7 +634,6 @@ init_ra (void)
 
   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;
@@ -643,7 +642,7 @@ init_ra (void)
 	{
 	  int r;
 	  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-	    if (REG_CANNOT_CHANGE_MODE_P (from, to, r))
+	    if (REG_CANNOT_CHANGE_MODE_P (r, from, to))
 	      SET_HARD_REG_BIT (invalid_mode_change_regs, r);
 	}
     }
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.87.2.10
diff -u -p -r1.87.2.10 recog.c
--- recog.c	10 Oct 2003 14:19:02 -0000	1.87.2.10
+++ recog.c	5 Apr 2004 08:28:54 -0000
@@ -1092,7 +1092,8 @@ scratch_operand (rtx op, enum machine_mo
   return (GET_CODE (op) == SCRATCH
 	  || (GET_CODE (op) == REG
 	      && (REGNO (op) < FIRST_PSEUDO_REGISTER || while_newra
-	          || (newra_in_progress && !SPILL_SLOT_P (REGNO (op))))));
+	          || (newra_in_progress && !SPILL_SLOT_P (REGNO (op)))))
+	  || (while_newra && GET_CODE (op) == SUBREG));
 }
 
 /* Return 1 if OP is a valid immediate operand for mode MODE.


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