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/auxiliary | |
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/auxiliary')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_intr.c | 68 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_intr.h | 11 |
2 files changed, 55 insertions, 24 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, |