summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/gallivm
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2017-02-22 02:29:12 +0100
committerMarek Olšák <[email protected]>2017-03-01 18:59:36 +0100
commit940da36a65c767ec9fc6817df3d0262b52de42f6 (patch)
treefd68b57b02c39b3c6bd60f56dff5333645a4f44f /src/gallium/auxiliary/gallivm
parent408f370710a6f012fcfcb6b4d8b200f722a2ec7f (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/gallivm')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_intr.c68
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_intr.h11
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,