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]

[new-regalloc-branch]: combine() fix


Hi,

The below diff makes combine also merge usable_regs of both to be combined
webs, and makes the resulting web also use them.  If this isn't done, then
the final web, if it had a broader usable_regs might get a color which
isn't suitable for the other web.  This wouldn't be a problem, because
reload would fix this up.  But when building the graph only conflicts
between webs are noted, which have some hardregs in common.  In result
this means, that the combined web might now might get a color, which
_would_ have made the other web conflicting with more webs, but which in
these circumstance are not in webs2 conflict list, so also not in results
conflict list, which is the error.

This btw. makes SPEC2000's INT-suite run (besides the C++ test eon, which
I usually don't test).  I only run the test workload.  The above error
manifests in 175.vpr/rr_graph2.c.


Ciao,
Michael.

-- 
2001-08-28  Michael Matz  <matzmich@cs.tu-berlin.de>

	* ra.c (combine): Merge usable_regs of both webs.


Index: ra.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/ra.c,v
retrieving revision 1.1.2.35
diff -u -p -c -p -r1.1.2.35 ra.c
*** ra.c	2001/08/28 18:28:15	1.1.2.35
--- ra.c	2001/08/29 23:33:06
*************** alias (web)
*** 2961,2971 ****
    return web;
  }

! /* Actually combine two webs, when they can be coalesced.  */
  static void
  combine (u, v)
       struct web *u, *v;
  {
    struct conflict_link *wl;
    if (v->type == FREEZE)
      remove_list (v->dlink, &freeze_wl);
--- 2961,2972 ----
    return web;
  }

! /* Actually combine two webs, that can be coalesced.  */
  static void
  combine (u, v)
       struct web *u, *v;
  {
+   int i;
    struct conflict_link *wl;
    if (v->type == FREEZE)
      remove_list (v->dlink, &freeze_wl);
*************** combine (u, v)
*** 2979,2985 ****
    /* combine add_hardregs's of U and V.  */
    if (u->type == PRECOLORED)
      {
-       int i;
        struct web *web;

        for (i = 0; i <= v->add_hardregs; ++i)
--- 2980,2985 ----
*************** combine (u, v)
*** 3034,3049 ****
  	  }
        }

    if (u->num_conflicts >= NUM_REGS (u) && u->type == FREEZE)
      {
        remove_list (u->dlink, &freeze_wl);
        put_web (u, SPILL);
      }

-   /* XXX combine the usable_regs together, and adjust the weight and
-      conflict.  As this might constrain more, it might make us uncolorable.
-      I think we should disallow this in conservative test, so only
-      webs with similar constraints are coalesced.  */
    /* If we coalesce a spill temporary together with a normal node,
       the result is not any longer a spill temporary.  */
    if (u->spill_temp && ! v->spill_temp)
--- 3034,3067 ----
  	  }
        }

+   /* Now merge the usable_regs together.  */
+   /* XXX That merging might normally make it necessary to
+      adjust add_hardregs, which also means to adjust neighbors.  This can
+      result in making some more webs trivially colorable, (or the opposite,
+      if this increases our add_hardregs).  Because we intersect the
+      usable_regs it should only be possible to decrease add_hardregs.  So a
+      conservative solution for now is to simply don't change it.  */
+   u->use_my_regs = 1;
+   AND_HARD_REG_SET (u->usable_regs, v->usable_regs);
+   u->regclass = reg_class_subunion[u->regclass][v->regclass];
+   /* Count number of possible hardregs.  This might make U a spillweb,
+      but that could also happen, if U and V together had too many
+      conflicts.  */
+   u->num_freedom = 0;
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     if (TEST_HARD_REG_BIT (u->usable_regs, i))
+       u->num_freedom++;
+   /* The next would mean an invalid coalesced move (both webs have no
+      possible hardreg in common), so abort.  */
+   if (!u->num_freedom)
+     abort();
+
    if (u->num_conflicts >= NUM_REGS (u) && u->type == FREEZE)
      {
        remove_list (u->dlink, &freeze_wl);
        put_web (u, SPILL);
      }

    /* If we coalesce a spill temporary together with a normal node,
       the result is not any longer a spill temporary.  */
    if (u->spill_temp && ! v->spill_temp)


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