Introduce .editorconfig
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_type.h
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Convenient representation of SIMD types.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 */
34
35
36 #ifndef LP_BLD_TYPE_H
37 #define LP_BLD_TYPE_H
38
39
40 #include "util/u_format.h"
41 #include "pipe/p_compiler.h"
42 #include "gallivm/lp_bld.h"
43
44 /**
45 * Native SIMD architecture width available at runtime.
46 *
47 * Using this width should give the best performance,
48 * and it determines the necessary alignment of vector variables.
49 */
50 extern unsigned lp_native_vector_width;
51
52 /**
53 * Maximum supported vector width (not necessarily supported at run-time).
54 *
55 * Should only be used when lp_native_vector_width isn't available,
56 * i.e. sizing/alignment of non-malloced variables.
57 */
58 #define LP_MAX_VECTOR_WIDTH 256
59
60 /**
61 * Minimum vector alignment for static variable alignment
62 *
63 * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An
64 * expression is non-portable.
65 */
66 #define LP_MIN_VECTOR_ALIGN 32
67
68 /**
69 * Several functions can only cope with vectors of length up to this value.
70 * You may need to increase that value if you want to represent bigger vectors.
71 */
72 #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
73
74 /**
75 * The LLVM type system can't conveniently express all the things we care about
76 * on the types used for intermediate computations, such as signed vs unsigned,
77 * normalized values, or fixed point.
78 */
79 struct lp_type {
80 /**
81 * Floating-point. Cannot be used with fixed. Integer numbers are
82 * represented by this zero.
83 */
84 unsigned floating:1;
85
86 /**
87 * Fixed-point. Cannot be used with floating. Integer numbers are
88 * represented by this zero.
89 */
90 unsigned fixed:1;
91
92 /**
93 * Whether it can represent negative values or not.
94 *
95 * If this is not set for floating point, it means that all values are
96 * assumed to be positive.
97 */
98 unsigned sign:1;
99
100 /**
101 * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
102 * interval for signed types.
103 *
104 * For integer types it means the representable integer range should be
105 * interpreted as the interval above.
106 *
107 * For floating and fixed point formats it means the values should be
108 * clamped to the interval above.
109 */
110 unsigned norm:1;
111
112 /**
113 * Element width.
114 *
115 * For fixed point values, the fixed point is assumed to be at half the
116 * width.
117 */
118 unsigned width:14;
119
120 /**
121 * Vector length. If length==1, this is a scalar (float/int) type.
122 *
123 * width*length should be a power of two greater or equal to eight.
124 *
125 * @sa LP_MAX_VECTOR_LENGTH
126 */
127 unsigned length:14;
128 };
129
130
131 /**
132 * We need most of the information here in order to correctly and efficiently
133 * translate an arithmetic operation into LLVM IR. Putting it here avoids the
134 * trouble of passing it as parameters.
135 */
136 struct lp_build_context
137 {
138 struct gallivm_state *gallivm;
139
140 /**
141 * This not only describes the input/output LLVM types, but also whether
142 * to normalize/clamp the results.
143 */
144 struct lp_type type;
145
146 /** Same as lp_build_elem_type(type) */
147 LLVMTypeRef elem_type;
148
149 /** Same as lp_build_vec_type(type) */
150 LLVMTypeRef vec_type;
151
152 /** Same as lp_build_int_elem_type(type) */
153 LLVMTypeRef int_elem_type;
154
155 /** Same as lp_build_int_vec_type(type) */
156 LLVMTypeRef int_vec_type;
157
158 /** Same as lp_build_undef(type) */
159 LLVMValueRef undef;
160
161 /** Same as lp_build_zero(type) */
162 LLVMValueRef zero;
163
164 /** Same as lp_build_one(type) */
165 LLVMValueRef one;
166 };
167
168
169 /**
170 * Converts a format description into an lp_type.
171 *
172 * Only works with "array formats".
173 *
174 * e.g. With PIPE_FORMAT_R32G32B32A32_FLOAT returns an lp_type with float[4]
175 */
176 static inline void
177 lp_type_from_format_desc(struct lp_type* type, const struct util_format_description *format_desc)
178 {
179 assert(format_desc->is_array);
180 assert(!format_desc->is_mixed);
181
182 memset(type, 0, sizeof(struct lp_type));
183 type->floating = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT;
184 type->fixed = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FIXED;
185 type->sign = format_desc->channel[0].type != UTIL_FORMAT_TYPE_UNSIGNED;
186 type->norm = format_desc->channel[0].normalized;
187 type->width = format_desc->channel[0].size;
188 type->length = format_desc->nr_channels;
189 }
190
191
192 static inline void
193 lp_type_from_format(struct lp_type* type, enum pipe_format format)
194 {
195 lp_type_from_format_desc(type, util_format_description(format));
196 }
197
198
199 static inline unsigned
200 lp_type_width(struct lp_type type)
201 {
202 return type.width * type.length;
203 }
204
205
206 /** Create scalar float type */
207 static inline struct lp_type
208 lp_type_float(unsigned width)
209 {
210 struct lp_type res_type;
211
212 memset(&res_type, 0, sizeof res_type);
213 res_type.floating = TRUE;
214 res_type.sign = TRUE;
215 res_type.width = width;
216 res_type.length = 1;
217
218 return res_type;
219 }
220
221
222 /** Create vector of float type */
223 static inline struct lp_type
224 lp_type_float_vec(unsigned width, unsigned total_width)
225 {
226 struct lp_type res_type;
227
228 memset(&res_type, 0, sizeof res_type);
229 res_type.floating = TRUE;
230 res_type.sign = TRUE;
231 res_type.width = width;
232 res_type.length = total_width / width;
233
234 return res_type;
235 }
236
237
238 /** Create scalar int type */
239 static inline struct lp_type
240 lp_type_int(unsigned width)
241 {
242 struct lp_type res_type;
243
244 memset(&res_type, 0, sizeof res_type);
245 res_type.sign = TRUE;
246 res_type.width = width;
247 res_type.length = 1;
248
249 return res_type;
250 }
251
252
253 /** Create vector int type */
254 static inline struct lp_type
255 lp_type_int_vec(unsigned width, unsigned total_width)
256 {
257 struct lp_type res_type;
258
259 memset(&res_type, 0, sizeof res_type);
260 res_type.sign = TRUE;
261 res_type.width = width;
262 res_type.length = total_width / width;
263
264 return res_type;
265 }
266
267
268 /** Create scalar uint type */
269 static inline struct lp_type
270 lp_type_uint(unsigned width)
271 {
272 struct lp_type res_type;
273
274 memset(&res_type, 0, sizeof res_type);
275 res_type.width = width;
276 res_type.length = 1;
277
278 return res_type;
279 }
280
281
282 /** Create vector uint type */
283 static inline struct lp_type
284 lp_type_uint_vec(unsigned width, unsigned total_width)
285 {
286 struct lp_type res_type;
287
288 memset(&res_type, 0, sizeof res_type);
289 res_type.width = width;
290 res_type.length = total_width / width;
291
292 return res_type;
293 }
294
295
296 static inline struct lp_type
297 lp_type_unorm(unsigned width, unsigned total_width)
298 {
299 struct lp_type res_type;
300
301 memset(&res_type, 0, sizeof res_type);
302 res_type.norm = TRUE;
303 res_type.width = width;
304 res_type.length = total_width / width;
305
306 return res_type;
307 }
308
309
310 static inline struct lp_type
311 lp_type_fixed(unsigned width, unsigned total_width)
312 {
313 struct lp_type res_type;
314
315 memset(&res_type, 0, sizeof res_type);
316 res_type.sign = TRUE;
317 res_type.fixed = TRUE;
318 res_type.width = width;
319 res_type.length = total_width / width;
320
321 return res_type;
322 }
323
324
325 static inline struct lp_type
326 lp_type_ufixed(unsigned width, unsigned total_width)
327 {
328 struct lp_type res_type;
329
330 memset(&res_type, 0, sizeof res_type);
331 res_type.fixed = TRUE;
332 res_type.width = width;
333 res_type.length = total_width / width;
334
335 return res_type;
336 }
337
338
339 LLVMTypeRef
340 lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type);
341
342
343 LLVMTypeRef
344 lp_build_vec_type(struct gallivm_state *gallivm, struct lp_type type);
345
346
347 boolean
348 lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type);
349
350
351 boolean
352 lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type);
353
354
355 boolean
356 lp_check_value(struct lp_type type, LLVMValueRef val);
357
358
359 LLVMTypeRef
360 lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type);
361
362
363 LLVMTypeRef
364 lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type);
365
366
367 static inline struct lp_type
368 lp_float32_vec4_type(void)
369 {
370 struct lp_type type;
371
372 memset(&type, 0, sizeof(type));
373 type.floating = TRUE;
374 type.sign = TRUE;
375 type.norm = FALSE;
376 type.width = 32;
377 type.length = 4;
378
379 return type;
380 }
381
382
383 static inline struct lp_type
384 lp_int32_vec4_type(void)
385 {
386 struct lp_type type;
387
388 memset(&type, 0, sizeof(type));
389 type.floating = FALSE;
390 type.sign = TRUE;
391 type.norm = FALSE;
392 type.width = 32;
393 type.length = 4;
394
395 return type;
396 }
397
398
399 static inline struct lp_type
400 lp_unorm8_vec4_type(void)
401 {
402 struct lp_type type;
403
404 memset(&type, 0, sizeof(type));
405 type.floating = FALSE;
406 type.sign = FALSE;
407 type.norm = TRUE;
408 type.width = 8;
409 type.length = 4;
410
411 return type;
412 }
413
414
415 struct lp_type
416 lp_elem_type(struct lp_type type);
417
418
419 struct lp_type
420 lp_uint_type(struct lp_type type);
421
422
423 struct lp_type
424 lp_int_type(struct lp_type type);
425
426
427 struct lp_type
428 lp_wider_type(struct lp_type type);
429
430
431 unsigned
432 lp_sizeof_llvm_type(LLVMTypeRef t);
433
434
435 const char *
436 lp_typekind_name(LLVMTypeKind t);
437
438
439 void
440 lp_dump_llvmtype(LLVMTypeRef t);
441
442
443 void
444 lp_build_context_init(struct lp_build_context *bld,
445 struct gallivm_state *gallivm,
446 struct lp_type type);
447
448
449 unsigned
450 lp_build_count_ir_module(LLVMModuleRef module);
451
452
453 #endif /* !LP_BLD_TYPE_H */