Module: Mesa Branch: main Commit: 6d5ff875d2b34d8fe8843665fcf1b39c2230d3e5 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=6d5ff875d2b34d8fe8843665fcf1b39c2230d3e5
Author: Jesse Natalie <[email protected]> Date: Tue Apr 4 13:41:10 2023 -0700 microsoft/compiler: Fix large shifts Unlike DXBC, DXIL's shift instructions don't have the implicit behavior that they only take the 5 bits. This is observable if you try to have DXC do a shift of a dynamic value, e.g. a constant buffer value, where the compiler inserts the appropriate 'and' op. We need to do the same. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22225> --- src/microsoft/compiler/nir_to_dxil.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index 245c5140f98..c4de9dd3a7c 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -2164,12 +2164,24 @@ emit_shift(struct ntd_context *ctx, nir_alu_instr *alu, { unsigned op0_bit_size = nir_src_bit_size(alu->src[0].src); unsigned op1_bit_size = nir_src_bit_size(alu->src[1].src); - if (op0_bit_size != op1_bit_size) { - const struct dxil_type *type = - dxil_module_get_int_type(&ctx->mod, op0_bit_size); - enum dxil_cast_opcode cast_op = - op1_bit_size < op0_bit_size ? DXIL_CAST_ZEXT : DXIL_CAST_TRUNC; - op1 = dxil_emit_cast(&ctx->mod, cast_op, type, op1); + + uint64_t shift_mask = op0_bit_size - 1; + if (!nir_src_is_const(alu->src[1].src)) { + if (op0_bit_size != op1_bit_size) { + const struct dxil_type *type = + dxil_module_get_int_type(&ctx->mod, op0_bit_size); + enum dxil_cast_opcode cast_op = + op1_bit_size < op0_bit_size ? DXIL_CAST_ZEXT : DXIL_CAST_TRUNC; + op1 = dxil_emit_cast(&ctx->mod, cast_op, type, op1); + } + op1 = dxil_emit_binop(&ctx->mod, DXIL_BINOP_AND, + op1, + dxil_module_get_int_const(&ctx->mod, shift_mask, op0_bit_size), + 0); + } else { + uint64_t val = nir_ssa_scalar_as_uint( + nir_ssa_scalar_chase_alu_src(nir_get_ssa_scalar(&alu->dest.dest.ssa, 0), 1)); + op1 = dxil_module_get_int_const(&ctx->mod, val & shift_mask, op0_bit_size); } const struct dxil_value *v =
