1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Convenient representation of SIMD types.
32 * @author Jose Fonseca <jfonseca@vmware.com>
40 #include "util/format/u_format.h"
41 #include "pipe/p_compiler.h"
42 #include "gallivm/lp_bld.h"
49 * Native SIMD architecture width available at runtime.
51 * Using this width should give the best performance,
52 * and it determines the necessary alignment of vector variables.
54 extern unsigned lp_native_vector_width
;
57 * Maximum supported vector width (not necessarily supported at run-time).
59 * Should only be used when lp_native_vector_width isn't available,
60 * i.e. sizing/alignment of non-malloced variables.
62 #define LP_MAX_VECTOR_WIDTH 512
65 * Minimum vector alignment for static variable alignment
67 * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An
68 * expression is non-portable.
70 #define LP_MIN_VECTOR_ALIGN 64
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.
76 #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
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.
85 * Floating-point. Cannot be used with fixed. Integer numbers are
86 * represented by this zero.
91 * Fixed-point. Cannot be used with floating. Integer numbers are
92 * represented by this zero.
97 * Whether it can represent negative values or not.
99 * If this is not set for floating point, it means that all values are
100 * assumed to be positive.
105 * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
106 * interval for signed types.
108 * For integer types it means the representable integer range should be
109 * interpreted as the interval above.
111 * For floating and fixed point formats it means the values should be
112 * clamped to the interval above.
119 * For fixed point values, the fixed point is assumed to be at half the
125 * Vector length. If length==1, this is a scalar (float/int) type.
127 * width*length should be a power of two greater or equal to eight.
129 * @sa LP_MAX_VECTOR_LENGTH
136 * We need most of the information here in order to correctly and efficiently
137 * translate an arithmetic operation into LLVM IR. Putting it here avoids the
138 * trouble of passing it as parameters.
140 struct lp_build_context
142 struct gallivm_state
*gallivm
;
145 * This not only describes the input/output LLVM types, but also whether
146 * to normalize/clamp the results.
150 /** Same as lp_build_elem_type(type) */
151 LLVMTypeRef elem_type
;
153 /** Same as lp_build_vec_type(type) */
154 LLVMTypeRef vec_type
;
156 /** Same as lp_build_int_elem_type(type) */
157 LLVMTypeRef int_elem_type
;
159 /** Same as lp_build_int_vec_type(type) */
160 LLVMTypeRef int_vec_type
;
162 /** Same as lp_build_undef(type) */
165 /** Same as lp_build_zero(type) */
168 /** Same as lp_build_one(type) */
174 * Converts a format description into an lp_type.
176 * Only works with "array formats".
178 * e.g. With PIPE_FORMAT_R32G32B32A32_FLOAT returns an lp_type with float[4]
181 lp_type_from_format_desc(struct lp_type
* type
, const struct util_format_description
*format_desc
)
183 assert(format_desc
->is_array
);
184 assert(!format_desc
->is_mixed
);
186 memset(type
, 0, sizeof(struct lp_type
));
187 type
->floating
= format_desc
->channel
[0].type
== UTIL_FORMAT_TYPE_FLOAT
;
188 type
->fixed
= format_desc
->channel
[0].type
== UTIL_FORMAT_TYPE_FIXED
;
189 type
->sign
= format_desc
->channel
[0].type
!= UTIL_FORMAT_TYPE_UNSIGNED
;
190 type
->norm
= format_desc
->channel
[0].normalized
;
191 type
->width
= format_desc
->channel
[0].size
;
192 type
->length
= format_desc
->nr_channels
;
197 lp_type_from_format(struct lp_type
* type
, enum pipe_format format
)
199 lp_type_from_format_desc(type
, util_format_description(format
));
203 static inline unsigned
204 lp_type_width(struct lp_type type
)
206 return type
.width
* type
.length
;
210 /** Create scalar float type */
211 static inline struct lp_type
212 lp_type_float(unsigned width
)
214 struct lp_type res_type
;
216 memset(&res_type
, 0, sizeof res_type
);
217 res_type
.floating
= TRUE
;
218 res_type
.sign
= TRUE
;
219 res_type
.width
= width
;
226 /** Create vector of float type */
227 static inline struct lp_type
228 lp_type_float_vec(unsigned width
, unsigned total_width
)
230 struct lp_type res_type
;
232 memset(&res_type
, 0, sizeof res_type
);
233 res_type
.floating
= TRUE
;
234 res_type
.sign
= TRUE
;
235 res_type
.width
= width
;
236 res_type
.length
= total_width
/ width
;
242 /** Create scalar int type */
243 static inline struct lp_type
244 lp_type_int(unsigned width
)
246 struct lp_type res_type
;
248 memset(&res_type
, 0, sizeof res_type
);
249 res_type
.sign
= TRUE
;
250 res_type
.width
= width
;
257 /** Create vector int type */
258 static inline struct lp_type
259 lp_type_int_vec(unsigned width
, unsigned total_width
)
261 struct lp_type res_type
;
263 memset(&res_type
, 0, sizeof res_type
);
264 res_type
.sign
= TRUE
;
265 res_type
.width
= width
;
266 res_type
.length
= total_width
/ width
;
272 /** Create scalar uint type */
273 static inline struct lp_type
274 lp_type_uint(unsigned width
)
276 struct lp_type res_type
;
278 memset(&res_type
, 0, sizeof res_type
);
279 res_type
.width
= width
;
286 /** Create vector uint type */
287 static inline struct lp_type
288 lp_type_uint_vec(unsigned width
, unsigned total_width
)
290 struct lp_type res_type
;
292 memset(&res_type
, 0, sizeof res_type
);
293 res_type
.width
= width
;
294 res_type
.length
= total_width
/ width
;
300 static inline struct lp_type
301 lp_type_unorm(unsigned width
, unsigned total_width
)
303 struct lp_type res_type
;
305 memset(&res_type
, 0, sizeof res_type
);
306 res_type
.norm
= TRUE
;
307 res_type
.width
= width
;
308 res_type
.length
= total_width
/ width
;
314 static inline struct lp_type
315 lp_type_fixed(unsigned width
, unsigned total_width
)
317 struct lp_type res_type
;
319 memset(&res_type
, 0, sizeof res_type
);
320 res_type
.sign
= TRUE
;
321 res_type
.fixed
= TRUE
;
322 res_type
.width
= width
;
323 res_type
.length
= total_width
/ width
;
329 static inline struct lp_type
330 lp_type_ufixed(unsigned width
, unsigned total_width
)
332 struct lp_type res_type
;
334 memset(&res_type
, 0, sizeof res_type
);
335 res_type
.fixed
= TRUE
;
336 res_type
.width
= width
;
337 res_type
.length
= total_width
/ width
;
344 lp_build_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
348 lp_build_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
352 lp_check_elem_type(struct lp_type type
, LLVMTypeRef elem_type
);
356 lp_check_vec_type(struct lp_type type
, LLVMTypeRef vec_type
);
360 lp_check_value(struct lp_type type
, LLVMValueRef val
);
364 lp_build_int_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
368 lp_build_int_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
371 static inline struct lp_type
372 lp_float32_vec4_type(void)
376 memset(&type
, 0, sizeof(type
));
377 type
.floating
= TRUE
;
387 static inline struct lp_type
388 lp_int32_vec4_type(void)
392 memset(&type
, 0, sizeof(type
));
393 type
.floating
= FALSE
;
403 static inline struct lp_type
404 lp_unorm8_vec4_type(void)
408 memset(&type
, 0, sizeof(type
));
409 type
.floating
= FALSE
;
420 lp_elem_type(struct lp_type type
);
424 lp_uint_type(struct lp_type type
);
428 lp_int_type(struct lp_type type
);
432 lp_wider_type(struct lp_type type
);
436 lp_sizeof_llvm_type(LLVMTypeRef t
);
440 lp_typekind_name(LLVMTypeKind t
);
444 lp_dump_llvmtype(LLVMTypeRef t
);
448 lp_build_context_init(struct lp_build_context
*bld
,
449 struct gallivm_state
*gallivm
,
450 struct lp_type type
);
454 lp_build_count_ir_module(LLVMModuleRef module
);
460 #endif /* !LP_BLD_TYPE_H */