[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