From 91626d0865851bc7e2e21296d1d8f34149216e40 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 29 Aug 2019 17:28:01 +0200 Subject: [PATCH] ac/nir: Support load_constant intrinsics MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Setup a constant global variable that LLVM will stick in a .rodata section and generate PC-relative loads for. Reviewed-by: Marek Olšák --- src/amd/common/ac_nir_to_llvm.c | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index baac8e5ec97..13578770d4a 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -43,6 +43,7 @@ struct ac_nir_context { LLVMValueRef *ssa_defs; LLVMValueRef scratch; + LLVMValueRef constant_data; struct hash_table *defs; struct hash_table *phis; @@ -3770,6 +3771,25 @@ static void visit_intrinsic(struct ac_nir_context *ctx, } break; } + case nir_intrinsic_load_constant: { + LLVMValueRef offset = get_src(ctx, instr->src[0]); + LLVMValueRef base = LLVMConstInt(ctx->ac.i32, + nir_intrinsic_base(instr), + false); + offset = LLVMBuildAdd(ctx->ac.builder, offset, base, ""); + LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->constant_data, + offset); + LLVMTypeRef comp_type = + LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size); + LLVMTypeRef vec_type = + instr->dest.ssa.num_components == 1 ? comp_type : + LLVMVectorType(comp_type, instr->dest.ssa.num_components); + unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); + ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, + LLVMPointerType(vec_type, addr_space), ""); + result = LLVMBuildLoad(ctx->ac.builder, ptr, ""); + break; + } default: fprintf(stderr, "Unknown intrinsic: "); nir_print_instr(&instr->instr, stderr); @@ -4682,6 +4702,40 @@ setup_scratch(struct ac_nir_context *ctx, "scratch"); } +static void +setup_constant_data(struct ac_nir_context *ctx, + struct nir_shader *shader) +{ + if (!shader->constant_data) + return; + + LLVMValueRef data = + LLVMConstStringInContext(ctx->ac.context, + shader->constant_data, + shader->constant_data_size, + true); + LLVMTypeRef type = LLVMArrayType(ctx->ac.i8, shader->constant_data_size); + + /* We want to put the constant data in the CONST address space so that + * we can use scalar loads. However, LLVM versions before 10 put these + * variables in the same section as the code, which is unacceptable + * for RadeonSI as it needs to relocate all the data sections after + * the code sections. See https://reviews.llvm.org/D65813. + */ + unsigned address_space = + HAVE_LLVM < 0x1000 ? AC_ADDR_SPACE_GLOBAL : AC_ADDR_SPACE_CONST; + + LLVMValueRef global = + LLVMAddGlobalInAddressSpace(ctx->ac.module, type, + "const_data", + address_space); + + LLVMSetInitializer(global, data); + LLVMSetGlobalConstant(global, true); + LLVMSetVisibility(global, LLVMHiddenVisibility); + ctx->constant_data = global; +} + static void setup_shared(struct ac_nir_context *ctx, struct nir_shader *nir) @@ -4728,6 +4782,7 @@ void ac_nir_translate(struct ac_llvm_context *ac, struct ac_shader_abi *abi, setup_locals(&ctx, func); setup_scratch(&ctx, nir); + setup_constant_data(&ctx, nir); if (gl_shader_stage_is_compute(nir->info.stage)) setup_shared(&ctx, nir); -- 2.30.2