From: Christoph Bumiller Date: Mon, 26 Jul 2010 13:06:58 +0000 (+0200) Subject: nv50: fix for empty BBs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=582311ca979ac2316807cdffb15e7a25000693f4;p=mesa.git nv50: fix for empty BBs --- diff --git a/src/gallium/drivers/nv50/nv50_pc.c b/src/gallium/drivers/nv50/nv50_pc.c index e09f94074d0..0e8aadf5a90 100644 --- a/src/gallium/drivers/nv50/nv50_pc.c +++ b/src/gallium/drivers/nv50/nv50_pc.c @@ -254,7 +254,7 @@ nv50_emit_program(struct nv_pc *pc) assert(pc->emit == &code[pc->bin_size / 4]); /* XXX: we can do better than this ... */ - if ((pc->emit[-1] & 3) == 3) { + if ((pc->emit[-2] & 2) || (pc->emit[-1] & 3) == 3) { pc->emit[0] = 0xf0000001; pc->emit[1] = 0xe0000000; pc->bin_size += 8; @@ -347,16 +347,16 @@ nvbb_insert_phi(struct nv_basic_block *b, struct nv_instruction *i) b->entry->prev = i; } else { b->entry = i; - b->exit = i; + b->exit = i; } } else { assert(b->entry); if (b->entry->opcode == NV_OP_PHI) { /* insert after entry */ - assert(b->entry == b->exit); + assert(b->entry == b->exit); b->entry->next = i; i->prev = b->entry; b->entry = i; - b->exit = i; + b->exit = i; } else { /* insert before entry */ assert(b->entry->prev && b->exit); i->next = b->entry; @@ -396,12 +396,9 @@ nv_nvi_delete(struct nv_instruction *nvi) debug_printf("REM: "); nv_print_instruction(nvi); - for (j = 0; j < 4; ++j) { - if (!nvi->src[j]) - break; - --(nvi->src[j]->value->refc); - nvi->src[j] = NULL; - } + for (j = 0; j < 5; ++j) + nv_reference(NULL, &nvi->src[j], NULL); + nv_reference(NULL, &nvi->flags_src, NULL); if (nvi->next) nvi->next->prev = nvi->prev; @@ -414,19 +411,16 @@ nv_nvi_delete(struct nv_instruction *nvi) nvi->prev->next = nvi->next; if (nvi == b->entry) { - assert(nvi->opcode != NV_OP_PHI || !nvi->next); - - if (!nvi->next || (nvi->opcode == NV_OP_PHI)) - b->entry = nvi->prev; - else - b->entry = nvi->next; + /* PHIs don't get hooked to b->entry */ + b->entry = nvi->next; + assert(!nvi->prev || nvi->prev->opcode == NV_OP_PHI); } if (nvi == b->phi) { - assert(!nvi->prev); if (nvi->opcode != NV_OP_PHI) - debug_printf("WARN: b->phi points to non-PHI instruction\n"); + debug_printf("NOTE: b->phi points to non-PHI instruction\n"); + assert(!nvi->prev); if (!nvi->next || nvi->next->opcode != NV_OP_PHI) b->phi = NULL; else diff --git a/src/gallium/drivers/nv50/nv50_pc.h b/src/gallium/drivers/nv50/nv50_pc.h index ffcdaf44af5..da3f9847839 100644 --- a/src/gallium/drivers/nv50/nv50_pc.h +++ b/src/gallium/drivers/nv50/nv50_pc.h @@ -402,7 +402,6 @@ nv_reference(struct nv_pc *pc, struct nv_ref **d, struct nv_value *s) ++(s->refc); } } else { - assert(*d); *d = NULL; } } diff --git a/src/gallium/drivers/nv50/nv50_pc_optimize.c b/src/gallium/drivers/nv50/nv50_pc_optimize.c index 107ef0f4bf4..42f3a8634ea 100644 --- a/src/gallium/drivers/nv50/nv50_pc_optimize.c +++ b/src/gallium/drivers/nv50/nv50_pc_optimize.c @@ -122,15 +122,29 @@ nvi_isnop(struct nv_instruction *nvi) static void nv_pc_pass_pre_emission(struct nv_pc *pc, struct nv_basic_block *b) { + struct nv_basic_block *in; struct nv_instruction *nvi, *next; int j; uint size, n32 = 0; b->priv = 0; - if (pc->num_blocks) - b->bin_pos = pc->bb_list[pc->num_blocks - 1]->bin_pos + - pc->bb_list[pc->num_blocks - 1]->bin_size; + for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->bin_size; --j); + if (j >= 0) { + in = pc->bb_list[j]; + + /* check for no-op branches (BRA $PC+8) */ + if (in->exit && in->exit->opcode == NV_OP_BRA && in->exit->target == b) { + in->bin_size -= 8; + pc->bin_size -= 8; + + for (++j; j < pc->num_blocks; ++j) + pc->bb_list[j]->bin_pos -= 8; + + nv_nvi_delete(in->exit); + } + b->bin_pos = in->bin_pos + in->bin_size; + } pc->bb_list[pc->num_blocks++] = b; @@ -183,7 +197,7 @@ nv_pc_pass_pre_emission(struct nv_pc *pc, struct nv_basic_block *b) b->exit->prev->is_long = 1; } } - assert(!b->exit || b->exit->is_long); + assert(!b->entry || (b->exit && b->exit->is_long)); pc->bin_size += b->bin_size *= 4; @@ -194,15 +208,6 @@ nv_pc_pass_pre_emission(struct nv_pc *pc, struct nv_basic_block *b) if (!b->out[1] && ++(b->out[0]->priv) != b->out[0]->num_in) return; -#if 0 - /* delete ELSE branch */ - if (b->entry && - b->entry->opcode == NV_OP_BRA && b->entry->target == b->out[0]) { - nv_nvi_delete(b->entry); - b->bin_size -= 2; - pc->bin_size -= 8; - } -#endif for (j = 0; j < 2; ++j) if (b->out[j] && b->out[j] != b) nv_pc_pass_pre_emission(pc, b->out[j]); diff --git a/src/gallium/drivers/nv50/nv50_pc_print.c b/src/gallium/drivers/nv50/nv50_pc_print.c index 82080779c37..c2c3eb25bcb 100644 --- a/src/gallium/drivers/nv50/nv50_pc_print.c +++ b/src/gallium/drivers/nv50/nv50_pc_print.c @@ -290,6 +290,9 @@ nv_print_instruction(struct nv_instruction *i) */ if (i->def[0]) nv_print_value(i->def[0], NULL, NV_TYPE_ANY); + else + if (i->target) + PRINT(" %s(BB:%i)", orng, i->target->id); else PRINT(" #"); @@ -304,7 +307,5 @@ nv_print_instruction(struct nv_instruction *i) (j == nv50_indirect_opnd(i)) ? i->src[4]->value : NULL); } - if (!i->is_long) - PRINT(" %ss", norm); - PRINT("\n"); + PRINT(" %s%c\n", norm, i->is_long ? 'l' : 's'); }