1627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca/**************************************************************************
2627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
3627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * Copyright 2009 VMware, Inc.
4627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * All Rights Reserved.
5627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
6627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * Permission is hereby granted, free of charge, to any person obtaining a
7627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * copy of this software and associated documentation files (the
8627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * "Software"), to deal in the Software without restriction, including
9627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * without limitation the rights to use, copy, modify, merge, publish,
10627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * distribute, sub license, and/or sell copies of the Software, and to
11627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * permit persons to whom the Software is furnished to do so, subject to
12627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * the following conditions:
13627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
14627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * The above copyright notice and this permission notice (including the
15627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * next paragraph) shall be included in all copies or substantial portions
16627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * of the Software.
17627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
18627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
26627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca **************************************************************************/
27627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
28627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
29627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca/**
30627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * @file
315811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * Helpers for emiting intrinsic calls.
325811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
335811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * LLVM vanilla IR doesn't represent all basic arithmetic operations we care
345811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * about, and it is often necessary to resort target-specific intrinsics for
355811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * performance, convenience.
365811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
375811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * Ideally we would like to stay away from target specific intrinsics and
385811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * move all the instruction selection logic into upstream LLVM where it belongs.
395811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca *
405811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * These functions are also used for calling C functions provided by us from
415811ed87d732101ab8cfbd087bc99d8c6c963f30José Fonseca * generated LLVM code.
42627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca *
43627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca * @author Jose Fonseca <jfonseca@vmware.com>
44627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca */
45627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
46627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
47627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca#include "util/u_debug.h"
48627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
49efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul#include "lp_bld_const.h"
50627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca#include "lp_bld_intr.h"
513469715a8a171512cf9b528702e70393f01c6041José Fonseca#include "lp_bld_type.h"
523469715a8a171512cf9b528702e70393f01c6041José Fonseca#include "lp_bld_pack.h"
53627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
54627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
55627d6a6b044b3916996cb9f50ce7f911f2196565José FonsecaLLVMValueRef
5603180dca7a3b5d57100158eb06d00419e55d9dc8José Fonsecalp_declare_intrinsic(LLVMModuleRef module,
5703180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca                     const char *name,
5803180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca                     LLVMTypeRef ret_type,
5903180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca                     LLVMTypeRef *arg_types,
6003180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca                     unsigned num_args)
6103180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca{
6203180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   LLVMTypeRef function_type;
6303180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   LLVMValueRef function;
6403180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
6503180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   assert(!LLVMGetNamedFunction(module, name));
6603180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
6703180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0);
6803180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   function = LLVMAddFunction(module, name, function_type);
6903180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
7003180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   LLVMSetFunctionCallConv(function, LLVMCCallConv);
7103180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   LLVMSetLinkage(function, LLVMExternalLinkage);
7203180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
7303180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   assert(LLVMIsDeclaration(function));
7403180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
7503180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   return function;
7603180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca}
7703180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
7803180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
7903180dca7a3b5d57100158eb06d00419e55d9dc8José FonsecaLLVMValueRef
8036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonsecalp_build_intrinsic(LLVMBuilderRef builder,
8136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                   const char *name,
8236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                   LLVMTypeRef ret_type,
8336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                   LLVMValueRef *args,
8436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                   unsigned num_args)
85627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca{
86627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
87627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   LLVMValueRef function;
8836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
89627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   function = LLVMGetNamedFunction(module, name);
90627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   if(!function) {
9136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS];
9236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      unsigned i;
9303180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
9403180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca      assert(num_args <= LP_MAX_FUNC_ARGS);
9503180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca
9636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      for(i = 0; i < num_args; ++i) {
9736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca         assert(args[i]);
9836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca         arg_types[i] = LLVMTypeOf(args[i]);
9936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      }
100627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
10103180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca      function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args);
10203180dca7a3b5d57100158eb06d00419e55d9dc8José Fonseca   }
10358f20b2b65ec0237202dad2be5db6b29d3cf6e93José Fonseca
10436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   return LLVMBuildCall(builder, function, args, num_args, "");
10536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca}
10636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
10736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
10836249348ed6dfae63ef2b81e6db88c975a801f2aJosé FonsecaLLVMValueRef
10936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonsecalp_build_intrinsic_unary(LLVMBuilderRef builder,
11036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                         const char *name,
11136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                         LLVMTypeRef ret_type,
11236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                         LLVMValueRef a)
11336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca{
11436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   return lp_build_intrinsic(builder, name, ret_type, &a, 1);
11536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca}
11636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
11736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
11836249348ed6dfae63ef2b81e6db88c975a801f2aJosé FonsecaLLVMValueRef
11936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonsecalp_build_intrinsic_binary(LLVMBuilderRef builder,
12036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                          const char *name,
12136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                          LLVMTypeRef ret_type,
12236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                          LLVMValueRef a,
12336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                          LLVMValueRef b)
12436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca{
12536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   LLVMValueRef args[2];
126627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
127627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   args[0] = a;
128627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca   args[1] = b;
129627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca
13036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   return lp_build_intrinsic(builder, name, ret_type, args, 2);
131627d6a6b044b3916996cb9f50ce7f911f2196565José Fonseca}
13236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
13336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
1343469715a8a171512cf9b528702e70393f01c6041José Fonseca/**
1353469715a8a171512cf9b528702e70393f01c6041José Fonseca * Call intrinsic with arguments adapted to intrinsic vector length.
1363469715a8a171512cf9b528702e70393f01c6041José Fonseca *
1373469715a8a171512cf9b528702e70393f01c6041José Fonseca * Split vectors which are too large for the hw, or expand them if they
1383469715a8a171512cf9b528702e70393f01c6041José Fonseca * are too small, so a caller calling a function which might use intrinsics
1393469715a8a171512cf9b528702e70393f01c6041José Fonseca * doesn't need to do splitting/expansion on its own.
1403469715a8a171512cf9b528702e70393f01c6041José Fonseca * This only supports intrinsics where src and dst types match.
1413469715a8a171512cf9b528702e70393f01c6041José Fonseca */
1423469715a8a171512cf9b528702e70393f01c6041José FonsecaLLVMValueRef
1433469715a8a171512cf9b528702e70393f01c6041José Fonsecalp_build_intrinsic_binary_anylength(struct gallivm_state *gallivm,
1443469715a8a171512cf9b528702e70393f01c6041José Fonseca                                    const char *name,
1453469715a8a171512cf9b528702e70393f01c6041José Fonseca                                    struct lp_type src_type,
1463469715a8a171512cf9b528702e70393f01c6041José Fonseca                                    unsigned intr_size,
1473469715a8a171512cf9b528702e70393f01c6041José Fonseca                                    LLVMValueRef a,
1483469715a8a171512cf9b528702e70393f01c6041José Fonseca                                    LLVMValueRef b)
1493469715a8a171512cf9b528702e70393f01c6041José Fonseca{
1503469715a8a171512cf9b528702e70393f01c6041José Fonseca   unsigned i;
1513469715a8a171512cf9b528702e70393f01c6041José Fonseca   struct lp_type intrin_type = src_type;
1523469715a8a171512cf9b528702e70393f01c6041José Fonseca   LLVMBuilderRef builder = gallivm->builder;
1533469715a8a171512cf9b528702e70393f01c6041José Fonseca   LLVMValueRef i32undef = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
1543469715a8a171512cf9b528702e70393f01c6041José Fonseca   LLVMValueRef anative, bnative;
1553469715a8a171512cf9b528702e70393f01c6041José Fonseca   unsigned intrin_length = intr_size / src_type.width;
1563469715a8a171512cf9b528702e70393f01c6041José Fonseca
1573469715a8a171512cf9b528702e70393f01c6041José Fonseca   intrin_type.length = intrin_length;
1583469715a8a171512cf9b528702e70393f01c6041José Fonseca
1593469715a8a171512cf9b528702e70393f01c6041José Fonseca   if (intrin_length > src_type.length) {
1603469715a8a171512cf9b528702e70393f01c6041José Fonseca      LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
1613469715a8a171512cf9b528702e70393f01c6041José Fonseca      LLVMValueRef constvec, tmp;
1623469715a8a171512cf9b528702e70393f01c6041José Fonseca
1633469715a8a171512cf9b528702e70393f01c6041José Fonseca      for (i = 0; i < src_type.length; i++) {
1643469715a8a171512cf9b528702e70393f01c6041José Fonseca         elems[i] = lp_build_const_int32(gallivm, i);
1653469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
1663469715a8a171512cf9b528702e70393f01c6041José Fonseca      for (; i < intrin_length; i++) {
1673469715a8a171512cf9b528702e70393f01c6041José Fonseca         elems[i] = i32undef;
1683469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
1693469715a8a171512cf9b528702e70393f01c6041José Fonseca      if (src_type.length == 1) {
1703469715a8a171512cf9b528702e70393f01c6041José Fonseca         LLVMTypeRef elem_type = lp_build_elem_type(gallivm, intrin_type);
1713469715a8a171512cf9b528702e70393f01c6041José Fonseca         a = LLVMBuildBitCast(builder, a, LLVMVectorType(elem_type, 1), "");
1723469715a8a171512cf9b528702e70393f01c6041José Fonseca         b = LLVMBuildBitCast(builder, b, LLVMVectorType(elem_type, 1), "");
1733469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
1743469715a8a171512cf9b528702e70393f01c6041José Fonseca      constvec = LLVMConstVector(elems, intrin_length);
1753469715a8a171512cf9b528702e70393f01c6041José Fonseca      anative = LLVMBuildShuffleVector(builder, a, a, constvec, "");
1763469715a8a171512cf9b528702e70393f01c6041José Fonseca      bnative = LLVMBuildShuffleVector(builder, b, b, constvec, "");
1773469715a8a171512cf9b528702e70393f01c6041José Fonseca      tmp = lp_build_intrinsic_binary(builder, name,
1783469715a8a171512cf9b528702e70393f01c6041José Fonseca                                      lp_build_vec_type(gallivm, intrin_type),
1793469715a8a171512cf9b528702e70393f01c6041José Fonseca                                      anative, bnative);
1803469715a8a171512cf9b528702e70393f01c6041José Fonseca      if (src_type.length > 1) {
1813469715a8a171512cf9b528702e70393f01c6041José Fonseca         constvec = LLVMConstVector(elems, src_type.length);
1823469715a8a171512cf9b528702e70393f01c6041José Fonseca         return LLVMBuildShuffleVector(builder, tmp, tmp, constvec, "");
1833469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
1843469715a8a171512cf9b528702e70393f01c6041José Fonseca      else {
1853469715a8a171512cf9b528702e70393f01c6041José Fonseca         return LLVMBuildExtractElement(builder, tmp, elems[0], "");
1863469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
1873469715a8a171512cf9b528702e70393f01c6041José Fonseca   }
1883469715a8a171512cf9b528702e70393f01c6041José Fonseca   else if (intrin_length < src_type.length) {
1893469715a8a171512cf9b528702e70393f01c6041José Fonseca      unsigned num_vec = src_type.length / intrin_length;
1903469715a8a171512cf9b528702e70393f01c6041José Fonseca      LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH];
1913469715a8a171512cf9b528702e70393f01c6041José Fonseca
1923469715a8a171512cf9b528702e70393f01c6041José Fonseca      /* don't support arbitrary size here as this is so yuck */
1933469715a8a171512cf9b528702e70393f01c6041José Fonseca      if (src_type.length % intrin_length) {
1943469715a8a171512cf9b528702e70393f01c6041José Fonseca         /* FIXME: This is something which should be supported
1953469715a8a171512cf9b528702e70393f01c6041José Fonseca          * but there doesn't seem to be any need for it currently
1963469715a8a171512cf9b528702e70393f01c6041José Fonseca          * so crash and burn.
1973469715a8a171512cf9b528702e70393f01c6041José Fonseca          */
1983469715a8a171512cf9b528702e70393f01c6041José Fonseca         debug_printf("%s: should handle arbitrary vector size\n",
1993469715a8a171512cf9b528702e70393f01c6041José Fonseca                      __FUNCTION__);
2003469715a8a171512cf9b528702e70393f01c6041José Fonseca         assert(0);
2013469715a8a171512cf9b528702e70393f01c6041José Fonseca         return NULL;
2023469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
2033469715a8a171512cf9b528702e70393f01c6041José Fonseca
2043469715a8a171512cf9b528702e70393f01c6041José Fonseca      for (i = 0; i < num_vec; i++) {
2053469715a8a171512cf9b528702e70393f01c6041José Fonseca         anative = lp_build_extract_range(gallivm, a, i*intrin_length,
2063469715a8a171512cf9b528702e70393f01c6041José Fonseca                                        intrin_length);
2073469715a8a171512cf9b528702e70393f01c6041José Fonseca         bnative = lp_build_extract_range(gallivm, b, i*intrin_length,
2083469715a8a171512cf9b528702e70393f01c6041José Fonseca                                        intrin_length);
2093469715a8a171512cf9b528702e70393f01c6041José Fonseca         tmp[i] = lp_build_intrinsic_binary(builder, name,
2103469715a8a171512cf9b528702e70393f01c6041José Fonseca                                            lp_build_vec_type(gallivm, intrin_type),
2113469715a8a171512cf9b528702e70393f01c6041José Fonseca                                            anative, bnative);
2123469715a8a171512cf9b528702e70393f01c6041José Fonseca      }
2133469715a8a171512cf9b528702e70393f01c6041José Fonseca      return lp_build_concat(gallivm, tmp, intrin_type, num_vec);
2143469715a8a171512cf9b528702e70393f01c6041José Fonseca   }
2153469715a8a171512cf9b528702e70393f01c6041José Fonseca   else {
2163469715a8a171512cf9b528702e70393f01c6041José Fonseca      return lp_build_intrinsic_binary(builder, name,
2173469715a8a171512cf9b528702e70393f01c6041José Fonseca                                       lp_build_vec_type(gallivm, src_type),
2183469715a8a171512cf9b528702e70393f01c6041José Fonseca                                       a, b);
2193469715a8a171512cf9b528702e70393f01c6041José Fonseca   }
2203469715a8a171512cf9b528702e70393f01c6041José Fonseca}
2213469715a8a171512cf9b528702e70393f01c6041José Fonseca
2223469715a8a171512cf9b528702e70393f01c6041José Fonseca
22336249348ed6dfae63ef2b81e6db88c975a801f2aJosé FonsecaLLVMValueRef
224efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paullp_build_intrinsic_map(struct gallivm_state *gallivm,
22536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                       const char *name,
22636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                       LLVMTypeRef ret_type,
22736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                       LLVMValueRef *args,
22836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                       unsigned num_args)
22936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca{
230efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul   LLVMBuilderRef builder = gallivm->builder;
23136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type);
23236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   unsigned n = LLVMGetVectorSize(ret_type);
23336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   unsigned i, j;
23436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   LLVMValueRef res;
23536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
23636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   assert(num_args <= LP_MAX_FUNC_ARGS);
23736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
23836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   res = LLVMGetUndef(ret_type);
23936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   for(i = 0; i < n; ++i) {
240efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul      LLVMValueRef index = lp_build_const_int32(gallivm, i);
24136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS];
24236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      LLVMValueRef res_elem;
24336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      for(j = 0; j < num_args; ++j)
24436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca         arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, "");
24536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args);
24636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca      res = LLVMBuildInsertElement(builder, res, res_elem, index, "");
24736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   }
24836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
24936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   return res;
25036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca}
25136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
25236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
25336249348ed6dfae63ef2b81e6db88c975a801f2aJosé FonsecaLLVMValueRef
254efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paullp_build_intrinsic_map_unary(struct gallivm_state *gallivm,
25536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                             const char *name,
25636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                             LLVMTypeRef ret_type,
25736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                             LLVMValueRef a)
25836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca{
259efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul   return lp_build_intrinsic_map(gallivm, name, ret_type, &a, 1);
26036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca}
26136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
26236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
26336249348ed6dfae63ef2b81e6db88c975a801f2aJosé FonsecaLLVMValueRef
264efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paullp_build_intrinsic_map_binary(struct gallivm_state *gallivm,
26536249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                              const char *name,
26636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                              LLVMTypeRef ret_type,
26736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                              LLVMValueRef a,
26836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca                              LLVMValueRef b)
26936249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca{
27036249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   LLVMValueRef args[2];
27136249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
27236249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   args[0] = a;
27336249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca   args[1] = b;
27436249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
275efc82aef35a2aac5d2ed9774f6d28f2626796416Brian Paul   return lp_build_intrinsic_map(gallivm, name, ret_type, args, 2);
27636249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca}
27736249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
27836249348ed6dfae63ef2b81e6db88c975a801f2aJosé Fonseca
279