From 5ab25bb4ba429a866c2e36bd543bf0405047e325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 17 Oct 2016 12:30:42 +0200 Subject: [PATCH] radeonsi: import all TGSI->LLVM code from gallium/radeon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Nicolai Hähnle Reviewed-by: Emil Velikov Acked-by: Edward O'Callaghan --- .../drivers/r600/evergreen_compute_internal.h | 1 - src/gallium/drivers/radeon/Makefile.sources | 6 +- src/gallium/drivers/radeon/radeon_llvm.h | 151 ----------- src/gallium/drivers/radeon/radeon_llvm_emit.c | 241 ------------------ src/gallium/drivers/radeon/radeon_llvm_emit.h | 46 ---- src/gallium/drivers/radeonsi/Makefile.sources | 1 + src/gallium/drivers/radeonsi/si_pipe.c | 2 +- src/gallium/drivers/radeonsi/si_shader.c | 2 - .../drivers/radeonsi/si_shader_internal.h | 132 ++++++++++ .../drivers/radeonsi/si_shader_tgsi_alu.c | 1 - .../si_shader_tgsi_setup.c} | 225 +++++++++++++++- 11 files changed, 346 insertions(+), 462 deletions(-) delete mode 100644 src/gallium/drivers/radeon/radeon_llvm.h delete mode 100644 src/gallium/drivers/radeon/radeon_llvm_emit.c delete mode 100644 src/gallium/drivers/radeon/radeon_llvm_emit.h rename src/gallium/drivers/{radeon/radeon_setup_tgsi_llvm.c => radeonsi/si_shader_tgsi_setup.c} (87%) diff --git a/src/gallium/drivers/r600/evergreen_compute_internal.h b/src/gallium/drivers/r600/evergreen_compute_internal.h index e6ff7609aea..34d96f6d239 100644 --- a/src/gallium/drivers/r600/evergreen_compute_internal.h +++ b/src/gallium/drivers/r600/evergreen_compute_internal.h @@ -27,7 +27,6 @@ #include "r600_asm.h" #ifdef HAVE_OPENCL -#include "radeon/radeon_llvm.h" #include #endif diff --git a/src/gallium/drivers/radeon/Makefile.sources b/src/gallium/drivers/radeon/Makefile.sources index 049da60c134..3e13dae3cbb 100644 --- a/src/gallium/drivers/radeon/Makefile.sources +++ b/src/gallium/drivers/radeon/Makefile.sources @@ -25,8 +25,4 @@ C_SOURCES := \ LLVM_C_FILES := \ radeon_elf_util.c \ - radeon_elf_util.h \ - radeon_llvm_emit.c \ - radeon_llvm_emit.h \ - radeon_llvm.h \ - radeon_setup_tgsi_llvm.c + radeon_elf_util.h diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h deleted file mode 100644 index b4b968b26b7..00000000000 --- a/src/gallium/drivers/radeon/radeon_llvm.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2011 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: Tom Stellard - * - */ - -#ifndef RADEON_LLVM_H -#define RADEON_LLVM_H - -#include -#include "gallivm/lp_bld_init.h" -#include "gallivm/lp_bld_tgsi.h" -#include "tgsi/tgsi_parse.h" - -#define RADEON_LLVM_MAX_INPUT_SLOTS 32 -#define RADEON_LLVM_MAX_INPUTS 32 * 4 -#define RADEON_LLVM_MAX_OUTPUTS 32 * 4 - -#define RADEON_LLVM_INITIAL_CF_DEPTH 4 - -#define RADEON_LLVM_MAX_SYSTEM_VALUES 4 - -struct radeon_llvm_flow; - -struct radeon_llvm_context { - struct lp_build_tgsi_soa_context soa; - - /*=== Front end configuration ===*/ - - /* Instructions that are not described by any of the TGSI opcodes. */ - - /** This function is responsible for initilizing the inputs array and will be - * called once for each input declared in the TGSI shader. - */ - void (*load_input)(struct radeon_llvm_context *, - unsigned input_index, - const struct tgsi_full_declaration *decl, - LLVMValueRef out[4]); - - void (*load_system_value)(struct radeon_llvm_context *, - unsigned index, - const struct tgsi_full_declaration *decl); - - void (*declare_memory_region)(struct radeon_llvm_context *, - const struct tgsi_full_declaration *decl); - - /** This array contains the input values for the shader. Typically these - * values will be in the form of a target intrinsic that will inform the - * backend how to load the actual inputs to the shader. - */ - struct tgsi_full_declaration input_decls[RADEON_LLVM_MAX_INPUT_SLOTS]; - LLVMValueRef inputs[RADEON_LLVM_MAX_INPUTS]; - LLVMValueRef outputs[RADEON_LLVM_MAX_OUTPUTS][TGSI_NUM_CHANNELS]; - - /** This pointer is used to contain the temporary values. - * The amount of temporary used in tgsi can't be bound to a max value and - * thus we must allocate this array at runtime. - */ - LLVMValueRef *temps; - unsigned temps_count; - LLVMValueRef system_values[RADEON_LLVM_MAX_SYSTEM_VALUES]; - - /*=== Private Members ===*/ - - struct radeon_llvm_flow *flow; - unsigned flow_depth; - unsigned flow_depth_max; - - struct tgsi_array_info *temp_arrays; - LLVMValueRef *temp_array_allocas; - - LLVMValueRef undef_alloca; - - LLVMValueRef main_fn; - LLVMTypeRef return_type; - - unsigned fpmath_md_kind; - LLVMValueRef fpmath_md_2p5_ulp; - - struct gallivm_state gallivm; -}; - -LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base, - enum tgsi_opcode_type type); - -LLVMValueRef bitcast(struct lp_build_tgsi_context *bld_base, - enum tgsi_opcode_type type, LLVMValueRef value); - -LLVMValueRef radeon_llvm_bound_index(struct radeon_llvm_context *ctx, - LLVMValueRef index, - unsigned num); - -void radeon_llvm_context_init(struct radeon_llvm_context *ctx, - const char *triple, - const struct tgsi_shader_info *info, - const struct tgsi_token *tokens); - -void radeon_llvm_create_func(struct radeon_llvm_context *ctx, - LLVMTypeRef *return_types, unsigned num_return_elems, - LLVMTypeRef *ParamTypes, unsigned ParamCount); - -void radeon_llvm_dispose(struct radeon_llvm_context *ctx); - -void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx, - bool run_verifier); - -LLVMValueRef radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base, - enum tgsi_opcode_type type, - LLVMValueRef ptr, - LLVMValueRef ptr2); - -LLVMValueRef radeon_llvm_saturate(struct lp_build_tgsi_context *bld_base, - LLVMValueRef value); - -LLVMValueRef radeon_llvm_emit_fetch(struct lp_build_tgsi_context *bld_base, - const struct tgsi_full_src_register *reg, - enum tgsi_opcode_type type, - unsigned swizzle); - -void radeon_llvm_emit_store(struct lp_build_tgsi_context *bld_base, - const struct tgsi_full_instruction *inst, - const struct tgsi_opcode_info *info, - LLVMValueRef dst[4]); - -static inline struct radeon_llvm_context * -radeon_llvm_context(struct lp_build_tgsi_context *bld_base) -{ - return (struct radeon_llvm_context*)bld_base; -} - -#endif /* RADEON_LLVM_H */ diff --git a/src/gallium/drivers/radeon/radeon_llvm_emit.c b/src/gallium/drivers/radeon/radeon_llvm_emit.c deleted file mode 100644 index 9611f15103c..00000000000 --- a/src/gallium/drivers/radeon/radeon_llvm_emit.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2011 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: Tom Stellard - * - */ - -#include "radeon_llvm_emit.h" -#include "radeon_elf_util.h" -#include "c11/threads.h" -#include "gallivm/lp_bld_misc.h" -#include "util/u_debug.h" -#include "util/u_memory.h" -#include "pipe/p_shader_tokens.h" -#include "pipe/p_state.h" - -#include -#include -#include - -#include -#include -#include - -#define CPU_STRING_LEN 30 -#define FS_STRING_LEN 30 -#define TRIPLE_STRING_LEN 7 - -/** - * Shader types for the LLVM backend. - */ -enum radeon_llvm_shader_type { - RADEON_LLVM_SHADER_PS = 0, - RADEON_LLVM_SHADER_VS = 1, - RADEON_LLVM_SHADER_GS = 2, - RADEON_LLVM_SHADER_CS = 3, -}; - -enum radeon_llvm_calling_convention { - RADEON_LLVM_AMDGPU_VS = 87, - RADEON_LLVM_AMDGPU_GS = 88, - RADEON_LLVM_AMDGPU_PS = 89, - RADEON_LLVM_AMDGPU_CS = 90, -}; - -void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value) -{ - char str[16]; - - snprintf(str, sizeof(str), "%i", value); - LLVMAddTargetDependentFunctionAttr(F, name, str); -} - -/** - * Set the shader type we want to compile - * - * @param type shader type to set - */ -void radeon_llvm_shader_type(LLVMValueRef F, unsigned type) -{ - enum radeon_llvm_shader_type llvm_type; - enum radeon_llvm_calling_convention calling_conv; - - switch (type) { - case PIPE_SHADER_VERTEX: - case PIPE_SHADER_TESS_CTRL: - case PIPE_SHADER_TESS_EVAL: - llvm_type = RADEON_LLVM_SHADER_VS; - calling_conv = RADEON_LLVM_AMDGPU_VS; - break; - case PIPE_SHADER_GEOMETRY: - llvm_type = RADEON_LLVM_SHADER_GS; - calling_conv = RADEON_LLVM_AMDGPU_GS; - break; - case PIPE_SHADER_FRAGMENT: - llvm_type = RADEON_LLVM_SHADER_PS; - calling_conv = RADEON_LLVM_AMDGPU_PS; - break; - case PIPE_SHADER_COMPUTE: - llvm_type = RADEON_LLVM_SHADER_CS; - calling_conv = RADEON_LLVM_AMDGPU_CS; - break; - default: - unreachable("Unhandle shader type"); - } - - if (HAVE_LLVM >= 0x309) - LLVMSetFunctionCallConv(F, calling_conv); - else - radeon_llvm_add_attribute(F, "ShaderType", llvm_type); -} - -static void init_r600_target() -{ - gallivm_init_llvm_targets(); -#if HAVE_LLVM < 0x0307 - LLVMInitializeR600TargetInfo(); - LLVMInitializeR600Target(); - LLVMInitializeR600TargetMC(); - LLVMInitializeR600AsmPrinter(); -#else - LLVMInitializeAMDGPUTargetInfo(); - LLVMInitializeAMDGPUTarget(); - LLVMInitializeAMDGPUTargetMC(); - LLVMInitializeAMDGPUAsmPrinter(); - -#endif -} - -static once_flag init_r600_target_once_flag = ONCE_FLAG_INIT; - -LLVMTargetRef radeon_llvm_get_r600_target(const char *triple) -{ - LLVMTargetRef target = NULL; - char *err_message = NULL; - - call_once(&init_r600_target_once_flag, init_r600_target); - - if (LLVMGetTargetFromTriple(triple, &target, &err_message)) { - fprintf(stderr, "Cannot find target for triple %s ", triple); - if (err_message) { - fprintf(stderr, "%s\n", err_message); - } - LLVMDisposeMessage(err_message); - return NULL; - } - return target; -} - -struct radeon_llvm_diagnostics { - struct pipe_debug_callback *debug; - unsigned retval; -}; - -static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context) -{ - struct radeon_llvm_diagnostics *diag = (struct radeon_llvm_diagnostics *)context; - LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(di); - char *description = LLVMGetDiagInfoDescription(di); - const char *severity_str = NULL; - - switch (severity) { - case LLVMDSError: - severity_str = "error"; - break; - case LLVMDSWarning: - severity_str = "warning"; - break; - case LLVMDSRemark: - severity_str = "remark"; - break; - case LLVMDSNote: - severity_str = "note"; - break; - default: - severity_str = "unknown"; - } - - pipe_debug_message(diag->debug, SHADER_INFO, - "LLVM diagnostic (%s): %s", severity_str, description); - - if (severity == LLVMDSError) { - diag->retval = 1; - fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", description); - } - - LLVMDisposeMessage(description); -} - -/** - * Compile an LLVM module to machine code. - * - * @returns 0 for success, 1 for failure - */ -unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary, - LLVMTargetMachineRef tm, - struct pipe_debug_callback *debug) -{ - struct radeon_llvm_diagnostics diag; - char *err; - LLVMContextRef llvm_ctx; - LLVMMemoryBufferRef out_buffer; - unsigned buffer_size; - const char *buffer_data; - LLVMBool mem_err; - - diag.debug = debug; - diag.retval = 0; - - /* Setup Diagnostic Handler*/ - llvm_ctx = LLVMGetModuleContext(M); - - LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &diag); - - /* Compile IR*/ - mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, - &out_buffer); - - /* Process Errors/Warnings */ - if (mem_err) { - fprintf(stderr, "%s: %s", __FUNCTION__, err); - pipe_debug_message(debug, SHADER_INFO, - "LLVM emit error: %s", err); - FREE(err); - diag.retval = 1; - goto out; - } - - /* Extract Shader Code*/ - buffer_size = LLVMGetBufferSize(out_buffer); - buffer_data = LLVMGetBufferStart(out_buffer); - - radeon_elf_read(buffer_data, buffer_size, binary); - - /* Clean up */ - LLVMDisposeMemoryBuffer(out_buffer); - -out: - if (diag.retval != 0) - pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed"); - return diag.retval; -} diff --git a/src/gallium/drivers/radeon/radeon_llvm_emit.h b/src/gallium/drivers/radeon/radeon_llvm_emit.h deleted file mode 100644 index 677978b4758..00000000000 --- a/src/gallium/drivers/radeon/radeon_llvm_emit.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: Tom Stellard - * - */ - -#ifndef RADEON_LLVM_EMIT_H -#define RADEON_LLVM_EMIT_H - -#include -#include -#include - -struct pipe_debug_callback; -struct radeon_shader_binary; - -void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value); -void radeon_llvm_shader_type(LLVMValueRef F, unsigned type); - -LLVMTargetRef radeon_llvm_get_r600_target(const char *triple); - -unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary, - LLVMTargetMachineRef tm, - struct pipe_debug_callback *debug); - -#endif /* RADEON_LLVM_EMIT_H */ diff --git a/src/gallium/drivers/radeonsi/Makefile.sources b/src/gallium/drivers/radeonsi/Makefile.sources index a16f19c7ffb..727a9cccfc2 100644 --- a/src/gallium/drivers/radeonsi/Makefile.sources +++ b/src/gallium/drivers/radeonsi/Makefile.sources @@ -17,6 +17,7 @@ C_SOURCES := \ si_shader.h \ si_shader_internal.h \ si_shader_tgsi_alu.c \ + si_shader_tgsi_setup.c \ si_state.c \ si_state_draw.c \ si_state_shaders.c \ diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 5a3f1014cf2..79243753647 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -23,9 +23,9 @@ #include "si_pipe.h" #include "si_public.h" +#include "si_shader_internal.h" #include "sid.h" -#include "radeon/radeon_llvm_emit.h" #include "radeon/radeon_uvd.h" #include "util/u_memory.h" #include "util/u_suballoc.h" diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 37a812a2840..194da3194f8 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -33,9 +33,7 @@ #include "gallivm/lp_bld_arit.h" #include "gallivm/lp_bld_flow.h" #include "gallivm/lp_bld_misc.h" -#include "radeon/radeon_llvm.h" #include "radeon/radeon_elf_util.h" -#include "radeon/radeon_llvm_emit.h" #include "util/u_memory.h" #include "util/u_string.h" #include "tgsi/tgsi_build.h" diff --git a/src/gallium/drivers/radeonsi/si_shader_internal.h b/src/gallium/drivers/radeonsi/si_shader_internal.h index 44dd5fdc3b5..b46cc1c379d 100644 --- a/src/gallium/drivers/radeonsi/si_shader_internal.h +++ b/src/gallium/drivers/radeonsi/si_shader_internal.h @@ -27,6 +27,138 @@ #include "si_shader.h" #include "gallivm/lp_bld_init.h" #include "gallivm/lp_bld_tgsi.h" +#include "tgsi/tgsi_parse.h" + +#include +#include + +struct pipe_debug_callback; +struct radeon_shader_binary; + +#define RADEON_LLVM_MAX_INPUT_SLOTS 32 +#define RADEON_LLVM_MAX_INPUTS 32 * 4 +#define RADEON_LLVM_MAX_OUTPUTS 32 * 4 + +#define RADEON_LLVM_INITIAL_CF_DEPTH 4 + +#define RADEON_LLVM_MAX_SYSTEM_VALUES 4 + +struct radeon_llvm_flow; + +struct radeon_llvm_context { + struct lp_build_tgsi_soa_context soa; + + /*=== Front end configuration ===*/ + + /* Instructions that are not described by any of the TGSI opcodes. */ + + /** This function is responsible for initilizing the inputs array and will be + * called once for each input declared in the TGSI shader. + */ + void (*load_input)(struct radeon_llvm_context *, + unsigned input_index, + const struct tgsi_full_declaration *decl, + LLVMValueRef out[4]); + + void (*load_system_value)(struct radeon_llvm_context *, + unsigned index, + const struct tgsi_full_declaration *decl); + + void (*declare_memory_region)(struct radeon_llvm_context *, + const struct tgsi_full_declaration *decl); + + /** This array contains the input values for the shader. Typically these + * values will be in the form of a target intrinsic that will inform the + * backend how to load the actual inputs to the shader. + */ + struct tgsi_full_declaration input_decls[RADEON_LLVM_MAX_INPUT_SLOTS]; + LLVMValueRef inputs[RADEON_LLVM_MAX_INPUTS]; + LLVMValueRef outputs[RADEON_LLVM_MAX_OUTPUTS][TGSI_NUM_CHANNELS]; + + /** This pointer is used to contain the temporary values. + * The amount of temporary used in tgsi can't be bound to a max value and + * thus we must allocate this array at runtime. + */ + LLVMValueRef *temps; + unsigned temps_count; + LLVMValueRef system_values[RADEON_LLVM_MAX_SYSTEM_VALUES]; + + /*=== Private Members ===*/ + + struct radeon_llvm_flow *flow; + unsigned flow_depth; + unsigned flow_depth_max; + + struct tgsi_array_info *temp_arrays; + LLVMValueRef *temp_array_allocas; + + LLVMValueRef undef_alloca; + + LLVMValueRef main_fn; + LLVMTypeRef return_type; + + unsigned fpmath_md_kind; + LLVMValueRef fpmath_md_2p5_ulp; + + struct gallivm_state gallivm; +}; + +static inline struct radeon_llvm_context * +radeon_llvm_context(struct lp_build_tgsi_context *bld_base) +{ + return (struct radeon_llvm_context*)bld_base; +} + +void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value); +void radeon_llvm_shader_type(LLVMValueRef F, unsigned type); + +LLVMTargetRef radeon_llvm_get_r600_target(const char *triple); + +unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary, + LLVMTargetMachineRef tm, + struct pipe_debug_callback *debug); + +LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base, + enum tgsi_opcode_type type); + +LLVMValueRef bitcast(struct lp_build_tgsi_context *bld_base, + enum tgsi_opcode_type type, LLVMValueRef value); + +LLVMValueRef radeon_llvm_bound_index(struct radeon_llvm_context *ctx, + LLVMValueRef index, + unsigned num); + +void radeon_llvm_context_init(struct radeon_llvm_context *ctx, + const char *triple, + const struct tgsi_shader_info *info, + const struct tgsi_token *tokens); + +void radeon_llvm_create_func(struct radeon_llvm_context *ctx, + LLVMTypeRef *return_types, unsigned num_return_elems, + LLVMTypeRef *ParamTypes, unsigned ParamCount); + +void radeon_llvm_dispose(struct radeon_llvm_context *ctx); + +void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx, + bool run_verifier); + +LLVMValueRef radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base, + enum tgsi_opcode_type type, + LLVMValueRef ptr, + LLVMValueRef ptr2); + +LLVMValueRef radeon_llvm_saturate(struct lp_build_tgsi_context *bld_base, + LLVMValueRef value); + +LLVMValueRef radeon_llvm_emit_fetch(struct lp_build_tgsi_context *bld_base, + const struct tgsi_full_src_register *reg, + enum tgsi_opcode_type type, + unsigned swizzle); + +void radeon_llvm_emit_store(struct lp_build_tgsi_context *bld_base, + const struct tgsi_full_instruction *inst, + const struct tgsi_opcode_info *info, + LLVMValueRef dst[4]); void si_shader_context_init_alu(struct lp_build_tgsi_context *bld_base); void si_prepare_cube_coords(struct lp_build_tgsi_context *bld_base, diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c index 192a2cbf0ae..75ceb577b9c 100644 --- a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c +++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c @@ -26,7 +26,6 @@ #include "gallivm/lp_bld_intr.h" #include "gallivm/lp_bld_gather.h" #include "tgsi/tgsi_parse.h" -#include "radeon/radeon_llvm.h" static void kill_if_fetch_args(struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) diff --git a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c similarity index 87% rename from src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c rename to src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c index c06eb3eba70..e1534c717a0 100644 --- a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c +++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c @@ -1,12 +1,12 @@ /* - * Copyright 2011 Advanced Micro Devices, Inc. + * Copyright 2016 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the @@ -14,16 +14,15 @@ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: Tom Stellard - * + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "radeon_llvm.h" + +#include "si_shader_internal.h" +#include "radeon/radeon_elf_util.h" #include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_gather.h" @@ -39,7 +38,6 @@ #include "util/u_debug.h" #include -#include #include /* Data for if/else/endif and bgnloop/endloop control flow structures. @@ -50,6 +48,205 @@ struct radeon_llvm_flow { LLVMBasicBlockRef loop_entry_block; }; +#define CPU_STRING_LEN 30 +#define FS_STRING_LEN 30 +#define TRIPLE_STRING_LEN 7 + +/** + * Shader types for the LLVM backend. + */ +enum radeon_llvm_shader_type { + RADEON_LLVM_SHADER_PS = 0, + RADEON_LLVM_SHADER_VS = 1, + RADEON_LLVM_SHADER_GS = 2, + RADEON_LLVM_SHADER_CS = 3, +}; + +enum radeon_llvm_calling_convention { + RADEON_LLVM_AMDGPU_VS = 87, + RADEON_LLVM_AMDGPU_GS = 88, + RADEON_LLVM_AMDGPU_PS = 89, + RADEON_LLVM_AMDGPU_CS = 90, +}; + +void radeon_llvm_add_attribute(LLVMValueRef F, const char *name, int value) +{ + char str[16]; + + snprintf(str, sizeof(str), "%i", value); + LLVMAddTargetDependentFunctionAttr(F, name, str); +} + +/** + * Set the shader type we want to compile + * + * @param type shader type to set + */ +void radeon_llvm_shader_type(LLVMValueRef F, unsigned type) +{ + enum radeon_llvm_shader_type llvm_type; + enum radeon_llvm_calling_convention calling_conv; + + switch (type) { + case PIPE_SHADER_VERTEX: + case PIPE_SHADER_TESS_CTRL: + case PIPE_SHADER_TESS_EVAL: + llvm_type = RADEON_LLVM_SHADER_VS; + calling_conv = RADEON_LLVM_AMDGPU_VS; + break; + case PIPE_SHADER_GEOMETRY: + llvm_type = RADEON_LLVM_SHADER_GS; + calling_conv = RADEON_LLVM_AMDGPU_GS; + break; + case PIPE_SHADER_FRAGMENT: + llvm_type = RADEON_LLVM_SHADER_PS; + calling_conv = RADEON_LLVM_AMDGPU_PS; + break; + case PIPE_SHADER_COMPUTE: + llvm_type = RADEON_LLVM_SHADER_CS; + calling_conv = RADEON_LLVM_AMDGPU_CS; + break; + default: + unreachable("Unhandle shader type"); + } + + if (HAVE_LLVM >= 0x309) + LLVMSetFunctionCallConv(F, calling_conv); + else + radeon_llvm_add_attribute(F, "ShaderType", llvm_type); +} + +static void init_r600_target() +{ + gallivm_init_llvm_targets(); +#if HAVE_LLVM < 0x0307 + LLVMInitializeR600TargetInfo(); + LLVMInitializeR600Target(); + LLVMInitializeR600TargetMC(); + LLVMInitializeR600AsmPrinter(); +#else + LLVMInitializeAMDGPUTargetInfo(); + LLVMInitializeAMDGPUTarget(); + LLVMInitializeAMDGPUTargetMC(); + LLVMInitializeAMDGPUAsmPrinter(); + +#endif +} + +static once_flag init_r600_target_once_flag = ONCE_FLAG_INIT; + +LLVMTargetRef radeon_llvm_get_r600_target(const char *triple) +{ + LLVMTargetRef target = NULL; + char *err_message = NULL; + + call_once(&init_r600_target_once_flag, init_r600_target); + + if (LLVMGetTargetFromTriple(triple, &target, &err_message)) { + fprintf(stderr, "Cannot find target for triple %s ", triple); + if (err_message) { + fprintf(stderr, "%s\n", err_message); + } + LLVMDisposeMessage(err_message); + return NULL; + } + return target; +} + +struct radeon_llvm_diagnostics { + struct pipe_debug_callback *debug; + unsigned retval; +}; + +static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context) +{ + struct radeon_llvm_diagnostics *diag = (struct radeon_llvm_diagnostics *)context; + LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(di); + char *description = LLVMGetDiagInfoDescription(di); + const char *severity_str = NULL; + + switch (severity) { + case LLVMDSError: + severity_str = "error"; + break; + case LLVMDSWarning: + severity_str = "warning"; + break; + case LLVMDSRemark: + severity_str = "remark"; + break; + case LLVMDSNote: + severity_str = "note"; + break; + default: + severity_str = "unknown"; + } + + pipe_debug_message(diag->debug, SHADER_INFO, + "LLVM diagnostic (%s): %s", severity_str, description); + + if (severity == LLVMDSError) { + diag->retval = 1; + fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", description); + } + + LLVMDisposeMessage(description); +} + +/** + * Compile an LLVM module to machine code. + * + * @returns 0 for success, 1 for failure + */ +unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary, + LLVMTargetMachineRef tm, + struct pipe_debug_callback *debug) +{ + struct radeon_llvm_diagnostics diag; + char *err; + LLVMContextRef llvm_ctx; + LLVMMemoryBufferRef out_buffer; + unsigned buffer_size; + const char *buffer_data; + LLVMBool mem_err; + + diag.debug = debug; + diag.retval = 0; + + /* Setup Diagnostic Handler*/ + llvm_ctx = LLVMGetModuleContext(M); + + LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &diag); + + /* Compile IR*/ + mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, + &out_buffer); + + /* Process Errors/Warnings */ + if (mem_err) { + fprintf(stderr, "%s: %s", __FUNCTION__, err); + pipe_debug_message(debug, SHADER_INFO, + "LLVM emit error: %s", err); + FREE(err); + diag.retval = 1; + goto out; + } + + /* Extract Shader Code*/ + buffer_size = LLVMGetBufferSize(out_buffer); + buffer_data = LLVMGetBufferStart(out_buffer); + + radeon_elf_read(buffer_data, buffer_size, binary); + + /* Clean up */ + LLVMDisposeMemoryBuffer(out_buffer); + +out: + if (diag.retval != 0) + pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed"); + return diag.retval; +} + LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base, enum tgsi_opcode_type type) {