}
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 &&
}
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
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;
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;
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;
{
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:
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.
*/
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
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];
/* 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];
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;
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;
}
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;
}
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);
}
}
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;
}
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);