xref: /aosp_15_r20/external/mesa3d/src/compiler/spirv/vtn_opencl.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2018 Red Hat
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  *
23*61046927SAndroid Build Coastguard Worker  * Authors:
24*61046927SAndroid Build Coastguard Worker  *    Rob Clark ([email protected])
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "math.h"
28*61046927SAndroid Build Coastguard Worker #include "nir/nir_builtin_builder.h"
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "util/u_printf.h"
31*61046927SAndroid Build Coastguard Worker #include "vtn_private.h"
32*61046927SAndroid Build Coastguard Worker #include "OpenCL.std.h"
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker typedef nir_def *(*nir_handler)(struct vtn_builder *b,
35*61046927SAndroid Build Coastguard Worker                                     uint32_t opcode,
36*61046927SAndroid Build Coastguard Worker                                     unsigned num_srcs, nir_def **srcs,
37*61046927SAndroid Build Coastguard Worker                                     struct vtn_type **src_types,
38*61046927SAndroid Build Coastguard Worker                                     const struct vtn_type *dest_type);
39*61046927SAndroid Build Coastguard Worker 
to_llvm_address_space(SpvStorageClass mode)40*61046927SAndroid Build Coastguard Worker static int to_llvm_address_space(SpvStorageClass mode)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker    switch (mode) {
43*61046927SAndroid Build Coastguard Worker    case SpvStorageClassPrivate:
44*61046927SAndroid Build Coastguard Worker    case SpvStorageClassFunction: return 0;
45*61046927SAndroid Build Coastguard Worker    case SpvStorageClassCrossWorkgroup: return 1;
46*61046927SAndroid Build Coastguard Worker    case SpvStorageClassUniform:
47*61046927SAndroid Build Coastguard Worker    case SpvStorageClassUniformConstant: return 2;
48*61046927SAndroid Build Coastguard Worker    case SpvStorageClassWorkgroup: return 3;
49*61046927SAndroid Build Coastguard Worker    case SpvStorageClassGeneric: return 4;
50*61046927SAndroid Build Coastguard Worker    default: return -1;
51*61046927SAndroid Build Coastguard Worker    }
52*61046927SAndroid Build Coastguard Worker }
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker static void
vtn_opencl_mangle(const char * in_name,uint32_t const_mask,int ntypes,struct vtn_type ** src_types,char ** outstring)56*61046927SAndroid Build Coastguard Worker vtn_opencl_mangle(const char *in_name,
57*61046927SAndroid Build Coastguard Worker                   uint32_t const_mask,
58*61046927SAndroid Build Coastguard Worker                   int ntypes, struct vtn_type **src_types,
59*61046927SAndroid Build Coastguard Worker                   char **outstring)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker    char local_name[256] = "";
62*61046927SAndroid Build Coastguard Worker    char *args_str = local_name + sprintf(local_name, "_Z%zu%s", strlen(in_name), in_name);
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ntypes; ++i) {
65*61046927SAndroid Build Coastguard Worker       const struct glsl_type *type = src_types[i]->type;
66*61046927SAndroid Build Coastguard Worker       enum vtn_base_type base_type = src_types[i]->base_type;
67*61046927SAndroid Build Coastguard Worker       if (src_types[i]->base_type == vtn_base_type_pointer) {
68*61046927SAndroid Build Coastguard Worker          *(args_str++) = 'P';
69*61046927SAndroid Build Coastguard Worker          int address_space = to_llvm_address_space(src_types[i]->storage_class);
70*61046927SAndroid Build Coastguard Worker          if (address_space > 0)
71*61046927SAndroid Build Coastguard Worker             args_str += sprintf(args_str, "U3AS%d", address_space);
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker          type = src_types[i]->pointed->type;
74*61046927SAndroid Build Coastguard Worker          base_type = src_types[i]->pointed->base_type;
75*61046927SAndroid Build Coastguard Worker       }
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker       if (const_mask & (1 << i))
78*61046927SAndroid Build Coastguard Worker          *(args_str++) = 'K';
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker       unsigned num_elements = glsl_get_components(type);
81*61046927SAndroid Build Coastguard Worker       if (num_elements > 1) {
82*61046927SAndroid Build Coastguard Worker          /* Vectors are not treated as built-ins for mangling, so check for substitution.
83*61046927SAndroid Build Coastguard Worker           * In theory, we'd need to know which substitution value this is. In practice,
84*61046927SAndroid Build Coastguard Worker           * the functions we need from libclc only support 1
85*61046927SAndroid Build Coastguard Worker           */
86*61046927SAndroid Build Coastguard Worker          bool substitution = false;
87*61046927SAndroid Build Coastguard Worker          for (unsigned j = 0; j < i; ++j) {
88*61046927SAndroid Build Coastguard Worker             const struct glsl_type *other_type = src_types[j]->base_type == vtn_base_type_pointer ?
89*61046927SAndroid Build Coastguard Worker                src_types[j]->pointed->type : src_types[j]->type;
90*61046927SAndroid Build Coastguard Worker             if (type == other_type) {
91*61046927SAndroid Build Coastguard Worker                substitution = true;
92*61046927SAndroid Build Coastguard Worker                break;
93*61046927SAndroid Build Coastguard Worker             }
94*61046927SAndroid Build Coastguard Worker          }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker          if (substitution) {
97*61046927SAndroid Build Coastguard Worker             args_str += sprintf(args_str, "S_");
98*61046927SAndroid Build Coastguard Worker             continue;
99*61046927SAndroid Build Coastguard Worker          } else
100*61046927SAndroid Build Coastguard Worker             args_str += sprintf(args_str, "Dv%d_", num_elements);
101*61046927SAndroid Build Coastguard Worker       }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker       const char *suffix = NULL;
104*61046927SAndroid Build Coastguard Worker       switch (base_type) {
105*61046927SAndroid Build Coastguard Worker       case vtn_base_type_sampler: suffix = "11ocl_sampler"; break;
106*61046927SAndroid Build Coastguard Worker       case vtn_base_type_event: suffix = "9ocl_event"; break;
107*61046927SAndroid Build Coastguard Worker       default: {
108*61046927SAndroid Build Coastguard Worker          const char *primitives[] = {
109*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_UINT] = "j",
110*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_INT] = "i",
111*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_FLOAT] = "f",
112*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_FLOAT16] = "Dh",
113*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_DOUBLE] = "d",
114*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_UINT8] = "h",
115*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_INT8] = "c",
116*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_UINT16] = "t",
117*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_INT16] = "s",
118*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_UINT64] = "m",
119*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_INT64] = "l",
120*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_BOOL] = "b",
121*61046927SAndroid Build Coastguard Worker             [GLSL_TYPE_ERROR] = NULL,
122*61046927SAndroid Build Coastguard Worker          };
123*61046927SAndroid Build Coastguard Worker          enum glsl_base_type glsl_base_type = glsl_get_base_type(type);
124*61046927SAndroid Build Coastguard Worker          assert(glsl_base_type < ARRAY_SIZE(primitives) && primitives[glsl_base_type]);
125*61046927SAndroid Build Coastguard Worker          suffix = primitives[glsl_base_type];
126*61046927SAndroid Build Coastguard Worker          break;
127*61046927SAndroid Build Coastguard Worker       }
128*61046927SAndroid Build Coastguard Worker       }
129*61046927SAndroid Build Coastguard Worker       args_str += sprintf(args_str, "%s", suffix);
130*61046927SAndroid Build Coastguard Worker    }
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker    *outstring = strdup(local_name);
133*61046927SAndroid Build Coastguard Worker }
134*61046927SAndroid Build Coastguard Worker 
mangle_and_find(struct vtn_builder * b,const char * name,uint32_t const_mask,uint32_t num_srcs,struct vtn_type ** src_types)135*61046927SAndroid Build Coastguard Worker static nir_function *mangle_and_find(struct vtn_builder *b,
136*61046927SAndroid Build Coastguard Worker                                      const char *name,
137*61046927SAndroid Build Coastguard Worker                                      uint32_t const_mask,
138*61046927SAndroid Build Coastguard Worker                                      uint32_t num_srcs,
139*61046927SAndroid Build Coastguard Worker                                      struct vtn_type **src_types)
140*61046927SAndroid Build Coastguard Worker {
141*61046927SAndroid Build Coastguard Worker    char *mname;
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    vtn_opencl_mangle(name, const_mask, num_srcs, src_types, &mname);
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker    /* try and find in current shader first. */
146*61046927SAndroid Build Coastguard Worker    nir_function *found = nir_shader_get_function_for_name(b->shader, mname);
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    /* if not found here find in clc shader and create a decl mirroring it */
149*61046927SAndroid Build Coastguard Worker    if (!found && b->options->clc_shader && b->options->clc_shader != b->shader) {
150*61046927SAndroid Build Coastguard Worker       found = nir_shader_get_function_for_name(b->options->clc_shader, mname);
151*61046927SAndroid Build Coastguard Worker       if (found) {
152*61046927SAndroid Build Coastguard Worker          nir_function *decl = nir_function_create(b->shader, mname);
153*61046927SAndroid Build Coastguard Worker          decl->num_params = found->num_params;
154*61046927SAndroid Build Coastguard Worker          decl->params = ralloc_array(b->shader, nir_parameter, decl->num_params);
155*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < decl->num_params; i++) {
156*61046927SAndroid Build Coastguard Worker             decl->params[i] = found->params[i];
157*61046927SAndroid Build Coastguard Worker          }
158*61046927SAndroid Build Coastguard Worker          found = decl;
159*61046927SAndroid Build Coastguard Worker       }
160*61046927SAndroid Build Coastguard Worker    }
161*61046927SAndroid Build Coastguard Worker    if (!found)
162*61046927SAndroid Build Coastguard Worker       vtn_fail("Can't find clc function %s\n", mname);
163*61046927SAndroid Build Coastguard Worker    free(mname);
164*61046927SAndroid Build Coastguard Worker    return found;
165*61046927SAndroid Build Coastguard Worker }
166*61046927SAndroid Build Coastguard Worker 
call_mangled_function(struct vtn_builder * b,const char * name,uint32_t const_mask,uint32_t num_srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type,nir_def ** srcs,nir_deref_instr ** ret_deref_ptr)167*61046927SAndroid Build Coastguard Worker static bool call_mangled_function(struct vtn_builder *b,
168*61046927SAndroid Build Coastguard Worker                                   const char *name,
169*61046927SAndroid Build Coastguard Worker                                   uint32_t const_mask,
170*61046927SAndroid Build Coastguard Worker                                   uint32_t num_srcs,
171*61046927SAndroid Build Coastguard Worker                                   struct vtn_type **src_types,
172*61046927SAndroid Build Coastguard Worker                                   const struct vtn_type *dest_type,
173*61046927SAndroid Build Coastguard Worker                                   nir_def **srcs,
174*61046927SAndroid Build Coastguard Worker                                   nir_deref_instr **ret_deref_ptr)
175*61046927SAndroid Build Coastguard Worker {
176*61046927SAndroid Build Coastguard Worker    nir_function *found = mangle_and_find(b, name, const_mask, num_srcs, src_types);
177*61046927SAndroid Build Coastguard Worker    if (!found)
178*61046927SAndroid Build Coastguard Worker       return false;
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    nir_call_instr *call = nir_call_instr_create(b->shader, found);
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    nir_deref_instr *ret_deref = NULL;
183*61046927SAndroid Build Coastguard Worker    uint32_t param_idx = 0;
184*61046927SAndroid Build Coastguard Worker    if (dest_type) {
185*61046927SAndroid Build Coastguard Worker       nir_variable *ret_tmp = nir_local_variable_create(b->nb.impl,
186*61046927SAndroid Build Coastguard Worker                                                         glsl_get_bare_type(dest_type->type),
187*61046927SAndroid Build Coastguard Worker                                                         "return_tmp");
188*61046927SAndroid Build Coastguard Worker       ret_deref = nir_build_deref_var(&b->nb, ret_tmp);
189*61046927SAndroid Build Coastguard Worker       call->params[param_idx++] = nir_src_for_ssa(&ret_deref->def);
190*61046927SAndroid Build Coastguard Worker    }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_srcs; i++)
193*61046927SAndroid Build Coastguard Worker       call->params[param_idx++] = nir_src_for_ssa(srcs[i]);
194*61046927SAndroid Build Coastguard Worker    nir_builder_instr_insert(&b->nb, &call->instr);
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    *ret_deref_ptr = ret_deref;
197*61046927SAndroid Build Coastguard Worker    return true;
198*61046927SAndroid Build Coastguard Worker }
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker static void
handle_instr(struct vtn_builder * b,uint32_t opcode,const uint32_t * w_src,unsigned num_srcs,const uint32_t * w_dest,nir_handler handler)201*61046927SAndroid Build Coastguard Worker handle_instr(struct vtn_builder *b, uint32_t opcode,
202*61046927SAndroid Build Coastguard Worker              const uint32_t *w_src, unsigned num_srcs, const uint32_t *w_dest, nir_handler handler)
203*61046927SAndroid Build Coastguard Worker {
204*61046927SAndroid Build Coastguard Worker    struct vtn_type *dest_type = w_dest ? vtn_get_type(b, w_dest[0]) : NULL;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    nir_def *srcs[5] = { NULL };
207*61046927SAndroid Build Coastguard Worker    struct vtn_type *src_types[5] = { NULL };
208*61046927SAndroid Build Coastguard Worker    vtn_assert(num_srcs <= ARRAY_SIZE(srcs));
209*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_srcs; i++) {
210*61046927SAndroid Build Coastguard Worker       struct vtn_value *val = vtn_untyped_value(b, w_src[i]);
211*61046927SAndroid Build Coastguard Worker       struct vtn_ssa_value *ssa = vtn_ssa_value(b, w_src[i]);
212*61046927SAndroid Build Coastguard Worker       srcs[i] = ssa->def;
213*61046927SAndroid Build Coastguard Worker       src_types[i] = val->type;
214*61046927SAndroid Build Coastguard Worker    }
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    nir_def *result = handler(b, opcode, num_srcs, srcs, src_types, dest_type);
217*61046927SAndroid Build Coastguard Worker    if (result) {
218*61046927SAndroid Build Coastguard Worker       vtn_push_nir_ssa(b, w_dest[1], result);
219*61046927SAndroid Build Coastguard Worker    } else {
220*61046927SAndroid Build Coastguard Worker       vtn_assert(dest_type == NULL);
221*61046927SAndroid Build Coastguard Worker    }
222*61046927SAndroid Build Coastguard Worker }
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker static nir_op
nir_alu_op_for_opencl_opcode(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode)225*61046927SAndroid Build Coastguard Worker nir_alu_op_for_opencl_opcode(struct vtn_builder *b,
226*61046927SAndroid Build Coastguard Worker                              enum OpenCLstd_Entrypoints opcode)
227*61046927SAndroid Build Coastguard Worker {
228*61046927SAndroid Build Coastguard Worker    switch (opcode) {
229*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fabs: return nir_op_fabs;
230*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAbs: return nir_op_iabs;
231*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAdd_sat: return nir_op_iadd_sat;
232*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAdd_sat: return nir_op_uadd_sat;
233*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ceil: return nir_op_fceil;
234*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Floor: return nir_op_ffloor;
235*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SHadd: return nir_op_ihadd;
236*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UHadd: return nir_op_uhadd;
237*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fmax: return nir_op_fmax;
238*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMax: return nir_op_imax;
239*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMax: return nir_op_umax;
240*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fmin: return nir_op_fmin;
241*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMin: return nir_op_imin;
242*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMin: return nir_op_umin;
243*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Mix: return nir_op_flrp;
244*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_cos: return nir_op_fcos;
245*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_divide: return nir_op_fdiv;
246*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp2: return nir_op_fexp2;
247*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log2: return nir_op_flog2;
248*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_powr: return nir_op_fpow;
249*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_recip: return nir_op_frcp;
250*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_rsqrt: return nir_op_frsq;
251*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_sin: return nir_op_fsin;
252*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_sqrt: return nir_op_fsqrt;
253*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMul_hi: return nir_op_imul_high;
254*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMul_hi: return nir_op_umul_high;
255*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Popcount: return nir_op_bit_count;
256*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SRhadd: return nir_op_irhadd;
257*61046927SAndroid Build Coastguard Worker    case OpenCLstd_URhadd: return nir_op_urhadd;
258*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rsqrt: return nir_op_frsq;
259*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sign: return nir_op_fsign;
260*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sqrt: return nir_op_fsqrt;
261*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SSub_sat: return nir_op_isub_sat;
262*61046927SAndroid Build Coastguard Worker    case OpenCLstd_USub_sat: return nir_op_usub_sat;
263*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Trunc: return nir_op_ftrunc;
264*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rint: return nir_op_fround_even;
265*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_divide: return nir_op_fdiv;
266*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_recip: return nir_op_frcp;
267*61046927SAndroid Build Coastguard Worker    /* uhm... */
268*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAbs: return nir_op_mov;
269*61046927SAndroid Build Coastguard Worker    default:
270*61046927SAndroid Build Coastguard Worker       vtn_fail("No NIR equivalent");
271*61046927SAndroid Build Coastguard Worker    }
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker static nir_def *
handle_alu(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)275*61046927SAndroid Build Coastguard Worker handle_alu(struct vtn_builder *b, uint32_t opcode,
276*61046927SAndroid Build Coastguard Worker            unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
277*61046927SAndroid Build Coastguard Worker            const struct vtn_type *dest_type)
278*61046927SAndroid Build Coastguard Worker {
279*61046927SAndroid Build Coastguard Worker    nir_def *ret = nir_build_alu(&b->nb, nir_alu_op_for_opencl_opcode(b, (enum OpenCLstd_Entrypoints)opcode),
280*61046927SAndroid Build Coastguard Worker                                     srcs[0], srcs[1], srcs[2], NULL);
281*61046927SAndroid Build Coastguard Worker    if (opcode == OpenCLstd_Popcount)
282*61046927SAndroid Build Coastguard Worker       ret = nir_u2uN(&b->nb, ret, glsl_get_bit_size(dest_type->type));
283*61046927SAndroid Build Coastguard Worker    return ret;
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker #define REMAP(op, str) [OpenCLstd_##op] = { str }
287*61046927SAndroid Build Coastguard Worker static const struct {
288*61046927SAndroid Build Coastguard Worker    const char *fn;
289*61046927SAndroid Build Coastguard Worker } remap_table[] = {
290*61046927SAndroid Build Coastguard Worker    REMAP(Distance, "distance"),
291*61046927SAndroid Build Coastguard Worker    REMAP(Fast_distance, "fast_distance"),
292*61046927SAndroid Build Coastguard Worker    REMAP(Fast_length, "fast_length"),
293*61046927SAndroid Build Coastguard Worker    REMAP(Fast_normalize, "fast_normalize"),
294*61046927SAndroid Build Coastguard Worker    REMAP(Half_rsqrt, "half_rsqrt"),
295*61046927SAndroid Build Coastguard Worker    REMAP(Half_sqrt, "half_sqrt"),
296*61046927SAndroid Build Coastguard Worker    REMAP(Length, "length"),
297*61046927SAndroid Build Coastguard Worker    REMAP(Normalize, "normalize"),
298*61046927SAndroid Build Coastguard Worker    REMAP(Degrees, "degrees"),
299*61046927SAndroid Build Coastguard Worker    REMAP(Radians, "radians"),
300*61046927SAndroid Build Coastguard Worker    REMAP(Rotate, "rotate"),
301*61046927SAndroid Build Coastguard Worker    REMAP(Smoothstep, "smoothstep"),
302*61046927SAndroid Build Coastguard Worker    REMAP(Step, "step"),
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    REMAP(Pow, "pow"),
305*61046927SAndroid Build Coastguard Worker    REMAP(Pown, "pown"),
306*61046927SAndroid Build Coastguard Worker    REMAP(Powr, "powr"),
307*61046927SAndroid Build Coastguard Worker    REMAP(Rootn, "rootn"),
308*61046927SAndroid Build Coastguard Worker    REMAP(Modf, "modf"),
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    REMAP(Acos, "acos"),
311*61046927SAndroid Build Coastguard Worker    REMAP(Acosh, "acosh"),
312*61046927SAndroid Build Coastguard Worker    REMAP(Acospi, "acospi"),
313*61046927SAndroid Build Coastguard Worker    REMAP(Asin, "asin"),
314*61046927SAndroid Build Coastguard Worker    REMAP(Asinh, "asinh"),
315*61046927SAndroid Build Coastguard Worker    REMAP(Asinpi, "asinpi"),
316*61046927SAndroid Build Coastguard Worker    REMAP(Atan, "atan"),
317*61046927SAndroid Build Coastguard Worker    REMAP(Atan2, "atan2"),
318*61046927SAndroid Build Coastguard Worker    REMAP(Atanh, "atanh"),
319*61046927SAndroid Build Coastguard Worker    REMAP(Atanpi, "atanpi"),
320*61046927SAndroid Build Coastguard Worker    REMAP(Atan2pi, "atan2pi"),
321*61046927SAndroid Build Coastguard Worker    REMAP(Cos, "cos"),
322*61046927SAndroid Build Coastguard Worker    REMAP(Cosh, "cosh"),
323*61046927SAndroid Build Coastguard Worker    REMAP(Cospi, "cospi"),
324*61046927SAndroid Build Coastguard Worker    REMAP(Sin, "sin"),
325*61046927SAndroid Build Coastguard Worker    REMAP(Sinh, "sinh"),
326*61046927SAndroid Build Coastguard Worker    REMAP(Sinpi, "sinpi"),
327*61046927SAndroid Build Coastguard Worker    REMAP(Tan, "tan"),
328*61046927SAndroid Build Coastguard Worker    REMAP(Tanh, "tanh"),
329*61046927SAndroid Build Coastguard Worker    REMAP(Tanpi, "tanpi"),
330*61046927SAndroid Build Coastguard Worker    REMAP(Sincos, "sincos"),
331*61046927SAndroid Build Coastguard Worker    REMAP(Fract, "fract"),
332*61046927SAndroid Build Coastguard Worker    REMAP(Frexp, "frexp"),
333*61046927SAndroid Build Coastguard Worker    REMAP(Fma, "fma"),
334*61046927SAndroid Build Coastguard Worker    REMAP(Fmod, "fmod"),
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker    REMAP(Half_cos, "cos"),
337*61046927SAndroid Build Coastguard Worker    REMAP(Half_exp, "exp"),
338*61046927SAndroid Build Coastguard Worker    REMAP(Half_exp2, "exp2"),
339*61046927SAndroid Build Coastguard Worker    REMAP(Half_exp10, "exp10"),
340*61046927SAndroid Build Coastguard Worker    REMAP(Half_log, "log"),
341*61046927SAndroid Build Coastguard Worker    REMAP(Half_log2, "log2"),
342*61046927SAndroid Build Coastguard Worker    REMAP(Half_log10, "log10"),
343*61046927SAndroid Build Coastguard Worker    REMAP(Half_powr, "powr"),
344*61046927SAndroid Build Coastguard Worker    REMAP(Half_sin, "sin"),
345*61046927SAndroid Build Coastguard Worker    REMAP(Half_tan, "tan"),
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    REMAP(Remainder, "remainder"),
348*61046927SAndroid Build Coastguard Worker    REMAP(Remquo, "remquo"),
349*61046927SAndroid Build Coastguard Worker    REMAP(Hypot, "hypot"),
350*61046927SAndroid Build Coastguard Worker    REMAP(Exp, "exp"),
351*61046927SAndroid Build Coastguard Worker    REMAP(Exp2, "exp2"),
352*61046927SAndroid Build Coastguard Worker    REMAP(Exp10, "exp10"),
353*61046927SAndroid Build Coastguard Worker    REMAP(Expm1, "expm1"),
354*61046927SAndroid Build Coastguard Worker    REMAP(Ldexp, "ldexp"),
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    REMAP(Ilogb, "ilogb"),
357*61046927SAndroid Build Coastguard Worker    REMAP(Log, "log"),
358*61046927SAndroid Build Coastguard Worker    REMAP(Log2, "log2"),
359*61046927SAndroid Build Coastguard Worker    REMAP(Log10, "log10"),
360*61046927SAndroid Build Coastguard Worker    REMAP(Log1p, "log1p"),
361*61046927SAndroid Build Coastguard Worker    REMAP(Logb, "logb"),
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    REMAP(Cbrt, "cbrt"),
364*61046927SAndroid Build Coastguard Worker    REMAP(Erfc, "erfc"),
365*61046927SAndroid Build Coastguard Worker    REMAP(Erf, "erf"),
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    REMAP(Lgamma, "lgamma"),
368*61046927SAndroid Build Coastguard Worker    REMAP(Lgamma_r, "lgamma_r"),
369*61046927SAndroid Build Coastguard Worker    REMAP(Tgamma, "tgamma"),
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker    REMAP(UMad_sat, "mad_sat"),
372*61046927SAndroid Build Coastguard Worker    REMAP(SMad_sat, "mad_sat"),
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    REMAP(Shuffle, "shuffle"),
375*61046927SAndroid Build Coastguard Worker    REMAP(Shuffle2, "shuffle2"),
376*61046927SAndroid Build Coastguard Worker };
377*61046927SAndroid Build Coastguard Worker #undef REMAP
378*61046927SAndroid Build Coastguard Worker 
remap_clc_opcode(enum OpenCLstd_Entrypoints opcode)379*61046927SAndroid Build Coastguard Worker static const char *remap_clc_opcode(enum OpenCLstd_Entrypoints opcode)
380*61046927SAndroid Build Coastguard Worker {
381*61046927SAndroid Build Coastguard Worker    if (opcode >= (sizeof(remap_table) / sizeof(const char *)))
382*61046927SAndroid Build Coastguard Worker       return NULL;
383*61046927SAndroid Build Coastguard Worker    return remap_table[opcode].fn;
384*61046927SAndroid Build Coastguard Worker }
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker static struct vtn_type *
get_vtn_type_for_glsl_type(struct vtn_builder * b,const struct glsl_type * type)387*61046927SAndroid Build Coastguard Worker get_vtn_type_for_glsl_type(struct vtn_builder *b, const struct glsl_type *type)
388*61046927SAndroid Build Coastguard Worker {
389*61046927SAndroid Build Coastguard Worker    struct vtn_type *ret = vtn_zalloc(b, struct vtn_type);
390*61046927SAndroid Build Coastguard Worker    assert(glsl_type_is_vector_or_scalar(type));
391*61046927SAndroid Build Coastguard Worker    ret->type = type;
392*61046927SAndroid Build Coastguard Worker    ret->length = glsl_get_vector_elements(type);
393*61046927SAndroid Build Coastguard Worker    ret->base_type = glsl_type_is_vector(type) ? vtn_base_type_vector : vtn_base_type_scalar;
394*61046927SAndroid Build Coastguard Worker    return ret;
395*61046927SAndroid Build Coastguard Worker }
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker static struct vtn_type *
get_pointer_type(struct vtn_builder * b,struct vtn_type * t,SpvStorageClass storage_class)398*61046927SAndroid Build Coastguard Worker get_pointer_type(struct vtn_builder *b, struct vtn_type *t, SpvStorageClass storage_class)
399*61046927SAndroid Build Coastguard Worker {
400*61046927SAndroid Build Coastguard Worker    struct vtn_type *ret = vtn_zalloc(b, struct vtn_type);
401*61046927SAndroid Build Coastguard Worker    ret->type = nir_address_format_to_glsl_type(
402*61046927SAndroid Build Coastguard Worker             vtn_mode_to_address_format(
403*61046927SAndroid Build Coastguard Worker                b, vtn_storage_class_to_mode(b, storage_class, NULL, NULL)));
404*61046927SAndroid Build Coastguard Worker    ret->base_type = vtn_base_type_pointer;
405*61046927SAndroid Build Coastguard Worker    ret->storage_class = storage_class;
406*61046927SAndroid Build Coastguard Worker    ret->pointed = t;
407*61046927SAndroid Build Coastguard Worker    return ret;
408*61046927SAndroid Build Coastguard Worker }
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker static struct vtn_type *
get_signed_type(struct vtn_builder * b,struct vtn_type * t)411*61046927SAndroid Build Coastguard Worker get_signed_type(struct vtn_builder *b, struct vtn_type *t)
412*61046927SAndroid Build Coastguard Worker {
413*61046927SAndroid Build Coastguard Worker    if (t->base_type == vtn_base_type_pointer) {
414*61046927SAndroid Build Coastguard Worker       return get_pointer_type(b, get_signed_type(b, t->pointed), t->storage_class);
415*61046927SAndroid Build Coastguard Worker    }
416*61046927SAndroid Build Coastguard Worker    return get_vtn_type_for_glsl_type(
417*61046927SAndroid Build Coastguard Worker       b, glsl_vector_type(glsl_signed_base_type_of(glsl_get_base_type(t->type)),
418*61046927SAndroid Build Coastguard Worker                           glsl_get_vector_elements(t->type)));
419*61046927SAndroid Build Coastguard Worker }
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker static nir_def *
handle_clc_fn(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode,int num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)422*61046927SAndroid Build Coastguard Worker handle_clc_fn(struct vtn_builder *b, enum OpenCLstd_Entrypoints opcode,
423*61046927SAndroid Build Coastguard Worker               int num_srcs,
424*61046927SAndroid Build Coastguard Worker               nir_def **srcs,
425*61046927SAndroid Build Coastguard Worker               struct vtn_type **src_types,
426*61046927SAndroid Build Coastguard Worker               const struct vtn_type *dest_type)
427*61046927SAndroid Build Coastguard Worker {
428*61046927SAndroid Build Coastguard Worker    const char *name = remap_clc_opcode(opcode);
429*61046927SAndroid Build Coastguard Worker    if (!name)
430*61046927SAndroid Build Coastguard Worker        return NULL;
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    /* Some functions which take params end up with uint (or pointer-to-uint) being passed,
433*61046927SAndroid Build Coastguard Worker     * which doesn't mangle correctly when the function expects int or pointer-to-int.
434*61046927SAndroid Build Coastguard Worker     * See https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_unsignedsigned_a_unsigned_versus_signed_integers
435*61046927SAndroid Build Coastguard Worker     */
436*61046927SAndroid Build Coastguard Worker    int signed_param = -1;
437*61046927SAndroid Build Coastguard Worker    switch (opcode) {
438*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Frexp:
439*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Lgamma_r:
440*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Pown:
441*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rootn:
442*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ldexp:
443*61046927SAndroid Build Coastguard Worker       signed_param = 1;
444*61046927SAndroid Build Coastguard Worker       break;
445*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Remquo:
446*61046927SAndroid Build Coastguard Worker       signed_param = 2;
447*61046927SAndroid Build Coastguard Worker       break;
448*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad_sat: {
449*61046927SAndroid Build Coastguard Worker       /* All parameters need to be converted to signed */
450*61046927SAndroid Build Coastguard Worker       src_types[0] = src_types[1] = src_types[2] = get_signed_type(b, src_types[0]);
451*61046927SAndroid Build Coastguard Worker       break;
452*61046927SAndroid Build Coastguard Worker    }
453*61046927SAndroid Build Coastguard Worker    default: break;
454*61046927SAndroid Build Coastguard Worker    }
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    if (signed_param >= 0) {
457*61046927SAndroid Build Coastguard Worker       src_types[signed_param] = get_signed_type(b, src_types[signed_param]);
458*61046927SAndroid Build Coastguard Worker    }
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    nir_deref_instr *ret_deref = NULL;
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker    if (!call_mangled_function(b, name, 0, num_srcs, src_types,
463*61046927SAndroid Build Coastguard Worker                               dest_type, srcs, &ret_deref))
464*61046927SAndroid Build Coastguard Worker       return NULL;
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker    return ret_deref ? nir_load_deref(&b->nb, ret_deref) : NULL;
467*61046927SAndroid Build Coastguard Worker }
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker static nir_def *
handle_special(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)470*61046927SAndroid Build Coastguard Worker handle_special(struct vtn_builder *b, uint32_t opcode,
471*61046927SAndroid Build Coastguard Worker                unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
472*61046927SAndroid Build Coastguard Worker                const struct vtn_type *dest_type)
473*61046927SAndroid Build Coastguard Worker {
474*61046927SAndroid Build Coastguard Worker    nir_builder *nb = &b->nb;
475*61046927SAndroid Build Coastguard Worker    enum OpenCLstd_Entrypoints cl_opcode = (enum OpenCLstd_Entrypoints)opcode;
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    switch (cl_opcode) {
478*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAbs_diff:
479*61046927SAndroid Build Coastguard Worker      /* these works easier in direct NIR */
480*61046927SAndroid Build Coastguard Worker       return nir_iabs_diff(nb, srcs[0], srcs[1]);
481*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAbs_diff:
482*61046927SAndroid Build Coastguard Worker       return nir_uabs_diff(nb, srcs[0], srcs[1]);
483*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Bitselect:
484*61046927SAndroid Build Coastguard Worker       return nir_bitselect(nb, srcs[0], srcs[1], srcs[2]);
485*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad_hi:
486*61046927SAndroid Build Coastguard Worker       return nir_imad_hi(nb, srcs[0], srcs[1], srcs[2]);
487*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMad_hi:
488*61046927SAndroid Build Coastguard Worker       return nir_umad_hi(nb, srcs[0], srcs[1], srcs[2]);
489*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMul24:
490*61046927SAndroid Build Coastguard Worker       return nir_imul24_relaxed(nb, srcs[0], srcs[1]);
491*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMul24:
492*61046927SAndroid Build Coastguard Worker       return nir_umul24_relaxed(nb, srcs[0], srcs[1]);
493*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad24:
494*61046927SAndroid Build Coastguard Worker       return nir_iadd(nb, nir_imul24_relaxed(nb, srcs[0], srcs[1]), srcs[2]);
495*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMad24:
496*61046927SAndroid Build Coastguard Worker       return nir_umad24_relaxed(nb, srcs[0], srcs[1], srcs[2]);
497*61046927SAndroid Build Coastguard Worker    case OpenCLstd_FClamp:
498*61046927SAndroid Build Coastguard Worker       return nir_fclamp(nb, srcs[0], srcs[1], srcs[2]);
499*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SClamp:
500*61046927SAndroid Build Coastguard Worker       return nir_iclamp(nb, srcs[0], srcs[1], srcs[2]);
501*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UClamp:
502*61046927SAndroid Build Coastguard Worker       return nir_uclamp(nb, srcs[0], srcs[1], srcs[2]);
503*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Copysign:
504*61046927SAndroid Build Coastguard Worker       return nir_copysign(nb, srcs[0], srcs[1]);
505*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cross:
506*61046927SAndroid Build Coastguard Worker       if (dest_type->length == 4)
507*61046927SAndroid Build Coastguard Worker          return nir_cross4(nb, srcs[0], srcs[1]);
508*61046927SAndroid Build Coastguard Worker       return nir_cross3(nb, srcs[0], srcs[1]);
509*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fdim:
510*61046927SAndroid Build Coastguard Worker       return nir_fdim(nb, srcs[0], srcs[1]);
511*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Mad: {
512*61046927SAndroid Build Coastguard Worker       /* The spec says mad is
513*61046927SAndroid Build Coastguard Worker        *
514*61046927SAndroid Build Coastguard Worker        *    Implemented either as a correctly rounded fma or as a multiply
515*61046927SAndroid Build Coastguard Worker        *    followed by an add both of which are correctly rounded
516*61046927SAndroid Build Coastguard Worker        *
517*61046927SAndroid Build Coastguard Worker        * So lower to fmul+fadd if we have to, but fuse to an ffma if the backend
518*61046927SAndroid Build Coastguard Worker        * supports that. This can be significantly faster.
519*61046927SAndroid Build Coastguard Worker        */
520*61046927SAndroid Build Coastguard Worker       bool lower =
521*61046927SAndroid Build Coastguard Worker          ((nb->shader->options->lower_ffma16 && srcs[0]->bit_size == 16) ||
522*61046927SAndroid Build Coastguard Worker           (nb->shader->options->lower_ffma32 && srcs[0]->bit_size == 32) ||
523*61046927SAndroid Build Coastguard Worker           (nb->shader->options->lower_ffma64 && srcs[0]->bit_size == 64));
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker       if (lower)
526*61046927SAndroid Build Coastguard Worker          return nir_fmad(nb, srcs[0], srcs[1], srcs[2]);
527*61046927SAndroid Build Coastguard Worker       else
528*61046927SAndroid Build Coastguard Worker          return nir_ffma(nb, srcs[0], srcs[1], srcs[2]);
529*61046927SAndroid Build Coastguard Worker    }
530*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Maxmag:
531*61046927SAndroid Build Coastguard Worker       return nir_maxmag(nb, srcs[0], srcs[1]);
532*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Minmag:
533*61046927SAndroid Build Coastguard Worker       return nir_minmag(nb, srcs[0], srcs[1]);
534*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Nan:
535*61046927SAndroid Build Coastguard Worker       return nir_nan(nb, srcs[0]);
536*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Nextafter:
537*61046927SAndroid Build Coastguard Worker       return nir_nextafter(nb, srcs[0], srcs[1]);
538*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Normalize:
539*61046927SAndroid Build Coastguard Worker       return nir_normalize(nb, srcs[0]);
540*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Clz:
541*61046927SAndroid Build Coastguard Worker       return nir_clz_u(nb, srcs[0]);
542*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ctz:
543*61046927SAndroid Build Coastguard Worker       return nir_ctz_u(nb, srcs[0]);
544*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Select:
545*61046927SAndroid Build Coastguard Worker       return nir_select(nb, srcs[0], srcs[1], srcs[2]);
546*61046927SAndroid Build Coastguard Worker    case OpenCLstd_S_Upsample:
547*61046927SAndroid Build Coastguard Worker    case OpenCLstd_U_Upsample:
548*61046927SAndroid Build Coastguard Worker       /* SPIR-V and CL have different defs for upsample, just implement in nir */
549*61046927SAndroid Build Coastguard Worker       return nir_upsample(nb, srcs[0], srcs[1]);
550*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp:
551*61046927SAndroid Build Coastguard Worker       return nir_fexp(nb, srcs[0]);
552*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp10:
553*61046927SAndroid Build Coastguard Worker       return nir_fexp2(nb, nir_fmul_imm(nb, srcs[0], log(10) / log(2)));
554*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log:
555*61046927SAndroid Build Coastguard Worker       return nir_flog(nb, srcs[0]);
556*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log10:
557*61046927SAndroid Build Coastguard Worker       return nir_fmul_imm(nb, nir_flog2(nb, srcs[0]), log(2) / log(10));
558*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_tan:
559*61046927SAndroid Build Coastguard Worker       return nir_ftan(nb, srcs[0]);
560*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ldexp:
561*61046927SAndroid Build Coastguard Worker       if (nb->shader->options->lower_ldexp)
562*61046927SAndroid Build Coastguard Worker          break;
563*61046927SAndroid Build Coastguard Worker       return nir_ldexp(nb, srcs[0], srcs[1]);
564*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fma:
565*61046927SAndroid Build Coastguard Worker       /* FIXME: the software implementation only supports fp32 for now. */
566*61046927SAndroid Build Coastguard Worker       if (nb->shader->options->lower_ffma32 && srcs[0]->bit_size == 32)
567*61046927SAndroid Build Coastguard Worker          break;
568*61046927SAndroid Build Coastguard Worker       return nir_ffma(nb, srcs[0], srcs[1], srcs[2]);
569*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rotate:
570*61046927SAndroid Build Coastguard Worker       return nir_urol(nb, srcs[0], nir_u2u32(nb, srcs[1]));
571*61046927SAndroid Build Coastguard Worker    default:
572*61046927SAndroid Build Coastguard Worker       break;
573*61046927SAndroid Build Coastguard Worker    }
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    nir_def *ret = handle_clc_fn(b, opcode, num_srcs, srcs, src_types, dest_type);
576*61046927SAndroid Build Coastguard Worker    if (!ret)
577*61046927SAndroid Build Coastguard Worker       vtn_fail("No NIR equivalent");
578*61046927SAndroid Build Coastguard Worker 
579*61046927SAndroid Build Coastguard Worker    return ret;
580*61046927SAndroid Build Coastguard Worker }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker static nir_def *
handle_core(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)583*61046927SAndroid Build Coastguard Worker handle_core(struct vtn_builder *b, uint32_t opcode,
584*61046927SAndroid Build Coastguard Worker             unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
585*61046927SAndroid Build Coastguard Worker             const struct vtn_type *dest_type)
586*61046927SAndroid Build Coastguard Worker {
587*61046927SAndroid Build Coastguard Worker    nir_deref_instr *ret_deref = NULL;
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    switch ((SpvOp)opcode) {
590*61046927SAndroid Build Coastguard Worker    case SpvOpGroupAsyncCopy: {
591*61046927SAndroid Build Coastguard Worker       /* Libclc doesn't include 3-component overloads of the async copy functions.
592*61046927SAndroid Build Coastguard Worker        * However, the CLC spec says:
593*61046927SAndroid Build Coastguard Worker        * async_work_group_copy and async_work_group_strided_copy for 3-component vector types
594*61046927SAndroid Build Coastguard Worker        * behave as async_work_group_copy and async_work_group_strided_copy respectively for 4-component
595*61046927SAndroid Build Coastguard Worker        * vector types
596*61046927SAndroid Build Coastguard Worker        */
597*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
598*61046927SAndroid Build Coastguard Worker          if (src_types[i]->base_type == vtn_base_type_pointer &&
599*61046927SAndroid Build Coastguard Worker              src_types[i]->pointed->base_type == vtn_base_type_vector &&
600*61046927SAndroid Build Coastguard Worker              src_types[i]->pointed->length == 3) {
601*61046927SAndroid Build Coastguard Worker             src_types[i] =
602*61046927SAndroid Build Coastguard Worker                get_pointer_type(b,
603*61046927SAndroid Build Coastguard Worker                                 get_vtn_type_for_glsl_type(b, glsl_replace_vector_type(src_types[i]->pointed->type, 4)),
604*61046927SAndroid Build Coastguard Worker                                 src_types[i]->storage_class);
605*61046927SAndroid Build Coastguard Worker          }
606*61046927SAndroid Build Coastguard Worker       }
607*61046927SAndroid Build Coastguard Worker       if (!call_mangled_function(b, "async_work_group_strided_copy", (1 << 1), num_srcs, src_types, dest_type, srcs, &ret_deref))
608*61046927SAndroid Build Coastguard Worker          return NULL;
609*61046927SAndroid Build Coastguard Worker       break;
610*61046927SAndroid Build Coastguard Worker    }
611*61046927SAndroid Build Coastguard Worker    case SpvOpGroupWaitEvents: {
612*61046927SAndroid Build Coastguard Worker       /* libclc and clang don't agree on the mangling of this function.
613*61046927SAndroid Build Coastguard Worker        * The libclc we have uses a __local pointer but clang gives us generic
614*61046927SAndroid Build Coastguard Worker        * pointers.  Fortunately, the whole function is just a barrier.
615*61046927SAndroid Build Coastguard Worker        */
616*61046927SAndroid Build Coastguard Worker       nir_barrier(&b->nb, .execution_scope = SCOPE_WORKGROUP,
617*61046927SAndroid Build Coastguard Worker                           .memory_scope = SCOPE_WORKGROUP,
618*61046927SAndroid Build Coastguard Worker                           .memory_semantics = NIR_MEMORY_ACQUIRE |
619*61046927SAndroid Build Coastguard Worker                                               NIR_MEMORY_RELEASE,
620*61046927SAndroid Build Coastguard Worker                           .memory_modes = nir_var_mem_shared |
621*61046927SAndroid Build Coastguard Worker                                           nir_var_mem_global);
622*61046927SAndroid Build Coastguard Worker       break;
623*61046927SAndroid Build Coastguard Worker    }
624*61046927SAndroid Build Coastguard Worker    default:
625*61046927SAndroid Build Coastguard Worker       return NULL;
626*61046927SAndroid Build Coastguard Worker    }
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker    return ret_deref ? nir_load_deref(&b->nb, ret_deref) : NULL;
629*61046927SAndroid Build Coastguard Worker }
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker 
632*61046927SAndroid Build Coastguard Worker static void
_handle_v_load_store(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode,const uint32_t * w,unsigned count,bool load,bool vec_aligned,nir_rounding_mode rounding)633*61046927SAndroid Build Coastguard Worker _handle_v_load_store(struct vtn_builder *b, enum OpenCLstd_Entrypoints opcode,
634*61046927SAndroid Build Coastguard Worker                      const uint32_t *w, unsigned count, bool load,
635*61046927SAndroid Build Coastguard Worker                      bool vec_aligned, nir_rounding_mode rounding)
636*61046927SAndroid Build Coastguard Worker {
637*61046927SAndroid Build Coastguard Worker    struct vtn_type *type;
638*61046927SAndroid Build Coastguard Worker    if (load)
639*61046927SAndroid Build Coastguard Worker       type = vtn_get_type(b, w[1]);
640*61046927SAndroid Build Coastguard Worker    else
641*61046927SAndroid Build Coastguard Worker       type = vtn_get_value_type(b, w[5]);
642*61046927SAndroid Build Coastguard Worker    unsigned a = load ? 0 : 1;
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    enum glsl_base_type base_type = glsl_get_base_type(type->type);
645*61046927SAndroid Build Coastguard Worker    unsigned components = glsl_get_vector_elements(type->type);
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker    nir_def *offset = vtn_get_nir_ssa(b, w[5 + a]);
648*61046927SAndroid Build Coastguard Worker    struct vtn_value *p = vtn_value(b, w[6 + a], vtn_value_type_pointer);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    struct vtn_ssa_value *comps[NIR_MAX_VEC_COMPONENTS];
651*61046927SAndroid Build Coastguard Worker    nir_def *ncomps[NIR_MAX_VEC_COMPONENTS];
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker    nir_def *moffset = nir_imul_imm(&b->nb, offset,
654*61046927SAndroid Build Coastguard Worker       (vec_aligned && components == 3) ? 4 : components);
655*61046927SAndroid Build Coastguard Worker    nir_deref_instr *deref = vtn_pointer_to_deref(b, p->pointer);
656*61046927SAndroid Build Coastguard Worker 
657*61046927SAndroid Build Coastguard Worker    unsigned alignment = vec_aligned ? glsl_get_cl_alignment(type->type) :
658*61046927SAndroid Build Coastguard Worker                                       glsl_get_bit_size(type->type) / 8;
659*61046927SAndroid Build Coastguard Worker    enum glsl_base_type ptr_base_type =
660*61046927SAndroid Build Coastguard Worker       glsl_get_base_type(p->pointer->type->pointed->type);
661*61046927SAndroid Build Coastguard Worker    if (base_type != ptr_base_type) {
662*61046927SAndroid Build Coastguard Worker       vtn_fail_if(ptr_base_type != GLSL_TYPE_FLOAT16 ||
663*61046927SAndroid Build Coastguard Worker                   (base_type != GLSL_TYPE_FLOAT &&
664*61046927SAndroid Build Coastguard Worker                    base_type != GLSL_TYPE_DOUBLE),
665*61046927SAndroid Build Coastguard Worker                   "vload/vstore cannot do type conversion. "
666*61046927SAndroid Build Coastguard Worker                   "vload/vstore_half can only convert from half to other "
667*61046927SAndroid Build Coastguard Worker                   "floating-point types.");
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker       /* Above-computed alignment was for floats/doubles, not halves */
670*61046927SAndroid Build Coastguard Worker       alignment /= glsl_get_bit_size(type->type) / glsl_base_type_get_bit_size(ptr_base_type);
671*61046927SAndroid Build Coastguard Worker    }
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker    deref = nir_alignment_deref_cast(&b->nb, deref, alignment, 0);
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < components; i++) {
676*61046927SAndroid Build Coastguard Worker       nir_def *coffset = nir_iadd_imm(&b->nb, moffset, i);
677*61046927SAndroid Build Coastguard Worker       nir_deref_instr *arr_deref = nir_build_deref_ptr_as_array(&b->nb, deref, coffset);
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker       if (load) {
680*61046927SAndroid Build Coastguard Worker          comps[i] = vtn_local_load(b, arr_deref, p->type->access);
681*61046927SAndroid Build Coastguard Worker          ncomps[i] = comps[i]->def;
682*61046927SAndroid Build Coastguard Worker          if (base_type != ptr_base_type) {
683*61046927SAndroid Build Coastguard Worker             assert(ptr_base_type == GLSL_TYPE_FLOAT16 &&
684*61046927SAndroid Build Coastguard Worker                    (base_type == GLSL_TYPE_FLOAT ||
685*61046927SAndroid Build Coastguard Worker                     base_type == GLSL_TYPE_DOUBLE));
686*61046927SAndroid Build Coastguard Worker             ncomps[i] = nir_f2fN(&b->nb, ncomps[i],
687*61046927SAndroid Build Coastguard Worker                                  glsl_base_type_get_bit_size(base_type));
688*61046927SAndroid Build Coastguard Worker          }
689*61046927SAndroid Build Coastguard Worker       } else {
690*61046927SAndroid Build Coastguard Worker          struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, glsl_scalar_type(base_type));
691*61046927SAndroid Build Coastguard Worker          struct vtn_ssa_value *val = vtn_ssa_value(b, w[5]);
692*61046927SAndroid Build Coastguard Worker          ssa->def = nir_channel(&b->nb, val->def, i);
693*61046927SAndroid Build Coastguard Worker          if (base_type != ptr_base_type) {
694*61046927SAndroid Build Coastguard Worker             assert(ptr_base_type == GLSL_TYPE_FLOAT16 &&
695*61046927SAndroid Build Coastguard Worker                    (base_type == GLSL_TYPE_FLOAT ||
696*61046927SAndroid Build Coastguard Worker                     base_type == GLSL_TYPE_DOUBLE));
697*61046927SAndroid Build Coastguard Worker             if (rounding == nir_rounding_mode_undef) {
698*61046927SAndroid Build Coastguard Worker                ssa->def = nir_f2f16(&b->nb, ssa->def);
699*61046927SAndroid Build Coastguard Worker             } else {
700*61046927SAndroid Build Coastguard Worker                ssa->def = nir_convert_alu_types(&b->nb, 16, ssa->def,
701*61046927SAndroid Build Coastguard Worker                                                 nir_type_float | ssa->def->bit_size,
702*61046927SAndroid Build Coastguard Worker                                                 nir_type_float16,
703*61046927SAndroid Build Coastguard Worker                                                 rounding, false);
704*61046927SAndroid Build Coastguard Worker             }
705*61046927SAndroid Build Coastguard Worker          }
706*61046927SAndroid Build Coastguard Worker          vtn_local_store(b, ssa, arr_deref, p->type->access);
707*61046927SAndroid Build Coastguard Worker       }
708*61046927SAndroid Build Coastguard Worker    }
709*61046927SAndroid Build Coastguard Worker    if (load) {
710*61046927SAndroid Build Coastguard Worker       vtn_push_nir_ssa(b, w[2], nir_vec(&b->nb, ncomps, components));
711*61046927SAndroid Build Coastguard Worker    }
712*61046927SAndroid Build Coastguard Worker }
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker static void
vtn_handle_opencl_vload(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode,const uint32_t * w,unsigned count)715*61046927SAndroid Build Coastguard Worker vtn_handle_opencl_vload(struct vtn_builder *b, enum OpenCLstd_Entrypoints opcode,
716*61046927SAndroid Build Coastguard Worker                         const uint32_t *w, unsigned count)
717*61046927SAndroid Build Coastguard Worker {
718*61046927SAndroid Build Coastguard Worker    _handle_v_load_store(b, opcode, w, count, true,
719*61046927SAndroid Build Coastguard Worker                         opcode == OpenCLstd_Vloada_halfn,
720*61046927SAndroid Build Coastguard Worker                         nir_rounding_mode_undef);
721*61046927SAndroid Build Coastguard Worker }
722*61046927SAndroid Build Coastguard Worker 
723*61046927SAndroid Build Coastguard Worker static void
vtn_handle_opencl_vstore(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode,const uint32_t * w,unsigned count)724*61046927SAndroid Build Coastguard Worker vtn_handle_opencl_vstore(struct vtn_builder *b, enum OpenCLstd_Entrypoints opcode,
725*61046927SAndroid Build Coastguard Worker                          const uint32_t *w, unsigned count)
726*61046927SAndroid Build Coastguard Worker {
727*61046927SAndroid Build Coastguard Worker    _handle_v_load_store(b, opcode, w, count, false,
728*61046927SAndroid Build Coastguard Worker                         opcode == OpenCLstd_Vstorea_halfn,
729*61046927SAndroid Build Coastguard Worker                         nir_rounding_mode_undef);
730*61046927SAndroid Build Coastguard Worker }
731*61046927SAndroid Build Coastguard Worker 
732*61046927SAndroid Build Coastguard Worker static void
vtn_handle_opencl_vstore_half_r(struct vtn_builder * b,enum OpenCLstd_Entrypoints opcode,const uint32_t * w,unsigned count)733*61046927SAndroid Build Coastguard Worker vtn_handle_opencl_vstore_half_r(struct vtn_builder *b, enum OpenCLstd_Entrypoints opcode,
734*61046927SAndroid Build Coastguard Worker                                 const uint32_t *w, unsigned count)
735*61046927SAndroid Build Coastguard Worker {
736*61046927SAndroid Build Coastguard Worker    _handle_v_load_store(b, opcode, w, count, false,
737*61046927SAndroid Build Coastguard Worker                         opcode == OpenCLstd_Vstorea_halfn_r,
738*61046927SAndroid Build Coastguard Worker                         vtn_rounding_mode_to_nir(b, w[8]));
739*61046927SAndroid Build Coastguard Worker }
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker static unsigned
vtn_add_printf_string(struct vtn_builder * b,uint32_t id,u_printf_info * info)742*61046927SAndroid Build Coastguard Worker vtn_add_printf_string(struct vtn_builder *b, uint32_t id, u_printf_info *info)
743*61046927SAndroid Build Coastguard Worker {
744*61046927SAndroid Build Coastguard Worker    nir_deref_instr *deref = vtn_nir_deref(b, id);
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker    while (deref->deref_type != nir_deref_type_var) {
747*61046927SAndroid Build Coastguard Worker       nir_scalar parent = nir_scalar_resolved(deref->parent.ssa, 0);
748*61046927SAndroid Build Coastguard Worker       if (parent.def->parent_instr->type != nir_instr_type_deref) {
749*61046927SAndroid Build Coastguard Worker          deref = NULL;
750*61046927SAndroid Build Coastguard Worker          break;
751*61046927SAndroid Build Coastguard Worker       }
752*61046927SAndroid Build Coastguard Worker       vtn_assert(parent.comp == 0);
753*61046927SAndroid Build Coastguard Worker       deref = nir_instr_as_deref(parent.def->parent_instr);
754*61046927SAndroid Build Coastguard Worker    }
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker    vtn_fail_if(deref == NULL || !nir_deref_mode_is(deref, nir_var_mem_constant),
757*61046927SAndroid Build Coastguard Worker                "Printf string argument must be a pointer to a constant variable");
758*61046927SAndroid Build Coastguard Worker    vtn_fail_if(deref->var->constant_initializer == NULL,
759*61046927SAndroid Build Coastguard Worker                "Printf string argument must have an initializer");
760*61046927SAndroid Build Coastguard Worker    vtn_fail_if(!glsl_type_is_array(deref->var->type),
761*61046927SAndroid Build Coastguard Worker                "Printf string must be an char array");
762*61046927SAndroid Build Coastguard Worker    const struct glsl_type *char_type = glsl_get_array_element(deref->var->type);
763*61046927SAndroid Build Coastguard Worker    vtn_fail_if(char_type != glsl_uint8_t_type() &&
764*61046927SAndroid Build Coastguard Worker                char_type != glsl_int8_t_type(),
765*61046927SAndroid Build Coastguard Worker                "Printf string must be an char array");
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker    nir_constant *c = deref->var->constant_initializer;
768*61046927SAndroid Build Coastguard Worker    assert(c->num_elements == glsl_get_length(deref->var->type));
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    unsigned idx = info->string_size;
771*61046927SAndroid Build Coastguard Worker    info->strings = reralloc_size(b->shader, info->strings,
772*61046927SAndroid Build Coastguard Worker                                  idx + c->num_elements);
773*61046927SAndroid Build Coastguard Worker    info->string_size += c->num_elements;
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    char *str = &info->strings[idx];
776*61046927SAndroid Build Coastguard Worker    bool found_null = false;
777*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < c->num_elements; i++) {
778*61046927SAndroid Build Coastguard Worker       memcpy((char *)str + i, c->elements[i]->values, 1);
779*61046927SAndroid Build Coastguard Worker       if (str[i] == '\0')
780*61046927SAndroid Build Coastguard Worker          found_null = true;
781*61046927SAndroid Build Coastguard Worker    }
782*61046927SAndroid Build Coastguard Worker    vtn_fail_if(!found_null, "Printf string must be null terminated");
783*61046927SAndroid Build Coastguard Worker    return idx;
784*61046927SAndroid Build Coastguard Worker }
785*61046927SAndroid Build Coastguard Worker 
786*61046927SAndroid Build Coastguard Worker /* printf is special because there are no limits on args */
787*61046927SAndroid Build Coastguard Worker static void
handle_printf(struct vtn_builder * b,uint32_t opcode,const uint32_t * w_src,unsigned num_srcs,const uint32_t * w_dest)788*61046927SAndroid Build Coastguard Worker handle_printf(struct vtn_builder *b, uint32_t opcode,
789*61046927SAndroid Build Coastguard Worker               const uint32_t *w_src, unsigned num_srcs, const uint32_t *w_dest)
790*61046927SAndroid Build Coastguard Worker {
791*61046927SAndroid Build Coastguard Worker    if (!b->options->printf) {
792*61046927SAndroid Build Coastguard Worker       vtn_push_nir_ssa(b, w_dest[1], nir_imm_int(&b->nb, -1));
793*61046927SAndroid Build Coastguard Worker       return;
794*61046927SAndroid Build Coastguard Worker    }
795*61046927SAndroid Build Coastguard Worker 
796*61046927SAndroid Build Coastguard Worker    /* Step 1. extract the format string */
797*61046927SAndroid Build Coastguard Worker 
798*61046927SAndroid Build Coastguard Worker    /*
799*61046927SAndroid Build Coastguard Worker     * info_idx is 1-based to match clover/llvm
800*61046927SAndroid Build Coastguard Worker     * the backend indexes the info table at info_idx - 1.
801*61046927SAndroid Build Coastguard Worker     */
802*61046927SAndroid Build Coastguard Worker    b->shader->printf_info_count++;
803*61046927SAndroid Build Coastguard Worker    unsigned info_idx = b->shader->printf_info_count;
804*61046927SAndroid Build Coastguard Worker 
805*61046927SAndroid Build Coastguard Worker    b->shader->printf_info = reralloc(b->shader, b->shader->printf_info,
806*61046927SAndroid Build Coastguard Worker                                      u_printf_info, info_idx);
807*61046927SAndroid Build Coastguard Worker    u_printf_info *info = &b->shader->printf_info[info_idx - 1];
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker    info->strings = NULL;
810*61046927SAndroid Build Coastguard Worker    info->string_size = 0;
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker    vtn_add_printf_string(b, w_src[0], info);
813*61046927SAndroid Build Coastguard Worker 
814*61046927SAndroid Build Coastguard Worker    info->num_args = num_srcs - 1;
815*61046927SAndroid Build Coastguard Worker    info->arg_sizes = ralloc_array(b->shader, unsigned, info->num_args);
816*61046927SAndroid Build Coastguard Worker 
817*61046927SAndroid Build Coastguard Worker    /* Step 2, build an ad-hoc struct type out of the args */
818*61046927SAndroid Build Coastguard Worker    unsigned field_offset = 0;
819*61046927SAndroid Build Coastguard Worker    struct glsl_struct_field *fields =
820*61046927SAndroid Build Coastguard Worker       rzalloc_array(b, struct glsl_struct_field, num_srcs - 1);
821*61046927SAndroid Build Coastguard Worker    for (unsigned i = 1; i < num_srcs; ++i) {
822*61046927SAndroid Build Coastguard Worker       struct vtn_value *val = vtn_untyped_value(b, w_src[i]);
823*61046927SAndroid Build Coastguard Worker       struct vtn_type *src_type = val->type;
824*61046927SAndroid Build Coastguard Worker       fields[i - 1].type = src_type->type;
825*61046927SAndroid Build Coastguard Worker       fields[i - 1].name = ralloc_asprintf(b->shader, "arg_%u", i);
826*61046927SAndroid Build Coastguard Worker       field_offset = align(field_offset, 4);
827*61046927SAndroid Build Coastguard Worker       fields[i - 1].offset = field_offset;
828*61046927SAndroid Build Coastguard Worker       info->arg_sizes[i - 1] = glsl_get_cl_size(src_type->type);
829*61046927SAndroid Build Coastguard Worker       field_offset += glsl_get_cl_size(src_type->type);
830*61046927SAndroid Build Coastguard Worker    }
831*61046927SAndroid Build Coastguard Worker    const struct glsl_type *struct_type =
832*61046927SAndroid Build Coastguard Worker       glsl_struct_type(fields, num_srcs - 1, "printf", true);
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    /* Step 3, create a variable of that type and populate its fields */
835*61046927SAndroid Build Coastguard Worker    nir_variable *var = nir_local_variable_create(b->nb.impl, struct_type, NULL);
836*61046927SAndroid Build Coastguard Worker    nir_deref_instr *deref_var = nir_build_deref_var(&b->nb, var);
837*61046927SAndroid Build Coastguard Worker    size_t fmt_pos = 0;
838*61046927SAndroid Build Coastguard Worker    for (unsigned i = 1; i < num_srcs; ++i) {
839*61046927SAndroid Build Coastguard Worker       nir_deref_instr *field_deref =
840*61046927SAndroid Build Coastguard Worker          nir_build_deref_struct(&b->nb, deref_var, i - 1);
841*61046927SAndroid Build Coastguard Worker       nir_def *field_src = vtn_ssa_value(b, w_src[i])->def;
842*61046927SAndroid Build Coastguard Worker       /* extract strings */
843*61046927SAndroid Build Coastguard Worker       fmt_pos = util_printf_next_spec_pos(info->strings, fmt_pos);
844*61046927SAndroid Build Coastguard Worker       if (fmt_pos != -1 && info->strings[fmt_pos] == 's') {
845*61046927SAndroid Build Coastguard Worker          unsigned idx = vtn_add_printf_string(b, w_src[i], info);
846*61046927SAndroid Build Coastguard Worker          nir_store_deref(&b->nb, field_deref,
847*61046927SAndroid Build Coastguard Worker                          nir_imm_intN_t(&b->nb, idx, field_src->bit_size),
848*61046927SAndroid Build Coastguard Worker                          ~0 /* write_mask */);
849*61046927SAndroid Build Coastguard Worker       } else
850*61046927SAndroid Build Coastguard Worker          nir_store_deref(&b->nb, field_deref, field_src, ~0);
851*61046927SAndroid Build Coastguard Worker    }
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker    /* Lastly, the actual intrinsic */
854*61046927SAndroid Build Coastguard Worker    nir_def *fmt_idx = nir_imm_int(&b->nb, info_idx);
855*61046927SAndroid Build Coastguard Worker    nir_def *ret = nir_printf(&b->nb, fmt_idx, &deref_var->def);
856*61046927SAndroid Build Coastguard Worker    vtn_push_nir_ssa(b, w_dest[1], ret);
857*61046927SAndroid Build Coastguard Worker 
858*61046927SAndroid Build Coastguard Worker    b->nb.shader->info.uses_printf = true;
859*61046927SAndroid Build Coastguard Worker }
860*61046927SAndroid Build Coastguard Worker 
861*61046927SAndroid Build Coastguard Worker static nir_def *
handle_round(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)862*61046927SAndroid Build Coastguard Worker handle_round(struct vtn_builder *b, uint32_t opcode,
863*61046927SAndroid Build Coastguard Worker              unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
864*61046927SAndroid Build Coastguard Worker              const struct vtn_type *dest_type)
865*61046927SAndroid Build Coastguard Worker {
866*61046927SAndroid Build Coastguard Worker    nir_def *src = srcs[0];
867*61046927SAndroid Build Coastguard Worker    nir_builder *nb = &b->nb;
868*61046927SAndroid Build Coastguard Worker    nir_def *half = nir_imm_floatN_t(nb, 0.5, src->bit_size);
869*61046927SAndroid Build Coastguard Worker    nir_def *truncated = nir_ftrunc(nb, src);
870*61046927SAndroid Build Coastguard Worker    nir_def *remainder = nir_fsub(nb, src, truncated);
871*61046927SAndroid Build Coastguard Worker 
872*61046927SAndroid Build Coastguard Worker    return nir_bcsel(nb, nir_fge(nb, nir_fabs(nb, remainder), half),
873*61046927SAndroid Build Coastguard Worker                     nir_fadd(nb, truncated, nir_fsign(nb, src)), truncated);
874*61046927SAndroid Build Coastguard Worker }
875*61046927SAndroid Build Coastguard Worker 
876*61046927SAndroid Build Coastguard Worker static nir_def *
handle_shuffle(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)877*61046927SAndroid Build Coastguard Worker handle_shuffle(struct vtn_builder *b, uint32_t opcode,
878*61046927SAndroid Build Coastguard Worker                unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
879*61046927SAndroid Build Coastguard Worker                const struct vtn_type *dest_type)
880*61046927SAndroid Build Coastguard Worker {
881*61046927SAndroid Build Coastguard Worker    struct nir_def *input = srcs[0];
882*61046927SAndroid Build Coastguard Worker    struct nir_def *mask = srcs[1];
883*61046927SAndroid Build Coastguard Worker 
884*61046927SAndroid Build Coastguard Worker    unsigned out_elems = dest_type->length;
885*61046927SAndroid Build Coastguard Worker    nir_def *outres[NIR_MAX_VEC_COMPONENTS];
886*61046927SAndroid Build Coastguard Worker    unsigned in_elems = input->num_components;
887*61046927SAndroid Build Coastguard Worker    if (mask->bit_size != 32)
888*61046927SAndroid Build Coastguard Worker       mask = nir_u2u32(&b->nb, mask);
889*61046927SAndroid Build Coastguard Worker    mask = nir_iand(&b->nb, mask, nir_imm_intN_t(&b->nb, in_elems - 1, mask->bit_size));
890*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < out_elems; i++)
891*61046927SAndroid Build Coastguard Worker       outres[i] = nir_vector_extract(&b->nb, input, nir_channel(&b->nb, mask, i));
892*61046927SAndroid Build Coastguard Worker 
893*61046927SAndroid Build Coastguard Worker    return nir_vec(&b->nb, outres, out_elems);
894*61046927SAndroid Build Coastguard Worker }
895*61046927SAndroid Build Coastguard Worker 
896*61046927SAndroid Build Coastguard Worker static nir_def *
handle_shuffle2(struct vtn_builder * b,uint32_t opcode,unsigned num_srcs,nir_def ** srcs,struct vtn_type ** src_types,const struct vtn_type * dest_type)897*61046927SAndroid Build Coastguard Worker handle_shuffle2(struct vtn_builder *b, uint32_t opcode,
898*61046927SAndroid Build Coastguard Worker                 unsigned num_srcs, nir_def **srcs, struct vtn_type **src_types,
899*61046927SAndroid Build Coastguard Worker                 const struct vtn_type *dest_type)
900*61046927SAndroid Build Coastguard Worker {
901*61046927SAndroid Build Coastguard Worker    struct nir_def *input0 = srcs[0];
902*61046927SAndroid Build Coastguard Worker    struct nir_def *input1 = srcs[1];
903*61046927SAndroid Build Coastguard Worker    struct nir_def *mask = srcs[2];
904*61046927SAndroid Build Coastguard Worker 
905*61046927SAndroid Build Coastguard Worker    unsigned out_elems = dest_type->length;
906*61046927SAndroid Build Coastguard Worker    nir_def *outres[NIR_MAX_VEC_COMPONENTS];
907*61046927SAndroid Build Coastguard Worker    unsigned in_elems = input0->num_components;
908*61046927SAndroid Build Coastguard Worker    unsigned total_mask = 2 * in_elems - 1;
909*61046927SAndroid Build Coastguard Worker    unsigned half_mask = in_elems - 1;
910*61046927SAndroid Build Coastguard Worker    if (mask->bit_size != 32)
911*61046927SAndroid Build Coastguard Worker       mask = nir_u2u32(&b->nb, mask);
912*61046927SAndroid Build Coastguard Worker    mask = nir_iand(&b->nb, mask, nir_imm_intN_t(&b->nb, total_mask, mask->bit_size));
913*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < out_elems; i++) {
914*61046927SAndroid Build Coastguard Worker       nir_def *this_mask = nir_channel(&b->nb, mask, i);
915*61046927SAndroid Build Coastguard Worker       nir_def *vmask = nir_iand(&b->nb, this_mask, nir_imm_intN_t(&b->nb, half_mask, mask->bit_size));
916*61046927SAndroid Build Coastguard Worker       nir_def *val0 = nir_vector_extract(&b->nb, input0, vmask);
917*61046927SAndroid Build Coastguard Worker       nir_def *val1 = nir_vector_extract(&b->nb, input1, vmask);
918*61046927SAndroid Build Coastguard Worker       nir_def *sel = nir_ilt_imm(&b->nb, this_mask, in_elems);
919*61046927SAndroid Build Coastguard Worker       outres[i] = nir_bcsel(&b->nb, sel, val0, val1);
920*61046927SAndroid Build Coastguard Worker    }
921*61046927SAndroid Build Coastguard Worker    return nir_vec(&b->nb, outres, out_elems);
922*61046927SAndroid Build Coastguard Worker }
923*61046927SAndroid Build Coastguard Worker 
924*61046927SAndroid Build Coastguard Worker bool
vtn_handle_opencl_instruction(struct vtn_builder * b,SpvOp ext_opcode,const uint32_t * w,unsigned count)925*61046927SAndroid Build Coastguard Worker vtn_handle_opencl_instruction(struct vtn_builder *b, SpvOp ext_opcode,
926*61046927SAndroid Build Coastguard Worker                               const uint32_t *w, unsigned count)
927*61046927SAndroid Build Coastguard Worker {
928*61046927SAndroid Build Coastguard Worker    enum OpenCLstd_Entrypoints cl_opcode = (enum OpenCLstd_Entrypoints) ext_opcode;
929*61046927SAndroid Build Coastguard Worker 
930*61046927SAndroid Build Coastguard Worker    switch (cl_opcode) {
931*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fabs:
932*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAbs:
933*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAbs:
934*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAdd_sat:
935*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAdd_sat:
936*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ceil:
937*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Floor:
938*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fmax:
939*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SHadd:
940*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UHadd:
941*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMax:
942*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMax:
943*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fmin:
944*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMin:
945*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMin:
946*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Mix:
947*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_cos:
948*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_divide:
949*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp2:
950*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log2:
951*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_powr:
952*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_recip:
953*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_rsqrt:
954*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_sin:
955*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_sqrt:
956*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMul_hi:
957*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMul_hi:
958*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Popcount:
959*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SRhadd:
960*61046927SAndroid Build Coastguard Worker    case OpenCLstd_URhadd:
961*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rsqrt:
962*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sign:
963*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sqrt:
964*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SSub_sat:
965*61046927SAndroid Build Coastguard Worker    case OpenCLstd_USub_sat:
966*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Trunc:
967*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rint:
968*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_divide:
969*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_recip:
970*61046927SAndroid Build Coastguard Worker       handle_instr(b, ext_opcode, w + 5, count - 5, w + 1, handle_alu);
971*61046927SAndroid Build Coastguard Worker       return true;
972*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SAbs_diff:
973*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UAbs_diff:
974*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad_hi:
975*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMad_hi:
976*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad24:
977*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMad24:
978*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMul24:
979*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMul24:
980*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Bitselect:
981*61046927SAndroid Build Coastguard Worker    case OpenCLstd_FClamp:
982*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SClamp:
983*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UClamp:
984*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Copysign:
985*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cross:
986*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Degrees:
987*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fdim:
988*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fma:
989*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Distance:
990*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fast_distance:
991*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fast_length:
992*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fast_normalize:
993*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_rsqrt:
994*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_sqrt:
995*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Length:
996*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Mad:
997*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Maxmag:
998*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Minmag:
999*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Nan:
1000*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Nextafter:
1001*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Normalize:
1002*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Radians:
1003*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rotate:
1004*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Select:
1005*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Step:
1006*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Smoothstep:
1007*61046927SAndroid Build Coastguard Worker    case OpenCLstd_S_Upsample:
1008*61046927SAndroid Build Coastguard Worker    case OpenCLstd_U_Upsample:
1009*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Clz:
1010*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ctz:
1011*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp:
1012*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_exp10:
1013*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log:
1014*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_log10:
1015*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Acos:
1016*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Acosh:
1017*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Acospi:
1018*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Asin:
1019*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Asinh:
1020*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Asinpi:
1021*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Atan:
1022*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Atan2:
1023*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Atanh:
1024*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Atanpi:
1025*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Atan2pi:
1026*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fract:
1027*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Frexp:
1028*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Exp:
1029*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Exp2:
1030*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Expm1:
1031*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Exp10:
1032*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Fmod:
1033*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ilogb:
1034*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Log:
1035*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Log2:
1036*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Log10:
1037*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Log1p:
1038*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Logb:
1039*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Ldexp:
1040*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cos:
1041*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cosh:
1042*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cospi:
1043*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sin:
1044*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sinh:
1045*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sinpi:
1046*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Tan:
1047*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Tanh:
1048*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Tanpi:
1049*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Cbrt:
1050*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Erfc:
1051*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Erf:
1052*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Lgamma:
1053*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Lgamma_r:
1054*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Tgamma:
1055*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Pow:
1056*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Powr:
1057*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Pown:
1058*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Rootn:
1059*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Remainder:
1060*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Remquo:
1061*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Hypot:
1062*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Sincos:
1063*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Modf:
1064*61046927SAndroid Build Coastguard Worker    case OpenCLstd_UMad_sat:
1065*61046927SAndroid Build Coastguard Worker    case OpenCLstd_SMad_sat:
1066*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Native_tan:
1067*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_cos:
1068*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_exp:
1069*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_exp2:
1070*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_exp10:
1071*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_log:
1072*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_log2:
1073*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_log10:
1074*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_powr:
1075*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_sin:
1076*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Half_tan:
1077*61046927SAndroid Build Coastguard Worker       handle_instr(b, ext_opcode, w + 5, count - 5, w + 1, handle_special);
1078*61046927SAndroid Build Coastguard Worker       return true;
1079*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vloadn:
1080*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vload_half:
1081*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vload_halfn:
1082*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vloada_halfn:
1083*61046927SAndroid Build Coastguard Worker       vtn_handle_opencl_vload(b, cl_opcode, w, count);
1084*61046927SAndroid Build Coastguard Worker       return true;
1085*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstoren:
1086*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstore_half:
1087*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstore_halfn:
1088*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstorea_halfn:
1089*61046927SAndroid Build Coastguard Worker       vtn_handle_opencl_vstore(b, cl_opcode, w, count);
1090*61046927SAndroid Build Coastguard Worker       return true;
1091*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstore_half_r:
1092*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstore_halfn_r:
1093*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Vstorea_halfn_r:
1094*61046927SAndroid Build Coastguard Worker       vtn_handle_opencl_vstore_half_r(b, cl_opcode, w, count);
1095*61046927SAndroid Build Coastguard Worker       return true;
1096*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Shuffle:
1097*61046927SAndroid Build Coastguard Worker       handle_instr(b, ext_opcode, w + 5, count - 5, w + 1, handle_shuffle);
1098*61046927SAndroid Build Coastguard Worker       return true;
1099*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Shuffle2:
1100*61046927SAndroid Build Coastguard Worker       handle_instr(b, ext_opcode, w + 5, count - 5, w + 1, handle_shuffle2);
1101*61046927SAndroid Build Coastguard Worker       return true;
1102*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Round:
1103*61046927SAndroid Build Coastguard Worker       handle_instr(b, ext_opcode, w + 5, count - 5, w + 1, handle_round);
1104*61046927SAndroid Build Coastguard Worker       return true;
1105*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Printf:
1106*61046927SAndroid Build Coastguard Worker       handle_printf(b, ext_opcode, w + 5, count - 5, w + 1);
1107*61046927SAndroid Build Coastguard Worker       return true;
1108*61046927SAndroid Build Coastguard Worker    case OpenCLstd_Prefetch:
1109*61046927SAndroid Build Coastguard Worker       /* TODO maybe add a nir instruction for this? */
1110*61046927SAndroid Build Coastguard Worker       return true;
1111*61046927SAndroid Build Coastguard Worker    default:
1112*61046927SAndroid Build Coastguard Worker       vtn_fail("unhandled opencl opc: %u\n", ext_opcode);
1113*61046927SAndroid Build Coastguard Worker       return false;
1114*61046927SAndroid Build Coastguard Worker    }
1115*61046927SAndroid Build Coastguard Worker }
1116*61046927SAndroid Build Coastguard Worker 
1117*61046927SAndroid Build Coastguard Worker bool
vtn_handle_opencl_core_instruction(struct vtn_builder * b,SpvOp opcode,const uint32_t * w,unsigned count)1118*61046927SAndroid Build Coastguard Worker vtn_handle_opencl_core_instruction(struct vtn_builder *b, SpvOp opcode,
1119*61046927SAndroid Build Coastguard Worker                                    const uint32_t *w, unsigned count)
1120*61046927SAndroid Build Coastguard Worker {
1121*61046927SAndroid Build Coastguard Worker    switch (opcode) {
1122*61046927SAndroid Build Coastguard Worker    case SpvOpGroupAsyncCopy:
1123*61046927SAndroid Build Coastguard Worker       handle_instr(b, opcode, w + 4, count - 4, w + 1, handle_core);
1124*61046927SAndroid Build Coastguard Worker       return true;
1125*61046927SAndroid Build Coastguard Worker    case SpvOpGroupWaitEvents:
1126*61046927SAndroid Build Coastguard Worker       handle_instr(b, opcode, w + 2, count - 2, NULL, handle_core);
1127*61046927SAndroid Build Coastguard Worker       return true;
1128*61046927SAndroid Build Coastguard Worker    default:
1129*61046927SAndroid Build Coastguard Worker       return false;
1130*61046927SAndroid Build Coastguard Worker    }
1131*61046927SAndroid Build Coastguard Worker    return true;
1132*61046927SAndroid Build Coastguard Worker }
1133