summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-07-20 12:21:41 -0700
committerJason Ekstrand <[email protected]>2016-08-10 15:19:55 -0700
commit4c3a6b07e2960266adca634f8607ef38f71b8318 (patch)
treeb2329b975bc774a006b862d9fe54eb52c2c4d678
parentac6966360fc2f31b5e862624c6ef0048e11148e7 (diff)
i965/vec4: Make opt_vector_float reset at the top of each block
The pass isn't really control-flow aware and you can get into case where it tries to combine instructions from different blocks. This can actually lead to an assertion failure when removing unneeded instructions if part of the vector is set in one block and part in another. This prevents regressions in the next commit. Signed-off-by: Jason Ekstrand <[email protected]> Cc: "12.0" <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.cpp162
1 files changed, 82 insertions, 80 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index 162b481573d..2cf0e1759e4 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -354,95 +354,97 @@ vec4_visitor::opt_vector_float()
{
bool progress = false;
- int last_reg = -1, last_reg_offset = -1;
- enum brw_reg_file last_reg_file = BAD_FILE;
+ foreach_block(block, cfg) {
+ int last_reg = -1, last_reg_offset = -1;
+ enum brw_reg_file last_reg_file = BAD_FILE;
+
+ uint8_t imm[4] = { 0 };
+ int inst_count = 0;
+ vec4_instruction *imm_inst[4];
+ unsigned writemask = 0;
+ enum brw_reg_type dest_type = BRW_REGISTER_TYPE_F;
+
+ foreach_inst_in_block_safe(vec4_instruction, inst, block) {
+ int vf = -1;
+ enum brw_reg_type need_type;
+
+ /* Look for unconditional MOVs from an immediate with a partial
+ * writemask. Skip type-conversion MOVs other than integer 0,
+ * where the type doesn't matter. See if the immediate can be
+ * represented as a VF.
+ */
+ if (inst->opcode == BRW_OPCODE_MOV &&
+ inst->src[0].file == IMM &&
+ inst->predicate == BRW_PREDICATE_NONE &&
+ inst->dst.writemask != WRITEMASK_XYZW &&
+ (inst->src[0].type == inst->dst.type || inst->src[0].d == 0)) {
+
+ vf = brw_float_to_vf(inst->src[0].d);
+ need_type = BRW_REGISTER_TYPE_D;
+
+ if (vf == -1) {
+ vf = brw_float_to_vf(inst->src[0].f);
+ need_type = BRW_REGISTER_TYPE_F;
+ }
+ } else {
+ last_reg = -1;
+ }
- uint8_t imm[4] = { 0 };
- int inst_count = 0;
- vec4_instruction *imm_inst[4];
- unsigned writemask = 0;
- enum brw_reg_type dest_type = BRW_REGISTER_TYPE_F;
+ /* If this wasn't a MOV, or the destination register doesn't match,
+ * or we have to switch destination types, then this breaks our
+ * sequence. Combine anything we've accumulated so far.
+ */
+ if (last_reg != inst->dst.nr ||
+ last_reg_offset != inst->dst.reg_offset ||
+ last_reg_file != inst->dst.file ||
+ (vf > 0 && dest_type != need_type)) {
+
+ if (inst_count > 1) {
+ unsigned vf;
+ memcpy(&vf, imm, sizeof(vf));
+ vec4_instruction *mov = MOV(imm_inst[0]->dst, brw_imm_vf(vf));
+ mov->dst.type = dest_type;
+ mov->dst.writemask = writemask;
+ inst->insert_before(block, mov);
+
+ for (int i = 0; i < inst_count; i++) {
+ imm_inst[i]->remove(block);
+ }
- foreach_block_and_inst_safe(block, vec4_instruction, inst, cfg) {
- int vf = -1;
- enum brw_reg_type need_type;
+ progress = true;
+ }
- /* Look for unconditional MOVs from an immediate with a partial
- * writemask. Skip type-conversion MOVs other than integer 0,
- * where the type doesn't matter. See if the immediate can be
- * represented as a VF.
- */
- if (inst->opcode == BRW_OPCODE_MOV &&
- inst->src[0].file == IMM &&
- inst->predicate == BRW_PREDICATE_NONE &&
- inst->dst.writemask != WRITEMASK_XYZW &&
- (inst->src[0].type == inst->dst.type || inst->src[0].d == 0)) {
-
- vf = brw_float_to_vf(inst->src[0].d);
- need_type = BRW_REGISTER_TYPE_D;
-
- if (vf == -1) {
- vf = brw_float_to_vf(inst->src[0].f);
- need_type = BRW_REGISTER_TYPE_F;
- }
- } else {
- last_reg = -1;
- }
+ inst_count = 0;
+ last_reg = -1;
+ writemask = 0;
+ dest_type = BRW_REGISTER_TYPE_F;
- /* If this wasn't a MOV, or the destination register doesn't match,
- * or we have to switch destination types, then this breaks our
- * sequence. Combine anything we've accumulated so far.
- */
- if (last_reg != inst->dst.nr ||
- last_reg_offset != inst->dst.reg_offset ||
- last_reg_file != inst->dst.file ||
- (vf > 0 && dest_type != need_type)) {
-
- if (inst_count > 1) {
- unsigned vf;
- memcpy(&vf, imm, sizeof(vf));
- vec4_instruction *mov = MOV(imm_inst[0]->dst, brw_imm_vf(vf));
- mov->dst.type = dest_type;
- mov->dst.writemask = writemask;
- inst->insert_before(block, mov);
-
- for (int i = 0; i < inst_count; i++) {
- imm_inst[i]->remove(block);
+ for (int i = 0; i < 4; i++) {
+ imm[i] = 0;
}
-
- progress = true;
}
- inst_count = 0;
- last_reg = -1;
- writemask = 0;
- dest_type = BRW_REGISTER_TYPE_F;
-
- for (int i = 0; i < 4; i++) {
- imm[i] = 0;
+ /* Record this instruction's value (if it was representable). */
+ if (vf != -1) {
+ if ((inst->dst.writemask & WRITEMASK_X) != 0)
+ imm[0] = vf;
+ if ((inst->dst.writemask & WRITEMASK_Y) != 0)
+ imm[1] = vf;
+ if ((inst->dst.writemask & WRITEMASK_Z) != 0)
+ imm[2] = vf;
+ if ((inst->dst.writemask & WRITEMASK_W) != 0)
+ imm[3] = vf;
+
+ writemask |= inst->dst.writemask;
+ imm_inst[inst_count++] = inst;
+
+ last_reg = inst->dst.nr;
+ last_reg_offset = inst->dst.reg_offset;
+ last_reg_file = inst->dst.file;
+ if (vf > 0)
+ dest_type = need_type;
}
}
-
- /* Record this instruction's value (if it was representable). */
- if (vf != -1) {
- if ((inst->dst.writemask & WRITEMASK_X) != 0)
- imm[0] = vf;
- if ((inst->dst.writemask & WRITEMASK_Y) != 0)
- imm[1] = vf;
- if ((inst->dst.writemask & WRITEMASK_Z) != 0)
- imm[2] = vf;
- if ((inst->dst.writemask & WRITEMASK_W) != 0)
- imm[3] = vf;
-
- writemask |= inst->dst.writemask;
- imm_inst[inst_count++] = inst;
-
- last_reg = inst->dst.nr;
- last_reg_offset = inst->dst.reg_offset;
- last_reg_file = inst->dst.file;
- if (vf > 0)
- dest_type = need_type;
- }
}
if (progress)