rename X86InstrX86-64.td -> X86Instr64bit.td
[oota-llvm.git] / lib / Target / X86 / README-SSE.txt
index 123446fae96b7a543ebb3a179ebaf950304d5d87..cadfc20bbb1b6a161bc12768314ac7887f971570 100644 (file)
@@ -2,6 +2,14 @@
 // Random ideas for the X86 backend: SSE-specific stuff.
 //===---------------------------------------------------------------------===//
 
+- Consider eliminating the unaligned SSE load intrinsics, replacing them with
+  unaligned LLVM load instructions.
+
+//===---------------------------------------------------------------------===//
+
+Expand libm rounding functions inline:  Significant speedups possible.
+http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00909.html
+
 //===---------------------------------------------------------------------===//
 
 When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and
@@ -136,43 +144,6 @@ This will be solved when we go to a dynamic programming based isel.
 
 //===---------------------------------------------------------------------===//
 
-Should generate min/max for stuff like:
-
-void minf(float a, float b, float *X) {
-  *X = a <= b ? a : b;
-}
-
-Make use of floating point min / max instructions. Perhaps introduce ISD::FMIN
-and ISD::FMAX node types?
-
-//===---------------------------------------------------------------------===//
-
-The first BB of this code:
-
-declare bool %foo()
-int %bar() {
-        %V = call bool %foo()
-        br bool %V, label %T, label %F
-T:
-        ret int 1
-F:
-        call bool %foo()
-        ret int 12
-}
-
-compiles to:
-
-_bar:
-        subl $12, %esp
-        call L_foo$stub
-        xorb $1, %al
-        testb %al, %al
-        jne LBB_bar_2   # F
-
-It would be better to emit "cmp %al, 1" than a xor and test.
-
-//===---------------------------------------------------------------------===//
-
 Lower memcpy / memset to a series of SSE 128 bit move instructions when it's
 feasible.
 
@@ -222,29 +193,6 @@ Perhaps use pxor / xorp* to clear a XMM register first?
 
 //===---------------------------------------------------------------------===//
 
-Better codegen for:
-
-void f(float a, float b, vector float * out) { *out = (vector float){ a, 0.0, 0.0, b}; }
-void f(float a, float b, vector float * out) { *out = (vector float){ a, b, 0.0, 0}; }
-
-For the later we generate:
-
-_f:
-        pxor %xmm0, %xmm0
-        movss 8(%esp), %xmm1
-        movaps %xmm0, %xmm2
-        unpcklps %xmm1, %xmm2
-        movss 4(%esp), %xmm1
-        unpcklps %xmm0, %xmm1
-        unpcklps %xmm2, %xmm1
-        movl 12(%esp), %eax
-        movaps %xmm1, (%eax)
-        ret
-
-This seems like it should use shufps, one for each of a & b.
-
-//===---------------------------------------------------------------------===//
-
 How to decide when to use the "floating point version" of logical ops? Here are
 some code fragments:
 
@@ -274,33 +222,6 @@ instead of por and movdqa. Does it matter?
 
 //===---------------------------------------------------------------------===//
 
-Use movddup to splat a v2f64 directly from a memory source. e.g.
-
-#include <emmintrin.h>
-
-void test(__m128d *r, double A) {
-  *r = _mm_set1_pd(A);
-}
-
-llc:
-
-_test:
-       movsd 8(%esp), %xmm0
-       unpcklpd %xmm0, %xmm0
-       movl 4(%esp), %eax
-       movapd %xmm0, (%eax)
-       ret
-
-icc:
-
-_test:
-       movl 4(%esp), %eax
-       movddup 8(%esp), %xmm0
-       movapd %xmm0, (%eax)
-       ret
-
-//===---------------------------------------------------------------------===//
-
 X86RegisterInfo::copyRegToReg() returns X86::MOVAPSrr for VR128. Is it possible
 to choose between movaps, movapd, and movdqa based on types of source and
 destination?
@@ -311,69 +232,6 @@ shorter.
 
 //===---------------------------------------------------------------------===//
 
