brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.4 KiB · c0c1bb6 Raw
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