From aff4a630aad2b7a4edc70b2e2c8f29748fc06c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Fri, 4 Nov 2016 16:11:31 +0100 Subject: [PATCH] radeonsi: apply the Convergent attribute to old-style image intrinsics TODO this is pending LLVM support This fixes piglit glsl-1.10/execution/fs-texture-select and similar bugs. At some point, we should use new-style intrinsics where the Convergent attribute from the .td files in LLVM is honored. However, those aren't ReadNone, and that might hurt the quality of generated code. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97988 --- src/amd/common/ac_llvm_helper.cpp | 16 ++++++++++++++++ src/amd/common/ac_llvm_util.h | 1 + src/gallium/drivers/radeonsi/si_shader.c | 4 ++++ 3 files changed, 21 insertions(+) diff --git a/src/amd/common/ac_llvm_helper.cpp b/src/amd/common/ac_llvm_helper.cpp index 594339e..bae184f 100644 --- a/src/amd/common/ac_llvm_helper.cpp +++ b/src/amd/common/ac_llvm_helper.cpp @@ -46,10 +46,26 @@ void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes) } bool ac_is_sgpr_param(LLVMValueRef arg) { llvm::Argument *A = llvm::unwrap(arg); llvm::AttributeSet AS = A->getParent()->getAttributes(); unsigned ArgNo = A->getArgNo(); return AS.hasAttribute(ArgNo + 1, llvm::Attribute::ByVal) || AS.hasAttribute(ArgNo + 1, llvm::Attribute::InReg); } + +/** + * Fix the definition of an old-style llvm.SI.image intrinsic. + */ +void ac_fixup_image_intrinsic(LLVMModuleRef module, const char *intr_name, + bool has_sampler) +{ + if (HAVE_LLVM < 0x0400) + return; + + LLVMValueRef func = LLVMGetNamedFunction(module, intr_name); + llvm::Function *F = llvm::unwrap(func); + F->addAttribute(1 + 2, llvm::Attribute::Convergent); + if (has_sampler) + F->addAttribute(1 + 3, llvm::Attribute::Convergent); +} diff --git a/src/amd/common/ac_llvm_util.h b/src/amd/common/ac_llvm_util.h index d9ea9bd..85c3cc6 100644 --- a/src/amd/common/ac_llvm_util.h +++ b/src/amd/common/ac_llvm_util.h @@ -30,14 +30,15 @@ #include "amd_family.h" #ifdef __cplusplus extern "C" { #endif LLVMTargetMachineRef ac_create_target_machine(enum radeon_family family); void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes); bool ac_is_sgpr_param(LLVMValueRef param); +void ac_fixup_image_intrinsic(LLVMModuleRef, const char *intr_name, bool has_sampler); #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 86dd9d5..6a8c648 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -4674,20 +4674,21 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, struct lp_build_emit_data *emit_data) { struct si_shader_context *ctx = si_shader_context(bld_base); struct lp_build_context *base = &bld_base->base; const struct tgsi_full_instruction *inst = emit_data->inst; unsigned opcode = inst->Instruction.Opcode; unsigned target = inst->Texture.Texture; char intr_name[127]; bool has_offset = inst->Texture.NumOffsets > 0; bool is_shadow = tgsi_is_shadow_target(target); + bool has_sampler = true; char type[64]; const char *name = "llvm.SI.image.sample"; const char *infix = ""; if (target == TGSI_TEXTURE_BUFFER) { emit_data->output[emit_data->chan] = lp_build_intrinsic( base->gallivm->builder, "llvm.SI.vs.load.input", emit_data->dst_type, emit_data->args, emit_data->arg_count, LLVMReadNoneAttribute); @@ -4695,20 +4696,21 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, } switch (opcode) { case TGSI_OPCODE_TXF: name = target == TGSI_TEXTURE_2D_MSAA || target == TGSI_TEXTURE_2D_ARRAY_MSAA ? "llvm.SI.image.load" : "llvm.SI.image.load.mip"; is_shadow = false; has_offset = false; + has_sampler = false; break; case TGSI_OPCODE_LODQ: name = "llvm.SI.getlod"; is_shadow = false; has_offset = false; break; case TGSI_OPCODE_TEX: case TGSI_OPCODE_TEX2: case TGSI_OPCODE_TXP: if (ctx->type != PIPE_SHADER_FRAGMENT) @@ -4753,28 +4755,30 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER); if (info->sampler_type[sampler] == TGSI_RETURN_TYPE_SINT || info->sampler_type[sampler] == TGSI_RETURN_TYPE_UINT) { /* Texture coordinates start after: * {offset, bias, z-compare, derivatives} * Only the offset and z-compare can occur here. */ si_lower_gather4_integer(ctx, emit_data, intr_name, (int)has_offset + (int)is_shadow); + ac_fixup_image_intrinsic(ctx->gallivm.module, intr_name, has_sampler); return; } } emit_data->output[emit_data->chan] = lp_build_intrinsic( base->gallivm->builder, intr_name, emit_data->dst_type, emit_data->args, emit_data->arg_count, LLVMReadNoneAttribute); + ac_fixup_image_intrinsic(ctx->gallivm.module, intr_name, has_sampler); } static void si_llvm_emit_txqs( const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct si_shader_context *ctx = si_shader_context(bld_base); struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; -- 2.7.4