vc4: Keep an array of pointers to instructions defining the temps around.
authorEric Anholt <eric@anholt.net>
Thu, 19 Feb 2015 21:22:31 +0000 (13:22 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 20 Feb 2015 07:35:17 +0000 (23:35 -0800)
The optimization passes are always regenerating it and throwing it away,
but it's not hard to keep track of.

src/gallium/drivers/vc4/vc4_opt_algebraic.c
src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
src/gallium/drivers/vc4/vc4_opt_dead_code.c
src/gallium/drivers/vc4/vc4_opt_small_immediates.c
src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
src/gallium/drivers/vc4/vc4_qir.c
src/gallium/drivers/vc4/vc4_qir.h
src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c

index 1e0b8c9c0974874fc9b3f8a347fd8013425ca047..d17669abaffba318cbb2e5fc20cb8558badd828c 100644 (file)
@@ -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;
                         }
index f8c49a44bd3b70d3fbf1e0aafcc4a801f3fa4115..5189a401248fcd62b9fc265acfa6992ca89b0dbf 100644 (file)
@@ -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;
 }
index dd1561d68d4713fb59dbd59696b7dd9d37c90c52..e4ead46c9c25688806d7f0144b636cefb700ba05 100644 (file)
@@ -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
index 74304b998885efd448019c3c65916a4436f38ded..a329ac69d11a3a5ea840bbe27c35dfb2b1246e59 100644 (file)
@@ -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] !=
index ba322b6421c196b3a43d2f6ab15831f281b326ed..e9711f222cd5a6497f1fc0649d12edf78cfef647 100644 (file)
@@ -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;
 
index 9addf9cafc8e05bd6565cdbdb873d3b470cee8bc..e453d848096963381adf174096b5f81cf1ee7502 100644 (file)
@@ -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);
index af92c8c66a92176d91722219143c6afdb62041d3..4f910e3c3df9702a6ebd7b18deb9a95ca3b57e87 100644 (file)
@@ -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);
index d527889e76f4d5df1c916ebfb50a145657b965d2..63f5eb2285829d1ce8bd1a1e16f5443d205081b4 100644 (file)
@@ -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);