1//===---------------------------------------------------------------------===// 2// Random ideas for the X86 backend: SSE-specific stuff. 3//===---------------------------------------------------------------------===// 4 5//===---------------------------------------------------------------------===// 6 7SSE Variable shift can be custom lowered to something like this, which uses a 8small table + unaligned load + shuffle instead of going through memory. 9 10__m128i_shift_right: 11 .byte 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 12 .byte -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 13 14... 15__m128i shift_right(__m128i value, unsigned long offset) { 16 return _mm_shuffle_epi8(value, 17 _mm_loadu_si128((__m128 *) (___m128i_shift_right + offset))); 18} 19 20//===---------------------------------------------------------------------===// 21 22SSE has instructions for doing operations on complex numbers, we should pattern 23match them. For example, this should turn into a horizontal add: 24 25typedef float __attribute__((vector_size(16))) v4f32; 26float f32(v4f32 A) { 27 return A[0]+A[1]+A[2]+A[3]; 28} 29 30Instead we get this: 31 32_f32: ## @f32 33 pshufd $1, %xmm0, %xmm1 ## xmm1 = xmm0[1,0,0,0] 34 addss %xmm0, %xmm1 35 pshufd $3, %xmm0, %xmm2 ## xmm2 = xmm0[3,0,0,0] 36 movhlps %xmm0, %xmm0 ## xmm0 = xmm0[1,1] 37 movaps %xmm0, %xmm3 38 addss %xmm1, %xmm3 39 movdqa %xmm2, %xmm0 40 addss %xmm3, %xmm0 41 ret 42 43Also, there are cases where some simple local SLP would improve codegen a bit. 44compiling this: 45 46_Complex float f32(_Complex float A, _Complex float B) { 47 return A+B; 48} 49 50into: 51 52_f32: ## @f32 53 movdqa %xmm0, %xmm2 54 addss %xmm1, %xmm2 55 pshufd $1, %xmm1, %xmm1 ## xmm1 = xmm1[1,0,0,0] 56 pshufd $1, %xmm0, %xmm3 ## xmm3 = xmm0[1,0,0,0] 57 addss %xmm1, %xmm3 58 movaps %xmm2, %xmm0 59 unpcklps %xmm3, %xmm0 ## xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] 60 ret 61 62seems silly when it could just be one addps. 63 64 65//===---------------------------------------------------------------------===// 66 67Expand libm rounding functions inline: Significant speedups possible. 68http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00909.html 69 70//===---------------------------------------------------------------------===// 71 72When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and 73other fast SSE modes. 74 75//===---------------------------------------------------------------------===// 76 77Think about doing i64 math in SSE regs on x86-32. 78 79//===---------------------------------------------------------------------===// 80 81This testcase should have no SSE instructions in it, and only one load from 82a constant pool: 83 84double %test3(bool %B) { 85 %C = select bool %B, double 123.412, double 523.01123123 86 ret double %C 87} 88 89Currently, the select is being lowered, which prevents the dag combiner from 90turning 'select (load CPI1), (load CPI2)' -> 'load (select CPI1, CPI2)' 91 92The pattern isel got this one right. 93 94//===---------------------------------------------------------------------===// 95 96Lower memcpy / memset to a series of SSE 128 bit move instructions when it's 97feasible. 98 99//===---------------------------------------------------------------------===// 100 101Codegen: 102 if (copysign(1.0, x) == copysign(1.0, y)) 103into: 104 if (x^y & mask) 105when using SSE. 106 107//===---------------------------------------------------------------------===// 108 109Use movhps to update upper 64-bits of a v4sf value. Also movlps on lower half 110of a v4sf value. 111 112//===---------------------------------------------------------------------===// 113 114Better codegen for vector_shuffles like this { x, 0, 0, 0 } or { x, 0, x, 0}. 115Perhaps use pxor / xorp* to clear a XMM register first? 116 117//===---------------------------------------------------------------------===// 118 119External test Nurbs exposed some problems. Look for 120__ZN15Nurbs_SSE_Cubic17TessellateSurfaceE, bb cond_next140. This is what icc 121emits: 122 123 movaps (%edx), %xmm2 #59.21 124 movaps (%edx), %xmm5 #60.21 125 movaps (%edx), %xmm4 #61.21 126 movaps (%edx), %xmm3 #62.21 127 movl 40(%ecx), %ebp #69.49 128 shufps $0, %xmm2, %xmm5 #60.21 129 movl 100(%esp), %ebx #69.20 130 movl (%ebx), %edi #69.20 131 imull %ebp, %edi #69.49 132 addl (%eax), %edi #70.33 133 shufps $85, %xmm2, %xmm4 #61.21 134 shufps $170, %xmm2, %xmm3 #62.21 135 shufps $255, %xmm2, %xmm2 #63.21 136 lea (%ebp,%ebp,2), %ebx #69.49 137 negl %ebx #69.49 138 lea -3(%edi,%ebx), %ebx #70.33 139 shll $4, %ebx #68.37 140 addl 32(%ecx), %ebx #68.37 141 testb $15, %bl #91.13 142 jne L_B1.24 # Prob 5% #91.13 143 144This is the llvm code after instruction scheduling: 145 146cond_next140 (0xa910740, LLVM BB @0xa90beb0): 147 %reg1078 = MOV32ri -3 148 %reg1079 = ADD32rm %reg1078, %reg1068, 1, %NOREG, 0 149 %reg1037 = MOV32rm %reg1024, 1, %NOREG, 40 150 %reg1080 = IMUL32rr %reg1079, %reg1037 151 %reg1081 = MOV32rm %reg1058, 1, %NOREG, 0 152 %reg1038 = LEA32r %reg1081, 1, %reg1080, -3 153 %reg1036 = MOV32rm %reg1024, 1, %NOREG, 32 154 %reg1082 = SHL32ri %reg1038, 4 155 %reg1039 = ADD32rr %reg1036, %reg1082 156 %reg1083 = MOVAPSrm %reg1059, 1, %NOREG, 0 157 %reg1034 = SHUFPSrr %reg1083, %reg1083, 170 158 %reg1032 = SHUFPSrr %reg1083, %reg1083, 0 159 %reg1035 = SHUFPSrr %reg1083, %reg1083, 255 160 %reg1033 = SHUFPSrr %reg1083, %reg1083, 85 161 %reg1040 = MOV32rr %reg1039 162 %reg1084 = AND32ri8 %reg1039, 15 163 CMP32ri8 %reg1084, 0 164 JE mbb<cond_next204,0xa914d30> 165 166Still ok. After register allocation: 167 168cond_next140 (0xa910740, LLVM BB @0xa90beb0): 169 %EAX = MOV32ri -3 170 %EDX = MOV32rm <fi#3>, 1, %NOREG, 0 171 ADD32rm %EAX<def&use>, %EDX, 1, %NOREG, 0 172 %EDX = MOV32rm <fi#7>, 1, %NOREG, 0 173 %EDX = MOV32rm %EDX, 1, %NOREG, 40 174 IMUL32rr %EAX<def&use>, %EDX 175 %ESI = MOV32rm <fi#5>, 1, %NOREG, 0 176 %ESI = MOV32rm %ESI, 1, %NOREG, 0 177 MOV32mr <fi#4>, 1, %NOREG, 0, %ESI 178 %EAX = LEA32r %ESI, 1, %EAX, -3 179 %ESI = MOV32rm <fi#7>, 1, %NOREG, 0 180 %ESI = MOV32rm %ESI, 1, %NOREG, 32 181 %EDI = MOV32rr %EAX 182 SHL32ri %EDI<def&use>, 4 183 ADD32rr %EDI<def&use>, %ESI 184 %XMM0 = MOVAPSrm %ECX, 1, %NOREG, 0 185 %XMM1 = MOVAPSrr %XMM0 186 SHUFPSrr %XMM1<def&use>, %XMM1, 170 187 %XMM2 = MOVAPSrr %XMM0 188 SHUFPSrr %XMM2<def&use>, %XMM2, 0 189 %XMM3 = MOVAPSrr %XMM0 190 SHUFPSrr %XMM3<def&use>, %XMM3, 255 191 SHUFPSrr %XMM0<def&use>, %XMM0, 85 192 %EBX = MOV32rr %EDI 193 AND32ri8 %EBX<def&use>, 15 194 CMP32ri8 %EBX, 0 195 JE mbb<cond_next204,0xa914d30> 196 197This looks really bad. The problem is shufps is a destructive opcode. Since it 198appears as operand two in more than one shufps ops. It resulted in a number of 199copies. Note icc also suffers from the same problem. Either the instruction 200selector should select pshufd or The register allocator can made the two-address 201to three-address transformation. 202 203It also exposes some other problems. See MOV32ri -3 and the spills. 204 205//===---------------------------------------------------------------------===// 206 207Consider: 208 209__m128 test(float a) { 210 return _mm_set_ps(0.0, 0.0, 0.0, a*a); 211} 212 213This compiles into: 214 215movss 4(%esp), %xmm1 216mulss %xmm1, %xmm1 217xorps %xmm0, %xmm0 218movss %xmm1, %xmm0 219ret 220 221Because mulss doesn't modify the top 3 elements, the top elements of 222xmm1 are already zero'd. We could compile this to: 223 224movss 4(%esp), %xmm0 225mulss %xmm0, %xmm0 226ret 227 228//===---------------------------------------------------------------------===// 229 230Here's a sick and twisted idea. Consider code like this: 231 232__m128 test(__m128 a) { 233 float b = *(float*)&A; 234 ... 235 return _mm_set_ps(0.0, 0.0, 0.0, b); 236} 237 238This might compile to this code: 239 240movaps c(%esp), %xmm1 241xorps %xmm0, %xmm0 242movss %xmm1, %xmm0 243ret 244 245Now consider if the ... code caused xmm1 to get spilled. This might produce 246this code: 247 248movaps c(%esp), %xmm1 249movaps %xmm1, c2(%esp) 250... 251 252xorps %xmm0, %xmm0 253movaps c2(%esp), %xmm1 254movss %xmm1, %xmm0 255ret 256 257However, since the reload is only used by these instructions, we could 258"fold" it into the uses, producing something like this: 259 260movaps c(%esp), %xmm1 261movaps %xmm1, c2(%esp) 262... 263 264movss c2(%esp), %xmm0 265ret 266 267... saving two instructions. 268 269The basic idea is that a reload from a spill slot, can, if only one 4-byte 270chunk is used, bring in 3 zeros the one element instead of 4 elements. 271This can be used to simplify a variety of shuffle operations, where the 272elements are fixed zeros. 273 274//===---------------------------------------------------------------------===// 275 276This code generates ugly code, probably due to costs being off or something: 277 278define void @test(float* %P, <4 x float>* %P2 ) { 279 %xFloat0.688 = load float* %P 280 %tmp = load <4 x float>* %P2 281 %inFloat3.713 = insertelement <4 x float> %tmp, float 0.0, i32 3 282 store <4 x float> %inFloat3.713, <4 x float>* %P2 283 ret void 284} 285 286Generates: 287 288_test: 289 movl 8(%esp), %eax 290 movaps (%eax), %xmm0 291 pxor %xmm1, %xmm1 292 movaps %xmm0, %xmm2 293 shufps $50, %xmm1, %xmm2 294 shufps $132, %xmm2, %xmm0 295 movaps %xmm0, (%eax) 296 ret 297 298Would it be better to generate: 299 300_test: 301 movl 8(%esp), %ecx 302 movaps (%ecx), %xmm0 303 xor %eax, %eax 304 pinsrw $6, %eax, %xmm0 305 pinsrw $7, %eax, %xmm0 306 movaps %xmm0, (%ecx) 307 ret 308 309? 310 311//===---------------------------------------------------------------------===// 312 313Some useful information in the Apple Altivec / SSE Migration Guide: 314 315http://developer.apple.com/documentation/Performance/Conceptual/ 316Accelerate_sse_migration/index.html 317 318e.g. SSE select using and, andnot, or. Various SSE compare translations. 319 320//===---------------------------------------------------------------------===// 321 322Add hooks to commute some CMPP operations. 323 324//===---------------------------------------------------------------------===// 325 326Apply the same transformation that merged four float into a single 128-bit load 327to loads from constant pool. 328 329//===---------------------------------------------------------------------===// 330 331Floating point max / min are commutable when -enable-unsafe-fp-path is 332specified. We should turn int_x86_sse_max_ss and X86ISD::FMIN etc. into other 333nodes which are selected to max / min instructions that are marked commutable. 334 335//===---------------------------------------------------------------------===// 336 337We should materialize vector constants like "all ones" and "signbit" with 338code like: 339 340 cmpeqps xmm1, xmm1 ; xmm1 = all-ones 341 342and: 343 cmpeqps xmm1, xmm1 ; xmm1 = all-ones 344 psrlq xmm1, 31 ; xmm1 = all 100000000000... 345 346instead of using a load from the constant pool. The later is important for 347ABS/NEG/copysign etc. 348 349//===---------------------------------------------------------------------===// 350 351These functions: 352 353#include <xmmintrin.h> 354__m128i a; 355void x(unsigned short n) { 356 a = _mm_slli_epi32 (a, n); 357} 358void y(unsigned n) { 359 a = _mm_slli_epi32 (a, n); 360} 361 362compile to ( -O3 -static -fomit-frame-pointer): 363_x: 364 movzwl 4(%esp), %eax 365 movd %eax, %xmm0 366 movaps _a, %xmm1 367 pslld %xmm0, %xmm1 368 movaps %xmm1, _a 369 ret 370_y: 371 movd 4(%esp), %xmm0 372 movaps _a, %xmm1 373 pslld %xmm0, %xmm1 374 movaps %xmm1, _a 375 ret 376 377"y" looks good, but "x" does silly movzwl stuff around into a GPR. It seems 378like movd would be sufficient in both cases as the value is already zero 379extended in the 32-bit stack slot IIRC. For signed short, it should also be 380save, as a really-signed value would be undefined for pslld. 381 382 383//===---------------------------------------------------------------------===// 384 385#include <math.h> 386int t1(double d) { return signbit(d); } 387 388This currently compiles to: 389 subl $12, %esp 390 movsd 16(%esp), %xmm0 391 movsd %xmm0, (%esp) 392 movl 4(%esp), %eax 393 shrl $31, %eax 394 addl $12, %esp 395 ret 396 397We should use movmskp{s|d} instead. 398 399//===---------------------------------------------------------------------===// 400 401CodeGen/X86/vec_align.ll tests whether we can turn 4 scalar loads into a single 402(aligned) vector load. This functionality has a couple of problems. 403 4041. The code to infer alignment from loads of globals is in the X86 backend, 405 not the dag combiner. This is because dagcombine2 needs to be able to see 406 through the X86ISD::Wrapper node, which DAGCombine can't really do. 4072. The code for turning 4 x load into a single vector load is target 408 independent and should be moved to the dag combiner. 4093. The code for turning 4 x load into a vector load can only handle a direct 410 load from a global or a direct load from the stack. It should be generalized 411 to handle any load from P, P+4, P+8, P+12, where P can be anything. 4124. The alignment inference code cannot handle loads from globals in non-static 413 mode because it doesn't look through the extra dyld stub load. If you try 414 vec_align.ll without -relocation-model=static, you'll see what I mean. 415 416//===---------------------------------------------------------------------===// 417 418We should lower store(fneg(load p), q) into an integer load+xor+store, which 419eliminates a constant pool load. For example, consider: 420 421define i64 @ccosf(float %z.0, float %z.1) nounwind readonly { 422entry: 423 %tmp6 = fsub float -0.000000e+00, %z.1 ; <float> [#uses=1] 424 %tmp20 = tail call i64 @ccoshf( float %tmp6, float %z.0 ) nounwind readonly 425 ret i64 %tmp20 426} 427declare i64 @ccoshf(float %z.0, float %z.1) nounwind readonly 428 429This currently compiles to: 430 431LCPI1_0: # <4 x float> 432 .long 2147483648 # float -0 433 .long 2147483648 # float -0 434 .long 2147483648 # float -0 435 .long 2147483648 # float -0 436_ccosf: 437 subl $12, %esp 438 movss 16(%esp), %xmm0 439 movss %xmm0, 4(%esp) 440 movss 20(%esp), %xmm0 441 xorps LCPI1_0, %xmm0 442 movss %xmm0, (%esp) 443 call L_ccoshf$stub 444 addl $12, %esp 445 ret 446 447Note the load into xmm0, then xor (to negate), then store. In PIC mode, 448this code computes the pic base and does two loads to do the constant pool 449load, so the improvement is much bigger. 450 451The tricky part about this xform is that the argument load/store isn't exposed 452until post-legalize, and at that point, the fneg has been custom expanded into 453an X86 fxor. This means that we need to handle this case in the x86 backend 454instead of in target independent code. 455 456//===---------------------------------------------------------------------===// 457 458Non-SSE4 insert into 16 x i8 is atrociously bad. 459 460//===---------------------------------------------------------------------===// 461 462<2 x i64> extract is substantially worse than <2 x f64>, even if the destination 463is memory. 464 465//===---------------------------------------------------------------------===// 466 467INSERTPS can match any insert (extract, imm1), imm2 for 4 x float, and insert 468any number of 0.0 simultaneously. Currently we only use it for simple 469insertions. 470 471See comments in LowerINSERT_VECTOR_ELT_SSE4. 472 473//===---------------------------------------------------------------------===// 474 475On a random note, SSE2 should declare insert/extract of 2 x f64 as legal, not 476Custom. All combinations of insert/extract reg-reg, reg-mem, and mem-reg are 477legal, it'll just take a few extra patterns written in the .td file. 478 479Note: this is not a code quality issue; the custom lowered code happens to be 480right, but we shouldn't have to custom lower anything. This is probably related 481to <2 x i64> ops being so bad. 482 483//===---------------------------------------------------------------------===// 484 485LLVM currently generates stack realignment code, when it is not necessary 486needed. The problem is that we need to know about stack alignment too early, 487before RA runs. 488 489At that point we don't know, whether there will be vector spill, or not. 490Stack realignment logic is overly conservative here, but otherwise we can 491produce unaligned loads/stores. 492 493Fixing this will require some huge RA changes. 494 495Testcase: 496#include <emmintrin.h> 497 498typedef short vSInt16 __attribute__ ((__vector_size__ (16))); 499 500static const vSInt16 a = {- 22725, - 12873, - 22725, - 12873, - 22725, - 12873, 501- 22725, - 12873};; 502 503vSInt16 madd(vSInt16 b) 504{ 505 return _mm_madd_epi16(a, b); 506} 507 508Generated code (x86-32, linux): 509madd: 510 pushl %ebp 511 movl %esp, %ebp 512 andl $-16, %esp 513 movaps .LCPI1_0, %xmm1 514 pmaddwd %xmm1, %xmm0 515 movl %ebp, %esp 516 popl %ebp 517 ret 518 519//===---------------------------------------------------------------------===// 520 521Consider: 522#include <emmintrin.h> 523__m128 foo2 (float x) { 524 return _mm_set_ps (0, 0, x, 0); 525} 526 527In x86-32 mode, we generate this spiffy code: 528 529_foo2: 530 movss 4(%esp), %xmm0 531 pshufd $81, %xmm0, %xmm0 532 ret 533 534in x86-64 mode, we generate this code, which could be better: 535 536_foo2: 537 xorps %xmm1, %xmm1 538 movss %xmm0, %xmm1 539 pshufd $81, %xmm1, %xmm0 540 ret 541 542In sse4 mode, we could use insertps to make both better. 543 544Here's another testcase that could use insertps [mem]: 545 546#include <xmmintrin.h> 547extern float x2, x3; 548__m128 foo1 (float x1, float x4) { 549 return _mm_set_ps (x2, x1, x3, x4); 550} 551 552gcc mainline compiles it to: 553 554foo1: 555 insertps $0x10, x2(%rip), %xmm0 556 insertps $0x10, x3(%rip), %xmm1 557 movaps %xmm1, %xmm2 558 movlhps %xmm0, %xmm2 559 movaps %xmm2, %xmm0 560 ret 561 562//===---------------------------------------------------------------------===// 563 564We compile vector multiply-by-constant into poor code: 565 566define <4 x i32> @f(<4 x i32> %i) nounwind { 567 %A = mul <4 x i32> %i, < i32 10, i32 10, i32 10, i32 10 > 568 ret <4 x i32> %A 569} 570 571On targets without SSE4.1, this compiles into: 572 573LCPI1_0: ## <4 x i32> 574 .long 10 575 .long 10 576 .long 10 577 .long 10 578 .text 579 .align 4,0x90 580 .globl _f 581_f: 582 pshufd $3, %xmm0, %xmm1 583 movd %xmm1, %eax 584 imull LCPI1_0+12, %eax 585 movd %eax, %xmm1 586 pshufd $1, %xmm0, %xmm2 587 movd %xmm2, %eax 588 imull LCPI1_0+4, %eax 589 movd %eax, %xmm2 590 punpckldq %xmm1, %xmm2 591 movd %xmm0, %eax 592 imull LCPI1_0, %eax 593 movd %eax, %xmm1 594 movhlps %xmm0, %xmm0 595 movd %xmm0, %eax 596 imull LCPI1_0+8, %eax 597 movd %eax, %xmm0 598 punpckldq %xmm0, %xmm1 599 movaps %xmm1, %xmm0 600 punpckldq %xmm2, %xmm0 601 ret 602 603It would be better to synthesize integer vector multiplication by constants 604using shifts and adds, pslld and paddd here. And even on targets with SSE4.1, 605simple cases such as multiplication by powers of two would be better as 606vector shifts than as multiplications. 607 608//===---------------------------------------------------------------------===// 609 610We compile this: 611 612__m128i 613foo2 (char x) 614{ 615 return _mm_set_epi8 (1, 0, 0, 0, 0, 0, 0, 0, 0, x, 0, 1, 0, 0, 0, 0); 616} 617 618into: 619 movl $1, %eax 620 xorps %xmm0, %xmm0 621 pinsrw $2, %eax, %xmm0 622 movzbl 4(%esp), %eax 623 pinsrw $3, %eax, %xmm0 624 movl $256, %eax 625 pinsrw $7, %eax, %xmm0 626 ret 627 628 629gcc-4.2: 630 subl $12, %esp 631 movzbl 16(%esp), %eax 632 movdqa LC0, %xmm0 633 pinsrw $3, %eax, %xmm0 634 addl $12, %esp 635 ret 636 .const 637 .align 4 638LC0: 639 .word 0 640 .word 0 641 .word 1 642 .word 0 643 .word 0 644 .word 0 645 .word 0 646 .word 256 647 648With SSE4, it should be 649 movdqa .LC0(%rip), %xmm0 650 pinsrb $6, %edi, %xmm0 651 652//===---------------------------------------------------------------------===// 653 654We should transform a shuffle of two vectors of constants into a single vector 655of constants. Also, insertelement of a constant into a vector of constants 656should also result in a vector of constants. e.g. 2008-06-25-VecISelBug.ll. 657 658We compiled it to something horrible: 659 660 .align 4 661LCPI1_1: ## float 662 .long 1065353216 ## float 1 663 .const 664 665 .align 4 666LCPI1_0: ## <4 x float> 667 .space 4 668 .long 1065353216 ## float 1 669 .space 4 670 .long 1065353216 ## float 1 671 .text 672 .align 4,0x90 673 .globl _t 674_t: 675 xorps %xmm0, %xmm0 676 movhps LCPI1_0, %xmm0 677 movss LCPI1_1, %xmm1 678 movaps %xmm0, %xmm2 679 shufps $2, %xmm1, %xmm2 680 shufps $132, %xmm2, %xmm0 681 movaps %xmm0, 0 682 683//===---------------------------------------------------------------------===// 684rdar://5907648 685 686This function: 687 688float foo(unsigned char x) { 689 return x; 690} 691 692compiles to (x86-32): 693 694define float @foo(i8 zeroext %x) nounwind { 695 %tmp12 = uitofp i8 %x to float ; <float> [#uses=1] 696 ret float %tmp12 697} 698 699compiles to: 700 701_foo: 702 subl $4, %esp 703 movzbl 8(%esp), %eax 704 cvtsi2ss %eax, %xmm0 705 movss %xmm0, (%esp) 706 flds (%esp) 707 addl $4, %esp 708 ret 709 710We should be able to use: 711 cvtsi2ss 8($esp), %xmm0 712since we know the stack slot is already zext'd. 713 714//===---------------------------------------------------------------------===// 715 716Consider using movlps instead of movsd to implement (scalar_to_vector (loadf64)) 717when code size is critical. movlps is slower than movsd on core2 but it's one 718byte shorter. 719 720//===---------------------------------------------------------------------===// 721 722We should use a dynamic programming based approach to tell when using FPStack 723operations is cheaper than SSE. SciMark montecarlo contains code like this 724for example: 725 726double MonteCarlo_num_flops(int Num_samples) { 727 return ((double) Num_samples)* 4.0; 728} 729 730In fpstack mode, this compiles into: 731 732LCPI1_0: 733 .long 1082130432 ## float 4.000000e+00 734_MonteCarlo_num_flops: 735 subl $4, %esp 736 movl 8(%esp), %eax 737 movl %eax, (%esp) 738 fildl (%esp) 739 fmuls LCPI1_0 740 addl $4, %esp 741 ret 742 743in SSE mode, it compiles into significantly slower code: 744 745_MonteCarlo_num_flops: 746 subl $12, %esp 747 cvtsi2sd 16(%esp), %xmm0 748 mulsd LCPI1_0, %xmm0 749 movsd %xmm0, (%esp) 750 fldl (%esp) 751 addl $12, %esp 752 ret 753 754There are also other cases in scimark where using fpstack is better, it is 755cheaper to do fld1 than load from a constant pool for example, so 756"load, add 1.0, store" is better done in the fp stack, etc. 757 758//===---------------------------------------------------------------------===// 759 760These should compile into the same code (PR6214): Perhaps instcombine should 761canonicalize the former into the later? 762 763define float @foo(float %x) nounwind { 764 %t = bitcast float %x to i32 765 %s = and i32 %t, 2147483647 766 %d = bitcast i32 %s to float 767 ret float %d 768} 769 770declare float @fabsf(float %n) 771define float @bar(float %x) nounwind { 772 %d = call float @fabsf(float %x) 773 ret float %d 774} 775 776//===---------------------------------------------------------------------===// 777 778This IR (from PR6194): 779 780target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" 781target triple = "x86_64-apple-darwin10.0.0" 782 783%0 = type { double, double } 784%struct.float3 = type { float, float, float } 785 786define void @test(%0, %struct.float3* nocapture %res) nounwind noinline ssp { 787entry: 788 %tmp18 = extractvalue %0 %0, 0 ; <double> [#uses=1] 789 %tmp19 = bitcast double %tmp18 to i64 ; <i64> [#uses=1] 790 %tmp20 = zext i64 %tmp19 to i128 ; <i128> [#uses=1] 791 %tmp10 = lshr i128 %tmp20, 32 ; <i128> [#uses=1] 792 %tmp11 = trunc i128 %tmp10 to i32 ; <i32> [#uses=1] 793 %tmp12 = bitcast i32 %tmp11 to float ; <float> [#uses=1] 794 %tmp5 = getelementptr inbounds %struct.float3* %res, i64 0, i32 1 ; <float*> [#uses=1] 795 store float %tmp12, float* %tmp5 796 ret void 797} 798 799Compiles to: 800 801_test: ## @test 802 movd %xmm0, %rax 803 shrq $32, %rax 804 movl %eax, 4(%rdi) 805 ret 806 807This would be better kept in the SSE unit by treating XMM0 as a 4xfloat and 808doing a shuffle from v[1] to v[0] then a float store. 809 810//===---------------------------------------------------------------------===// 811 812[UNSAFE FP] 813 814void foo(double, double, double); 815void norm(double x, double y, double z) { 816 double scale = __builtin_sqrt(x*x + y*y + z*z); 817 foo(x/scale, y/scale, z/scale); 818} 819 820We currently generate an sqrtsd and 3 divsd instructions. This is bad, fp div is 821slow and not pipelined. In -ffast-math mode we could compute "1.0/scale" first 822and emit 3 mulsd in place of the divs. This can be done as a target-independent 823transform. 824 825If we're dealing with floats instead of doubles we could even replace the sqrtss 826and inversion with an rsqrtss instruction, which computes 1/sqrt faster at the 827cost of reduced accuracy. 828 829//===---------------------------------------------------------------------===// 830 831This function should be matched to haddpd when the appropriate CPU is enabled: 832 833#include <x86intrin.h> 834double f (__m128d p) { 835 return p[0] + p[1]; 836} 837 838similarly, v[0]-v[1] should match to hsubpd, and {v[0]-v[1], w[0]-w[1]} should 839turn into hsubpd also. 840 841//===---------------------------------------------------------------------===// 842 843define <2 x i32> @foo(<2 x double> %in) { 844 %x = fptosi <2 x double> %in to <2 x i32> 845 ret <2 x i32> %x 846} 847 848Should compile into cvttpd2dq instead of being scalarized into 2 cvttsd2si. 849 850//===---------------------------------------------------------------------===// 851