ac/llvm: correctly set alignment of vector global load/store

For coherent/volatile access, this would be too high for vector access.

Even when we didn't set the alignment, LLVM seemed to assume too high of
an alignment for 8/16-bit vector access.

Fixes generated_tests/cl/vload/vload-char-constant.cl

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Michel Dänzer <mdaenzer@redhat.com>
Backport-to: 25.0
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34903>
(cherry picked from commit d0a09b6ff7)
This commit is contained in:
Rhys Perry 2025-05-09 17:28:26 +01:00 committed by Eric Engestrom
parent 3936208f3c
commit 161e3d942d
2 changed files with 16 additions and 7 deletions

View file

@ -984,7 +984,7 @@
"description": "ac/llvm: correctly set alignment of vector global load/store",
"nominated": true,
"nomination_type": 4,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -1885,10 +1885,17 @@ static LLVMValueRef visit_load_global(struct ac_nir_context *ctx,
val = LLVMBuildLoad2(ctx->ac.builder, result_type, addr, "");
if (nir_intrinsic_access(instr) & (ACCESS_COHERENT | ACCESS_VOLATILE)) {
/* From the LLVM 21.0.0 language reference:
* > An alignment value higher than the size of the loaded type implies memory up to the
* > alignment value bytes can be safely loaded without trapping in the default address space.
* So limit the alignment to the access size, since this isn't true in NIR.
*/
uint32_t align = nir_intrinsic_align(instr);
uint32_t size = ac_get_type_size(result_type);
LLVMSetAlignment(val, MIN2(align, 1 << (ffs(size) - 1)));
if (nir_intrinsic_access(instr) & (ACCESS_COHERENT | ACCESS_VOLATILE))
LLVMSetOrdering(val, LLVMAtomicOrderingMonotonic);
LLVMSetAlignment(val, ac_get_type_size(result_type));
}
return val;
}
@ -1907,10 +1914,12 @@ static void visit_store_global(struct ac_nir_context *ctx,
val = LLVMBuildStore(ctx->ac.builder, data, addr);
if (nir_intrinsic_access(instr) & (ACCESS_COHERENT | ACCESS_VOLATILE)) {
uint32_t align = nir_intrinsic_align(instr);
uint32_t size = ac_get_type_size(type);
LLVMSetAlignment(val, MIN2(align, 1 << (ffs(size) - 1)));
if (nir_intrinsic_access(instr) & (ACCESS_COHERENT | ACCESS_VOLATILE))
LLVMSetOrdering(val, LLVMAtomicOrderingMonotonic);
LLVMSetAlignment(val, ac_get_type_size(type));
}
}
static LLVMValueRef visit_global_atomic(struct ac_nir_context *ctx,