/**
* @file
- * Helper
+ * Helpers for emiting intrinsic calls.
*
- * LLVM IR doesn't support all basic arithmetic operations we care about (most
- * notably min/max and saturated operations), and it is often necessary to
- * resort machine-specific intrinsics directly. The functions here hide all
- * these implementation details from the other modules.
+ * LLVM vanilla IR doesn't represent all basic arithmetic operations we care
+ * about, and it is often necessary to resort target-specific intrinsics for
+ * performance, convenience.
*
- * We also do simple expressions simplification here. Reasons are:
- * - it is very easy given we have all necessary information readily available
- * - LLVM optimization passes fail to simplify several vector expressions
- * - We often know value constraints which the optimization passes have no way
- * of knowing, such as when source arguments are known to be in [0, 1] range.
+ * Ideally we would like to stay away from target specific intrinsics and
+ * move all the instruction selection logic into upstream LLVM where it belongs.
+ *
+ * These functions are also used for calling C functions provided by us from
+ * generated LLVM code.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#include "lp_bld_intr.h"
+LLVMValueRef
+lp_declare_intrinsic(LLVMModuleRef module,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMTypeRef *arg_types,
+ unsigned num_args)
+{
+ LLVMTypeRef function_type;
+ LLVMValueRef function;
+
+ assert(!LLVMGetNamedFunction(module, name));
+
+ function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0);
+ function = LLVMAddFunction(module, name, function_type);
+
+ LLVMSetFunctionCallConv(function, LLVMCCallConv);
+ LLVMSetLinkage(function, LLVMExternalLinkage);
+
+ assert(LLVMIsDeclaration(function));
+
+ if(name[0] == 'l' &&
+ name[1] == 'l' &&
+ name[2] == 'v' &&
+ name[3] == 'm' &&
+ name[4] == '.')
+ assert(LLVMGetIntrinsicID(function));
+
+ return function;
+}
+
+
LLVMValueRef
lp_build_intrinsic(LLVMBuilderRef builder,
const char *name,
LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
LLVMValueRef function;
- assert(num_args <= LP_MAX_FUNC_ARGS);
-
function = LLVMGetNamedFunction(module, name);
if(!function) {
LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS];
unsigned i;
+
+ assert(num_args <= LP_MAX_FUNC_ARGS);
+
for(i = 0; i < num_args; ++i) {
assert(args[i]);
arg_types[i] = LLVMTypeOf(args[i]);
}
- function = LLVMAddFunction(module, name, LLVMFunctionType(ret_type, arg_types, num_args, 0));
- LLVMSetFunctionCallConv(function, LLVMCCallConv);
- LLVMSetLinkage(function, LLVMExternalLinkage);
+
+ function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args);
}
- assert(LLVMIsDeclaration(function));
return LLVMBuildCall(builder, function, args, num_args, "");
}