diff options
author | Eric Anholt <[email protected]> | 2018-05-08 13:04:37 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2018-06-06 13:44:28 -0700 |
commit | 73953b071365ca64db353023fff78a06b20503a3 (patch) | |
tree | bec8d88ada08f12ae509f6ac00c6dc69a60b1f99 /src/compiler/nir | |
parent | 7afa26d4e39c73502ad75b95605197eb52c8d099 (diff) |
nir: Add lowering for nir_op_bit_count.
This is basically the same as the GLSL lowering path.
v2: Fix typo in the link
Reviewed-by: Matt Turner <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/compiler/nir')
-rw-r--r-- | src/compiler/nir/nir.h | 2 | ||||
-rw-r--r-- | src/compiler/nir/nir_lower_alu.c | 36 |
2 files changed, 38 insertions, 0 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 06154aa9900..bb477742dc6 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1913,6 +1913,8 @@ typedef struct nir_shader_compiler_options { bool lower_bitfield_insert_to_shifts; /** Lowers bitfield_reverse to shifts. */ bool lower_bitfield_reverse; + /** Lowers bit_count to shifts. */ + bool lower_bit_count; /** Lowers bfm to shifts and subtracts. */ bool lower_bfm; /** Lowers ifind_msb to compare and ufind_msb */ diff --git a/src/compiler/nir/nir_lower_alu.c b/src/compiler/nir/nir_lower_alu.c index ff977f01696..8d1a1d37467 100644 --- a/src/compiler/nir/nir_lower_alu.c +++ b/src/compiler/nir/nir_lower_alu.c @@ -94,6 +94,42 @@ lower_alu_instr(nir_alu_instr *instr, nir_builder *b) } break; + case nir_op_bit_count: + if (b->shader->options->lower_bit_count) { + /* For more details, see: + * + * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + */ + nir_ssa_def *c1 = nir_imm_int(b, 1); + nir_ssa_def *c2 = nir_imm_int(b, 2); + nir_ssa_def *c4 = nir_imm_int(b, 4); + nir_ssa_def *c24 = nir_imm_int(b, 24); + nir_ssa_def *c33333333 = nir_imm_int(b, 0x33333333); + nir_ssa_def *c55555555 = nir_imm_int(b, 0x55555555); + nir_ssa_def *c0f0f0f0f = nir_imm_int(b, 0x0f0f0f0f); + nir_ssa_def *c01010101 = nir_imm_int(b, 0x01010101); + + lowered = nir_ssa_for_alu_src(b, instr, 0); + + lowered = nir_isub(b, lowered, + nir_iand(b, nir_ushr(b, lowered, c1), c55555555)); + + lowered = nir_iadd(b, + nir_iand(b, lowered, c33333333), + nir_iand(b, nir_ushr(b, lowered, c2), c33333333)); + + lowered = nir_ushr(b, + nir_imul(b, + nir_iand(b, + nir_iadd(b, + lowered, + nir_ushr(b, lowered, c4)), + c0f0f0f0f), + c01010101), + c24); + } + break; + case nir_op_imul_high: case nir_op_umul_high: if (b->shader->options->lower_mul_high) { |