-We are emitting bad code for this:
-
-float %test(float* %V, int %I, int %D, float %V) {
-entry:
-       %tmp = seteq int %D, 0
-       br bool %tmp, label %cond_true, label %cond_false23
-
-cond_true:
-       %tmp3 = getelementptr float* %V, int %I
-       %tmp = load float* %tmp3
-       %tmp5 = setgt float %tmp, %V
-       %tmp6 = tail call bool %llvm.isunordered.f32( float %tmp, float %V )
-       %tmp7 = or bool %tmp5, %tmp6
-       br bool %tmp7, label %UnifiedReturnBlock, label %cond_next
-
-cond_next:
-       %tmp10 = add int %I, 1
-       %tmp12 = getelementptr float* %V, int %tmp10
-       %tmp13 = load float* %tmp12
-       %tmp15 = setle float %tmp13, %V
-       %tmp16 = tail call bool %llvm.isunordered.f32( float %tmp13, float %V )
-       %tmp17 = or bool %tmp15, %tmp16
-       %retval = select bool %tmp17, float 0.000000e+00, float 1.000000e+00
-       ret float %retval
-
-cond_false23:
-       %tmp28 = tail call float %foo( float* %V, int %I, int %D, float %V )
-       ret float %tmp28
-
-UnifiedReturnBlock:            ; preds = %cond_true
-       ret float 0.000000e+00
-}
-
-declare bool %llvm.isunordered.f32(float, float)
-
-declare float %foo(float*, int, int, float)
-
-
-It exposes a known load folding problem:
-
-       movss (%edx,%ecx,4), %xmm1
-       ucomiss %xmm1, %xmm0
-
-As well as this:
-
-LBB_test_2:    # cond_next
-       movss LCPI1_0, %xmm2
-       pxor %xmm3, %xmm3
-       ucomiss %xmm0, %xmm1
-       jbe LBB_test_6  # cond_next
-LBB_test_5:    # cond_next
-       movaps %xmm2, %xmm3
-LBB_test_6:    # cond_next
-       movss %xmm3, 40(%esp)
-       flds 40(%esp)
-       addl $44, %esp
-       ret
-
-Clearly it's unnecessary to clear %xmm3. It's also not clear why we are emitting
-three moves (movss, movaps, movss).
-
-//===---------------------------------------------------------------------===//
-
 External test Nurbs exposed some problems. Look for
 __ZN15Nurbs_SSE_Cubic17TessellateSurfaceE, bb cond_next140. This is what icc
 emits:
@@ -598,6 +456,18 @@ icc generates:
 So icc is smart enough to know that B is in memory so it doesn't load it and
 store it back to stack.
 
