diff options
author | Marek Olšák <[email protected]> | 2017-02-22 02:29:12 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2017-03-01 18:59:36 +0100 |
commit | 940da36a65c767ec9fc6817df3d0262b52de42f6 (patch) | |
tree | fd68b57b02c39b3c6bd60f56dff5333645a4f44f /src/gallium | |
parent | 408f370710a6f012fcfcb6b4d8b200f722a2ec7f (diff) |
gallivm,ac: add function attributes at call sites instead of declarations
They can vary at call sites if the intrinsic is NOT a legacy SI intrinsic.
We need this to force readnone or inaccessiblememonly on some amdgcn
intrinsics.
This is only used with LLVM 4.0 and later. Intrinsics only used with
LLVM <= 3.9 don't need the LEGACY flag.
gallivm and ac code is in the same patch, because splitting would be
more complicated with all the LEGACY uses all over the place.
v2: don't change the prototype of lp_add_function_attr.
Reviewed-by: Jose Fonseca <[email protected]> (v1)
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_intr.c | 68 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_intr.h | 11 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader.c | 52 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c | 14 |
4 files changed, 91 insertions, 54 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.c b/src/gallium/auxiliary/gallivm/lp_bld_intr.c index 049671a09f2..0b25ae5d9d6 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.c @@ -159,28 +159,56 @@ static const char *attr_to_str(enum lp_func_attr attr) #endif void -lp_add_function_attr(LLVMValueRef function, - int attr_idx, - enum lp_func_attr attr) +lp_add_function_attr(LLVMValueRef function_or_call, + int attr_idx, enum lp_func_attr attr) { #if HAVE_LLVM < 0x0400 LLVMAttribute llvm_attr = lp_attr_to_llvm_attr(attr); if (attr_idx == -1) { - LLVMAddFunctionAttr(function, llvm_attr); + LLVMAddFunctionAttr(function_or_call, llvm_attr); } else { - LLVMAddAttribute(LLVMGetParam(function, attr_idx - 1), llvm_attr); + LLVMAddAttribute(LLVMGetParam(function_or_call, attr_idx - 1), llvm_attr); } #else - LLVMContextRef context = LLVMGetModuleContext(LLVMGetGlobalParent(function)); + + LLVMModuleRef module; + if (LLVMIsAFunction(function_or_call)) { + module = LLVMGetGlobalParent(function_or_call); + } else { + LLVMBasicBlockRef bb = LLVMGetInstructionParent(function_or_call); + LLVMValueRef function = LLVMGetBasicBlockParent(bb); + module = LLVMGetGlobalParent(function); + } + LLVMContextRef ctx = LLVMGetModuleContext(module); + const char *attr_name = attr_to_str(attr); unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); - LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context, kind_id, 0); - LLVMAddAttributeAtIndex(function, attr_idx, llvm_attr); + LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(ctx, kind_id, 0); + + if (LLVMIsAFunction(function_or_call)) + LLVMAddAttributeAtIndex(function_or_call, attr_idx, llvm_attr); + else + LLVMAddCallSiteAttribute(function_or_call, attr_idx, llvm_attr); #endif } +static void +lp_add_func_attributes(LLVMValueRef function, unsigned attrib_mask) +{ + /* NoUnwind indicates that the intrinsic never raises a C++ exception. + * Set it for all intrinsics. + */ + attrib_mask |= LP_FUNC_ATTR_NOUNWIND; + attrib_mask &= ~LP_FUNC_ATTR_LEGACY; + + while (attrib_mask) { + enum lp_func_attr attr = 1u << u_bit_scan(&attrib_mask); + lp_add_function_attr(function, -1, attr); + } +} + LLVMValueRef lp_build_intrinsic(LLVMBuilderRef builder, const char *name, @@ -190,7 +218,9 @@ lp_build_intrinsic(LLVMBuilderRef builder, unsigned attr_mask) { LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); - LLVMValueRef function; + LLVMValueRef function, call; + bool set_callsite_attrs = HAVE_LLVM >= 0x0400 && + !(attr_mask & LP_FUNC_ATTR_LEGACY); function = LLVMGetNamedFunction(module, name); if(!function) { @@ -206,22 +236,18 @@ lp_build_intrinsic(LLVMBuilderRef builder, function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args); - /* NoUnwind indicates that the intrinsic never raises a C++ exception. - * Set it for all intrinsics. - */ - attr_mask |= LP_FUNC_ATTR_NOUNWIND; - - while (attr_mask) { - enum lp_func_attr attr = 1 << u_bit_scan(&attr_mask); - lp_add_function_attr(function, -1, attr); - } + if (!set_callsite_attrs) + lp_add_func_attributes(function, attr_mask); if (gallivm_debug & GALLIVM_DEBUG_IR) { lp_debug_dump_value(function); } } - return LLVMBuildCall(builder, function, args, num_args, ""); + call = LLVMBuildCall(builder, function, args, num_args, ""); + if (set_callsite_attrs) + lp_add_func_attributes(call, attr_mask); + return call; } @@ -309,9 +335,9 @@ lp_build_intrinsic_binary_anylength(struct gallivm_state *gallivm, unsigned num_vec = src_type.length / intrin_length; LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; - /* don't support arbitrary size here as this is so yuck */ + /* don't support arbitrary size here as this is so yuck */ if (src_type.length % intrin_length) { - /* FIXME: This is something which should be supported + /* FIXME: This is something which should be supported * but there doesn't seem to be any need for it currently * so crash and burn. */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.h b/src/gallium/auxiliary/gallivm/lp_bld_intr.h index 039e9ab8888..0032df5ceac 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.h @@ -54,6 +54,12 @@ enum lp_func_attr { LP_FUNC_ATTR_NOUNWIND = (1 << 4), LP_FUNC_ATTR_READNONE = (1 << 5), LP_FUNC_ATTR_READONLY = (1 << 6), + + /* Legacy intrinsic that needs attributes on function declarations + * and they must match the internal LLVM definition exactly, otherwise + * intrinsic selection fails. + */ + LP_FUNC_ATTR_LEGACY = (1u << 31), }; void @@ -70,9 +76,8 @@ lp_declare_intrinsic(LLVMModuleRef module, unsigned num_args); void -lp_add_function_attr(LLVMValueRef function, - int attr_idx, - enum lp_func_attr attr); +lp_add_function_attr(LLVMValueRef function_or_call, + int attr_idx, enum lp_func_attr attr); LLVMValueRef lp_build_intrinsic(LLVMBuilderRef builder, diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 8e51ae82d52..212a9bee800 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -401,7 +401,8 @@ static void declare_input_vs( input[i] = lp_build_intrinsic(gallivm->builder, "llvm.SI.vs.load.input", ctx->v4f32, args, 3, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | + LP_FUNC_ATTR_LEGACY); } /* Break up the vec4 into individual components */ @@ -1123,14 +1124,16 @@ static LLVMValueRef fetch_input_gs( value = lp_build_intrinsic(gallivm->builder, "llvm.SI.buffer.load.dword.i32.i32", ctx->i32, args, 9, - LP_FUNC_ATTR_READONLY); + LP_FUNC_ATTR_READONLY | + LP_FUNC_ATTR_LEGACY); if (tgsi_type_is_64bit(type)) { LLVMValueRef value2; args[2] = lp_build_const_int32(gallivm, (param * 4 + swizzle + 1) * 256); value2 = lp_build_intrinsic(gallivm->builder, "llvm.SI.buffer.load.dword.i32.i32", ctx->i32, args, 9, - LP_FUNC_ATTR_READONLY); + LP_FUNC_ATTR_READONLY | + LP_FUNC_ATTR_LEGACY); return si_llvm_emit_fetch_64bit(bld_base, type, value, value2); } @@ -1368,7 +1371,8 @@ static LLVMValueRef buffer_load_const(struct si_shader_context *ctx, LLVMValueRef args[2] = {resource, offset}; return lp_build_intrinsic(builder, "llvm.SI.load.const", ctx->f32, args, 2, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | + LP_FUNC_ATTR_LEGACY); } static LLVMValueRef load_sample_position(struct si_shader_context *radeon_bld, LLVMValueRef sample_id) @@ -1822,7 +1826,8 @@ static void si_llvm_init_export_args(struct lp_build_tgsi_context *bld_base, packed = lp_build_intrinsic(base->gallivm->builder, "llvm.SI.packf16", ctx->i32, pack_args, 2, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | + LP_FUNC_ATTR_LEGACY); args[chan + 5] = LLVMBuildBitCast(base->gallivm->builder, packed, ctx->f32, ""); @@ -1954,10 +1959,10 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base, lp_build_const_float(gallivm, -1.0f)); lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill", - ctx->voidt, &arg, 1, 0); + ctx->voidt, &arg, 1, LP_FUNC_ATTR_LEGACY); } else { lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kilp", - ctx->voidt, NULL, 0, 0); + ctx->voidt, NULL, 0, LP_FUNC_ATTR_LEGACY); } } @@ -2302,7 +2307,7 @@ handle_semantic: } else { lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", ctx->voidt, - args, 9, 0); + args, 9, LP_FUNC_ATTR_LEGACY); } if (semantic_name == TGSI_SEMANTIC_CLIPDIST) { @@ -2388,7 +2393,8 @@ handle_semantic: pos_args[i][2] = uint->one; lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", - ctx->voidt, pos_args[i], 9, 0); + ctx->voidt, pos_args[i], 9, + LP_FUNC_ATTR_LEGACY); } } @@ -2979,7 +2985,7 @@ static void si_emit_ps_exports(struct si_shader_context *ctx, for (unsigned i = 0; i < exp->num; i++) lp_build_intrinsic(ctx->gallivm.builder, "llvm.SI.export", ctx->voidt, - exp->args[i], 9, 0); + exp->args[i], 9, LP_FUNC_ATTR_LEGACY); } static void si_export_null(struct lp_build_tgsi_context *bld_base) @@ -3000,7 +3006,7 @@ static void si_export_null(struct lp_build_tgsi_context *bld_base) args[8] = base->undef; /* A */ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", - ctx->voidt, args, 9, 0); + ctx->voidt, args, 9, LP_FUNC_ATTR_LEGACY); } /** @@ -4089,7 +4095,7 @@ static void resq_emit( out = lp_build_intrinsic( builder, "llvm.SI.getresinfo.i32", emit_data->dst_type, emit_data->args, emit_data->arg_count, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY); /* Divide the number of layers by 6 to get the number of cubes. */ if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY) { @@ -4326,7 +4332,7 @@ static void txq_emit(const struct lp_build_tgsi_action *action, emit_data->output[emit_data->chan] = lp_build_intrinsic( base->gallivm->builder, "llvm.SI.getresinfo.i32", emit_data->dst_type, emit_data->args, emit_data->arg_count, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY); /* Divide the number of layers by 6 to get the number of cubes. */ if (target == TGSI_TEXTURE_CUBE_ARRAY || @@ -4735,7 +4741,7 @@ static void si_lower_gather4_integer(struct si_shader_context *ctx, emit_data->output[emit_data->chan] = lp_build_intrinsic(builder, intr_name, emit_data->dst_type, emit_data->args, emit_data->arg_count, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY); } static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, @@ -4759,7 +4765,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, base->gallivm->builder, "llvm.SI.vs.load.input", emit_data->dst_type, emit_data->args, emit_data->arg_count, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY); return; } @@ -4836,7 +4842,7 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action, 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, - LP_FUNC_ATTR_READNONE); + LP_FUNC_ATTR_READNONE | LP_FUNC_ATTR_LEGACY); } static void si_llvm_emit_txqs( @@ -5125,7 +5131,7 @@ static void si_llvm_emit_vertex( lp_build_const_float(gallivm, -1.0f)); lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.kill", - ctx->voidt, &kill, 1, 0); + ctx->voidt, &kill, 1, LP_FUNC_ATTR_LEGACY); } else { lp_build_if(&if_state, gallivm, can_emit); } @@ -5747,7 +5753,8 @@ static void si_llvm_emit_polygon_stipple(struct si_shader_context *ctx, /* The intrinsic kills the thread if arg < 0. */ bit = LLVMBuildSelect(builder, bit, LLVMConstReal(ctx->f32, 0), LLVMConstReal(ctx->f32, -1), ""); - lp_build_intrinsic(builder, "llvm.AMDGPU.kill", ctx->voidt, &bit, 1, 0); + lp_build_intrinsic(builder, "llvm.AMDGPU.kill", ctx->voidt, &bit, 1, + LP_FUNC_ATTR_LEGACY); } void si_shader_binary_read_config(struct ac_shader_binary *binary, @@ -6315,9 +6322,10 @@ si_generate_gs_copy_shader(struct si_screen *sscreen, outputs[i].values[chan] = LLVMBuildBitCast(gallivm->builder, lp_build_intrinsic(gallivm->builder, - "llvm.SI.buffer.load.dword.i32.i32", - ctx.i32, args, 9, - LP_FUNC_ATTR_READONLY), + "llvm.SI.buffer.load.dword.i32.i32", + ctx.i32, args, 9, + LP_FUNC_ATTR_READONLY | + LP_FUNC_ATTR_LEGACY), ctx.f32, ""); } } @@ -7686,7 +7694,7 @@ static void si_build_vs_epilog_function(struct si_shader_context *ctx, lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export", LLVMVoidTypeInContext(base->gallivm->context), - args, 9, 0); + args, 9, LP_FUNC_ATTR_LEGACY); } LLVMBuildRetVoid(gallivm->builder); diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c index 10268e9a28b..ee59fed607e 100644 --- a/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c +++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_alu.c @@ -58,13 +58,9 @@ static void kil_emit(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { - unsigned i; - for (i = 0; i < emit_data->arg_count; i++) { - emit_data->output[i] = lp_build_intrinsic_unary( - bld_base->base.gallivm->builder, - action->intr_name, - emit_data->dst_type, emit_data->args[i]); - } + lp_build_intrinsic(bld_base->base.gallivm->builder, + action->intr_name, emit_data->dst_type, + &emit_data->args[0], 1, LP_FUNC_ATTR_LEGACY); } static void emit_icmp(const struct lp_build_tgsi_action *action, @@ -507,7 +503,9 @@ static void emit_bfe(const struct lp_build_tgsi_action *action, bfe_sm5 = lp_build_intrinsic(builder, action->intr_name, emit_data->dst_type, emit_data->args, - emit_data->arg_count, LP_FUNC_ATTR_READNONE); + emit_data->arg_count, + LP_FUNC_ATTR_READNONE | + LP_FUNC_ATTR_LEGACY); /* Correct for GLSL semantics. */ cond = LLVMBuildICmp(builder, LLVMIntUGE, emit_data->args[2], |