diff options
author | Connor Abbott <[email protected]> | 2019-08-29 17:28:01 +0200 |
---|---|---|
committer | Connor Abbott <[email protected]> | 2019-09-05 12:21:42 +0200 |
commit | 91626d0865851bc7e2e21296d1d8f34149216e40 (patch) | |
tree | f499736f19c0e1fe23f22fdff78a13abebf702e1 | |
parent | 5dadbabb47c317f58a3b939d08e8e50745d92990 (diff) |
ac/nir: Support load_constant intrinsics
Setup a constant global variable that LLVM will stick in a .rodata
section and generate PC-relative loads for.
Reviewed-by: Marek Olšák <[email protected]>
-rw-r--r-- | src/amd/common/ac_nir_to_llvm.c | 55 |
1 files changed, 55 insertions, 0 deletions
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); @@ -4683,6 +4703,40 @@ setup_scratch(struct ac_nir_context *ctx, } 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); |