799 lines · plain
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 a8small 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, 1512 .byte -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -113 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 pattern23match 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: ## @f3233 pshufd $1, %xmm0, %xmm1 ## xmm1 = xmm0[1,0,0,0]34 addss %xmm0, %xmm135 pshufd $3, %xmm0, %xmm2 ## xmm2 = xmm0[3,0,0,0]36 movhlps %xmm0, %xmm0 ## xmm0 = xmm0[1,1]37 movaps %xmm0, %xmm338 addss %xmm1, %xmm339 movdqa %xmm2, %xmm040 addss %xmm3, %xmm041 ret42 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: ## @f3253 movdqa %xmm0, %xmm254 addss %xmm1, %xmm255 pshufd $1, %xmm1, %xmm1 ## xmm1 = xmm1[1,0,0,0]56 pshufd $1, %xmm0, %xmm3 ## xmm3 = xmm0[1,0,0,0]57 addss %xmm1, %xmm358 movaps %xmm2, %xmm059 unpcklps %xmm3, %xmm0 ## xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]60 ret61 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.html69 70//===---------------------------------------------------------------------===//71 72When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and73other 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 from82a constant pool:83 84double %test3(bool %B) {85 %C = select bool %B, double 123.412, double 523.0112312386 ret double %C87}88 89Currently, the select is being lowered, which prevents the dag combiner from90turning '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's97feasible.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 half110of 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 for120__ZN15Nurbs_SSE_Cubic17TessellateSurfaceE, bb cond_next140. This is what icc121emits:122 123 movaps (%edx), %xmm2 #59.21124 movaps (%edx), %xmm5 #60.21125 movaps (%edx), %xmm4 #61.21126 movaps (%edx), %xmm3 #62.21127 movl 40(%ecx), %ebp #69.49128 shufps $0, %xmm2, %xmm5 #60.21129 movl 100(%esp), %ebx #69.20130 movl (%ebx), %edi #69.20131 imull %ebp, %edi #69.49132 addl (%eax), %edi #70.33133 shufps $85, %xmm2, %xmm4 #61.21134 shufps $170, %xmm2, %xmm3 #62.21135 shufps $255, %xmm2, %xmm2 #63.21136 lea (%ebp,%ebp,2), %ebx #69.49137 negl %ebx #69.49138 lea -3(%edi,%ebx), %ebx #70.33139 shll $4, %ebx #68.37140 addl 32(%ecx), %ebx #68.37141 testb $15, %bl #91.13142 jne L_B1.24 # Prob 5% #91.13143 144This is the llvm code after instruction scheduling:145 146cond_next140 (0xa910740, LLVM BB @0xa90beb0):147 %reg1078 = MOV32ri -3148 %reg1079 = ADD32rm %reg1078, %reg1068, 1, %noreg, 0149 %reg1037 = MOV32rm %reg1024, 1, %noreg, 40150 %reg1080 = IMUL32rr %reg1079, %reg1037151 %reg1081 = MOV32rm %reg1058, 1, %noreg, 0152 %reg1038 = LEA32r %reg1081, 1, %reg1080, -3153 %reg1036 = MOV32rm %reg1024, 1, %noreg, 32154 %reg1082 = SHL32ri %reg1038, 4155 %reg1039 = ADD32rr %reg1036, %reg1082156 %reg1083 = MOVAPSrm %reg1059, 1, %noreg, 0157 %reg1034 = SHUFPSrr %reg1083, %reg1083, 170158 %reg1032 = SHUFPSrr %reg1083, %reg1083, 0159 %reg1035 = SHUFPSrr %reg1083, %reg1083, 255160 %reg1033 = SHUFPSrr %reg1083, %reg1083, 85161 %reg1040 = MOV32rr %reg1039162 %reg1084 = AND32ri8 %reg1039, 15163 CMP32ri8 %reg1084, 0164 JE mbb<cond_next204,0xa914d30>165 166Still ok. After register allocation:167 168cond_next140 (0xa910740, LLVM BB @0xa90beb0):169 %eax = MOV32ri -3170 %edx = MOV32rm %stack.3, 1, %noreg, 0171 ADD32rm %eax<def&use>, %edx, 1, %noreg, 0172 %edx = MOV32rm %stack.7, 1, %noreg, 0173 %edx = MOV32rm %edx, 1, %noreg, 40174 IMUL32rr %eax<def&use>, %edx175 %esi = MOV32rm %stack.5, 1, %noreg, 0176 %esi = MOV32rm %esi, 1, %noreg, 0177 MOV32mr %stack.4, 1, %noreg, 0, %esi178 %eax = LEA32r %esi, 1, %eax, -3179 %esi = MOV32rm %stack.7, 1, %noreg, 0180 %esi = MOV32rm %esi, 1, %noreg, 32181 %edi = MOV32rr %eax182 SHL32ri %edi<def&use>, 4183 ADD32rr %edi<def&use>, %esi184 %xmm0 = MOVAPSrm %ecx, 1, %noreg, 0185 %xmm1 = MOVAPSrr %xmm0186 SHUFPSrr %xmm1<def&use>, %xmm1, 170187 %xmm2 = MOVAPSrr %xmm0188 SHUFPSrr %xmm2<def&use>, %xmm2, 0189 %xmm3 = MOVAPSrr %xmm0190 SHUFPSrr %xmm3<def&use>, %xmm3, 255191 SHUFPSrr %xmm0<def&use>, %xmm0, 85192 %ebx = MOV32rr %edi193 AND32ri8 %ebx<def&use>, 15194 CMP32ri8 %ebx, 0195 JE mbb<cond_next204,0xa914d30>196 197This looks really bad. The problem is shufps is a destructive opcode. Since it198appears as operand two in more than one shufps ops. It resulted in a number of199copies. Note icc also suffers from the same problem. Either the instruction200selector should select pshufd or The register allocator can made the two-address201to 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), %xmm1216mulss %xmm1, %xmm1217xorps %xmm0, %xmm0218movss %xmm1, %xmm0219ret220 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), %xmm0225mulss %xmm0, %xmm0226ret227 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), %xmm1241xorps %xmm0, %xmm0242movss %xmm1, %xmm0243ret244 245Now consider if the ... code caused xmm1 to get spilled. This might produce246this code:247 248movaps c(%esp), %xmm1249movaps %xmm1, c2(%esp)250...251 252xorps %xmm0, %xmm0253movaps c2(%esp), %xmm1254movss %xmm1, %xmm0255ret256 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), %xmm1261movaps %xmm1, c2(%esp)262...263 264movss c2(%esp), %xmm0265ret266 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 the272elements 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* %P280 %tmp = load <4 x float>* %P2281 %inFloat3.713 = insertelement <4 x float> %tmp, float 0.0, i32 3282 store <4 x float> %inFloat3.713, <4 x float>* %P2283 ret void284}285 286Generates:287 288_test:289 movl 8(%esp), %eax290 movaps (%eax), %xmm0291 pxor %xmm1, %xmm1292 movaps %xmm0, %xmm2293 shufps $50, %xmm1, %xmm2294 shufps $132, %xmm2, %xmm0295 movaps %xmm0, (%eax)296 ret297 298Would it be better to generate:299 300_test:301 movl 8(%esp), %ecx302 movaps (%ecx), %xmm0303 xor %eax, %eax304 pinsrw $6, %eax, %xmm0305 pinsrw $7, %eax, %xmm0306 movaps %xmm0, (%ecx)307 ret308 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.html317 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 load327to loads from constant pool.328 329//===---------------------------------------------------------------------===//330 331Floating point max / min are commutable when -enable-unsafe-fp-path is332specified. We should turn int_x86_sse_max_ss and X86ISD::FMIN etc. into other333nodes 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-ones341 342and:343 cmpeqps xmm1, xmm1 ; xmm1 = all-ones344 psrlq xmm1, 31 ; xmm1 = all 100000000000...345 346instead of using a load from the constant pool. The later is important for347ABS/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), %eax365 movd %eax, %xmm0366 movaps _a, %xmm1367 pslld %xmm0, %xmm1368 movaps %xmm1, _a369 ret370_y:371 movd 4(%esp), %xmm0372 movaps _a, %xmm1373 pslld %xmm0, %xmm1374 movaps %xmm1, _a375 ret376 377"y" looks good, but "x" does silly movzwl stuff around into a GPR. It seems378like 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 be380save, 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, %esp390 movsd 16(%esp), %xmm0391 movsd %xmm0, (%esp)392 movl 4(%esp), %eax393 shrl $31, %eax394 addl $12, %esp395 ret396 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 single402(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 see406 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 generalized411 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-static413 mode because it doesn't look through the extra dyld stub load. If you try414 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, which419eliminates 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 readonly425 ret i64 %tmp20426}427declare i64 @ccoshf(float %z.0, float %z.1) nounwind readonly428 429This currently compiles to:430 431LCPI1_0: # <4 x float>432 .long 2147483648 # float -0433 .long 2147483648 # float -0434 .long 2147483648 # float -0435 .long 2147483648 # float -0436_ccosf:437 subl $12, %esp438 movss 16(%esp), %xmm0439 movss %xmm0, 4(%esp)440 movss 20(%esp), %xmm0441 xorps LCPI1_0, %xmm0442 movss %xmm0, (%esp)443 call L_ccoshf$stub444 addl $12, %esp445 ret446 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 exposed452until 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 backend454instead 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 destination463is memory.464 465//===---------------------------------------------------------------------===//466 467INSERTPS can match any insert (extract, imm1), imm2 for 4 x float, and insert468any number of 0.0 simultaneously. Currently we only use it for simple469insertions.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, not476Custom. All combinations of insert/extract reg-reg, reg-mem, and mem-reg are477legal, 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 be480right, but we shouldn't have to custom lower anything. This is probably related481to <2 x i64> ops being so bad.482 483//===---------------------------------------------------------------------===//484 485LLVM currently generates stack realignment code, when it is not necessary486needed. 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 can491produce 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 %ebp511 movl %esp, %ebp512 andl $-16, %esp513 movaps .LCPI1_0, %xmm1514 pmaddwd %xmm1, %xmm0515 movl %ebp, %esp516 popl %ebp517 ret518 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), %xmm0531 pshufd $81, %xmm0, %xmm0532 ret533 534in x86-64 mode, we generate this code, which could be better:535 536_foo2:537 xorps %xmm1, %xmm1538 movss %xmm0, %xmm1539 pshufd $81, %xmm1, %xmm0540 ret541 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), %xmm0556 insertps $0x10, x3(%rip), %xmm1557 movaps %xmm1, %xmm2558 movlhps %xmm0, %xmm2559 movaps %xmm2, %xmm0560 ret561 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> %A569}570 571On targets without SSE4.1, this compiles into:572 573LCPI1_0: ## <4 x i32>574 .long 10575 .long 10576 .long 10577 .long 10578 .text579 .align 4,0x90580 .globl _f581_f:582 pshufd $3, %xmm0, %xmm1583 movd %xmm1, %eax584 imull LCPI1_0+12, %eax585 movd %eax, %xmm1586 pshufd $1, %xmm0, %xmm2587 movd %xmm2, %eax588 imull LCPI1_0+4, %eax589 movd %eax, %xmm2590 punpckldq %xmm1, %xmm2591 movd %xmm0, %eax592 imull LCPI1_0, %eax593 movd %eax, %xmm1594 movhlps %xmm0, %xmm0595 movd %xmm0, %eax596 imull LCPI1_0+8, %eax597 movd %eax, %xmm0598 punpckldq %xmm0, %xmm1599 movaps %xmm1, %xmm0600 punpckldq %xmm2, %xmm0601 ret602 603It would be better to synthesize integer vector multiplication by constants604using 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 as606vector shifts than as multiplications.607 608//===---------------------------------------------------------------------===//609 610We compile this:611 612__m128i613foo2 (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, %eax620 xorps %xmm0, %xmm0621 pinsrw $2, %eax, %xmm0622 movzbl 4(%esp), %eax623 pinsrw $3, %eax, %xmm0624 movl $256, %eax625 pinsrw $7, %eax, %xmm0626 ret627 628 629gcc-4.2:630 subl $12, %esp631 movzbl 16(%esp), %eax632 movdqa LC0, %xmm0633 pinsrw $3, %eax, %xmm0634 addl $12, %esp635 ret636 .const637 .align 4638LC0:639 .word 0640 .word 0641 .word 1642 .word 0643 .word 0644 .word 0645 .word 0646 .word 256647 648With SSE4, it should be649 movdqa .LC0(%rip), %xmm0650 pinsrb $6, %edi, %xmm0651 652//===---------------------------------------------------------------------===//653 654We should transform a shuffle of two vectors of constants into a single vector655of constants. Also, insertelement of a constant into a vector of constants656should also result in a vector of constants. e.g. 2008-06-25-VecISelBug.ll.657 658We compiled it to something horrible:659 660 .align 4661LCPI1_1: ## float662 .long 1065353216 ## float 1663 .const664 665 .align 4666LCPI1_0: ## <4 x float>667 .space 4668 .long 1065353216 ## float 1669 .space 4670 .long 1065353216 ## float 1671 .text672 .align 4,0x90673 .globl _t674_t:675 xorps %xmm0, %xmm0676 movhps LCPI1_0, %xmm0677 movss LCPI1_1, %xmm1678 movaps %xmm0, %xmm2679 shufps $2, %xmm1, %xmm2680 shufps $132, %xmm2, %xmm0681 movaps %xmm0, 0682 683//===---------------------------------------------------------------------===//684 685Consider using movlps instead of movsd to implement (scalar_to_vector (loadf64))686when code size is critical. movlps is slower than movsd on core2 but it's one687byte shorter.688 689//===---------------------------------------------------------------------===//690 691We should use a dynamic programming based approach to tell when using FPStack692operations is cheaper than SSE. SciMark montecarlo contains code like this693for example:694 695double MonteCarlo_num_flops(int Num_samples) {696 return ((double) Num_samples)* 4.0;697}698 699In fpstack mode, this compiles into:700 701LCPI1_0: 702 .long 1082130432 ## float 4.000000e+00703_MonteCarlo_num_flops:704 subl $4, %esp705 movl 8(%esp), %eax706 movl %eax, (%esp)707 fildl (%esp)708 fmuls LCPI1_0709 addl $4, %esp710 ret711 712in SSE mode, it compiles into significantly slower code:713 714_MonteCarlo_num_flops:715 subl $12, %esp716 cvtsi2sd 16(%esp), %xmm0717 mulsd LCPI1_0, %xmm0718 movsd %xmm0, (%esp)719 fldl (%esp)720 addl $12, %esp721 ret722 723There are also other cases in scimark where using fpstack is better, it is724cheaper to do fld1 than load from a constant pool for example, so725"load, add 1.0, store" is better done in the fp stack, etc.726 727//===---------------------------------------------------------------------===//728 729These should compile into the same code (PR6214): Perhaps instcombine should730canonicalize the former into the later?731 732define float @foo(float %x) nounwind {733 %t = bitcast float %x to i32734 %s = and i32 %t, 2147483647735 %d = bitcast i32 %s to float736 ret float %d737}738 739declare float @fabsf(float %n)740define float @bar(float %x) nounwind {741 %d = call float @fabsf(float %x)742 ret float %d743}744 745//===---------------------------------------------------------------------===//746 747This IR (from PR6194):748 749target 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"750target triple = "x86_64-apple-darwin10.0.0"751 752%0 = type { double, double }753%struct.float3 = type { float, float, float }754 755define void @test(%0, %struct.float3* nocapture %res) nounwind noinline ssp {756entry:757 %tmp18 = extractvalue %0 %0, 0 ; <double> [#uses=1]758 %tmp19 = bitcast double %tmp18 to i64 ; <i64> [#uses=1]759 %tmp20 = zext i64 %tmp19 to i128 ; <i128> [#uses=1]760 %tmp10 = lshr i128 %tmp20, 32 ; <i128> [#uses=1]761 %tmp11 = trunc i128 %tmp10 to i32 ; <i32> [#uses=1]762 %tmp12 = bitcast i32 %tmp11 to float ; <float> [#uses=1]763 %tmp5 = getelementptr inbounds %struct.float3* %res, i64 0, i32 1 ; <float*> [#uses=1]764 store float %tmp12, float* %tmp5765 ret void766}767 768Compiles to:769 770_test: ## @test771 movd %xmm0, %rax772 shrq $32, %rax773 movl %eax, 4(%rdi)774 ret775 776This would be better kept in the SSE unit by treating XMM0 as a 4xfloat and777doing a shuffle from v[1] to v[0] then a float store.778 779//===---------------------------------------------------------------------===//780 781[UNSAFE FP]782 783void foo(double, double, double);784void norm(double x, double y, double z) {785 double scale = __builtin_sqrt(x*x + y*y + z*z);786 foo(x/scale, y/scale, z/scale);787}788 789We currently generate an sqrtsd and 3 divsd instructions. This is bad, fp div is790slow and not pipelined. In -ffast-math mode we could compute "1.0/scale" first791and emit 3 mulsd in place of the divs. This can be done as a target-independent792transform.793 794If we're dealing with floats instead of doubles we could even replace the sqrtss795and inversion with an rsqrtss instruction, which computes 1/sqrt faster at the796cost of reduced accuracy.797 798//===---------------------------------------------------------------------===//799