* SOFTWARE.
*/
+/* #define NV50PC_DEBUG */
+
#include "nv50_pc.h"
#include "nv50_program.h"
return n;
}
+struct nv_value *
+nvcg_find_constant(struct nv_ref *ref)
+{
+ struct nv_value *src;
+
+ if (!ref)
+ return NULL;
+
+ src = ref->value;
+ while (src->insn && src->insn->opcode == NV_OP_MOV) {
+ assert(!src->insn->src[0]->mod);
+ src = src->insn->src[0]->value;
+ }
+ if ((src->reg.file == NV_FILE_IMM) ||
+ (src->insn && src->insn->opcode == NV_OP_LDA &&
+ src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
+ src->insn->src[0]->value->reg.file <= NV_FILE_MEM_C(15)))
+ return src;
+ return NULL;
+}
+
+struct nv_value *
+nvcg_find_immediate(struct nv_ref *ref)
+{
+ struct nv_value *src = nvcg_find_constant(ref);
+
+ return (src && src->reg.file == NV_FILE_IMM) ? src : NULL;
+}
+
static void
nv_pc_free_refs(struct nv_pc *pc)
{
case CFG_EDGE_BACK: return "back";
case CFG_EDGE_LOOP_ENTER: return "loop";
case CFG_EDGE_LOOP_LEAVE: return "break";
+ case CFG_EDGE_FAKE: return "fake";
default:
return "?";
}
case CFG_EDGE_BACK:
continue;
case CFG_EDGE_FORWARD:
+ case CFG_EDGE_FAKE:
if (++b->out[j]->priv == b->out[j]->num_in)
bb[p++] = b->out[j];
break;
f(priv, b);
- if (!p)
- while (pp > 0)
- bb[p++] = bbb[--pp];
+ if (!p) {
+ p = pp;
+ for (; pp > 0; --pp)
+ bb[pp - 1] = bbb[pp - 1];
+ }
}
}
uint32_t *code = pc->emit;
int n;
- debug_printf("emitting program: size = %u\n", pc->bin_size);
+ NV50_DBGMSG("emitting program: size = %u\n", pc->bin_size);
for (n = 0; n < pc->num_blocks; ++n) {
struct nv_instruction *i;
pc->emit = code;
code[pc->bin_size / 4 - 1] |= 1;
+#ifdef NV50PC_DEBUG
nvcg_show_bincode(pc);
+#endif
return 0;
}
ret = nv50_tgsi_to_nc(pc, ti);
if (ret)
goto out;
+#ifdef NV50PC_DEBUG
nv_print_program(pc->root);
+#endif
/* optimization */
ret = nv_pc_exec_pass0(pc);
if (ret)
goto out;
+#ifdef NV50PC_DEBUG
+ nv_print_program(pc->root);
+#endif
/* register allocation */
ret = nv_pc_exec_pass1(pc);
if (ret)
goto out;
+#ifdef NV50PC_DEBUG
+ nv_print_program(pc->root);
+#endif
/* prepare for emission */
ret = nv_pc_exec_pass2(pc);
ti->p->fixups = pc->fixups;
ti->p->num_fixups = pc->num_fixups;
- debug_printf("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
+ NV50_DBGMSG("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
out:
nv_pc_free_refs(pc);
if (nvi == b->phi) {
if (nvi->opcode != NV_OP_PHI)
- debug_printf("NOTE: b->phi points to non-PHI instruction\n");
+ NV50_DBGMSG("NOTE: b->phi points to non-PHI instruction\n");
assert(!nvi->prev);
if (!nvi->next || nvi->next->opcode != NV_OP_PHI)
if (bp == bt)
return FALSE;
- if (bp->out[0] && bp->out_kind[0] != CFG_EDGE_BACK &&
+ if (bp->out[0] && !IS_WALL_EDGE(bp->out_kind[0]) &&
nvbb_reachable_by(bf, bp->out[0], bt))
return TRUE;
- if (bp->out[1] && bp->out_kind[1] != CFG_EDGE_BACK &&
+ if (bp->out[1] && !IS_WALL_EDGE(bp->out_kind[1]) &&
nvbb_reachable_by(bf, bp->out[1], bt))
return TRUE;
return FALSE;
static struct nv_basic_block *
nvbb_find_dom_frontier(struct nv_basic_block *b, struct nv_basic_block *df)
{
+ struct nv_basic_block *out;
int i;
if (!nvbb_dominated_by(df, b)) {
return df;
}
}
- for (i = 0; i < 2 && b->out[i]; ++i) {
- if (b->out_kind[i] == CFG_EDGE_BACK)
+ for (i = 0; i < 2 && df->out[i]; ++i) {
+ if (df->out_kind[i] == CFG_EDGE_BACK)
continue;
- if ((df = nvbb_find_dom_frontier(b, b->out[i])))
- return df;
+ if ((out = nvbb_find_dom_frontier(b, df->out[i])))
+ return out;
}
return NULL;
}