summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv50/nv50_pc_regalloc.c
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-08-10 17:36:25 +0200
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-08-10 17:36:25 +0200
commit3a68fcfb6b406cf864afbf200e436fc384fd0865 (patch)
tree84e21b6659361cfa6c202c097256365faf97c45c /src/gallium/drivers/nv50/nv50_pc_regalloc.c
parentfc1d72d15d929b629be399d977ad05611f01fc59 (diff)
nv50: begin implementing loops
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_pc_regalloc.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_pc_regalloc.c52
1 files changed, 25 insertions, 27 deletions
diff --git a/src/gallium/drivers/nv50/nv50_pc_regalloc.c b/src/gallium/drivers/nv50/nv50_pc_regalloc.c
index 172e44f62b..d45dd7f95f 100644
--- a/src/gallium/drivers/nv50/nv50_pc_regalloc.c
+++ b/src/gallium/drivers/nv50/nv50_pc_regalloc.c
@@ -358,6 +358,18 @@ try_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b)
do_join_values(ctx, a, b);
}
+static INLINE boolean
+need_new_else_block(struct nv_basic_block *b, struct nv_basic_block *p)
+{
+ int i = 0, n = 0;
+
+ for (; i < 2; ++i)
+ if (p->out[i] && p->out_kind[i] != CFG_EDGE_LOOP_LEAVE)
+ ++n;
+
+ return (b->num_in > 1) && (n == 2);
+}
+
/* For each operand of each PHI in b, generate a new value by inserting a MOV
* at the end of the block it is coming from and replace the operand with its
* result. This eliminates liveness conflicts and enables us to let values be
@@ -377,7 +389,7 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b)
p = pn = b->in[n];
assert(p);
- if (b->num_in > 1 && p->out[0] && p->out[1]) {
+ if (need_new_else_block(b, p)) {
pn = new_basic_block(ctx->pc);
if (p->out[0] == b)
@@ -481,32 +493,19 @@ pass_join_values(struct nv_pc_pass *ctx, int iter)
}
/* Order the instructions so that live intervals can be expressed in numbers. */
-static int
-pass_order_instructions(struct nv_pc_pass *ctx, struct nv_basic_block *b)
+static void
+pass_order_instructions(void *priv, struct nv_basic_block *b)
{
+ struct nv_pc_pass *ctx = (struct nv_pc_pass *)priv;
struct nv_instruction *i;
- b->priv = 0;
+ b->pass_seq = ctx->pc->pass_seq;
assert(!b->exit || !b->exit->next);
for (i = b->phi; i; i = i->next) {
i->serial = ctx->num_insns;
ctx->insns[ctx->num_insns++] = i;
}
-
- b->pass_seq = ctx->pc->pass_seq;
-
- if (!b->out[0])
- return 0;
- if (!b->out[1] && ++(b->out[0]->priv) != b->out[0]->num_in)
- return 0;
-
- if (b->out[0] != b)
- pass_order_instructions(ctx, b->out[0]);
- if (b->out[1] && b->out[1] != b)
- pass_order_instructions(ctx, b->out[1]);
-
- return 0;
}
static void
@@ -691,13 +690,15 @@ pass_build_intervals(struct nv_pc_pass *ctx, struct nv_basic_block *b)
}
/* remaining live-outs are live until the end */
- for (j = 0; j < ctx->pc->num_values; ++j) {
- if (!(b->live_set[j / 32] & (1 << (j % 32))))
- continue;
+ if (b->exit) {
+ for (j = 0; j < ctx->pc->num_values; ++j) {
+ if (!(b->live_set[j / 32] & (1 << (j % 32))))
+ continue;
#ifdef NV50_RA_DEBUG_LIVEI
- debug_printf("adding range for live value %i\n", j);
+ debug_printf("adding range for live value %i\n", j);
#endif
- add_range(&ctx->pc->values[j], b, b->exit->serial + 1);
+ add_range(&ctx->pc->values[j], b, b->exit->serial + 1);
+ }
}
debug_printf("%s: looping through instructions now\n", __func__);
@@ -905,10 +906,7 @@ nv_pc_exec_pass1(struct nv_pc *pc)
}
pc->pass_seq++;
- ret = pass_order_instructions(ctx, pc->root);
- assert(!ret && "order instructions");
- if (ret)
- goto out;
+ nv_pc_pass_in_order(pc->root, pass_order_instructions, ctx);
pc->pass_seq++;
ret = pass_build_intervals(ctx, pc->root);