• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/format/u_format.h"
41 #include "util/compiler.h"
42 #include "gallivm/lp_bld.h"
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /**
49  * Native SIMD architecture width available at runtime.
50  *
51  * Using this width should give the best performance,
52  * and it determines the necessary alignment of vector variables.
53  */
54 extern unsigned lp_native_vector_width;
55 
56 /**
57  * Maximum supported vector width (not necessarily supported at run-time).
58  *
59  * Should only be used when lp_native_vector_width isn't available,
60  * i.e. sizing/alignment of non-malloced variables.
61  */
62 #define LP_MAX_VECTOR_WIDTH 512
63 
64 /**
65  * Minimum vector alignment for static variable alignment
66  *
67  * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8.  An
68  * expression is non-portable.
69  */
70 #define LP_MIN_VECTOR_ALIGN 64
71 
72 /**
73  * Several functions can only cope with vectors of length up to this value.
74  * You may need to increase that value if you want to represent bigger vectors.
75  */
76 #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
77 
78 /**
79  * The LLVM type system can't conveniently express all the things we care about
80  * on the types used for intermediate computations, such as signed vs unsigned,
81  * normalized values, or fixed point.
82  */
83 struct lp_type {
84    /**
85     * Floating-point. Cannot be used with fixed. Integer numbers are
86     * represented by this zero.
87     */
88    unsigned floating:1;
89 
90    /**
91     * Fixed-point. Cannot be used with floating. Integer numbers are
92     * represented by this zero.
93     */
94    unsigned fixed:1;
95 
96    /**
97     * Whether it can represent negative values or not.
98     *
99     * If this is not set for floating point, it means that all values are
100     * assumed to be positive.
101     */
102    unsigned sign:1;
103 
104    /**
105     * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
106     * interval for signed types.
107     *
108     * For integer types it means the representable integer range should be
109     * interpreted as the interval above.
110     *
111     * For floating and fixed point formats it means the values should be
112     * clamped to the interval above.
113     */
114    unsigned norm:1;
115 
116    /** Arithmetic operations that use this type can not flust -0 to 0. */
117    unsigned signed_zero_preserve:1;
118 
119    /** Arithmetic operations that use this type can not flust nan to 0. */
120    unsigned nan_preserve:1;
121 
122    /**
123     * Element width.
124     *
125     * For fixed point values, the fixed point is assumed to be at half the
126     * width.
127     */
128    unsigned width:14;
129 
130    /**
131     * Vector length.  If length==1, this is a scalar (float/int) type.
132     *
133     * width*length should be a power of two greater or equal to eight.
134     *
135     * @sa LP_MAX_VECTOR_LENGTH
136     */
137    unsigned length:14;
138 };
139 
140 
141 /**
142  * We need most of the information here in order to correctly and efficiently
143  * translate an arithmetic operation into LLVM IR. Putting it here avoids the
144  * trouble of passing it as parameters.
145  */
146 struct lp_build_context
147 {
148    struct gallivm_state *gallivm;
149 
150    /**
151     * This not only describes the input/output LLVM types, but also whether
152     * to normalize/clamp the results.
153     */
154    struct lp_type type;
155 
156    /** Same as lp_build_elem_type(type) */
157    LLVMTypeRef elem_type;
158 
159    /** Same as lp_build_vec_type(type) */
160    LLVMTypeRef vec_type;
161 
162    /** Same as lp_build_int_elem_type(type) */
163    LLVMTypeRef int_elem_type;
164 
165    /** Same as lp_build_int_vec_type(type) */
166    LLVMTypeRef int_vec_type;
167 
168    /** Same as lp_build_undef(type) */
169    LLVMValueRef undef;
170 
171    /** Same as lp_build_zero(type) */
172    LLVMValueRef zero;
173 
174    /** Same as lp_build_one(type) */
175    LLVMValueRef one;
176 };
177 
178 
179 /**
180  * Converts a format description into an lp_type.
181  *
182  * Only works with "array formats".
183  *
184  * e.g. With PIPE_FORMAT_R32G32B32A32_FLOAT returns an lp_type with float[4]
185  */
186 static inline void
lp_type_from_format_desc(struct lp_type * type,const struct util_format_description * format_desc)187 lp_type_from_format_desc(struct lp_type* type, const struct util_format_description *format_desc)
188 {
189    assert(format_desc->is_array);
190    assert(!format_desc->is_mixed);
191 
192    memset(type, 0, sizeof(struct lp_type));
193    type->floating = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT;
194    type->fixed    = format_desc->channel[0].type == UTIL_FORMAT_TYPE_FIXED;
195    type->sign     = format_desc->channel[0].type != UTIL_FORMAT_TYPE_UNSIGNED;
196    type->norm     = format_desc->channel[0].normalized;
197    type->width    = format_desc->channel[0].size;
198    type->length   = format_desc->nr_channels;
199 }
200 
201 
202 static inline void
lp_type_from_format(struct lp_type * type,enum pipe_format format)203 lp_type_from_format(struct lp_type* type, enum pipe_format format)
204 {
205    lp_type_from_format_desc(type, util_format_description(format));
206 }
207 
208 
209 static inline unsigned
lp_type_width(struct lp_type type)210 lp_type_width(struct lp_type type)
211 {
212    return type.width * type.length;
213 }
214 
215 
216 /** Create scalar float type */
217 static inline struct lp_type
lp_type_float(unsigned width)218 lp_type_float(unsigned width)
219 {
220    struct lp_type res_type;
221 
222    memset(&res_type, 0, sizeof res_type);
223    res_type.floating = true;
224    res_type.sign = true;
225    res_type.width = width;
226    res_type.length = 1;
227 
228    return res_type;
229 }
230 
231 
232 /** Create vector of float type */
233 static inline struct lp_type
lp_type_float_vec(unsigned width,unsigned total_width)234 lp_type_float_vec(unsigned width, unsigned total_width)
235 {
236    struct lp_type res_type;
237 
238    memset(&res_type, 0, sizeof res_type);
239    res_type.floating = true;
240    res_type.sign = true;
241    res_type.width = width;
242    res_type.length = total_width / width;
243 
244    return res_type;
245 }
246 
247 
248 /** Create scalar int type */
249 static inline struct lp_type
lp_type_int(unsigned width)250 lp_type_int(unsigned width)
251 {
252    struct lp_type res_type;
253 
254    memset(&res_type, 0, sizeof res_type);
255    res_type.sign = true;
256    res_type.width = width;
257    res_type.length = 1;
258 
259    return res_type;
260 }
261 
262 
263 /** Create vector int type */
264 static inline struct lp_type
lp_type_int_vec(unsigned width,unsigned total_width)265 lp_type_int_vec(unsigned width, unsigned total_width)
266 {
267    struct lp_type res_type;
268 
269    memset(&res_type, 0, sizeof res_type);
270    res_type.sign = true;
271    res_type.width = width;
272    res_type.length = total_width / width;
273 
274    return res_type;
275 }
276 
277 
278 /** Create scalar uint type */
279 static inline struct lp_type
lp_type_uint(unsigned width)280 lp_type_uint(unsigned width)
281 {
282    struct lp_type res_type;
283 
284    memset(&res_type, 0, sizeof res_type);
285    res_type.width = width;
286    res_type.length = 1;
287 
288    return res_type;
289 }
290 
291 
292 /** Create vector uint type */
293 static inline struct lp_type
lp_type_uint_vec(unsigned width,unsigned total_width)294 lp_type_uint_vec(unsigned width, unsigned total_width)
295 {
296    struct lp_type res_type;
297 
298    memset(&res_type, 0, sizeof res_type);
299    res_type.width = width;
300    res_type.length = total_width / width;
301 
302    return res_type;
303 }
304 
305 
306 static inline struct lp_type
lp_type_unorm(unsigned width,unsigned total_width)307 lp_type_unorm(unsigned width, unsigned total_width)
308 {
309    struct lp_type res_type;
310 
311    memset(&res_type, 0, sizeof res_type);
312    res_type.norm = true;
313    res_type.width = width;
314    res_type.length = total_width / width;
315 
316    return res_type;
317 }
318 
319 
320 static inline struct lp_type
lp_type_fixed(unsigned width,unsigned total_width)321 lp_type_fixed(unsigned width, unsigned total_width)
322 {
323    struct lp_type res_type;
324 
325    memset(&res_type, 0, sizeof res_type);
326    res_type.sign = true;
327    res_type.fixed = true;
328    res_type.width = width;
329    res_type.length = total_width / width;
330 
331    return res_type;
332 }
333 
334 
335 static inline struct lp_type
lp_type_ufixed(unsigned width,unsigned total_width)336 lp_type_ufixed(unsigned width, unsigned total_width)
337 {
338    struct lp_type res_type;
339 
340    memset(&res_type, 0, sizeof res_type);
341    res_type.fixed = true;
342    res_type.width = width;
343    res_type.length = total_width / width;
344 
345    return res_type;
346 }
347 
348 
349 LLVMTypeRef
350 lp_build_elem_type(const struct gallivm_state *gallivm, struct lp_type type);
351 
352 
353 LLVMTypeRef
354 lp_build_vec_type(const struct gallivm_state *gallivm, struct lp_type type);
355 
356 
357 bool
358 lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type);
359 
360 
361 bool
362 lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type);
363 
364 
365 bool
366 lp_check_value(struct lp_type type, LLVMValueRef val);
367 
368 
369 LLVMTypeRef
370 lp_build_int_elem_type(const struct gallivm_state *gallivm,
371                        struct lp_type type);
372 
373 
374 LLVMTypeRef
375 lp_build_int_vec_type(const struct gallivm_state *gallivm,
376                       struct lp_type type);
377 
378 
379 static inline struct lp_type
lp_float32_vec4_type(void)380 lp_float32_vec4_type(void)
381 {
382    struct lp_type type;
383 
384    memset(&type, 0, sizeof(type));
385    type.floating = true;
386    type.sign = true;
387    type.norm = false;
388    type.width = 32;
389    type.length = 4;
390 
391    return type;
392 }
393 
394 
395 static inline struct lp_type
lp_int32_vec4_type(void)396 lp_int32_vec4_type(void)
397 {
398    struct lp_type type;
399 
400    memset(&type, 0, sizeof(type));
401    type.floating = false;
402    type.sign = true;
403    type.norm = false;
404    type.width = 32;
405    type.length = 4;
406 
407    return type;
408 }
409 
410 
411 static inline struct lp_type
lp_unorm8_vec4_type(void)412 lp_unorm8_vec4_type(void)
413 {
414    struct lp_type type;
415 
416    memset(&type, 0, sizeof(type));
417    type.floating = false;
418    type.sign = false;
419    type.norm = true;
420    type.width = 8;
421    type.length = 4;
422 
423    return type;
424 }
425 
426 
427 struct lp_type
428 lp_elem_type(struct lp_type type);
429 
430 
431 struct lp_type
432 lp_uint_type(struct lp_type type);
433 
434 
435 struct lp_type
436 lp_int_type(struct lp_type type);
437 
438 
439 struct lp_type
440 lp_wider_type(struct lp_type type);
441 
442 
443 unsigned
444 lp_sizeof_llvm_type(LLVMTypeRef t);
445 
446 
447 const char *
448 lp_typekind_name(LLVMTypeKind t);
449 
450 
451 void
452 lp_dump_llvmtype(LLVMTypeRef t);
453 
454 
455 void
456 lp_build_context_init(struct lp_build_context *bld,
457                       struct gallivm_state *gallivm,
458                       struct lp_type type);
459 
460 
461 unsigned
462 lp_build_count_ir_module(LLVMModuleRef module);
463 
464 #ifdef __cplusplus
465 }
466 #endif
467 
468 #endif /* !LP_BLD_TYPE_H */
469