diff options
author | Ian Romanick <[email protected]> | 2016-06-22 13:12:26 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2016-07-19 12:19:29 -0700 |
commit | 3e7cebc8da5c9f16fa1b9a25ea72b8d31c86a440 (patch) | |
tree | 79342916637d30f355a0135fde4b21f8354512f2 /src/mesa | |
parent | c2019c6c261d5c46a4e5d3edc88836bcedf75f30 (diff) |
i965: Use LZD to implement nir_op_find_lsb on Gen < 7
v2: Rebase on changes to previous two patches.
Signed-off-by: Ian Romanick <[email protected]>
Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 22 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 26 |
2 files changed, 45 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 5bf9aa4bbc7..3da6d7523e9 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -1387,7 +1387,27 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr) case nir_op_find_lsb: assert(nir_dest_bit_size(instr->dest.dest) < 64); - bld.FBL(result, op[0]); + + if (devinfo->gen < 7) { + fs_reg temp = vgrf(glsl_type::int_type); + + /* (x & -x) generates a value that consists of only the LSB of x. + * For all powers of 2, findMSB(y) == findLSB(y). + */ + fs_reg src = retype(op[0], BRW_REGISTER_TYPE_D); + fs_reg negated_src = src; + + /* One must be negated, and the other must be non-negated. It + * doesn't matter which is which. + */ + negated_src.negate = true; + src.negate = false; + + bld.AND(temp, src, negated_src); + emit_find_msb_using_lzd(bld, result, temp, false); + } else { + bld.FBL(result, op[0]); + } break; case nir_op_ubitfield_extract: diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index 85fa775dc6b..3b2050801ad 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -1535,9 +1535,31 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) break; } - case nir_op_find_lsb: - emit(FBL(dst, op[0])); + case nir_op_find_lsb: { + vec4_builder bld = vec4_builder(this).at_end(); + + if (devinfo->gen < 7) { + dst_reg temp = bld.vgrf(BRW_REGISTER_TYPE_D); + + /* (x & -x) generates a value that consists of only the LSB of x. + * For all powers of 2, findMSB(y) == findLSB(y). + */ + src_reg src = src_reg(retype(op[0], BRW_REGISTER_TYPE_D)); + src_reg negated_src = src; + + /* One must be negated, and the other must be non-negated. It + * doesn't matter which is which. + */ + negated_src.negate = true; + src.negate = false; + + bld.AND(temp, src, negated_src); + emit_find_msb_using_lzd(bld, dst, src_reg(temp), false); + } else { + bld.FBL(dst, op[0]); + } break; + } case nir_op_ubitfield_extract: case nir_op_ibitfield_extract: |