i965/fs: Track flag register liveness with byte granularity.

This is required for correctness in presence of multiple 8-wide flag
writes (e.g. 8-wide instructions with a conditional mod set) which
update a different portion of the same 16-bit flag subregister.  Right
now we keep track of flag dataflow with 16-bit granularity and
consider flag writes to have killed any previous definition of the
same subregister even if the write was less than 16 channels wide,
which can cause live flag register updates to be dead code-eliminated
incorrectly.

Additionally this makes sure that we handle 32-wide flag writes and
reads which may span multiple flag subregisters so the current
approach of just setting/testing a single bit from the live set
wouldn't have worked.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
Francisco Jerez 2016-05-18 21:34:27 -07:00
parent df1aec763e
commit 0fec265373
2 changed files with 9 additions and 25 deletions

View file

@ -77,7 +77,7 @@ fs_visitor::dead_code_eliminate()
}
if (inst->dst.is_null() && inst->writes_flag()) {
if (!BITSET_TEST(flag_live, inst->flag_subreg)) {
if (!(flag_live[0] & inst->flags_written())) {
inst->opcode = BRW_OPCODE_NOP;
progress = true;
}
@ -102,9 +102,8 @@ fs_visitor::dead_code_eliminate()
}
}
if (inst->writes_flag() && !inst->predicate) {
BITSET_CLEAR(flag_live, inst->flag_subreg);
}
if (!inst->predicate && inst->exec_size >= 8)
flag_live[0] &= ~inst->flags_written();
if (inst->opcode == BRW_OPCODE_NOP) {
inst->remove(block);
@ -121,9 +120,7 @@ fs_visitor::dead_code_eliminate()
}
}
if (inst->reads_flag()) {
BITSET_SET(flag_live, inst->flag_subreg);
}
flag_live[0] |= inst->flags_read(devinfo);
}
}

View file

@ -123,19 +123,8 @@ fs_live_variables::setup_def_use()
reg.reg_offset++;
}
}
if (inst->reads_flag()) {
/* The vertical combination predicates read f0.0 and f0.1. */
if (inst->predicate == BRW_PREDICATE_ALIGN1_ANYV ||
inst->predicate == BRW_PREDICATE_ALIGN1_ALLV) {
assert(inst->flag_subreg == 0);
if (!BITSET_TEST(bd->flag_def, 1)) {
BITSET_SET(bd->flag_use, 1);
}
}
if (!BITSET_TEST(bd->flag_def, inst->flag_subreg)) {
BITSET_SET(bd->flag_use, inst->flag_subreg);
}
}
bd->flag_use[0] |= inst->flags_read(v->devinfo) & ~bd->flag_def[0];
/* Set def[] for this instruction */
if (inst->dst.file == VGRF) {
@ -145,11 +134,9 @@ fs_live_variables::setup_def_use()
reg.reg_offset++;
}
}
if (inst->writes_flag()) {
if (!BITSET_TEST(bd->flag_use, inst->flag_subreg)) {
BITSET_SET(bd->flag_def, inst->flag_subreg);
}
}
if (!inst->predicate && inst->exec_size >= 8)
bd->flag_def[0] |= inst->flags_written() & ~bd->flag_use[0];
ip++;
}