cvsuser 04/12/10 21:38:37
Modified: imcc pcc.c reg_alloc.c
imcc/t/reg spill.t
Log:
[perl #32996] Register coloring not dirtying registers for method
calls properly
* backport preserved register check from new allocator
* work around continuation bug by allocating temps 16..5
* add bug code as a test case
Revision Changes Path
1.85 +0 -2 parrot/imcc/pcc.c
Index: pcc.c
===================================================================
RCS file: /cvs/public/parrot/imcc/pcc.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -r1.84 -r1.85
--- pcc.c 7 Dec 2004 10:50:38 -0000 1.84
+++ pcc.c 11 Dec 2004 05:38:35 -0000 1.85
@@ -449,8 +449,6 @@
sprintf(buf, "%d", CURRENT_OBJECT);
regs[1] = get_const(interp, buf, 'I');
ins = insINS(interp, unit, ins, "interpinfo", regs, 2);
- regs[1] = get_pasm_reg(interp, "P2");
- ins = insINS(interp, unit, ins, "set", regs, 2);
}
/*
* check if there is a return
1.27 +66 -33 parrot/imcc/reg_alloc.c
Index: reg_alloc.c
===================================================================
RCS file: /cvs/public/parrot/imcc/reg_alloc.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- reg_alloc.c 30 Nov 2004 10:28:51 -0000 1.26
+++ reg_alloc.c 11 Dec 2004 05:38:35 -0000 1.27
@@ -41,7 +41,7 @@
static void compute_du_chain(IMC_Unit * unit);
static void compute_one_du_chain(SymReg * r, IMC_Unit * unit);
static int interferes(Interp *, IMC_Unit *, SymReg * r0, SymReg * r1);
-static int map_colors(IMC_Unit *, int x, unsigned int * graph, int colors[],
int typ);
+static void map_colors(IMC_Unit *, int x, unsigned int * graph, char
colors[], int typ);
#ifdef DO_SIMPLIFY
static int simplify (IMC_Unit *);
#endif
@@ -893,6 +893,48 @@
}
}
/*
+ * find available color for register #x in available colors
+ */
+static int
+ig_find_color(Interp* interpreter, IMC_Unit *unit, int x, char *avail)
+{
+ int c, t;
+ SymReg *r;
+ static const char types[] = "ISPN";
+
+ static const char assignable[4][5] = {
+ /* 0 1 2 3 4 */
+ { 0, 0, 0, 0, 0, }, /* I */
+ { 0, 1, 1, 1, 1, }, /* S */
+ { 0, 0, 0, 1, 1, }, /* P */
+ { 1, 1, 1, 1, 1, }, /* N */
+ };
+
+
+ UNUSED(interpreter);
+ r = unit->reglist[x];
+ t = strchr(types, r->set) - types;
+
+ /* please note: c is starting at 1 for R0 */
+ if (!(r->usage & U_NON_VOLATILE)) {
+ /* 1) 5-15 volatile range
+ * XXX allocate down to work around continuation bug
+ * */
+ for (c = 16; c >= 6; c--)
+ if (avail[c])
+ return c;
+ /* some lower regs are usable too 0...4 */
+ for (c = 1; c <= 5; c++)
+ if (avail[c] && assignable[t][c - 1])
+ return c;
+ }
+ /* 2) try upper non-volatiles, 16...31 */
+ for (c = 17; c <= 32; c++)
+ if (avail[c])
+ return c;
+ return 0;
+}
+/*
* Color the graph assigning registers to each symbol:
*
* We just proceed poping items from the stack, and assigning
@@ -905,8 +947,9 @@
try_allocate(Parrot_Interp interpreter, IMC_Unit * unit)
{
int x = 0;
- int color, colors[MAX_COLOR];
- int free_colors, t;
+ int color;
+ char avail[MAX_COLOR + 1];
+ int t;
unsigned int *graph = unit->interference_graph;
SymReg ** reglist = unit->reglist;
@@ -915,28 +958,23 @@
for (t = 0; t < 4; t++) {
int typ = "INSP"[t];
- memset(colors, 0, sizeof(colors));
if (reglist[x]->set == typ && reglist[x]->color == -1) {
- free_colors = map_colors(unit, x, graph, colors, typ);
- if (free_colors > 0) {
- for (color = 0; color < MAX_COLOR; color++) {
- int c = (color + MAX_COLOR/2) % MAX_COLOR;
- if (!colors[c]) {
- reglist[x]->color = c;
-
- IMCC_debug(interpreter, DEBUG_IMC,
- "#[%s] provisionally gets color [%d]"
- "(%d free colors, score %d)\n",
- reglist[x]->name, c,
- free_colors, reglist[x]->score);
- break;
- }
- }
+ map_colors(unit, x, graph, avail, typ);
+ color = ig_find_color(interpreter, unit, x, avail);
+ if (color) {
+ reglist[x]->color = color - 1;
+
+ IMCC_debug(interpreter, DEBUG_IMC,
+ "#[%s] provisionally gets color [%d]"
+ "(score %d)\n",
+ reglist[x]->name, color - 1,
+ reglist[x]->score);
+ break;
}
if (reglist[x]->color == -1) {
IMCC_debug(interpreter, DEBUG_IMC,
- "# no more colors free = %d\n", free_colors);
+ "# no more colors\n");
/* It has been impossible to assign a color
* to this node, return it so it gets spilled
@@ -958,22 +996,21 @@
/*
* map_colors: calculates what colors can be assigned to the x-th symbol.
*/
-static int
-map_colors(IMC_Unit* unit, int x, unsigned int *graph, int colors[], int typ)
+static void
+map_colors(IMC_Unit* unit, int x, unsigned int *graph, char avail[], int typ)
{
int y = 0, n_symbols;
SymReg * r;
- int color, free_colors;
n_symbols = unit->n_symbols;
- memset(colors, 0, sizeof(colors[0]) * MAX_COLOR);
+ memset(avail, 1, MAX_COLOR + 1);
/* reserved for spilling */
if (typ == 'P')
- colors[31] = 1;
+ avail[31+1] = 0;
#ifdef ALLOCATE_HACK
- colors[28] = 1; /* for immediate allocation */
- colors[29] = 1; /* for immediate allocation */
- colors[30] = 1; /* for immediate allocation */
+ avail[28+1] = 0; /* for immediate allocation */
+ avail[29+1] = 0; /* for immediate allocation */
+ avail[30+1] = 0; /* for immediate allocation */
#endif
for (y = 0; y < n_symbols; y++) {
if (! ig_test(x, y, n_symbols, graph))
@@ -982,13 +1019,9 @@
if ( r
&& r->color != -1
&& r->set == typ) {
- colors[r->color] = 1;
+ avail[r->color+1] = 0;
}
}
- for (color = free_colors = 0; color < MAX_COLOR; color++)
- if (!colors[color])
- free_colors++;
- return free_colors;
}
#if ! DOIT_AGAIN_SAM
1.9 +176 -1 parrot/imcc/t/reg/spill.t
Index: spill.t
===================================================================
RCS file: /cvs/public/parrot/imcc/t/reg/spill.t,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- spill.t 5 Aug 2004 09:49:49 -0000 1.8
+++ spill.t 11 Dec 2004 05:38:37 -0000 1.9
@@ -1,6 +1,6 @@
#!perl
use strict;
-use TestCompiler tests => 4;
+use TestCompiler tests => 5;
##############################
@@ -424,3 +424,178 @@
CODE
ok
OUT
+
+output_is(<<'CODE', <<'OUT', "bug #32996");
+
+.namespace ["Foo"]
+
+.sub __biginit prototyped, @MAIN
+ newclass $P0, "Foo"
+ $I1 = find_type "Foo"
+ $P1 = new $I1
+ $P1.method1()
+ $P1.method2()
+
+ $P2 = new $I1
+ $P2.method1()
+ $P2.method2()
+
+ $P3 = new $I1
+ $P3.method1()
+ $P3.method2()
+
+ $P4 = new $I1
+ $P4.method1()
+ $P4.method2()
+
+ $P5 = new $I1
+ $P5.method1()
+ $P5.method2()
+
+ $P6 = new $I1
+ $P6.method1()
+ $P6.method2()
+
+ $P7 = new $I1
+ $P7.method1()
+ $P7.method2()
+
+ $P8 = new $I1
+ $P8.method1()
+ $P8.method2()
+
+ $P9 = new $I1
+ $P9.method1()
+ $P9.method2()
+
+ $P10 = new $I1
+ $P10.method1()
+ $P10.method2()
+
+ $P11 = new $I1
+ $P11.method1()
+ $P11.method2()
+
+ $P12 = new $I1
+ $P12.method1()
+ $P12.method2()
+
+ $P13 = new $I1
+ $P13.method1()
+ $P13.method2()
+
+ $P14 = new $I1
+ $P14.method1()
+ $P14.method2()
+
+ $P15 = new $I1
+ $P15.method1()
+ $P15.method2()
+
+ $P1.method1()
+ $P1.method2()
+ $P2.method1()
+ $P2.method2()
+ $P3.method1()
+ $P3.method2()
+ $P4.method1()
+ $P4.method2()
+ $P5.method1()
+ $P5.method2()
+ $P6.method1()
+ $P6.method2()
+ $P7.method1()
+ $P7.method2()
+ $P8.method1()
+ $P8.method2()
+ $P9.method1()
+ $P9.method2()
+ $P10.method1()
+ $P10.method2()
+ $P11.method1()
+ $P11.method2()
+ $P12.method1()
+ $P12.method2()
+ $P13.method1()
+ $P13.method2()
+ $P14.method1()
+ $P14.method2()
+ $P15.method1()
+ $P15.method2()
+
+ end
+.end
+
+.sub method1 prototyped, method
+ print "In method 1\n"
+ .pcc_begin_return
+ .pcc_end_return
+.end
+
+.sub method2 prototyped, method
+ print "In method 2\n"
+ .pcc_begin_return
+ .pcc_end_return
+.end
+CODE
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+In method 1
+In method 2
+OUT