lp_bld_type.h revision 3469715a8a171512cf9b528702e70393f01c6041
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 "pipe/p_compiler.h" 41#include "gallivm/lp_bld.h" 42 43/** 44 * Native SIMD architecture width available at runtime. 45 * 46 * Using this width should give the best performance, 47 * and it determines the necessary alignment of vector variables. 48 */ 49extern unsigned lp_native_vector_width; 50 51/** 52 * Maximum supported vector width (not necessarily supported at run-time). 53 * 54 * Should only be used when lp_native_vector_width isn't available, 55 * i.e. sizing/alignment of non-malloced variables. 56 */ 57#define LP_MAX_VECTOR_WIDTH 256 58 59/** 60 * Minimum vector alignment for static variable alignment 61 * 62 * It should always be a constant equal to LP_MAX_VECTOR_WIDTH/8. An 63 * expression is non-portable. 64 */ 65#define LP_MIN_VECTOR_ALIGN 32 66 67/** 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. 70 */ 71#define LP_MAX_VECTOR_LENGTH (LP_MAX_VECTOR_WIDTH/8) 72 73/** 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. 77 */ 78struct lp_type { 79 /** 80 * Floating-point. Cannot be used with fixed. Integer numbers are 81 * represented by this zero. 82 */ 83 unsigned floating:1; 84 85 /** 86 * Fixed-point. Cannot be used with floating. Integer numbers are 87 * represented by this zero. 88 */ 89 unsigned fixed:1; 90 91 /** 92 * Whether it can represent negative values or not. 93 * 94 * If this is not set for floating point, it means that all values are 95 * assumed to be positive. 96 */ 97 unsigned sign:1; 98 99 /** 100 * Whether values are normalized to fit [0, 1] interval, or [-1, 1] 101 * interval for signed types. 102 * 103 * For integer types it means the representable integer range should be 104 * interpreted as the interval above. 105 * 106 * For floating and fixed point formats it means the values should be 107 * clamped to the interval above. 108 */ 109 unsigned norm:1; 110 111 /** 112 * Element width. 113 * 114 * For fixed point values, the fixed point is assumed to be at half the 115 * width. 116 */ 117 unsigned width:14; 118 119 /** 120 * Vector length. If length==1, this is a scalar (float/int) type. 121 * 122 * width*length should be a power of two greater or equal to eight. 123 * 124 * @sa LP_MAX_VECTOR_LENGTH 125 */ 126 unsigned length:14; 127}; 128 129 130/** 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. 134 */ 135struct lp_build_context 136{ 137 struct gallivm_state *gallivm; 138 139 /** 140 * This not only describes the input/output LLVM types, but also whether 141 * to normalize/clamp the results. 142 */ 143 struct lp_type type; 144 145 /** Same as lp_build_elem_type(type) */ 146 LLVMTypeRef elem_type; 147 148 /** Same as lp_build_vec_type(type) */ 149 LLVMTypeRef vec_type; 150 151 /** Same as lp_build_int_elem_type(type) */ 152 LLVMTypeRef int_elem_type; 153 154 /** Same as lp_build_int_vec_type(type) */ 155 LLVMTypeRef int_vec_type; 156 157 /** Same as lp_build_undef(type) */ 158 LLVMValueRef undef; 159 160 /** Same as lp_build_zero(type) */ 161 LLVMValueRef zero; 162 163 /** Same as lp_build_one(type) */ 164 LLVMValueRef one; 165}; 166 167 168static INLINE unsigned 169lp_type_width(struct lp_type type) 170{ 171 return type.width * type.length; 172} 173 174 175/** Create scalar float type */ 176static INLINE struct lp_type 177lp_type_float(unsigned width) 178{ 179 struct lp_type res_type; 180 181 memset(&res_type, 0, sizeof res_type); 182 res_type.floating = TRUE; 183 res_type.sign = TRUE; 184 res_type.width = width; 185 res_type.length = 1; 186 187 return res_type; 188} 189 190 191/** Create vector of float type */ 192static INLINE struct lp_type 193lp_type_float_vec(unsigned width, unsigned total_width) 194{ 195 struct lp_type res_type; 196 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; 202 203 return res_type; 204} 205 206 207/** Create scalar int type */ 208static INLINE struct lp_type 209lp_type_int(unsigned width) 210{ 211 struct lp_type res_type; 212 213 memset(&res_type, 0, sizeof res_type); 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 int type */ 223static INLINE struct lp_type 224lp_type_int_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.sign = TRUE; 230 res_type.width = width; 231 res_type.length = total_width / width; 232 233 return res_type; 234} 235 236 237/** Create scalar uint type */ 238static INLINE struct lp_type 239lp_type_uint(unsigned width) 240{ 241 struct lp_type res_type; 242 243 memset(&res_type, 0, sizeof res_type); 244 res_type.width = width; 245 res_type.length = 1; 246 247 return res_type; 248} 249 250 251/** Create vector uint type */ 252static INLINE struct lp_type 253lp_type_uint_vec(unsigned width, unsigned total_width) 254{ 255 struct lp_type res_type; 256 257 memset(&res_type, 0, sizeof res_type); 258 res_type.width = width; 259 res_type.length = total_width / width; 260 261 return res_type; 262} 263 264 265static INLINE struct lp_type 266lp_type_unorm(unsigned width, unsigned total_width) 267{ 268 struct lp_type res_type; 269 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; 274 275 return res_type; 276} 277 278 279static INLINE struct lp_type 280lp_type_fixed(unsigned width, unsigned total_width) 281{ 282 struct lp_type res_type; 283 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; 289 290 return res_type; 291} 292 293 294static INLINE struct lp_type 295lp_type_ufixed(unsigned width, unsigned total_width) 296{ 297 struct lp_type res_type; 298 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; 303 304 return res_type; 305} 306 307 308LLVMTypeRef 309lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type); 310 311 312LLVMTypeRef 313lp_build_vec_type(struct gallivm_state *gallivm, struct lp_type type); 314 315 316boolean 317lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type); 318 319 320boolean 321lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type); 322 323 324boolean 325lp_check_value(struct lp_type type, LLVMValueRef val); 326 327 328LLVMTypeRef 329lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type); 330 331 332LLVMTypeRef 333lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type); 334 335 336static INLINE struct lp_type 337lp_float32_vec4_type(void) 338{ 339 struct lp_type type; 340 341 memset(&type, 0, sizeof(type)); 342 type.floating = TRUE; 343 type.sign = TRUE; 344 type.norm = FALSE; 345 type.width = 32; 346 type.length = 4; 347 348 return type; 349} 350 351 352static INLINE struct lp_type 353lp_int32_vec4_type(void) 354{ 355 struct lp_type type; 356 357 memset(&type, 0, sizeof(type)); 358 type.floating = FALSE; 359 type.sign = TRUE; 360 type.norm = FALSE; 361 type.width = 32; 362 type.length = 4; 363 364 return type; 365} 366 367 368static INLINE struct lp_type 369lp_unorm8_vec4_type(void) 370{ 371 struct lp_type type; 372 373 memset(&type, 0, sizeof(type)); 374 type.floating = FALSE; 375 type.sign = FALSE; 376 type.norm = TRUE; 377 type.width = 8; 378 type.length = 4; 379 380 return type; 381} 382 383 384struct lp_type 385lp_elem_type(struct lp_type type); 386 387 388struct lp_type 389lp_uint_type(struct lp_type type); 390 391 392struct lp_type 393lp_int_type(struct lp_type type); 394 395 396struct lp_type 397lp_wider_type(struct lp_type type); 398 399 400unsigned 401lp_sizeof_llvm_type(LLVMTypeRef t); 402 403 404const char * 405lp_typekind_name(LLVMTypeKind t); 406 407 408void 409lp_dump_llvmtype(LLVMTypeRef t); 410 411 412void 413lp_build_context_init(struct lp_build_context *bld, 414 struct gallivm_state *gallivm, 415 struct lp_type type); 416 417 418unsigned 419lp_build_count_instructions(LLVMValueRef function); 420 421 422#endif /* !LP_BLD_TYPE_H */ 423