ac/llvm: Fix buffer_load_amd with larger than 32-bit channel sizes.

LLVM is unable to select instructions for larger than 32-bit channel types.
Workaround by using i32 and casting to the correct type later.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Qiang Yu <yuq825@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Acked-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21358>
This commit is contained in:
Timur Kristóf 2023-02-13 10:56:37 +01:00 committed by Marge Bot
parent b5b0ded4c1
commit a2755fc203

View file

@ -4054,24 +4054,32 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
assert(instr->src[0].ssa->bit_size == 16 || instr->src[0].ssa->bit_size == 32);
ac_build_buffer_store_format(&ctx->ac, descriptor, store_data, vidx, voffset, cache_policy);
} else if (instr->intrinsic == nir_intrinsic_load_buffer_amd) {
LLVMTypeRef channel_type;
if (instr->dest.ssa.bit_size == 8)
channel_type = ctx->ac.i8;
else if (instr->dest.ssa.bit_size == 16)
channel_type = ctx->ac.i16;
else if (instr->dest.ssa.bit_size == 32)
channel_type = ctx->ac.i32;
else if (instr->dest.ssa.bit_size == 64)
channel_type = ctx->ac.i64;
else if (instr->dest.ssa.bit_size == 128)
channel_type = ctx->ac.i128;
else
unreachable("Unsupported channel type for load_buffer_amd");
/* LLVM is unable to select instructions for larger than 32-bit channel types.
* Workaround by using i32 and casting to the correct type later.
*/
const unsigned fetch_num_components =
num_components * MAX2(32, instr->dest.ssa.bit_size) / 32;
LLVMTypeRef channel_type =
LLVMIntTypeInContext(ctx->ac.context, MIN2(32, instr->dest.ssa.bit_size));
result = ac_build_buffer_load(&ctx->ac, descriptor, num_components, vidx, voffset,
result = ac_build_buffer_load(&ctx->ac, descriptor, fetch_num_components, vidx, voffset,
addr_soffset, channel_type, cache_policy, reorder, false);
result = ac_to_integer(&ctx->ac, ac_trim_vector(&ctx->ac, result, num_components));
/* Trim to needed vector components. */
result = ac_trim_vector(&ctx->ac, result, fetch_num_components);
/* Cast to larger than 32-bit sized components if needed. */
if (instr->dest.ssa.bit_size > 32) {
LLVMTypeRef cast_channel_type =
LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size);
LLVMTypeRef cast_type =
num_components == 1 ? cast_channel_type :
LLVMVectorType(cast_channel_type, num_components);
result = LLVMBuildBitCast(ctx->ac.builder, result, cast_type, "");
}
/* Cast the result to an integer (or vector of integers). */
result = ac_to_integer(&ctx->ac, result);
} else {
unsigned writemask = nir_intrinsic_write_mask(instr);
while (writemask) {