From a2755fc203fa62f48bc3547c5493f959dd300726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timur=20Krist=C3=B3f?= Date: Mon, 13 Feb 2023 10:56:37 +0100 Subject: [PATCH] ac/llvm: Fix buffer_load_amd with larger than 32-bit channel sizes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Qiang Yu Reviewed-by: Marek Olšák Acked-by: Konstantin Seurer Part-of: --- src/amd/llvm/ac_nir_to_llvm.c | 38 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 5f90edd7619..76dffdd831f 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -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) {