[Mesa-dev] [PATCH 7/7] radeonsi: optionally run the LLVM IR verifier pass
Marek Olšák
maraeo at gmail.com
Fri Sep 30 13:46:19 UTC 2016
I'm not so familiar with the LLVM basic block API, but this series
makes sense to me. For the series:
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Marek
On Thu, Sep 29, 2016 at 3:15 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> This is enabled automatically if shader printing is enabled, or separately
> by R600_DEBUG=checkir. Catch mal-formed IR before it crashes in a later
> pass.
> ---
> src/gallium/drivers/radeon/r600_pipe_common.c | 7 ++++++
> src/gallium/drivers/radeon/r600_pipe_common.h | 3 +++
> src/gallium/drivers/radeon/radeon_llvm.h | 3 ++-
> .../drivers/radeon/radeon_setup_tgsi_llvm.c | 6 ++++-
> src/gallium/drivers/radeonsi/si_shader.c | 28 ++++++++++++++++------
> 5 files changed, 38 insertions(+), 9 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 5b1ce04..e7bf7f2 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -632,20 +632,21 @@ static const struct debug_named_value common_debug_options[] = {
> { "vs", DBG_VS, "Print vertex shaders" },
> { "gs", DBG_GS, "Print geometry shaders" },
> { "ps", DBG_PS, "Print pixel shaders" },
> { "cs", DBG_CS, "Print compute shaders" },
> { "tcs", DBG_TCS, "Print tessellation control shaders" },
> { "tes", DBG_TES, "Print tessellation evaluation shaders" },
> { "noir", DBG_NO_IR, "Don't print the LLVM IR"},
> { "notgsi", DBG_NO_TGSI, "Don't print the TGSI"},
> { "noasm", DBG_NO_ASM, "Don't print disassembled shaders"},
> { "preoptir", DBG_PREOPT_IR, "Print the LLVM IR before initial optimizations" },
> + { "checkir", DBG_CHECK_IR, "Enable additional sanity checks on shader IR" },
>
> { "testdma", DBG_TEST_DMA, "Invoke SDMA tests and exit." },
>
> /* features */
> { "nodma", DBG_NO_ASYNC_DMA, "Disable asynchronous DMA" },
> { "nohyperz", DBG_NO_HYPERZ, "Disable Hyper-Z" },
> /* GL uses the word INVALIDATE, gallium uses the word DISCARD */
> { "noinvalrange", DBG_NO_DISCARD_RANGE, "Disable handling of INVALIDATE_RANGE map flags" },
> { "no2d", DBG_NO_2D_TILING, "Disable 2D tiling" },
> { "notiling", DBG_NO_TILING, "Disable tiling" },
> @@ -1276,20 +1277,26 @@ bool r600_can_dump_shader(struct r600_common_screen *rscreen,
> return (rscreen->debug_flags & DBG_GS) != 0;
> case PIPE_SHADER_FRAGMENT:
> return (rscreen->debug_flags & DBG_PS) != 0;
> case PIPE_SHADER_COMPUTE:
> return (rscreen->debug_flags & DBG_CS) != 0;
> default:
> return false;
> }
> }
>
> +bool r600_extra_shader_checks(struct r600_common_screen *rscreen, unsigned processor)
> +{
> + return (rscreen->debug_flags & DBG_CHECK_IR) ||
> + r600_can_dump_shader(rscreen, processor);
> +}
> +
> void r600_screen_clear_buffer(struct r600_common_screen *rscreen, struct pipe_resource *dst,
> uint64_t offset, uint64_t size, unsigned value,
> enum r600_coherency coher)
> {
> struct r600_common_context *rctx = (struct r600_common_context*)rscreen->aux_context;
>
> pipe_mutex_lock(rscreen->aux_context_lock);
> rctx->clear_buffer(&rctx->b, dst, offset, size, value, coher);
> rscreen->aux_context->flush(rscreen->aux_context, NULL, 0);
> pipe_mutex_unlock(rscreen->aux_context_lock);
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
> index f23f1c4..c836ab1 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.h
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.h
> @@ -71,20 +71,21 @@
> #define DBG_VS (1 << 6)
> #define DBG_GS (1 << 7)
> #define DBG_PS (1 << 8)
> #define DBG_CS (1 << 9)
> #define DBG_TCS (1 << 10)
> #define DBG_TES (1 << 11)
> #define DBG_NO_IR (1 << 12)
> #define DBG_NO_TGSI (1 << 13)
> #define DBG_NO_ASM (1 << 14)
> #define DBG_PREOPT_IR (1 << 15)
> +#define DBG_CHECK_IR (1 << 16)
> /* gaps */
> #define DBG_TEST_DMA (1 << 20)
> /* Bits 21-31 are reserved for the r600g driver. */
> /* features */
> #define DBG_NO_ASYNC_DMA (1llu << 32)
> #define DBG_NO_HYPERZ (1llu << 33)
> #define DBG_NO_DISCARD_RANGE (1llu << 34)
> #define DBG_NO_2D_TILING (1llu << 35)
> #define DBG_NO_TILING (1llu << 36)
> #define DBG_SWITCH_ON_EOP (1llu << 37)
> @@ -714,20 +715,22 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen,
> void r600_destroy_common_screen(struct r600_common_screen *rscreen);
> void r600_preflush_suspend_features(struct r600_common_context *ctx);
> void r600_postflush_resume_features(struct r600_common_context *ctx);
> bool r600_common_context_init(struct r600_common_context *rctx,
> struct r600_common_screen *rscreen,
> unsigned context_flags);
> void r600_common_context_cleanup(struct r600_common_context *rctx);
> void r600_context_add_resource_size(struct pipe_context *ctx, struct pipe_resource *r);
> bool r600_can_dump_shader(struct r600_common_screen *rscreen,
> unsigned processor);
> +bool r600_extra_shader_checks(struct r600_common_screen *rscreen,
> + unsigned processor);
> void r600_screen_clear_buffer(struct r600_common_screen *rscreen, struct pipe_resource *dst,
> uint64_t offset, uint64_t size, unsigned value,
> enum r600_coherency coher);
> struct pipe_resource *r600_resource_create_common(struct pipe_screen *screen,
> const struct pipe_resource *templ);
> const char *r600_get_llvm_processor_name(enum radeon_family family);
> void r600_need_dma_space(struct r600_common_context *ctx, unsigned num_dw,
> struct r600_resource *dst, struct r600_resource *src);
> void r600_dma_emit_wait_idle(struct r600_common_context *rctx);
> void radeon_save_cs(struct radeon_winsys *ws, struct radeon_winsys_cs *cs,
> diff --git a/src/gallium/drivers/radeon/radeon_llvm.h b/src/gallium/drivers/radeon/radeon_llvm.h
> index 2f9572a..6010254 100644
> --- a/src/gallium/drivers/radeon/radeon_llvm.h
> +++ b/src/gallium/drivers/radeon/radeon_llvm.h
> @@ -121,21 +121,22 @@ void radeon_llvm_context_init(struct radeon_llvm_context *ctx,
> 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);
>
> unsigned radeon_llvm_reg_index_soa(unsigned index, unsigned chan);
>
> -void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx);
> +void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx,
> + bool run_verifier);
>
> void build_tgsi_intrinsic_nomem(const struct lp_build_tgsi_action *action,
> struct lp_build_tgsi_context *bld_base,
> struct lp_build_emit_data *emit_data);
>
> LLVMValueRef radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base,
> enum tgsi_opcode_type type,
> LLVMValueRef ptr,
> LLVMValueRef ptr2);
>
> diff --git a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> index 80e9707..8e364c9 100644
> --- a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> +++ b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> @@ -2107,33 +2107,37 @@ void radeon_llvm_create_func(struct radeon_llvm_context *ctx,
>
> /* Setup the function */
> ctx->return_type = ret_type;
> main_fn_type = LLVMFunctionType(ret_type, ParamTypes, ParamCount, 0);
> ctx->main_fn = LLVMAddFunction(ctx->gallivm.module, "main", main_fn_type);
> main_fn_body = LLVMAppendBasicBlockInContext(ctx->gallivm.context,
> ctx->main_fn, "main_body");
> LLVMPositionBuilderAtEnd(ctx->gallivm.builder, main_fn_body);
> }
>
> -void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx)
> +void radeon_llvm_finalize_module(struct radeon_llvm_context *ctx,
> + bool run_verifier)
> {
> struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
> const char *triple = LLVMGetTarget(gallivm->module);
> LLVMTargetLibraryInfoRef target_library_info;
>
> /* Create the pass manager */
> gallivm->passmgr = LLVMCreateFunctionPassManagerForModule(
> gallivm->module);
>
> target_library_info = gallivm_create_target_library_info(triple);
> LLVMAddTargetLibraryInfo(target_library_info, gallivm->passmgr);
>
> + if (run_verifier)
> + LLVMAddVerifierPass(gallivm->passmgr);
> +
> /* This pass should eliminate all the load and store instructions */
> LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr);
>
> /* Add some optimization passes */
> LLVMAddScalarReplAggregatesPass(gallivm->passmgr);
> LLVMAddLICMPass(gallivm->passmgr);
> LLVMAddAggressiveDCEPass(gallivm->passmgr);
> LLVMAddCFGSimplificationPass(gallivm->passmgr);
> LLVMAddInstructionCombiningPass(gallivm->passmgr);
>
> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
> index 3ccff7a..2cabff6 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.c
> +++ b/src/gallium/drivers/radeonsi/si_shader.c
> @@ -6424,21 +6424,23 @@ static int si_generate_gs_copy_shader(struct si_screen *sscreen,
>
> si_llvm_export_vs(bld_base, outputs, gsinfo->num_outputs);
>
> LLVMBuildRetVoid(gallivm->builder);
>
> /* Dump LLVM IR before any optimization passes */
> if (sscreen->b.debug_flags & DBG_PREOPT_IR &&
> r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
> LLVMDumpModule(bld_base->base.gallivm->module);
>
> - radeon_llvm_finalize_module(&ctx->radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx->radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_GEOMETRY));
>
> r = si_compile_llvm(sscreen, &ctx->shader->binary,
> &ctx->shader->config, ctx->tm,
> bld_base->base.gallivm->module,
> debug, PIPE_SHADER_GEOMETRY,
> "GS Copy Shader");
> if (!r) {
> if (r600_can_dump_shader(&sscreen->b, PIPE_SHADER_GEOMETRY))
> fprintf(stderr, "GS Copy Shader:\n");
> si_shader_dump(sscreen, ctx->shader, debug,
> @@ -6708,21 +6710,23 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
> }
>
> si_llvm_build_ret(&ctx, ctx.return_value);
> mod = bld_base->base.gallivm->module;
>
> /* Dump LLVM IR before any optimization passes */
> if (sscreen->b.debug_flags & DBG_PREOPT_IR &&
> r600_can_dump_shader(&sscreen->b, ctx.type))
> LLVMDumpModule(mod);
>
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, ctx.type));
>
> r = si_compile_llvm(sscreen, &shader->binary, &shader->config, tm,
> mod, debug, ctx.type, "TGSI shader");
> if (r) {
> fprintf(stderr, "LLVM failed to compile shader\n");
> goto out;
> }
>
> radeon_llvm_dispose(&ctx.radeon_bld);
>
> @@ -6969,21 +6973,23 @@ static bool si_compile_vs_prolog(struct si_screen *sscreen,
> LLVMGetParam(func, SI_SGPR_BASE_VERTEX), "");
> }
>
> index = LLVMBuildBitCast(gallivm->builder, index, ctx.f32, "");
> ret = LLVMBuildInsertValue(gallivm->builder, ret, index,
> num_params++, "");
> }
>
> /* Compile. */
> si_llvm_build_ret(&ctx, ret);
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
>
> if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
> gallivm->module, debug, ctx.type,
> "Vertex Shader Prolog"))
> status = false;
>
> radeon_llvm_dispose(&ctx.radeon_bld);
> return status;
> }
>
> @@ -7041,21 +7047,23 @@ static bool si_compile_vs_epilog(struct si_screen *sscreen,
> args[7] = uint->undef; /* Z */
> args[8] = uint->undef; /* W */
>
> lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
> LLVMVoidTypeInContext(base->gallivm->context),
> args, 9, 0);
> }
>
> /* Compile. */
> LLVMBuildRetVoid(gallivm->builder);
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_VERTEX));
>
> if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
> gallivm->module, debug, ctx.type,
> "Vertex Shader Epilog"))
> status = false;
>
> radeon_llvm_dispose(&ctx.radeon_bld);
> return status;
> }
>
> @@ -7194,21 +7202,23 @@ static bool si_compile_tcs_epilog(struct si_screen *sscreen,
> declare_tess_lds(&ctx);
> func = ctx.radeon_bld.main_fn;
>
> si_write_tess_factors(bld_base,
> LLVMGetParam(func, last_sgpr + 1),
> LLVMGetParam(func, last_sgpr + 2),
> LLVMGetParam(func, last_sgpr + 3));
>
> /* Compile. */
> LLVMBuildRetVoid(gallivm->builder);
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_TESS_CTRL));
>
> if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
> gallivm->module, debug, ctx.type,
> "Tessellation Control Shader Epilog"))
> status = false;
>
> radeon_llvm_dispose(&ctx.radeon_bld);
> return status;
> }
>
> @@ -7478,21 +7488,23 @@ static bool si_compile_ps_prolog(struct si_screen *sscreen,
> }
>
> /* Tell LLVM to insert WQM instruction sequence when needed. */
> if (key->ps_prolog.wqm) {
> LLVMAddTargetDependentFunctionAttr(func,
> "amdgpu-ps-wqm-outputs", "");
> }
>
> /* Compile. */
> si_llvm_build_ret(&ctx, ret);
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
>
> if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
> gallivm->module, debug, ctx.type,
> "Fragment Shader Prolog"))
> status = false;
>
> radeon_llvm_dispose(&ctx.radeon_bld);
> return status;
> }
>
> @@ -7598,21 +7610,23 @@ static bool si_compile_ps_epilog(struct si_screen *sscreen,
> if (depth || stencil || samplemask)
> si_export_mrt_z(bld_base, depth, stencil, samplemask, &exp);
> else if (last_color_export == -1)
> si_export_null(bld_base);
>
> if (exp.num)
> si_emit_ps_exports(&ctx, &exp);
>
> /* Compile. */
> LLVMBuildRetVoid(gallivm->builder);
> - radeon_llvm_finalize_module(&ctx.radeon_bld);
> + radeon_llvm_finalize_module(
> + &ctx.radeon_bld,
> + r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_FRAGMENT));
>
> if (si_compile_llvm(sscreen, &out->binary, &out->config, tm,
> gallivm->module, debug, ctx.type,
> "Fragment Shader Epilog"))
> status = false;
>
> radeon_llvm_dispose(&ctx.radeon_bld);
> return status;
> }
>
> --
> 2.7.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list