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/** 30 * @file 31 * Helper functions for packing/unpacking. 32 * 33 * Pack/unpacking is necessary for conversion between types of different 34 * bit width. 35 * 36 * They are also commonly used when an computation needs higher 37 * precision for the intermediate values. For example, if one needs the 38 * function: 39 * 40 * c = compute(a, b); 41 * 42 * to use more precision for intermediate results then one should implement it 43 * as: 44 * 45 * LLVMValueRef 46 * compute(LLVMBuilderRef builder struct lp_type type, LLVMValueRef a, LLVMValueRef b) 47 * { 48 * struct lp_type wide_type = lp_wider_type(type); 49 * LLVMValueRef al, ah, bl, bh, cl, ch, c; 50 * 51 * lp_build_unpack2(builder, type, wide_type, a, &al, &ah); 52 * lp_build_unpack2(builder, type, wide_type, b, &bl, &bh); 53 * 54 * cl = compute_half(al, bl); 55 * ch = compute_half(ah, bh); 56 * 57 * c = lp_build_pack2(bld->builder, wide_type, type, cl, ch); 58 * 59 * return c; 60 * } 61 * 62 * where compute_half() would do the computation for half the elements with 63 * twice the precision. 64 * 65 * @author Jose Fonseca <jfonseca@vmware.com> 66 */ 67 68 69#include "util/u_debug.h" 70#include "util/u_math.h" 71#include "util/u_cpu_detect.h" 72#include "util/u_memory.h" 73 74#include "lp_bld_type.h" 75#include "lp_bld_const.h" 76#include "lp_bld_init.h" 77#include "lp_bld_intr.h" 78#include "lp_bld_arit.h" 79#include "lp_bld_pack.h" 80#include "lp_bld_swizzle.h" 81 82 83/** 84 * Build shuffle vectors that match PUNPCKLxx and PUNPCKHxx instructions. 85 */ 86static LLVMValueRef 87lp_build_const_unpack_shuffle(struct gallivm_state *gallivm, 88 unsigned n, unsigned lo_hi) 89{ 90 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; 91 unsigned i, j; 92 93 assert(n <= LP_MAX_VECTOR_LENGTH); 94 assert(lo_hi < 2); 95 96 /* TODO: cache results in a static table */ 97 98 for(i = 0, j = lo_hi*n/2; i < n; i += 2, ++j) { 99 elems[i + 0] = lp_build_const_int32(gallivm, 0 + j); 100 elems[i + 1] = lp_build_const_int32(gallivm, n + j); 101 } 102 103 return LLVMConstVector(elems, n); 104} 105 106/** 107 * Similar to lp_build_const_unpack_shuffle but for special AVX 256bit unpack. 108 * See comment above lp_build_interleave2_half for more details. 109 */ 110static LLVMValueRef 111lp_build_const_unpack_shuffle_half(struct gallivm_state *gallivm, 112 unsigned n, unsigned lo_hi) 113{ 114 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; 115 unsigned i, j; 116 117 assert(n <= LP_MAX_VECTOR_LENGTH); 118 assert(lo_hi < 2); 119 120 for (i = 0, j = lo_hi*(n/4); i < n; i += 2, ++j) { 121 if (i == (n / 2)) 122 j += n / 4; 123 124 elems[i + 0] = lp_build_const_int32(gallivm, 0 + j); 125 elems[i + 1] = lp_build_const_int32(gallivm, n + j); 126 } 127 128 return LLVMConstVector(elems, n); 129} 130 131/** 132 * Build shuffle vectors that match PACKxx instructions. 133 */ 134static LLVMValueRef 135lp_build_const_pack_shuffle(struct gallivm_state *gallivm, unsigned n) 136{ 137 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; 138 unsigned i; 139 140 assert(n <= LP_MAX_VECTOR_LENGTH); 141 142 for(i = 0; i < n; ++i) 143 elems[i] = lp_build_const_int32(gallivm, 2*i); 144 145 return LLVMConstVector(elems, n); 146} 147 148/** 149 * Return a vector with elements src[start:start+size] 150 * Most useful for getting half the values out of a 256bit sized vector, 151 * otherwise may cause data rearrangement to happen. 152 */ 153LLVMValueRef 154lp_build_extract_range(struct gallivm_state *gallivm, 155 LLVMValueRef src, 156 unsigned start, 157 unsigned size) 158{ 159 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; 160 unsigned i; 161 162 assert(size <= Elements(elems)); 163 164 for (i = 0; i < size; ++i) 165 elems[i] = lp_build_const_int32(gallivm, i + start); 166 167 if (size == 1) { 168 return LLVMBuildExtractElement(gallivm->builder, src, elems[0], ""); 169 } 170 else { 171 return LLVMBuildShuffleVector(gallivm->builder, src, src, 172 LLVMConstVector(elems, size), ""); 173 } 174} 175 176/** 177 * Concatenates several (must be a power of 2) vectors (of same type) 178 * into a larger one. 179 * Most useful for building up a 256bit sized vector out of two 128bit ones. 180 */ 181LLVMValueRef 182lp_build_concat(struct gallivm_state *gallivm, 183 LLVMValueRef src[], 184 struct lp_type src_type, 185 unsigned num_vectors) 186{ 187 unsigned new_length, i; 188 LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH/2]; 189 LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; 190 191 assert(src_type.length * num_vectors <= Elements(shuffles)); 192 assert(util_is_power_of_two(num_vectors)); 193 194 new_length = src_type.length; 195 196 for (i = 0; i < num_vectors; i++) 197 tmp[i] = src[i]; 198 199 while (num_vectors > 1) { 200 num_vectors >>= 1; 201 new_length <<= 1; 202 for (i = 0; i < new_length; i++) { 203 shuffles[i] = lp_build_const_int32(gallivm, i); 204 } 205 for (i = 0; i < num_vectors; i++) { 206 tmp[i] = LLVMBuildShuffleVector(gallivm->builder, tmp[i*2], tmp[i*2 + 1], 207 LLVMConstVector(shuffles, new_length), ""); 208 } 209 } 210 211 return tmp[0]; 212} 213 214/** 215 * Interleave vector elements. 216 * 217 * Matches the PUNPCKLxx and PUNPCKHxx SSE instructions. 218 */ 219LLVMValueRef 220lp_build_interleave2(struct gallivm_state *gallivm, 221 struct lp_type type, 222 LLVMValueRef a, 223 LLVMValueRef b, 224 unsigned lo_hi) 225{ 226 LLVMValueRef shuffle; 227 228 shuffle = lp_build_const_unpack_shuffle(gallivm, type.length, lo_hi); 229 230 return LLVMBuildShuffleVector(gallivm->builder, a, b, shuffle, ""); 231} 232 233/** 234 * Interleave vector elements but with 256 bit, 235 * treats it as interleave with 2 concatenated 128 bit vectors. 236 * 237 * This differs to lp_build_interleave2 as that function would do the following (for lo): 238 * a0 b0 a1 b1 a2 b2 a3 b3, and this does not compile into an AVX unpack instruction. 239 * 240 * 241 * An example interleave 8x float with 8x float on AVX 256bit unpack: 242 * a0 a1 a2 a3 a4 a5 a6 a7 <-> b0 b1 b2 b3 b4 b5 b6 b7 243 * 244 * Equivalent to interleaving 2x 128 bit vectors 245 * a0 a1 a2 a3 <-> b0 b1 b2 b3 concatenated with a4 a5 a6 a7 <-> b4 b5 b6 b7 246 * 247 * So interleave-lo would result in: 248 * a0 b0 a1 b1 a4 b4 a5 b5 249 * 250 * And interleave-hi would result in: 251 * a2 b2 a3 b3 a6 b6 a7 b7 252 */ 253LLVMValueRef 254lp_build_interleave2_half(struct gallivm_state *gallivm, 255 struct lp_type type, 256 LLVMValueRef a, 257 LLVMValueRef b, 258 unsigned lo_hi) 259{ 260 if (type.length * type.width == 256) { 261 LLVMValueRef shuffle = lp_build_const_unpack_shuffle_half(gallivm, type.length, lo_hi); 262 return LLVMBuildShuffleVector(gallivm->builder, a, b, shuffle, ""); 263 } else { 264 return lp_build_interleave2(gallivm, type, a, b, lo_hi); 265 } 266} 267 268/** 269 * Double the bit width. 270 * 271 * This will only change the number of bits the values are represented, not the 272 * values themselves. 273 */ 274void 275lp_build_unpack2(struct gallivm_state *gallivm, 276 struct lp_type src_type, 277 struct lp_type dst_type, 278 LLVMValueRef src, 279 LLVMValueRef *dst_lo, 280 LLVMValueRef *dst_hi) 281{ 282 LLVMBuilderRef builder = gallivm->builder; 283 LLVMValueRef msb; 284 LLVMTypeRef dst_vec_type; 285 286 assert(!src_type.floating); 287 assert(!dst_type.floating); 288 assert(dst_type.width == src_type.width * 2); 289 assert(dst_type.length * 2 == src_type.length); 290 291 if(dst_type.sign && src_type.sign) { 292 /* Replicate the sign bit in the most significant bits */ 293 msb = LLVMBuildAShr(builder, src, lp_build_const_int_vec(gallivm, src_type, src_type.width - 1), ""); 294 } 295 else 296 /* Most significant bits always zero */ 297 msb = lp_build_zero(gallivm, src_type); 298 299 /* Interleave bits */ 300#ifdef PIPE_ARCH_LITTLE_ENDIAN 301 *dst_lo = lp_build_interleave2(gallivm, src_type, src, msb, 0); 302 *dst_hi = lp_build_interleave2(gallivm, src_type, src, msb, 1); 303#else 304 *dst_lo = lp_build_interleave2(gallivm, src_type, msb, src, 0); 305 *dst_hi = lp_build_interleave2(gallivm, src_type, msb, src, 1); 306#endif 307 308 /* Cast the result into the new type (twice as wide) */ 309 310 dst_vec_type = lp_build_vec_type(gallivm, dst_type); 311 312 *dst_lo = LLVMBuildBitCast(builder, *dst_lo, dst_vec_type, ""); 313 *dst_hi = LLVMBuildBitCast(builder, *dst_hi, dst_vec_type, ""); 314} 315 316 317/** 318 * Expand the bit width. 319 * 320 * This will only change the number of bits the values are represented, not the 321 * values themselves. 322 */ 323void 324lp_build_unpack(struct gallivm_state *gallivm, 325 struct lp_type src_type, 326 struct lp_type dst_type, 327 LLVMValueRef src, 328 LLVMValueRef *dst, unsigned num_dsts) 329{ 330 unsigned num_tmps; 331 unsigned i; 332 333 /* Register width must remain constant */ 334 assert(src_type.width * src_type.length == dst_type.width * dst_type.length); 335 336 /* We must not loose or gain channels. Only precision */ 337 assert(src_type.length == dst_type.length * num_dsts); 338 339 num_tmps = 1; 340 dst[0] = src; 341 342 while(src_type.width < dst_type.width) { 343 struct lp_type tmp_type = src_type; 344 345 tmp_type.width *= 2; 346 tmp_type.length /= 2; 347 348 for(i = num_tmps; i--; ) { 349 lp_build_unpack2(gallivm, src_type, tmp_type, dst[i], &dst[2*i + 0], &dst[2*i + 1]); 350 } 351 352 src_type = tmp_type; 353 354 num_tmps *= 2; 355 } 356 357 assert(num_tmps == num_dsts); 358} 359 360 361/** 362 * Non-interleaved pack. 363 * 364 * This will move values as 365 * (LSB) (MSB) 366 * lo = l0 __ l1 __ l2 __.. __ ln __ 367 * hi = h0 __ h1 __ h2 __.. __ hn __ 368 * res = l0 l1 l2 .. ln h0 h1 h2 .. hn 369 * 370 * This will only change the number of bits the values are represented, not the 371 * values themselves. 372 * 373 * It is assumed the values are already clamped into the destination type range. 374 * Values outside that range will produce undefined results. Use 375 * lp_build_packs2 instead. 376 */ 377LLVMValueRef 378lp_build_pack2(struct gallivm_state *gallivm, 379 struct lp_type src_type, 380 struct lp_type dst_type, 381 LLVMValueRef lo, 382 LLVMValueRef hi) 383{ 384 LLVMBuilderRef builder = gallivm->builder; 385 LLVMTypeRef dst_vec_type = lp_build_vec_type(gallivm, dst_type); 386 LLVMValueRef shuffle; 387 LLVMValueRef res = NULL; 388 struct lp_type intr_type = dst_type; 389 390#if HAVE_LLVM < 0x0207 391 intr_type = src_type; 392#endif 393 394 assert(!src_type.floating); 395 assert(!dst_type.floating); 396 assert(src_type.width == dst_type.width * 2); 397 assert(src_type.length * 2 == dst_type.length); 398 399 /* Check for special cases first */ 400 if(util_cpu_caps.has_sse2 && src_type.width * src_type.length >= 128) { 401 const char *intrinsic = NULL; 402 403 switch(src_type.width) { 404 case 32: 405 if(dst_type.sign) { 406 intrinsic = "llvm.x86.sse2.packssdw.128"; 407 } 408 else { 409 if (util_cpu_caps.has_sse4_1) { 410 intrinsic = "llvm.x86.sse41.packusdw"; 411#if HAVE_LLVM < 0x0207 412 /* llvm < 2.7 has inconsistent signatures except for packusdw */ 413 intr_type = dst_type; 414#endif 415 } 416 } 417 break; 418 case 16: 419 if (dst_type.sign) { 420 intrinsic = "llvm.x86.sse2.packsswb.128"; 421 } 422 else { 423 intrinsic = "llvm.x86.sse2.packuswb.128"; 424 } 425 break; 426 /* default uses generic shuffle below */ 427 } 428 if (intrinsic) { 429 if (src_type.width * src_type.length == 128) { 430 LLVMTypeRef intr_vec_type = lp_build_vec_type(gallivm, intr_type); 431 res = lp_build_intrinsic_binary(builder, intrinsic, intr_vec_type, lo, hi); 432 if (dst_vec_type != intr_vec_type) { 433 res = LLVMBuildBitCast(builder, res, dst_vec_type, ""); 434 } 435 } 436 else { 437 int num_split = src_type.width * src_type.length / 128; 438 int i; 439 int nlen = 128 / src_type.width; 440 struct lp_type ndst_type = lp_type_unorm(dst_type.width, 128); 441 struct lp_type nintr_type = lp_type_unorm(intr_type.width, 128); 442 LLVMValueRef tmpres[LP_MAX_VECTOR_WIDTH / 128]; 443 LLVMValueRef tmplo, tmphi; 444 LLVMTypeRef ndst_vec_type = lp_build_vec_type(gallivm, ndst_type); 445 LLVMTypeRef nintr_vec_type = lp_build_vec_type(gallivm, nintr_type); 446 447 assert(num_split <= LP_MAX_VECTOR_WIDTH / 128); 448 449 for (i = 0; i < num_split / 2; i++) { 450 tmplo = lp_build_extract_range(gallivm, 451 lo, i*nlen*2, nlen); 452 tmphi = lp_build_extract_range(gallivm, 453 lo, i*nlen*2 + nlen, nlen); 454 tmpres[i] = lp_build_intrinsic_binary(builder, intrinsic, 455 nintr_vec_type, tmplo, tmphi); 456 if (ndst_vec_type != nintr_vec_type) { 457 tmpres[i] = LLVMBuildBitCast(builder, tmpres[i], ndst_vec_type, ""); 458 } 459 } 460 for (i = 0; i < num_split / 2; i++) { 461 tmplo = lp_build_extract_range(gallivm, 462 hi, i*nlen*2, nlen); 463 tmphi = lp_build_extract_range(gallivm, 464 hi, i*nlen*2 + nlen, nlen); 465 tmpres[i+num_split/2] = lp_build_intrinsic_binary(builder, intrinsic, 466 nintr_vec_type, 467 tmplo, tmphi); 468 if (ndst_vec_type != nintr_vec_type) { 469 tmpres[i+num_split/2] = LLVMBuildBitCast(builder, tmpres[i+num_split/2], 470 ndst_vec_type, ""); 471 } 472 } 473 res = lp_build_concat(gallivm, tmpres, ndst_type, num_split); 474 } 475 return res; 476 } 477 } 478 479 /* generic shuffle */ 480 lo = LLVMBuildBitCast(builder, lo, dst_vec_type, ""); 481 hi = LLVMBuildBitCast(builder, hi, dst_vec_type, ""); 482 483 shuffle = lp_build_const_pack_shuffle(gallivm, dst_type.length); 484 485 res = LLVMBuildShuffleVector(builder, lo, hi, shuffle, ""); 486 487 return res; 488} 489 490 491 492/** 493 * Non-interleaved pack and saturate. 494 * 495 * Same as lp_build_pack2 but will saturate values so that they fit into the 496 * destination type. 497 */ 498LLVMValueRef 499lp_build_packs2(struct gallivm_state *gallivm, 500 struct lp_type src_type, 501 struct lp_type dst_type, 502 LLVMValueRef lo, 503 LLVMValueRef hi) 504{ 505 boolean clamp; 506 507 assert(!src_type.floating); 508 assert(!dst_type.floating); 509 assert(src_type.sign == dst_type.sign); 510 assert(src_type.width == dst_type.width * 2); 511 assert(src_type.length * 2 == dst_type.length); 512 513 clamp = TRUE; 514 515 /* All X86 SSE non-interleaved pack instructions take signed inputs and 516 * saturate them, so no need to clamp for those cases. */ 517 if(util_cpu_caps.has_sse2 && 518 src_type.width * src_type.length >= 128 && 519 src_type.sign && 520 (src_type.width == 32 || src_type.width == 16)) 521 clamp = FALSE; 522 523 if(clamp) { 524 struct lp_build_context bld; 525 unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width; 526 LLVMValueRef dst_max = lp_build_const_int_vec(gallivm, src_type, ((unsigned long long)1 << dst_bits) - 1); 527 lp_build_context_init(&bld, gallivm, src_type); 528 lo = lp_build_min(&bld, lo, dst_max); 529 hi = lp_build_min(&bld, hi, dst_max); 530 /* FIXME: What about lower bound? */ 531 } 532 533 return lp_build_pack2(gallivm, src_type, dst_type, lo, hi); 534} 535 536 537/** 538 * Truncate the bit width. 539 * 540 * TODO: Handle saturation consistently. 541 */ 542LLVMValueRef 543lp_build_pack(struct gallivm_state *gallivm, 544 struct lp_type src_type, 545 struct lp_type dst_type, 546 boolean clamped, 547 const LLVMValueRef *src, unsigned num_srcs) 548{ 549 LLVMValueRef (*pack2)(struct gallivm_state *gallivm, 550 struct lp_type src_type, 551 struct lp_type dst_type, 552 LLVMValueRef lo, 553 LLVMValueRef hi); 554 LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; 555 unsigned i; 556 557 /* Register width must remain constant */ 558 assert(src_type.width * src_type.length == dst_type.width * dst_type.length); 559 560 /* We must not loose or gain channels. Only precision */ 561 assert(src_type.length * num_srcs == dst_type.length); 562 563 if(clamped) 564 pack2 = &lp_build_pack2; 565 else 566 pack2 = &lp_build_packs2; 567 568 for(i = 0; i < num_srcs; ++i) 569 tmp[i] = src[i]; 570 571 while(src_type.width > dst_type.width) { 572 struct lp_type tmp_type = src_type; 573 574 tmp_type.width /= 2; 575 tmp_type.length *= 2; 576 577 /* Take in consideration the sign changes only in the last step */ 578 if(tmp_type.width == dst_type.width) 579 tmp_type.sign = dst_type.sign; 580 581 num_srcs /= 2; 582 583 for(i = 0; i < num_srcs; ++i) 584 tmp[i] = pack2(gallivm, src_type, tmp_type, 585 tmp[2*i + 0], tmp[2*i + 1]); 586 587 src_type = tmp_type; 588 } 589 590 assert(num_srcs == 1); 591 592 return tmp[0]; 593} 594 595 596/** 597 * Truncate or expand the bitwidth. 598 * 599 * NOTE: Getting the right sign flags is crucial here, as we employ some 600 * intrinsics that do saturation. 601 */ 602void 603lp_build_resize(struct gallivm_state *gallivm, 604 struct lp_type src_type, 605 struct lp_type dst_type, 606 const LLVMValueRef *src, unsigned num_srcs, 607 LLVMValueRef *dst, unsigned num_dsts) 608{ 609 LLVMBuilderRef builder = gallivm->builder; 610 LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; 611 unsigned i; 612 613 /* 614 * We don't support float <-> int conversion here. That must be done 615 * before/after calling this function. 616 */ 617 assert(src_type.floating == dst_type.floating); 618 619 /* 620 * We don't support double <-> float conversion yet, although it could be 621 * added with little effort. 622 */ 623 assert((!src_type.floating && !dst_type.floating) || 624 src_type.width == dst_type.width); 625 626 /* We must not loose or gain channels. Only precision */ 627 assert(src_type.length * num_srcs == dst_type.length * num_dsts); 628 629 /* We don't support M:N conversion, only 1:N, M:1, or 1:1 */ 630 assert(num_srcs == 1 || num_dsts == 1); 631 632 assert(src_type.length <= LP_MAX_VECTOR_LENGTH); 633 assert(dst_type.length <= LP_MAX_VECTOR_LENGTH); 634 assert(num_srcs <= LP_MAX_VECTOR_LENGTH); 635 assert(num_dsts <= LP_MAX_VECTOR_LENGTH); 636 637 if (src_type.width > dst_type.width) { 638 /* 639 * Truncate bit width. 640 */ 641 642 assert(num_dsts == 1); 643 644 if (src_type.width * src_type.length == dst_type.width * dst_type.length) { 645 /* 646 * Register width remains constant -- use vector packing intrinsics 647 */ 648 tmp[0] = lp_build_pack(gallivm, src_type, dst_type, TRUE, src, num_srcs); 649 } 650 else { 651 if (src_type.width / dst_type.width > num_srcs) { 652 /* 653 * First change src vectors size (with shuffle) so they have the 654 * same size as the destination vector, then pack normally. 655 * Note: cannot use cast/extract because llvm generates atrocious code. 656 */ 657 unsigned size_ratio = (src_type.width * src_type.length) / 658 (dst_type.length * dst_type.width); 659 unsigned new_length = src_type.length / size_ratio; 660 661 for (i = 0; i < size_ratio * num_srcs; i++) { 662 unsigned start_index = (i % size_ratio) * new_length; 663 tmp[i] = lp_build_extract_range(gallivm, src[i / size_ratio], 664 start_index, new_length); 665 } 666 num_srcs *= size_ratio; 667 src_type.length = new_length; 668 tmp[0] = lp_build_pack(gallivm, src_type, dst_type, TRUE, tmp, num_srcs); 669 } 670 else { 671 /* 672 * Truncate bit width but expand vector size - first pack 673 * then expand simply because this should be more AVX-friendly 674 * for the cases we probably hit. 675 */ 676 unsigned size_ratio = (dst_type.width * dst_type.length) / 677 (src_type.length * src_type.width); 678 unsigned num_pack_srcs = num_srcs / size_ratio; 679 dst_type.length = dst_type.length / size_ratio; 680 681 for (i = 0; i < size_ratio; i++) { 682 tmp[i] = lp_build_pack(gallivm, src_type, dst_type, TRUE, 683 &src[i*num_pack_srcs], num_pack_srcs); 684 } 685 tmp[0] = lp_build_concat(gallivm, tmp, dst_type, size_ratio); 686 } 687 } 688 } 689 else if (src_type.width < dst_type.width) { 690 /* 691 * Expand bit width. 692 */ 693 694 assert(num_srcs == 1); 695 696 if (src_type.width * src_type.length == dst_type.width * dst_type.length) { 697 /* 698 * Register width remains constant -- use vector unpack intrinsics 699 */ 700 lp_build_unpack(gallivm, src_type, dst_type, src[0], tmp, num_dsts); 701 } 702 else { 703 /* 704 * Do it element-wise. 705 */ 706 assert(src_type.length * num_srcs == dst_type.length * num_dsts); 707 708 for (i = 0; i < num_dsts; i++) { 709 tmp[i] = lp_build_undef(gallivm, dst_type); 710 } 711 712 for (i = 0; i < src_type.length; ++i) { 713 unsigned j = i / dst_type.length; 714 LLVMValueRef srcindex = lp_build_const_int32(gallivm, i); 715 LLVMValueRef dstindex = lp_build_const_int32(gallivm, i % dst_type.length); 716 LLVMValueRef val = LLVMBuildExtractElement(builder, src[0], srcindex, ""); 717 718 if (src_type.sign && dst_type.sign) { 719 val = LLVMBuildSExt(builder, val, lp_build_elem_type(gallivm, dst_type), ""); 720 } else { 721 val = LLVMBuildZExt(builder, val, lp_build_elem_type(gallivm, dst_type), ""); 722 } 723 tmp[j] = LLVMBuildInsertElement(builder, tmp[j], val, dstindex, ""); 724 } 725 } 726 } 727 else { 728 /* 729 * No-op 730 */ 731 732 assert(num_srcs == 1); 733 assert(num_dsts == 1); 734 735 tmp[0] = src[0]; 736 } 737 738 for(i = 0; i < num_dsts; ++i) 739 dst[i] = tmp[i]; 740} 741 742 743/** 744 * Expands src vector from src.length to dst_length 745 */ 746LLVMValueRef 747lp_build_pad_vector(struct gallivm_state *gallivm, 748 LLVMValueRef src, 749 struct lp_type src_type, 750 unsigned dst_length) 751{ 752 LLVMValueRef undef = LLVMGetUndef(lp_build_vec_type(gallivm, src_type)); 753 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; 754 unsigned i; 755 756 assert(dst_length <= Elements(elems)); 757 assert(dst_length > src_type.length); 758 759 if (src_type.length == dst_length) 760 return src; 761 762 /* If its a single scalar type, no need to reinvent the wheel */ 763 if (src_type.length == 1) { 764 return lp_build_broadcast(gallivm, LLVMVectorType(lp_build_elem_type(gallivm, src_type), dst_length), src); 765 } 766 767 /* All elements from src vector */ 768 for (i = 0; i < src_type.length; ++i) 769 elems[i] = lp_build_const_int32(gallivm, i); 770 771 /* Undef fill remaining space */ 772 for (i = src_type.length; i < dst_length; ++i) 773 elems[i] = lp_build_const_int32(gallivm, src_type.length); 774 775 /* Combine the two vectors */ 776 return LLVMBuildShuffleVector(gallivm->builder, src, undef, LLVMConstVector(elems, dst_length), ""); 777} 778