summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2015-02-19 13:22:31 -0800
committerEric Anholt <[email protected]>2015-02-19 23:35:17 -0800
commit85316d059c899ac096331251de6b233229aa0b4f (patch)
tree27431fdde4bf5bcc03c52b2c3f94c16bb19f04a8 /src/gallium/drivers/vc4
parent877b48a531adc397493e508e509aba2918915349 (diff)
vc4: Keep an array of pointers to instructions defining the temps around.
The optimization passes are always regenerating it and throwing it away, but it's not hard to keep track of.
Diffstat (limited to 'src/gallium/drivers/vc4')
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_algebraic.c73
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_copy_propagation.c9
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_dead_code.c2
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_small_immediates.c6
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_vpm_writes.c12
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.c25
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.h7
-rw-r--r--src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c1
8 files changed, 67 insertions, 68 deletions
diff --git a/src/gallium/drivers/vc4/vc4_opt_algebraic.c b/src/gallium/drivers/vc4/vc4_opt_algebraic.c
index 1e0b8c9c097..d17669abaff 100644
--- a/src/gallium/drivers/vc4/vc4_opt_algebraic.c
+++ b/src/gallium/drivers/vc4/vc4_opt_algebraic.c
@@ -60,7 +60,7 @@ dump_to(struct vc4_compile *c, struct qinst *inst)
}
static bool
-is_constant_value(struct vc4_compile *c, struct qinst **defs, struct qreg reg,
+is_constant_value(struct vc4_compile *c, struct qreg reg,
uint32_t val)
{
if (reg.file == QFILE_UNIF &&
@@ -76,17 +76,17 @@ is_constant_value(struct vc4_compile *c, struct qinst **defs, struct qreg reg,
}
static bool
-is_zero(struct vc4_compile *c, struct qinst **defs, struct qreg reg)
+is_zero(struct vc4_compile *c, struct qreg reg)
{
- reg = qir_follow_movs(defs, reg);
- return is_constant_value(c, defs, reg, 0);
+ reg = qir_follow_movs(c, reg);
+ return is_constant_value(c, reg, 0);
}
static bool
-is_1f(struct vc4_compile *c, struct qinst **defs, struct qreg reg)
+is_1f(struct vc4_compile *c, struct qreg reg)
{
- reg = qir_follow_movs(defs, reg);
- return is_constant_value(c, defs, reg, fui(1.0));
+ reg = qir_follow_movs(c, reg);
+ return is_constant_value(c, reg, fui(1.0));
}
static void
@@ -101,11 +101,10 @@ replace_with_mov(struct vc4_compile *c, struct qinst *inst, struct qreg arg)
static bool
replace_x_0_with_x(struct vc4_compile *c,
- struct qinst **defs,
struct qinst *inst,
int arg)
{
- if (!is_zero(c, defs, inst->src[arg]))
+ if (!is_zero(c, inst->src[arg]))
return false;
replace_with_mov(c, inst, inst->src[1 - arg]);
return true;
@@ -113,11 +112,10 @@ replace_x_0_with_x(struct vc4_compile *c,
static bool
replace_x_0_with_0(struct vc4_compile *c,
- struct qinst **defs,
struct qinst *inst,
int arg)
{
- if (!is_zero(c, defs, inst->src[arg]))
+ if (!is_zero(c, inst->src[arg]))
return false;
replace_with_mov(c, inst, inst->src[arg]);
return true;
@@ -125,11 +123,10 @@ replace_x_0_with_0(struct vc4_compile *c,
static bool
fmul_replace_one(struct vc4_compile *c,
- struct qinst **defs,
struct qinst *inst,
int arg)
{
- if (!is_1f(c, defs, inst->src[arg]))
+ if (!is_1f(c, inst->src[arg]))
return false;
replace_with_mov(c, inst, inst->src[1 - arg]);
return true;
@@ -140,14 +137,10 @@ qir_opt_algebraic(struct vc4_compile *c)
{
bool progress = false;
struct simple_node *node;
- struct qinst *defs[c->num_temps];
foreach(node, &c->instructions) {
struct qinst *inst = (struct qinst *)node;
- if (inst->dst.file == QFILE_TEMP)
- defs[inst->dst.index] = inst;
-
switch (inst->op) {
case QOP_SEL_X_Y_ZS:
case QOP_SEL_X_Y_ZC:
@@ -162,7 +155,7 @@ qir_opt_algebraic(struct vc4_compile *c)
break;
}
- if (is_zero(c, defs, inst->src[1])) {
+ if (is_zero(c, inst->src[1])) {
/* Replace references to a 0 uniform value
* with the SEL_X_0 equivalent.
*/
@@ -174,7 +167,7 @@ qir_opt_algebraic(struct vc4_compile *c)
break;
}
- if (is_zero(c, defs, inst->src[0])) {
+ if (is_zero(c, inst->src[0])) {
/* Replace references to a 0 uniform value
* with the SEL_X_0 equivalent, flipping the
* condition being evaluated since the operand
@@ -195,31 +188,31 @@ qir_opt_algebraic(struct vc4_compile *c)
case QOP_FSUB:
case QOP_SUB:
- if (is_zero(c, defs, inst->src[1])) {
+ if (is_zero(c, inst->src[1])) {
replace_with_mov(c, inst, inst->src[0]);
}
break;
case QOP_ADD:
- if (replace_x_0_with_x(c, defs, inst, 0) ||
- replace_x_0_with_x(c, defs, inst, 1)) {
+ if (replace_x_0_with_x(c, inst, 0) ||
+ replace_x_0_with_x(c, inst, 1)) {
progress = true;
break;
}
break;
case QOP_FADD:
- if (replace_x_0_with_x(c, defs, inst, 0) ||
- replace_x_0_with_x(c, defs, inst, 1)) {
+ if (replace_x_0_with_x(c, inst, 0) ||
+ replace_x_0_with_x(c, inst, 1)) {
progress = true;
break;
}
/* FADD(a, FSUB(0, b)) -> FSUB(a, b) */
if (inst->src[1].file == QFILE_TEMP &&
- defs[inst->src[1].index]->op == QOP_FSUB) {
- struct qinst *fsub = defs[inst->src[1].index];
- if (is_zero(c, defs, fsub->src[0])) {
+ c->defs[inst->src[1].index]->op == QOP_FSUB) {
+ struct qinst *fsub = c->defs[inst->src[1].index];
+ if (is_zero(c, fsub->src[0])) {
dump_from(c, inst);
inst->op = QOP_FSUB;
inst->src[1] = fsub->src[1];
@@ -231,9 +224,9 @@ qir_opt_algebraic(struct vc4_compile *c)
/* FADD(FSUB(0, b), a) -> FSUB(a, b) */
if (inst->src[0].file == QFILE_TEMP &&
- defs[inst->src[0].index]->op == QOP_FSUB) {
- struct qinst *fsub = defs[inst->src[0].index];
- if (is_zero(c, defs, fsub->src[0])) {
+ c->defs[inst->src[0].index]->op == QOP_FSUB) {
+ struct qinst *fsub = c->defs[inst->src[0].index];
+ if (is_zero(c, fsub->src[0])) {
dump_from(c, inst);
inst->op = QOP_FSUB;
inst->src[0] = inst->src[1];
@@ -246,28 +239,28 @@ qir_opt_algebraic(struct vc4_compile *c)
break;
case QOP_FMUL:
- if (replace_x_0_with_0(c, defs, inst, 0) ||
- replace_x_0_with_0(c, defs, inst, 1) ||
- fmul_replace_one(c, defs, inst, 0) ||
- fmul_replace_one(c, defs, inst, 1)) {
+ if (replace_x_0_with_0(c, inst, 0) ||
+ replace_x_0_with_0(c, inst, 1) ||
+ fmul_replace_one(c, inst, 0) ||
+ fmul_replace_one(c, inst, 1)) {
progress = true;
break;
}
break;
case QOP_AND:
- if (replace_x_0_with_0(c, defs, inst, 0) ||
- replace_x_0_with_0(c, defs, inst, 1)) {
+ if (replace_x_0_with_0(c, inst, 0) ||
+ replace_x_0_with_0(c, inst, 1)) {
progress = true;
break;
}
- if (is_constant_value(c, defs, inst->src[0], ~0)) {
+ if (is_constant_value(c, inst->src[0], ~0)) {
replace_with_mov(c, inst, inst->src[1]);
progress = true;
break;
}
- if (is_constant_value(c, defs, inst->src[1], ~0)) {
+ if (is_constant_value(c, inst->src[1], ~0)) {
replace_with_mov(c, inst, inst->src[0]);
progress = true;
break;
@@ -275,8 +268,8 @@ qir_opt_algebraic(struct vc4_compile *c)
break;
case QOP_OR:
- if (replace_x_0_with_x(c, defs, inst, 0) ||
- replace_x_0_with_x(c, defs, inst, 1)) {
+ if (replace_x_0_with_x(c, inst, 0) ||
+ replace_x_0_with_x(c, inst, 1)) {
progress = true;
break;
}
diff --git a/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c b/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
index f8c49a44bd3..5189a401248 100644
--- a/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
+++ b/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
@@ -41,14 +41,10 @@ qir_opt_copy_propagation(struct vc4_compile *c)
struct simple_node *node;
bool debug = false;
struct qreg *movs = calloc(c->num_temps, sizeof(struct qreg));
- struct qinst **defs = calloc(c->num_temps, sizeof(struct qreg));
foreach(node, &c->instructions) {
struct qinst *inst = (struct qinst *)node;
- if (inst->dst.file == QFILE_TEMP)
- defs[inst->dst.index] = inst;
-
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
int index = inst->src[i].index;
if (inst->src[i].file == QFILE_TEMP &&
@@ -76,13 +72,12 @@ qir_opt_copy_propagation(struct vc4_compile *c)
inst->dst.file == QFILE_TEMP &&
inst->src[0].file != QFILE_VPM &&
!(inst->src[0].file == QFILE_TEMP &&
- (defs[inst->src[0].index]->op == QOP_TEX_RESULT ||
- defs[inst->src[0].index]->op == QOP_TLB_COLOR_READ))) {
+ (c->defs[inst->src[0].index]->op == QOP_TEX_RESULT ||
+ c->defs[inst->src[0].index]->op == QOP_TLB_COLOR_READ))) {
movs[inst->dst.index] = inst->src[0];
}
}
free(movs);
- free(defs);
return progress;
}
diff --git a/src/gallium/drivers/vc4/vc4_opt_dead_code.c b/src/gallium/drivers/vc4/vc4_opt_dead_code.c
index dd1561d68d4..e4ead46c9c2 100644
--- a/src/gallium/drivers/vc4/vc4_opt_dead_code.c
+++ b/src/gallium/drivers/vc4/vc4_opt_dead_code.c
@@ -44,7 +44,7 @@ dce(struct vc4_compile *c, struct qinst *inst)
fprintf(stderr, "\n");
}
assert(!inst->sf);
- qir_remove_instruction(inst);
+ qir_remove_instruction(c, inst);
}
static bool
diff --git a/src/gallium/drivers/vc4/vc4_opt_small_immediates.c b/src/gallium/drivers/vc4/vc4_opt_small_immediates.c
index 74304b99888..a329ac69d11 100644
--- a/src/gallium/drivers/vc4/vc4_opt_small_immediates.c
+++ b/src/gallium/drivers/vc4/vc4_opt_small_immediates.c
@@ -38,14 +38,10 @@ qir_opt_small_immediates(struct vc4_compile *c)
{
bool progress = false;
struct simple_node *node;
- struct qinst *defs[c->num_temps];
foreach(node, &c->instructions) {
struct qinst *inst = (struct qinst *)node;
- if (inst->dst.file == QFILE_TEMP)
- defs[inst->dst.index] = inst;
-
/* The small immediate value sits in the raddr B field, so we
* can't have 2 small immediates in one instruction (unless
* they're the same value, but that should be optimized away
@@ -60,7 +56,7 @@ qir_opt_small_immediates(struct vc4_compile *c)
continue;
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
- struct qreg src = qir_follow_movs(defs, inst->src[i]);
+ struct qreg src = qir_follow_movs(c, inst->src[i]);
if (src.file != QFILE_UNIF ||
c->uniform_contents[src.index] !=
diff --git a/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c b/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
index ba322b6421c..e9711f222cd 100644
--- a/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
+++ b/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
@@ -38,20 +38,15 @@ qir_opt_vpm_writes(struct vc4_compile *c)
bool progress = false;
struct simple_node *node;
- struct qinst *defs[c->num_temps];
struct qinst *vpm_writes[64] = { 0 };
uint32_t use_count[c->num_temps];
uint32_t vpm_write_count = 0;
- memset(&defs, 0, sizeof(defs));
memset(&use_count, 0, sizeof(use_count));
foreach(node, &c->instructions) {
struct qinst *inst = (struct qinst *)node;
switch (inst->dst.file) {
- case QFILE_TEMP:
- defs[inst->dst.index] = inst;
- break;
case QFILE_VPM:
vpm_writes[vpm_write_count++] = inst;
break;
@@ -75,7 +70,7 @@ qir_opt_vpm_writes(struct vc4_compile *c)
if (use_count[temp] != 1)
continue;
- struct qinst *inst = defs[temp];
+ struct qinst *inst = c->defs[temp];
if (qir_is_multi_instruction(inst))
continue;
@@ -94,7 +89,7 @@ qir_opt_vpm_writes(struct vc4_compile *c)
int src;
for (src = 0; src < qir_get_op_nsrc(inst->op); src++) {
if (inst->src[src].file == QFILE_TEMP) {
- if (defs[inst->src[src].index]->op ==
+ if (c->defs[inst->src[src].index]->op ==
QOP_TEX_RESULT) {
break;
}
@@ -108,8 +103,9 @@ qir_opt_vpm_writes(struct vc4_compile *c)
*/
assert(!vpm_writes[i]->sf);
move_to_tail(&vpm_writes[i]->link, &inst->link);
- qir_remove_instruction(vpm_writes[i]);
+ qir_remove_instruction(c, vpm_writes[i]);
+ c->defs[inst->dst.index] = NULL;
inst->dst.file = QFILE_VPM;
inst->dst.index = 0;
diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c
index 9addf9cafc8..e453d848096 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -318,6 +318,15 @@ qir_get_temp(struct vc4_compile *c)
reg.file = QFILE_TEMP;
reg.index = c->num_temps++;
+ if (c->num_temps > c->defs_array_size) {
+ uint32_t old_size = c->defs_array_size;
+ c->defs_array_size = MAX2(old_size * 2, 16);
+ c->defs = reralloc(c, c->defs, struct qinst *,
+ c->defs_array_size);
+ memset(&c->defs[old_size], 0,
+ sizeof(c->defs[0]) * (c->defs_array_size - old_size));
+ }
+
return reg;
}
@@ -358,6 +367,9 @@ qir_inst4(enum qop op, struct qreg dst,
void
qir_emit(struct vc4_compile *c, struct qinst *inst)
{
+ if (inst->dst.file == QFILE_TEMP)
+ c->defs[inst->dst.index] = inst;
+
insert_at_tail(&c->instructions, &inst->link);
}
@@ -383,18 +395,21 @@ qir_compile_init(void)
}
void
-qir_remove_instruction(struct qinst *qinst)
+qir_remove_instruction(struct vc4_compile *c, struct qinst *qinst)
{
+ if (qinst->dst.file == QFILE_TEMP)
+ c->defs[qinst->dst.index] = NULL;
+
remove_from_list(&qinst->link);
free(qinst->src);
free(qinst);
}
struct qreg
-qir_follow_movs(struct qinst **defs, struct qreg reg)
+qir_follow_movs(struct vc4_compile *c, struct qreg reg)
{
- while (reg.file == QFILE_TEMP && defs[reg.index]->op == QOP_MOV)
- reg = defs[reg.index]->src[0];
+ while (reg.file == QFILE_TEMP && c->defs[reg.index]->op == QOP_MOV)
+ reg = c->defs[reg.index]->src[0];
return reg;
}
@@ -405,7 +420,7 @@ qir_compile_destroy(struct vc4_compile *c)
while (!is_empty_list(&c->instructions)) {
struct qinst *qinst =
(struct qinst *)first_elem(&c->instructions);
- qir_remove_instruction(qinst);
+ qir_remove_instruction(c, qinst);
}
ralloc_free(c);
diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h
index af92c8c66a9..4f910e3c3df 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -284,6 +284,9 @@ struct vc4_compile {
struct vc4_context *vc4;
struct tgsi_parse_context parser;
struct qreg *temps;
+ /* For each temp, the instruction generating its value. */
+ struct qinst **defs;
+ uint32_t defs_array_size;
/**
* Inputs to the shader, arranged by TGSI declaration order.
*
@@ -368,7 +371,7 @@ struct qinst *qir_inst4(enum qop op, struct qreg dst,
struct qreg b,
struct qreg c,
struct qreg d);
-void qir_remove_instruction(struct qinst *qinst);
+void qir_remove_instruction(struct vc4_compile *c, struct qinst *qinst);
struct qreg qir_uniform(struct vc4_compile *c,
enum quniform_contents contents,
uint32_t data);
@@ -385,7 +388,7 @@ bool qir_depends_on_flags(struct qinst *inst);
bool qir_writes_r4(struct qinst *inst);
bool qir_reads_r4(struct qinst *inst);
bool qir_src_needs_a_file(struct qinst *inst);
-struct qreg qir_follow_movs(struct qinst **defs, struct qreg reg);
+struct qreg qir_follow_movs(struct vc4_compile *c, struct qreg reg);
void qir_dump(struct vc4_compile *c);
void qir_dump_inst(struct vc4_compile *c, struct qinst *inst);
diff --git a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
index d527889e76f..63f5eb22858 100644
--- a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
+++ b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c
@@ -138,6 +138,7 @@ qir_lower_uniforms(struct vc4_compile *c)
struct qreg unif = { QFILE_UNIF, max_index };
struct qinst *mov = qir_inst(QOP_MOV, temp, unif, c->undef);
insert_at_head(&c->instructions, &mov->link);
+ c->defs[temp.index] = mov;
foreach(node, &c->instructions) {
struct qinst *inst = (struct qinst *)node;
uint32_t nsrc = qir_get_op_nsrc(inst->op);