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/u_format.h"
41 #include "pipe/p_compiler.h"
42 #include "gallivm/lp_bld.h"
45 * Native SIMD architecture width available at runtime.
47 * Using this width should give the best performance,
48 * and it determines the necessary alignment of vector variables.
50 extern unsigned lp_native_vector_width
;
53 * Maximum supported vector width (not necessarily supported at run-time).
55 * Should only be used when lp_native_vector_width isn't available,
56 * i.e. sizing/alignment of non-malloced variables.
58 #define LP_MAX_VECTOR_WIDTH 256
61 * Minimum vector alignment for static variable alignment
63 * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An
64 * expression is non-portable.
66 #define LP_MIN_VECTOR_ALIGN 32
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.
72 #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
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.
81 * Floating-point. Cannot be used with fixed. Integer numbers are
82 * represented by this zero.
87 * Fixed-point. Cannot be used with floating. Integer numbers are
88 * represented by this zero.
93 * Whether it can represent negative values or not.
95 * If this is not set for floating point, it means that all values are
96 * assumed to be positive.
101 * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
102 * interval for signed types.
104 * For integer types it means the representable integer range should be
105 * interpreted as the interval above.
107 * For floating and fixed point formats it means the values should be
108 * clamped to the interval above.
115 * For fixed point values, the fixed point is assumed to be at half the
121 * Vector length. If length==1, this is a scalar (float/int) type.
123 * width*length should be a power of two greater or equal to eight.
125 * @sa LP_MAX_VECTOR_LENGTH
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.
136 struct lp_build_context
138 struct gallivm_state
*gallivm
;
141 * This not only describes the input/output LLVM types, but also whether
142 * to normalize/clamp the results.
146 /** Same as lp_build_elem_type(type) */
147 LLVMTypeRef elem_type
;
149 /** Same as lp_build_vec_type(type) */
150 LLVMTypeRef vec_type
;
152 /** Same as lp_build_int_elem_type(type) */
153 LLVMTypeRef int_elem_type
;
155 /** Same as lp_build_int_vec_type(type) */
156 LLVMTypeRef int_vec_type
;
158 /** Same as lp_build_undef(type) */
161 /** Same as lp_build_zero(type) */
164 /** Same as lp_build_one(type) */
170 * Converts a format description into an lp_type.
172 * Only works with "array formats".
174 * e.g. With PIPE_FORMAT_R32G32B32A32_FLOAT returns an lp_type with float[4]
177 lp_type_from_format_desc(struct lp_type
* type
, const struct util_format_description
*format_desc
)
179 assert(format_desc
->is_array
);
180 assert(!format_desc
->is_mixed
);
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
;
193 lp_type_from_format(struct lp_type
* type
, enum pipe_format format
)
195 lp_type_from_format_desc(type
, util_format_description(format
));
199 static INLINE
unsigned
200 lp_type_width(struct lp_type type
)
202 return type
.width
* type
.length
;
206 /** Create scalar float type */
207 static INLINE
struct lp_type
208 lp_type_float(unsigned width
)
210 struct lp_type res_type
;
212 memset(&res_type
, 0, sizeof res_type
);
213 res_type
.floating
= TRUE
;
214 res_type
.sign
= TRUE
;
215 res_type
.width
= width
;
222 /** Create vector of float type */
223 static INLINE
struct lp_type
224 lp_type_float_vec(unsigned width
, unsigned total_width
)
226 struct lp_type res_type
;
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
;
238 /** Create scalar int type */
239 static INLINE
struct lp_type
240 lp_type_int(unsigned width
)
242 struct lp_type res_type
;
244 memset(&res_type
, 0, sizeof res_type
);
245 res_type
.sign
= TRUE
;
246 res_type
.width
= width
;
253 /** Create vector int type */
254 static INLINE
struct lp_type
255 lp_type_int_vec(unsigned width
, unsigned total_width
)
257 struct lp_type res_type
;
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
;
268 /** Create scalar uint type */
269 static INLINE
struct lp_type
270 lp_type_uint(unsigned width
)
272 struct lp_type res_type
;
274 memset(&res_type
, 0, sizeof res_type
);
275 res_type
.width
= width
;
282 /** Create vector uint type */
283 static INLINE
struct lp_type
284 lp_type_uint_vec(unsigned width
, unsigned total_width
)
286 struct lp_type res_type
;
288 memset(&res_type
, 0, sizeof res_type
);
289 res_type
.width
= width
;
290 res_type
.length
= total_width
/ width
;
296 static INLINE
struct lp_type
297 lp_type_unorm(unsigned width
, unsigned total_width
)
299 struct lp_type res_type
;
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
;
310 static INLINE
struct lp_type
311 lp_type_fixed(unsigned width
, unsigned total_width
)
313 struct lp_type res_type
;
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
;
325 static INLINE
struct lp_type
326 lp_type_ufixed(unsigned width
, unsigned total_width
)
328 struct lp_type res_type
;
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
;
340 lp_build_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
344 lp_build_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
348 lp_check_elem_type(struct lp_type type
, LLVMTypeRef elem_type
);
352 lp_check_vec_type(struct lp_type type
, LLVMTypeRef vec_type
);
356 lp_check_value(struct lp_type type
, LLVMValueRef val
);
360 lp_build_int_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
364 lp_build_int_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
367 static INLINE
struct lp_type
368 lp_float32_vec4_type(void)
372 memset(&type
, 0, sizeof(type
));
373 type
.floating
= TRUE
;
383 static INLINE
struct lp_type
384 lp_int32_vec4_type(void)
388 memset(&type
, 0, sizeof(type
));
389 type
.floating
= FALSE
;
399 static INLINE
struct lp_type
400 lp_unorm8_vec4_type(void)
404 memset(&type
, 0, sizeof(type
));
405 type
.floating
= FALSE
;
416 lp_elem_type(struct lp_type type
);
420 lp_uint_type(struct lp_type type
);
424 lp_int_type(struct lp_type type
);
428 lp_wider_type(struct lp_type type
);
432 lp_sizeof_llvm_type(LLVMTypeRef t
);
436 lp_typekind_name(LLVMTypeKind t
);
440 lp_dump_llvmtype(LLVMTypeRef t
);
444 lp_build_context_init(struct lp_build_context
*bld
,
445 struct gallivm_state
*gallivm
,
446 struct lp_type type
);
450 lp_build_count_ir_module(LLVMModuleRef module
);
453 #endif /* !LP_BLD_TYPE_H */