From 7cc09e9952c0429fd9cd6a1f477b5a67ef8d20e6 Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Tue, 19 Aug 2025 10:41:45 +0200 Subject: [PATCH] nir: add offset_shift intrinsic index For load/store intrinsics that take an offset, this specifies the amount the offset is shifted left to calculate the final offset: offset = (offset_src + base) << offset_shift This is useful for backends that have memory operations that use offset units other than bytes (i.e., where the shift is implicit). Signed-off-by: Job Noorman Reviewed-by: Emma Anholt Part-of: --- src/compiler/nir/nir_intrinsics.py | 14 ++++++++++++++ src/compiler/nir/nir_validate.c | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index beb2fa6b555..bb40fab9d02 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -214,6 +214,20 @@ index("unsigned", "stack_size") index("unsigned", "align_mul") index("unsigned", "align_offset") +# For load/store intrinsics that take an offset, the amount the offset is +# shifted left to calculate the final byte offset: +# +# offset = (offset_src + base) << offset_shift +# +# It is unspecified how overflows due to offset_shift are handled: they may +# either be treated as out-of-bounds, or wrap around and generate an in-bounds +# offset. NIR passes may implement either behavior and may not be consistent +# about it. +# +# This is useful for backends that have memory operations that use offset units +# other than bytes (i.e., where the shift is implicit). +index("unsigned", "offset_shift") + # The Vulkan descriptor type for a vulkan_resource_[re]index intrinsic. index("unsigned", "desc_type") diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 12f1b60ef64..bd02c35d61f 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -809,6 +809,12 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) (state->shader->info.stage == MESA_SHADER_FRAGMENT && instr->intrinsic == nir_intrinsic_load_input_vertex)); } + + if (nir_intrinsic_has_offset_shift(instr) && + nir_intrinsic_has_align(instr)) { + unsigned min_align = 1 << nir_intrinsic_offset_shift(instr); + validate_assert(state, nir_intrinsic_align(instr) >= min_align); + } } static void