llvmpipe: More intrinsic helpers.
This commit is contained in:
@@ -50,6 +50,46 @@
|
||||
#include "lp_bld_intr.h"
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef *args,
|
||||
unsigned num_args)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
assert(LLVMIsDeclaration(function));
|
||||
|
||||
return LLVMBuildCall(builder, function, args, num_args, "");
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_unary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
return lp_build_intrinsic(builder, name, ret_type, &a, 1);
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_binary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
@@ -57,31 +97,67 @@ lp_build_intrinsic_binary(LLVMBuilderRef builder,
|
||||
LLVMValueRef a,
|
||||
LLVMValueRef b)
|
||||
{
|
||||
LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
|
||||
LLVMValueRef function;
|
||||
LLVMValueRef args[2];
|
||||
|
||||
function = LLVMGetNamedFunction(module, name);
|
||||
if(!function) {
|
||||
LLVMTypeRef arg_types[2];
|
||||
arg_types[0] = LLVMTypeOf(a);
|
||||
arg_types[1] = LLVMTypeOf(b);
|
||||
function = LLVMAddFunction(module, name, LLVMFunctionType(ret_type, arg_types, 2, 0));
|
||||
LLVMSetFunctionCallConv(function, LLVMCCallConv);
|
||||
LLVMSetLinkage(function, LLVMExternalLinkage);
|
||||
}
|
||||
assert(LLVMIsDeclaration(function));
|
||||
|
||||
#ifdef DEBUG
|
||||
/* We shouldn't use only constants with intrinsics, as they won't be
|
||||
* propagated by LLVM optimization passes.
|
||||
*/
|
||||
if(LLVMIsConstant(a) && LLVMIsConstant(b))
|
||||
debug_printf("warning: invoking intrinsic \"%s\" with constants\n");
|
||||
#endif
|
||||
|
||||
args[0] = a;
|
||||
args[1] = b;
|
||||
|
||||
return LLVMBuildCall(builder, function, args, 2, "");
|
||||
return lp_build_intrinsic(builder, name, ret_type, args, 2);
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef *args,
|
||||
unsigned num_args)
|
||||
{
|
||||
LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type);
|
||||
unsigned n = LLVMGetVectorSize(ret_type);
|
||||
unsigned i, j;
|
||||
LLVMValueRef res;
|
||||
|
||||
assert(num_args <= LP_MAX_FUNC_ARGS);
|
||||
|
||||
res = LLVMGetUndef(ret_type);
|
||||
for(i = 0; i < n; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS];
|
||||
LLVMValueRef res_elem;
|
||||
for(j = 0; j < num_args; ++j)
|
||||
arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, "");
|
||||
res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args);
|
||||
res = LLVMBuildInsertElement(builder, res, res_elem, index, "");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map_unary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
return lp_build_intrinsic_map(builder, name, ret_type, &a, 1);
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map_binary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a,
|
||||
LLVMValueRef b)
|
||||
{
|
||||
LLVMValueRef args[2];
|
||||
|
||||
args[0] = a;
|
||||
args[1] = b;
|
||||
|
||||
return lp_build_intrinsic_map(builder, name, ret_type, args, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper arithmetic functions.
|
||||
* Helper functions for calling intrinsics.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
@@ -40,6 +40,24 @@
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
|
||||
#define LP_MAX_FUNC_ARGS 32
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef *args,
|
||||
unsigned num_args);
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_unary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a);
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_binary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
@@ -48,4 +66,27 @@ lp_build_intrinsic_binary(LLVMBuilderRef builder,
|
||||
LLVMValueRef b);
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef *args,
|
||||
unsigned num_args);
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map_unary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a);
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_intrinsic_map_binary(LLVMBuilderRef builder,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMValueRef a,
|
||||
LLVMValueRef b);
|
||||
|
||||
|
||||
#endif /* !LP_BLD_INTR_H */
|
||||
|
||||
Reference in New Issue
Block a user