+This should be fixed by eliminating the llvm.x86.sse2.loadl.pd intrinsic, 
+lowering it to a load+insertelement instead.  Already match the load+shuffle 
+as movlpd, so this should be easy.  We already get optimal code for:
+
+define void @test2(<2 x double>* %r, <2 x double>* %A, double %B) {
+entry:
+       %tmp2 = load <2 x double>* %A, align 16
+       %tmp8 = insertelement <2 x double> %tmp2, double %B, i32 0
+       store <2 x double> %tmp8, <2 x double>* %r, align 16
+       ret void
+}
+
 //===---------------------------------------------------------------------===//
 
 __m128d test1( __m128d A, __m128d B) {
@@ -618,10 +488,10 @@ Don't know if unpckhpd is faster. But it is shorter.
 
 This code generates ugly code, probably due to costs being off or something:
 
-void %test(float* %P, <4 x float>* %P2 ) {
+define void @test(float* %P, <4 x float>* %P2 ) {
         %xFloat0.688 = load float* %P
-        %loadVector37.712 = load <4 x float>* %P2
-        %inFloat3.713 = insertelement <4 x float> %loadVector37.712, float 0.000000e+00, uint 3
+        %tmp = load <4 x float>* %P2
+        %inFloat3.713 = insertelement <4 x float> %tmp, float 0.0, i32 3
         store <4 x float> %inFloat3.713, <4 x float>* %P2
         ret void
 }
@@ -629,17 +499,16 @@ void %test(float* %P, <4 x float>* %P2 ) {
 Generates:
 
 _test:
-        pxor %xmm0, %xmm0
-        movd %xmm0, %eax        ;; EAX = 0!
-        movl 8(%esp), %ecx
-        movaps (%ecx), %xmm0
-        pinsrw $6, %eax, %xmm0
-        shrl $16, %eax          ;; EAX = 0 again!
-        pinsrw $7, %eax, %xmm0
-        movaps %xmm0, (%ecx)
-        ret
+       movl    8(%esp), %eax
+       movaps  (%eax), %xmm0
+       pxor    %xmm1, %xmm1
+       movaps  %xmm0, %xmm2
+       shufps  $50, %xmm1, %xmm2
+       shufps  $132, %xmm2, %xmm0
+       movaps  %xmm0, (%eax)
+       ret
 
-It would be better to generate:
+Would it be better to generate:
 
 _test:
         movl 8(%esp), %ecx
@@ -650,7 +519,7 @@ _test:
         movaps %xmm0, (%ecx)
         ret
 
-or use pxor (to make a zero vector) and shuffle (to insert it).
+?
 
 //===---------------------------------------------------------------------===//
 
@@ -660,3 +529,178 @@ http://developer.apple.com/documentation/Performance/Conceptual/
 Accelerate_sse_migration/index.html
 
 e.g. SSE select using and, andnot, or. Various SSE compare translations.
+
+//===---------------------------------------------------------------------===//
+
+Add hooks to commute some CMPP operations.
+
+//===---------------------------------------------------------------------===//
+
+Apply the same transformation that merged four float into a single 128-bit load
+to loads from constant pool.
+
+//===---------------------------------------------------------------------===//
+
+Floating point max / min are commutable when -enable-unsafe-fp-path is
+specified. We should turn int_x86_sse_max_ss and X86ISD::FMIN etc. into other
+nodes which are selected to max / min instructions that are marked commutable.
+
+//===---------------------------------------------------------------------===//
+
+We should compile this:
+#include <xmmintrin.h>
+typedef union {
+  int i[4];
+  float f[4];
+  __m128 v;
+} vector4_t;
+void swizzle (const void *a, vector4_t * b, vector4_t * c) {
+  b->v = _mm_loadl_pi (b->v, (__m64 *) a);
+  c->v = _mm_loadl_pi (c->v, ((__m64 *) a) + 1);
+}
+
+to:
+
+_swizzle:
+        movl    4(%esp), %eax
+        movl    8(%esp), %edx
+        movl    12(%esp), %ecx
+        movlps  (%eax), %xmm0
+        movlps  %xmm0, (%edx)
+        movlps  8(%eax), %xmm0
+        movlps  %xmm0, (%ecx)
+        ret
+
+not:
+
+swizzle:
+        movl 8(%esp), %eax
+        movaps (%eax), %xmm0
+        movl 4(%esp), %ecx
+        movlps (%ecx), %xmm0
+        movaps %xmm0, (%eax)
+        movl 12(%esp), %eax
+        movaps (%eax), %xmm0
+        movlps 8(%ecx), %xmm0
+        movaps %xmm0, (%eax)
+        ret
+
+//===---------------------------------------------------------------------===//
+
+These functions should produce the same code:
+
+#include <emmintrin.h>
+
+typedef long long __m128i __attribute__ ((__vector_size__ (16)));
+
+int foo(__m128i* val) {
+  return __builtin_ia32_vec_ext_v4si(*val, 1);
+}
+int bar(__m128i* val) {
+  union vs {
+    __m128i *_v;
+    int* _s;
+  } v = {val};
+  return v._s[1];
+}
+
+We currently produce (with -m64):
+
+_foo:
+        pshufd $1, (%rdi), %xmm0
+        movd %xmm0, %eax
+        ret
+_bar:
+        movl 4(%rdi), %eax
+        ret
+
+//===---------------------------------------------------------------------===//
+
+We should materialize vector constants like "all ones" and "signbit" with 
+code like:
+
+     cmpeqps xmm1, xmm1   ; xmm1 = all-ones
+
+and:
+     cmpeqps xmm1, xmm1   ; xmm1 = all-ones
+     psrlq   xmm1, 31     ; xmm1 = all 100000000000...
+
+instead of using a load from the constant pool.  The later is important for
+ABS/NEG/copysign etc.
+
+//===---------------------------------------------------------------------===//
+
+"converting 64-bit constant pool entry to 32-bit not necessarily beneficial"
+http://llvm.org/PR1264
+
+For this test case:
+
+define double @foo(double %x) {
+        %y = mul double %x, 5.000000e-01
+        ret double %y
+}
+
+llc -march=x86-64 currently produces a 32-bit constant pool entry and this code:
+
+        cvtss2sd .LCPI1_0(%rip), %xmm1
+        mulsd %xmm1, %xmm0
+
+instead of just using a 64-bit constant pool entry with this:
+
+        mulsd .LCPI1_0(%rip), %xmm0
+
+This is due to the code in ExpandConstantFP in LegalizeDAG.cpp. It notices that
+x86-64 indeed has an instruction to load a 32-bit float from memory and convert
+it into a 64-bit float in a register, however it doesn't notice that this isn't
+beneficial because it prevents the load from being folded into the multiply.
+
+//===---------------------------------------------------------------------===//
+
+These functions:
+
+#include <xmmintrin.h>
+__m128i a;
+void x(unsigned short n) {
+  a = _mm_slli_epi32 (a, n);
+}
+void y(unsigned n) {
+  a = _mm_slli_epi32 (a, n);
+}
+
+compile to ( -O3 -static -fomit-frame-pointer):
+_x:
+        movzwl  4(%esp), %eax
+        movd    %eax, %xmm0
+        movaps  _a, %xmm1
+        pslld   %xmm0, %xmm1
+        movaps  %xmm1, _a
+        ret
+_y:
+        movd    4(%esp), %xmm0
+        movaps  _a, %xmm1
+        pslld   %xmm0, %xmm1
+        movaps  %xmm1, _a
+        ret
+
+"y" looks good, but "x" does silly movzwl stuff around into a GPR.  It seems
+like movd would be sufficient in both cases as the value is already zero 
+extended in the 32-bit stack slot IIRC.  For signed short, it should also be
+save, as a really-signed value would be undefined for pslld.
+
+
+//===---------------------------------------------------------------------===//
+
+#include <math.h>
+int t1(double d) { return signbit(d); }
+
+This currently compiles to:
+       subl    $12, %esp
+       movsd   16(%esp), %xmm0
+       movsd   %xmm0, (%esp)
+       movl    4(%esp), %eax
+       shrl    $31, %eax
+       addl    $12, %esp
+       ret
+
+We should use movmskp{s|d} instead.
+