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 =

Reply via email to