mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-18 01:41:13 +00:00
[qfcc] Merge code blocks more aggressively
The merge_blocks function wasn't reporting whether it had done anything so the thread/merge/dead blocks loop was bailing early. With this, simple functions (ie, no control flow) are fully visible to the CSE optimizer and it can get quite aggressive (removed 3 assignments and a cross product from my barycenter test code).
This commit is contained in:
parent
6096edb1ca
commit
51fbdfe87d
1 changed files with 11 additions and 9 deletions
|
@ -2333,17 +2333,18 @@ move_code (sblock_t *dst, sblock_t *src)
|
||||||
src->tail = &src->statements;
|
src->tail = &src->statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sblock_t *
|
static int
|
||||||
merge_blocks (sblock_t *blocks)
|
merge_blocks (sblock_t **blocks)
|
||||||
{
|
{
|
||||||
sblock_t **sb;
|
sblock_t **sb;
|
||||||
sblock_t *sblock;
|
sblock_t *sblock;
|
||||||
statement_t *s;
|
statement_t *s;
|
||||||
|
int did_something = 0;
|
||||||
|
|
||||||
if (!blocks)
|
if (!*blocks)
|
||||||
return blocks;
|
return did_something;
|
||||||
// merge any blocks that can be merged
|
// merge any blocks that can be merged
|
||||||
for (sblock = blocks; sblock; sblock = sblock->next) {
|
for (sblock = *blocks; sblock; sblock = sblock->next) {
|
||||||
if (sblock->statements && sblock->next) {
|
if (sblock->statements && sblock->next) {
|
||||||
s = (statement_t *) sblock->tail;
|
s = (statement_t *) sblock->tail;
|
||||||
// func and flow statements end blocks
|
// func and flow statements end blocks
|
||||||
|
@ -2354,9 +2355,10 @@ merge_blocks (sblock_t *blocks)
|
||||||
continue;
|
continue;
|
||||||
// blocks can be merged
|
// blocks can be merged
|
||||||
move_code (sblock, sblock->next);
|
move_code (sblock, sblock->next);
|
||||||
|
did_something = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (sb = &blocks; (*sb)->next;) {
|
for (sb = blocks; (*sb)->next;) {
|
||||||
if (!(*sb)->statements) {
|
if (!(*sb)->statements) {
|
||||||
// empty non-final block
|
// empty non-final block
|
||||||
// move labels from empty block to next block
|
// move labels from empty block to next block
|
||||||
|
@ -2370,7 +2372,7 @@ merge_blocks (sblock_t *blocks)
|
||||||
sb = &(*sb)->next;
|
sb = &(*sb)->next;
|
||||||
}
|
}
|
||||||
// so long as blocks doesn't become null, remove an empty final block
|
// so long as blocks doesn't become null, remove an empty final block
|
||||||
if (sb != &blocks) {
|
if (sb != blocks) {
|
||||||
if (!(*sb)->statements && !(*sb)->labels) {
|
if (!(*sb)->statements && !(*sb)->labels) {
|
||||||
// empty final block with no labels
|
// empty final block with no labels
|
||||||
sblock = *sb;
|
sblock = *sb;
|
||||||
|
@ -2378,7 +2380,7 @@ merge_blocks (sblock_t *blocks)
|
||||||
free_sblock (sblock);
|
free_sblock (sblock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return blocks;
|
return did_something;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2653,7 +2655,7 @@ make_statements (expr_t *e)
|
||||||
if (options.block_dot.thread)
|
if (options.block_dot.thread)
|
||||||
dump_dot (va (0, "thread-%d", pass), sblock, dump_dot_sblock);
|
dump_dot (va (0, "thread-%d", pass), sblock, dump_dot_sblock);
|
||||||
did_something |= remove_dead_blocks (sblock);
|
did_something |= remove_dead_blocks (sblock);
|
||||||
sblock = merge_blocks (sblock);
|
did_something |= merge_blocks (&sblock);
|
||||||
if (options.block_dot.dead)
|
if (options.block_dot.dead)
|
||||||
dump_dot (va (0, "dead-%d", pass), sblock, dump_dot_sblock);
|
dump_dot (va (0, "dead-%d", pass), sblock, dump_dot_sblock);
|
||||||
pass++;
|
pass++;
|
||||||
|
|
Loading…
Reference in a new issue