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 (at) 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 */ 49 extern 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 */ 78 struct 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 */ 135 struct 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 168 static INLINE unsigned 169 lp_type_width(struct lp_type type) 170 { 171 return type.width * type.length; 172 } 173 174 175 /** Create scalar float type */ 176 static INLINE struct lp_type 177 lp_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 */ 192 static INLINE struct lp_type 193 lp_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 */ 208 static INLINE struct lp_type 209 lp_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 */ 223 static INLINE struct lp_type 224 lp_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 */ 238 static INLINE struct lp_type 239 lp_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 */ 252 static INLINE struct lp_type 253 lp_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 265 static INLINE struct lp_type 266 lp_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 279 static INLINE struct lp_type 280 lp_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 294 static INLINE struct lp_type 295 lp_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 308 LLVMTypeRef 309 lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type); 310 311 312 LLVMTypeRef 313 lp_build_vec_type(struct gallivm_state *gallivm, struct lp_type type); 314 315 316 boolean 317 lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type); 318 319 320 boolean 321 lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type); 322 323 324 boolean 325 lp_check_value(struct lp_type type, LLVMValueRef val); 326 327 328 LLVMTypeRef 329 lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type); 330 331 332 LLVMTypeRef 333 lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type); 334 335 336 static INLINE struct lp_type 337 lp_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 352 static INLINE struct lp_type 353 lp_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 368 static INLINE struct lp_type 369 lp_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 384 struct lp_type 385 lp_elem_type(struct lp_type type); 386 387 388 struct lp_type 389 lp_uint_type(struct lp_type type); 390 391 392 struct lp_type 393 lp_int_type(struct lp_type type); 394 395 396 struct lp_type 397 lp_wider_type(struct lp_type type); 398 399 400 unsigned 401 lp_sizeof_llvm_type(LLVMTypeRef t); 402 403 404 const char * 405 lp_typekind_name(LLVMTypeKind t); 406 407 408 void 409 lp_dump_llvmtype(LLVMTypeRef t); 410 411 412 void 413 lp_build_context_init(struct lp_build_context *bld, 414 struct gallivm_state *gallivm, 415 struct lp_type type); 416 417 418 unsigned 419 lp_build_count_instructions(LLVMValueRef function); 420 421 422 #endif /* !LP_BLD_TYPE_H */ 423