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 "pipe/p_compiler.h"
41 #include "gallivm/lp_bld.h"
44 * Native SIMD architecture width available at runtime.
46 * Using this width should give the best performance,
47 * and it determines the necessary alignment of vector variables.
49 extern unsigned lp_native_vector_width
;
52 * Maximum supported vector width (not necessarily supported at run-time).
54 * Should only be used when lp_native_vector_width isn't available,
55 * i.e. sizing/alignment of non-malloced variables.
57 #define LP_MAX_VECTOR_WIDTH 256
60 * Minimum vector alignment for static variable alignment
62 * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An
63 * expression is non-portable.
65 #define LP_MIN_VECTOR_ALIGN 32
68 * Several functions can only cope with vectors of length up to this value.
69 * You may need to increase that value if you want to represent bigger vectors.
71 #define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8)
74 * The LLVM type system can't conveniently express all the things we care about
75 * on the types used for intermediate computations, such as signed vs unsigned,
76 * normalized values, or fixed point.
80 * Floating-point. Cannot be used with fixed. Integer numbers are
81 * represented by this zero.
86 * Fixed-point. Cannot be used with floating. Integer numbers are
87 * represented by this zero.
92 * Whether it can represent negative values or not.
94 * If this is not set for floating point, it means that all values are
95 * assumed to be positive.
100 * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
101 * interval for signed types.
103 * For integer types it means the representable integer range should be
104 * interpreted as the interval above.
106 * For floating and fixed point formats it means the values should be
107 * clamped to the interval above.
114 * For fixed point values, the fixed point is assumed to be at half the
120 * Vector length. If length==1, this is a scalar (float/int) type.
122 * width*length should be a power of two greater or equal to eight.
124 * @sa LP_MAX_VECTOR_LENGTH
131 * We need most of the information here in order to correctly and efficiently
132 * translate an arithmetic operation into LLVM IR. Putting it here avoids the
133 * trouble of passing it as parameters.
135 struct lp_build_context
137 struct gallivm_state
*gallivm
;
140 * This not only describes the input/output LLVM types, but also whether
141 * to normalize/clamp the results.
145 /** Same as lp_build_elem_type(type) */
146 LLVMTypeRef elem_type
;
148 /** Same as lp_build_vec_type(type) */
149 LLVMTypeRef vec_type
;
151 /** Same as lp_build_int_elem_type(type) */
152 LLVMTypeRef int_elem_type
;
154 /** Same as lp_build_int_vec_type(type) */
155 LLVMTypeRef int_vec_type
;
157 /** Same as lp_build_undef(type) */
160 /** Same as lp_build_zero(type) */
163 /** Same as lp_build_one(type) */
168 static INLINE
unsigned
169 lp_type_width(struct lp_type type
)
171 return type
.width
* type
.length
;
175 /** Create scalar float type */
176 static INLINE
struct lp_type
177 lp_type_float(unsigned width
)
179 struct lp_type res_type
;
181 memset(&res_type
, 0, sizeof res_type
);
182 res_type
.floating
= TRUE
;
183 res_type
.sign
= TRUE
;
184 res_type
.width
= width
;
191 /** Create vector of float type */
192 static INLINE
struct lp_type
193 lp_type_float_vec(unsigned width
, unsigned total_width
)
195 struct lp_type res_type
;
197 memset(&res_type
, 0, sizeof res_type
);
198 res_type
.floating
= TRUE
;
199 res_type
.sign
= TRUE
;
200 res_type
.width
= width
;
201 res_type
.length
= total_width
/ width
;
207 /** Create scalar int type */
208 static INLINE
struct lp_type
209 lp_type_int(unsigned width
)
211 struct lp_type res_type
;
213 memset(&res_type
, 0, sizeof res_type
);
214 res_type
.sign
= TRUE
;
215 res_type
.width
= width
;
222 /** Create vector int type */
223 static INLINE
struct lp_type
224 lp_type_int_vec(unsigned width
, unsigned total_width
)
226 struct lp_type res_type
;
228 memset(&res_type
, 0, sizeof res_type
);
229 res_type
.sign
= TRUE
;
230 res_type
.width
= width
;
231 res_type
.length
= total_width
/ width
;
237 /** Create scalar uint type */
238 static INLINE
struct lp_type
239 lp_type_uint(unsigned width
)
241 struct lp_type res_type
;
243 memset(&res_type
, 0, sizeof res_type
);
244 res_type
.width
= width
;
251 /** Create vector uint type */
252 static INLINE
struct lp_type
253 lp_type_uint_vec(unsigned width
, unsigned total_width
)
255 struct lp_type res_type
;
257 memset(&res_type
, 0, sizeof res_type
);
258 res_type
.width
= width
;
259 res_type
.length
= total_width
/ width
;
265 static INLINE
struct lp_type
266 lp_type_unorm(unsigned width
, unsigned total_width
)
268 struct lp_type res_type
;
270 memset(&res_type
, 0, sizeof res_type
);
271 res_type
.norm
= TRUE
;
272 res_type
.width
= width
;
273 res_type
.length
= total_width
/ width
;
279 static INLINE
struct lp_type
280 lp_type_fixed(unsigned width
, unsigned total_width
)
282 struct lp_type res_type
;
284 memset(&res_type
, 0, sizeof res_type
);
285 res_type
.sign
= TRUE
;
286 res_type
.fixed
= TRUE
;
287 res_type
.width
= width
;
288 res_type
.length
= total_width
/ width
;
294 static INLINE
struct lp_type
295 lp_type_ufixed(unsigned width
, unsigned total_width
)
297 struct lp_type res_type
;
299 memset(&res_type
, 0, sizeof res_type
);
300 res_type
.fixed
= TRUE
;
301 res_type
.width
= width
;
302 res_type
.length
= total_width
/ width
;
309 lp_build_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
313 lp_build_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
317 lp_check_elem_type(struct lp_type type
, LLVMTypeRef elem_type
);
321 lp_check_vec_type(struct lp_type type
, LLVMTypeRef vec_type
);
325 lp_check_value(struct lp_type type
, LLVMValueRef val
);
329 lp_build_int_elem_type(struct gallivm_state
*gallivm
, struct lp_type type
);
333 lp_build_int_vec_type(struct gallivm_state
*gallivm
, struct lp_type type
);
336 static INLINE
struct lp_type
337 lp_float32_vec4_type(void)
341 memset(&type
, 0, sizeof(type
));
342 type
.floating
= TRUE
;
352 static INLINE
struct lp_type
353 lp_int32_vec4_type(void)
357 memset(&type
, 0, sizeof(type
));
358 type
.floating
= FALSE
;
368 static INLINE
struct lp_type
369 lp_unorm8_vec4_type(void)
373 memset(&type
, 0, sizeof(type
));
374 type
.floating
= FALSE
;
385 lp_elem_type(struct lp_type type
);
389 lp_uint_type(struct lp_type type
);
393 lp_int_type(struct lp_type type
);
397 lp_wider_type(struct lp_type type
);
401 lp_sizeof_llvm_type(LLVMTypeRef t
);
405 lp_typekind_name(LLVMTypeKind t
);
409 lp_dump_llvmtype(LLVMTypeRef t
);
413 lp_build_context_init(struct lp_build_context
*bld
,
414 struct gallivm_state
*gallivm
,
415 struct lp_type type
);
419 lp_build_count_instructions(LLVMValueRef function
);
422 #endif /* !LP_BLD_TYPE_H */