i965g: fix some reloc counts
[mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_intr.c
index a2051211b7a13780cee70150c22d7101db207b11..9895749d5686978930db5537b2cf0e7be64b0d38 100644 (file)
 
 /**
  * @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,
@@ -60,21 +90,20 @@ lp_build_intrinsic(LLVMBuilderRef builder,
    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, "");
 }