Fix END pseudo in util/ego/sr; closes #203
The strength reduction (SR) phase mishandled the END pseudo when SR
found at least 2 different expressions in the same loop, and SR made a
new header for the loop.
Since 1987 (commit 159b84e
), SR appended the new header to the end of
the procedure. Later, SR fixed the header by adding a BRA branch to
the loop's entry, and moving the END pseudo from the previous basic
block to the header. If SR found multiple expressions, it called
fix_header() multiple times, and tried to move the END again. The
extra move failed assert(INSTR(e) == ps_end), or moved another line
after the END, so opt2 (the peephole optimizer) would crash.
Fix by removing fix_header() and moving the code to make_header(), so
SR adds the BRA and moves the END when it makes the header, and does
so only once for each header.
Adjust init_code(), which inserts code into a header. Stop checking
for an empty header, because make_header() now adds BRA. After
inserting code before BRA, don't move LP_INSTR, because later
insertions should go before BRA, not after END.
This commit is contained in:
parent
fc1476c88b
commit
e841adf970
|
@ -171,9 +171,7 @@ STATIC line_p add_code(pl, l)
|
|||
|
||||
|
||||
|
||||
STATIC void init_code(code,tmp)
|
||||
code_p code;
|
||||
offset tmp;
|
||||
STATIC void init_code(code_p code, offset tmp)
|
||||
{
|
||||
/* Generate code to set up the temporary local.
|
||||
* For multiplication, its initial value is const*iv_expr,
|
||||
|
@ -223,21 +221,20 @@ STATIC void init_code(code,tmp)
|
|||
assert(FALSE); /* non-reducible instruction */
|
||||
}
|
||||
PREV(l->l_next) = l;
|
||||
|
||||
/* Now insert the code at the end of the header block */
|
||||
p = &code->co_loop->LP_INSTR;
|
||||
if (*p == (line_p) 0 || (PREV((*p)) == 0 && INSTR((*p)) == op_bra)) {
|
||||
/* LP_INSTR points to last instruction of header block,
|
||||
* so if it is 0, the header block is empty yet.
|
||||
*/
|
||||
code->co_loop->LP_HEADER->b_start =
|
||||
add_code(code->co_loop->LP_HEADER->b_start, code->co_lfirst);
|
||||
} else if (INSTR((*p)) == op_bra) {
|
||||
if (INSTR((*p)) == op_bra) {
|
||||
/* Add code before branching to the loop. */
|
||||
add_code(PREV((*p)), code->co_lfirst);
|
||||
}
|
||||
else add_code(*p, code->co_lfirst);
|
||||
while (l->l_next) l = l->l_next;
|
||||
} else {
|
||||
/* Add code before falling into the loop. */
|
||||
add_code(*p, code->co_lfirst);
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
*p = l; /* new last instruction */
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void incr_code(code,tmp)
|
||||
code_p code;
|
||||
|
@ -453,43 +450,7 @@ STATIC code_p available(c,vars)
|
|||
return (code_p) 0;
|
||||
}
|
||||
|
||||
STATIC void fix_header(lp)
|
||||
loop_p lp;
|
||||
{
|
||||
/* Check if a header block was added, and if so, add a branch to
|
||||
* the entry block.
|
||||
* If it was added, it was added to the end of the procedure, so
|
||||
* move the END pseudo.
|
||||
*/
|
||||
bblock_p b = curproc->p_start;
|
||||
|
||||
if (lp->LP_HEADER->b_next == 0) {
|
||||
line_p l = last_instr(lp->LP_HEADER);
|
||||
line_p e;
|
||||
|
||||
assert(l != 0);
|
||||
if (INSTR(l) != op_bra) {
|
||||
line_p j = newline(OPINSTRLAB);
|
||||
|
||||
assert(INSTR(lp->lp_entry->b_start) == op_lab);
|
||||
INSTRLAB(j) = INSTRLAB(lp->lp_entry->b_start);
|
||||
j->l_instr = op_bra;
|
||||
DLINK(l, j);
|
||||
l = j;
|
||||
}
|
||||
|
||||
while (b->b_next != lp->LP_HEADER) b = b->b_next;
|
||||
e = last_instr(b);
|
||||
assert(INSTR(e) == ps_end);
|
||||
assert(PREV(e) != 0);
|
||||
PREV(e)->l_next = 0;
|
||||
DLINK(l, e);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void reduce(code,vars)
|
||||
code_p code;
|
||||
lset vars;
|
||||
STATIC void reduce(code_p code, lset vars)
|
||||
{
|
||||
/* Perform the actual transformations. The code on the left
|
||||
* gets transformed into the code on the right. Note that
|
||||
|
@ -538,7 +499,6 @@ STATIC void reduce(code,vars)
|
|||
incr_code(code,tmp); /* emit code to increment temp. local */
|
||||
OUTTRACE("emitted increment code",0);
|
||||
Ladd(code,&avail);
|
||||
fix_header(code->co_loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,9 +138,7 @@ STATIC void adjust_jump(newtarg,oldtarg,c)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
make_header(lp)
|
||||
loop_p lp;
|
||||
void make_header(loop_p lp)
|
||||
{
|
||||
/* Make sure that the loop has a header block, i.e. a block
|
||||
* has the loop entry block as its only successor and
|
||||
|
@ -149,6 +147,7 @@ make_header(lp)
|
|||
*/
|
||||
|
||||
bblock_p b,c,entry;
|
||||
line_p branch,last;
|
||||
Lindex i,next;
|
||||
|
||||
if (lp->LP_HEADER != (bblock_p) 0) return;
|
||||
|
@ -160,6 +159,17 @@ make_header(lp)
|
|||
b = freshblock(); /* new block with new b_id */
|
||||
entry = lp->lp_entry;
|
||||
|
||||
/* In the header, add a branch from to the entry block. */
|
||||
branch = newline(OPINSTRLAB);
|
||||
assert(INSTR(entry->b_start) == op_lab);
|
||||
INSTRLAB(branch) = INSTRLAB(entry->b_start);
|
||||
branch->l_instr = op_bra;
|
||||
b->b_start = branch;
|
||||
|
||||
/* Plan to insert code before the branch. */
|
||||
assert(lp->LP_INSTR == 0);
|
||||
lp->LP_INSTR = branch;
|
||||
|
||||
/* update succ/pred. Also take care that any jump from outside
|
||||
* the loop to the entry block now goes to b.
|
||||
*/
|
||||
|
@ -180,14 +190,24 @@ make_header(lp)
|
|||
adjust_jump(b,entry,c);
|
||||
}
|
||||
}
|
||||
assert(lp->LP_INSTR == 0);
|
||||
lp->LP_INSTR = b->b_start;
|
||||
|
||||
Ladd(b,&entry->b_pred);
|
||||
Ladd(entry,&b->b_succ);
|
||||
|
||||
/* put header block at end of procedure */
|
||||
for (c = curproc->p_start; c->b_next != 0; c = c->b_next);
|
||||
for (c = curproc->p_start; c->b_next != 0; c = c->b_next)
|
||||
continue;
|
||||
c->b_next = b;
|
||||
/* b->b_next = 0; */
|
||||
|
||||
/* move the END pseudo to header block */
|
||||
last = last_instr(c);
|
||||
assert(INSTR(last) == ps_end);
|
||||
assert(PREV(last) != (line_p) 0);
|
||||
PREV(last)->l_next = 0;
|
||||
DLINK(branch, last);
|
||||
|
||||
/* fix loops and dominance */
|
||||
copy_loops(b,entry,lp);
|
||||
b->b_idom = entry->b_idom;
|
||||
entry->b_idom = b;
|
||||
|
|
Loading…
Reference in a new issue