diff options
author | Connor Abbott <cwabbott0@gmail.com> | 2017-06-01 18:43:56 -0700 |
---|---|---|
committer | Connor Abbott <cwabbott0@gmail.com> | 2017-06-05 18:34:18 -0700 |
commit | d99ac8bb86962ac9bb136afb5a70296c5cf48b3d (patch) | |
tree | 5d03528f9934da7c38ff4f9eeb0e1ec526c9fb0b | |
parent | c87fc02cac410e738c1a56cbdea9725073690d6d (diff) |
nir: take cross-thread operations into account into a few places
These optimizations happened to work with derivatives, but they won't
with upcoming shader_ballot and group_vote instructions.
-rw-r--r-- | src/compiler/nir/nir_instr_set.c | 12 | ||||
-rw-r--r-- | src/compiler/nir/nir_opt_peephole_select.c | 11 |
2 files changed, 23 insertions, 0 deletions
diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c index 9cb9ed43e8..74309d60f6 100644 --- a/src/compiler/nir/nir_instr_set.c +++ b/src/compiler/nir/nir_instr_set.c @@ -178,6 +178,18 @@ hash_instr(const void *data) const nir_instr *instr = data; uint32_t hash = _mesa_fnv32_1a_offset_bias; + /* + * If an instruction is cross-thread but not convergent, hash its block. If + * an instruction is convergent, then we can always replace one invocation + * with another since every invocation is guaranteed convergent. But not so + * for non-convergent instructions, since different invocations may be + * called with different execution maskes and therefore have different + * results. + */ + if (nir_instr_is_cross_thread(instr) && !nir_instr_is_convergent(instr)) { + HASH(hash, instr->block); + } + switch (instr->type) { case nir_instr_type_alu: hash = hash_alu(hash, nir_instr_as_alu(instr)); diff --git a/src/compiler/nir/nir_opt_peephole_select.c b/src/compiler/nir/nir_opt_peephole_select.c index 4ca4f80d78..ce41781e45 100644 --- a/src/compiler/nir/nir_opt_peephole_select.c +++ b/src/compiler/nir/nir_opt_peephole_select.c @@ -61,6 +61,17 @@ static bool block_check_for_allowed_instrs(nir_block *block, unsigned *count, bool alu_ok) { nir_foreach_instr(instr, block) { + if (nir_instr_is_cross_thread(instr) && !nir_instr_is_convergent(instr)) { + /* If the instruction is cross-thread, then we can't execute it + * conditionally when we would've executed it unconditionally before, + * except when the condition is uniform. If the instruction is + * convergent, though, we're already guaranteed that the entire + * region is convergent (including the condition) so we can go ahead. + * + * TODO: allow when the if-condition is uniform + */ + return false; + } switch (instr->type) { case nir_instr_type_intrinsic: { nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); |