summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-05-08 13:04:37 -0700
committerEric Anholt <[email protected]>2018-06-06 13:44:28 -0700
commit73953b071365ca64db353023fff78a06b20503a3 (patch)
treebec8d88ada08f12ae509f6ac00c6dc69a60b1f99 /src/compiler/nir
parent7afa26d4e39c73502ad75b95605197eb52c8d099 (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.h2
-rw-r--r--src/compiler/nir/nir_lower_alu.c36
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) {