X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FREADME.txt;h=073e2dacef183b26bab7ac32332d4a19f2702471;hb=c59e52108bbfca50b23c5d10706484d4b012c344;hp=8f5e15aa57df3ee256ee56b5285d7da0f0c7107b;hpb=46cd65dfa6d0713e666d07996b63c1fbaf7a8325;p=oota-llvm.git diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt index 8f5e15aa57d..073e2dacef1 100644 --- a/lib/Target/X86/README.txt +++ b/lib/Target/X86/README.txt @@ -2,6 +2,14 @@ // Random ideas for the X86 backend. //===---------------------------------------------------------------------===// +Missing features: + - Support for SSE4: http://www.intel.com/software/penryn +http://softwarecommunity.intel.com/isn/Downloads/Intel%20SSE4%20Programming%20Reference.pdf + - support for 3DNow! + - weird abis? + +//===---------------------------------------------------------------------===// + Add a MUL2U and MUL2S nodes to represent a multiply that returns both the Hi and Lo parts (combination of MUL and MULH[SU] into one node). Add this to X86, & make the dag combiner produce it when needed. This will eliminate one @@ -18,6 +26,26 @@ long long test(int X, int Y) { return (long long)X*Y; } ... which should only be one imul instruction. +or: + +unsigned long long int t2(unsigned int a, unsigned int b) { + return (unsigned long long)a * b; +} + +... which should be one mul instruction. + + +This can be done with a custom expander, but it would be nice to move this to +generic code. + +//===---------------------------------------------------------------------===// + +CodeGen/X86/lea-3.ll:test3 should be a single LEA, not a shift/move. The X86 +backend knows how to three-addressify this shift, but it appears the register +allocator isn't even asking it to do so in this case. We should investigate +why this isn't happening, it could have significant impact on other important +cases for X86 as well. + //===---------------------------------------------------------------------===// This should be one DIV/IDIV instruction, not a libcall: @@ -45,6 +73,20 @@ http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01136.html Another useful one would be ~0ULL >> X and ~0ULL << X. +One better solution for 1LL << x is: + xorl %eax, %eax + xorl %edx, %edx + testb $32, %cl + sete %al + setne %dl + sall %cl, %eax + sall %cl, %edx + +But that requires good 8-bit subreg support. + +64-bit shifts (in general) expand to really bad code. Instead of using +cmovs, we should expand to a conditional branch like GCC produces. + //===---------------------------------------------------------------------===// Compile this: @@ -80,15 +122,6 @@ allocator. Delay codegen until post register allocation. //===---------------------------------------------------------------------===// -Model X86 EFLAGS as a real register to avoid redudant cmp / test. e.g. - - cmpl $1, %eax - setg %al - testb %al, %al # unnecessary - jne .BB7 - -//===---------------------------------------------------------------------===// - Count leading zeros and count trailing zeros: int clz(int X) { return __builtin_clz(X); } @@ -106,11 +139,18 @@ ctz: however, check that these are defined for 0 and 32. Our intrinsics are, GCC's aren't. +Another example (use predsimplify to eliminate a select): + +int foo (unsigned long j) { + if (j) + return __builtin_ffs (j) - 1; + else + return 0; +} + //===---------------------------------------------------------------------===// -Use push/pop instructions in prolog/epilog sequences instead of stores off -ESP (certain code size win, perf win on some [which?] processors). -Also, it appears icc use push for parameter passing. Need to investigate. +It appears icc use push for parameter passing. Need to investigate. //===---------------------------------------------------------------------===// @@ -126,6 +166,8 @@ commutative, it is not matched with the load on both sides. The dag combiner should be made smart enough to cannonicalize the load into the RHS of a compare when it can invert the result of the compare for free. +//===---------------------------------------------------------------------===// + How about intrinsics? An example is: *res = _mm_mulhi_epu16(*A, _mm_mul_epu32(*B, *C)); @@ -140,51 +182,6 @@ target specific hook. //===---------------------------------------------------------------------===// -The DAG Isel doesn't fold the loads into the adds in this testcase. The -pattern selector does. This is because the chain value of the load gets -selected first, and the loads aren't checking to see if they are only used by -and add. - -.ll: - -int %test(int* %x, int* %y, int* %z) { - %X = load int* %x - %Y = load int* %y - %Z = load int* %z - %a = add int %X, %Y - %b = add int %a, %Z - ret int %b -} - -dag isel: - -_test: - movl 4(%esp), %eax - movl (%eax), %eax - movl 8(%esp), %ecx - movl (%ecx), %ecx - addl %ecx, %eax - movl 12(%esp), %ecx - movl (%ecx), %ecx - addl %ecx, %eax - ret - -pattern isel: - -_test: - movl 12(%esp), %ecx - movl 4(%esp), %edx - movl 8(%esp), %eax - movl (%eax), %eax - addl (%edx), %eax - addl (%ecx), %eax - ret - -This is bad for register pressure, though the dag isel is producing a -better schedule. :) - -//===---------------------------------------------------------------------===// - In many cases, LLVM generates code like this: _test: @@ -198,7 +195,7 @@ on some processors (which ones?), it is more efficient to do this: _test: movl 8(%esp), %ebx - xor %eax, %eax + xor %eax, %eax cmpl %ebx, 4(%esp) setl %al ret @@ -207,38 +204,6 @@ Doing this correctly is tricky though, as the xor clobbers the flags. //===---------------------------------------------------------------------===// -We should generate 'test' instead of 'cmp' in various cases, e.g.: - -bool %test(int %X) { - %Y = shl int %X, ubyte 1 - %C = seteq int %Y, 0 - ret bool %C -} -bool %test(int %X) { - %Y = and int %X, 8 - %C = seteq int %Y, 0 - ret bool %C -} - -This may just be a matter of using 'test' to write bigger patterns for X86cmp. - -An important case is comparison against zero: - -if (X == 0) ... - -instead of: - - cmpl $0, %eax - je LBB4_2 #cond_next - -use: - test %eax, %eax - jz LBB4_2 - -which is smaller. - -//===---------------------------------------------------------------------===// - We should generate bts/btr/etc instructions on targets where they are cheap or when codesize is important. e.g., for: @@ -299,17 +264,6 @@ which is probably slower, but it's interesting at least :) //===---------------------------------------------------------------------===// -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() @@ -340,22 +294,6 @@ Enable X86InstrInfo::convertToThreeAddress(). //===---------------------------------------------------------------------===// -Investigate whether it is better to codegen the following - - %tmp.1 = mul int %x, 9 -to - - movl 4(%esp), %eax - leal (%eax,%eax,8), %eax - -as opposed to what llc is currently generating: - - imull $9, 4(%esp), %eax - -Currently the load folding imull has a higher complexity than the LEA32 pattern. - -//===---------------------------------------------------------------------===// - We are currently lowering large (1MB+) memmove/memcpy to rep/stosl and rep/movsl We should leave these as libcalls for everything over a much lower threshold, since libc is hand tuned for medium and large mem ops (avoiding RFO for large @@ -424,6 +362,51 @@ lambda, siod, optimizer-eval, ackermann, hash2, nestedloop, strcat, and Treesor. //===---------------------------------------------------------------------===// +We are generating far worse code than gcc: + +volatile short X, Y; + +void foo(int N) { + int i; + for (i = 0; i < N; i++) { X = i; Y = i*4; } +} + +LBB1_1: #bb.preheader + xorl %ecx, %ecx + xorw %dx, %dx +LBB1_2: #bb + movl L_X$non_lazy_ptr, %esi + movw %dx, (%esi) + movw %dx, %si + shlw $2, %si + movl L_Y$non_lazy_ptr, %edi + movw %si, (%edi) + incl %ecx + incw %dx + cmpl %eax, %ecx + jne LBB1_2 #bb + +vs. + + xorl %edx, %edx + movl L_X$non_lazy_ptr-"L00000000001$pb"(%ebx), %esi + movl L_Y$non_lazy_ptr-"L00000000001$pb"(%ebx), %ecx +L4: + movw %dx, (%esi) + leal 0(,%edx,4), %eax + movw %ax, (%ecx) + addl $1, %edx + cmpl %edx, %edi + jne L4 + +There are 3 issues: + +1. Lack of post regalloc LICM. +2. LSR unable to reused IV for a different type (i16 vs. i32) even though + the cast would be free. + +//===---------------------------------------------------------------------===// + Teach the coalescer to coalesce vregs of different register classes. e.g. FR32 / FR64 to VR128. @@ -490,59 +473,6 @@ require a copy to be inserted (in X86InstrInfo::convertToThreeAddress). //===---------------------------------------------------------------------===// -This code generates ugly code, probably due to costs being off or something: - -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 - store <4 x float> %inFloat3.713, <4 x float>* %P2 - ret void -} - -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 - -It would be better to generate: - -_test: - movl 8(%esp), %ecx - movaps (%ecx), %xmm0 - xor %eax, %eax - pinsrw $6, %eax, %xmm0 - pinsrw $7, %eax, %xmm0 - movaps %xmm0, (%ecx) - ret - -or use pxor (to make a zero vector) and shuffle (to insert it). - -//===---------------------------------------------------------------------===// - -Bad codegen: - -char foo(int x) { return x; } - -_foo: - movl 4(%esp), %eax - shll $24, %eax - sarl $24, %eax - ret - -SIGN_EXTEND_INREG can be implemented as (sext (trunc)) to take advantage of -sub-registers. - -//===---------------------------------------------------------------------===// - Consider this: typedef struct pair { float A, B; } pair; @@ -553,16 +483,13 @@ void pairtest(pair P, float *FP) { We currently generate this code with llvmgcc4: _pairtest: - subl $12, %esp - movl 20(%esp), %eax - movl %eax, 4(%esp) - movl 16(%esp), %eax - movl %eax, (%esp) - movss (%esp), %xmm0 - addss 4(%esp), %xmm0 - movl 24(%esp), %eax - movss %xmm0, (%eax) - addl $12, %esp + movl 8(%esp), %eax + movl 4(%esp), %ecx + movd %eax, %xmm0 + movd %ecx, %xmm1 + addss %xmm0, %xmm1 + movl 12(%esp), %eax + movss %xmm1, (%eax) ret we should be able to generate: @@ -578,16 +505,9 @@ integer chunks. It does this so that structs like {short,short} are passed in a single 32-bit integer stack slot. We should handle the safe cases above much nicer, while still handling the hard cases. -//===---------------------------------------------------------------------===// - -Some ideas for instruction selection code simplification: 1. A pre-pass to -determine which chain producing node can or cannot be folded. The generated -isel code would then use the information. 2. The same pre-pass can force -ordering of TokenFactor operands to allow load / store folding. 3. During isel, -instead of recursively going up the chain operand chain, mark the chain operand -as available and put it in some work list. Select other nodes in the normal -manner. The chain operands are selected after all other nodes are selected. Uses -of chain nodes are modified after instruction selection is completed. +While true in general, in this specific case we could do better by promoting +load int + bitcast to float -> load fload. This basically needs alignment info, +the code is already implemented (but disabled) in dag combine). //===---------------------------------------------------------------------===// @@ -667,43 +587,26 @@ do not make use of. //===---------------------------------------------------------------------===// -We should handle __attribute__ ((__visibility__ ("hidden"))). - -//===---------------------------------------------------------------------===// - -Consider: -int foo(int *a, int t) { -int x; -for (x=0; x<40; ++x) - t = t + a[x] + x; -return t; +int %foo(int* %a, int %t) { +entry: + br label %cond_true + +cond_true: ; preds = %cond_true, %entry + %x.0.0 = phi int [ 0, %entry ], [ %tmp9, %cond_true ] + %t_addr.0.0 = phi int [ %t, %entry ], [ %tmp7, %cond_true ] + %tmp2 = getelementptr int* %a, int %x.0.0 + %tmp3 = load int* %tmp2 ; [#uses=1] + %tmp5 = add int %t_addr.0.0, %x.0.0 ; [#uses=1] + %tmp7 = add int %tmp5, %tmp3 ; [#uses=2] + %tmp9 = add int %x.0.0, 1 ; [#uses=2] + %tmp = setgt int %tmp9, 39 ; [#uses=1] + br bool %tmp, label %bb12, label %cond_true + +bb12: ; preds = %cond_true + ret int %tmp7 } -We generate: -LBB1_1: #cond_true - movl %ecx, %esi - movl (%edx,%eax,4), %edi - movl %esi, %ecx - addl %edi, %ecx - addl %eax, %ecx - incl %eax - cmpl $40, %eax - jne LBB1_1 #cond_true - -GCC generates: - -L2: - addl (%ecx,%edx,4), %eax - addl %edx, %eax - addl $1, %edx - cmpl $40, %edx - jne L2 - -Smells like a register coallescing/reassociation issue. - -//===---------------------------------------------------------------------===// - -Use cpuid to auto-detect CPU features such as SSE, SSE2, and SSE3. +is pessimized by -loop-reduce and -indvars //===---------------------------------------------------------------------===// @@ -729,3 +632,484 @@ float uint32_2_float( unsigned u ) { 0000002a flds (%esp,1) 0000002d addl $0x04,%esp 00000030 ret + +//===---------------------------------------------------------------------===// + +When using fastcc abi, align stack slot of argument of type double on 8 byte +boundary to improve performance. + +//===---------------------------------------------------------------------===// + +Codegen: + +int f(int a, int b) { + if (a == 4 || a == 6) + b++; + return b; +} + + +as: + +or eax, 2 +cmp eax, 6 +jz label + +//===---------------------------------------------------------------------===// + +GCC's ix86_expand_int_movcc function (in i386.c) has a ton of interesting +simplifications for integer "x cmp y ? a : b". For example, instead of: + +int G; +void f(int X, int Y) { + G = X < 0 ? 14 : 13; +} + +compiling to: + +_f: + movl $14, %eax + movl $13, %ecx + movl 4(%esp), %edx + testl %edx, %edx + cmovl %eax, %ecx + movl %ecx, _G + ret + +it could be: +_f: + movl 4(%esp), %eax + sarl $31, %eax + notl %eax + addl $14, %eax + movl %eax, _G + ret + +etc. + +//===---------------------------------------------------------------------===// + +Currently we don't have elimination of redundant stack manipulations. Consider +the code: + +int %main() { +entry: + call fastcc void %test1( ) + call fastcc void %test2( sbyte* cast (void ()* %test1 to sbyte*) ) + ret int 0 +} + +declare fastcc void %test1() + +declare fastcc void %test2(sbyte*) + + +This currently compiles to: + + subl $16, %esp + call _test5 + addl $12, %esp + subl $16, %esp + movl $_test5, (%esp) + call _test6 + addl $12, %esp + +The add\sub pair is really unneeded here. + +//===---------------------------------------------------------------------===// + +We currently compile sign_extend_inreg into two shifts: + +long foo(long X) { + return (long)(signed char)X; +} + +becomes: + +_foo: + movl 4(%esp), %eax + shll $24, %eax + sarl $24, %eax + ret + +This could be: + +_foo: + movsbl 4(%esp),%eax + ret + +//===---------------------------------------------------------------------===// + +Consider the expansion of: + +uint %test3(uint %X) { + %tmp1 = rem uint %X, 255 + ret uint %tmp1 +} + +Currently it compiles to: + +... + movl $2155905153, %ecx + movl 8(%esp), %esi + movl %esi, %eax + mull %ecx +... + +This could be "reassociated" into: + + movl $2155905153, %eax + movl 8(%esp), %ecx + mull %ecx + +to avoid the copy. In fact, the existing two-address stuff would do this +except that mul isn't a commutative 2-addr instruction. I guess this has +to be done at isel time based on the #uses to mul? + +//===---------------------------------------------------------------------===// + +Make sure the instruction which starts a loop does not cross a cacheline +boundary. This requires knowning the exact length of each machine instruction. +That is somewhat complicated, but doable. Example 256.bzip2: + +In the new trace, the hot loop has an instruction which crosses a cacheline +boundary. In addition to potential cache misses, this can't help decoding as I +imagine there has to be some kind of complicated decoder reset and realignment +to grab the bytes from the next cacheline. + +532 532 0x3cfc movb (1809(%esp, %esi), %bl <<<--- spans 2 64 byte lines +942 942 0x3d03 movl %dh, (1809(%esp, %esi) +937 937 0x3d0a incl %esi +3 3 0x3d0b cmpb %bl, %dl +27 27 0x3d0d jnz 0x000062db + +//===---------------------------------------------------------------------===// + +In c99 mode, the preprocessor doesn't like assembly comments like #TRUNCATE. + +//===---------------------------------------------------------------------===// + +This could be a single 16-bit load. + +int f(char *p) { + if ((p[0] == 1) & (p[1] == 2)) return 1; + return 0; +} + +//===---------------------------------------------------------------------===// + +We should inline lrintf and probably other libc functions. + +//===---------------------------------------------------------------------===// + +Start using the flags more. For example, compile: + +int add_zf(int *x, int y, int a, int b) { + if ((*x += y) == 0) + return a; + else + return b; +} + +to: + addl %esi, (%rdi) + movl %edx, %eax + cmovne %ecx, %eax + ret +instead of: + +_add_zf: + addl (%rdi), %esi + movl %esi, (%rdi) + testl %esi, %esi + cmove %edx, %ecx + movl %ecx, %eax + ret + +and: + +int add_zf(int *x, int y, int a, int b) { + if ((*x + y) < 0) + return a; + else + return b; +} + +to: + +add_zf: + addl (%rdi), %esi + movl %edx, %eax + cmovns %ecx, %eax + ret + +instead of: + +_add_zf: + addl (%rdi), %esi + testl %esi, %esi + cmovs %edx, %ecx + movl %ecx, %eax + ret + +//===---------------------------------------------------------------------===// + +This: +#include +int foo(double X) { return isnan(X); } + +compiles to (-m64): + +_foo: + pxor %xmm1, %xmm1 + ucomisd %xmm1, %xmm0 + setp %al + movzbl %al, %eax + ret + +the pxor is not needed, we could compare the value against itself. + +//===---------------------------------------------------------------------===// + +These two functions have identical effects: + +unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return i;} +unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;} + +We currently compile them to: + +_f: + movl 4(%esp), %eax + movl %eax, %ecx + incl %ecx + movl 8(%esp), %edx + cmpl %edx, %ecx + jne LBB1_2 #UnifiedReturnBlock +LBB1_1: #cond_true + addl $2, %eax + ret +LBB1_2: #UnifiedReturnBlock + movl %ecx, %eax + ret +_f2: + movl 4(%esp), %eax + movl %eax, %ecx + incl %ecx + cmpl 8(%esp), %ecx + sete %cl + movzbl %cl, %ecx + leal 1(%ecx,%eax), %eax + ret + +both of which are inferior to GCC's: + +_f: + movl 4(%esp), %edx + leal 1(%edx), %eax + addl $2, %edx + cmpl 8(%esp), %eax + cmove %edx, %eax + ret +_f2: + movl 4(%esp), %eax + addl $1, %eax + xorl %edx, %edx + cmpl 8(%esp), %eax + sete %dl + addl %edx, %eax + ret + +//===---------------------------------------------------------------------===// + +This code: + +void test(int X) { + if (X) abort(); +} + +is currently compiled to: + +_test: + subl $12, %esp + cmpl $0, 16(%esp) + jne LBB1_1 + addl $12, %esp + ret +LBB1_1: + call L_abort$stub + +It would be better to produce: + +_test: + subl $12, %esp + cmpl $0, 16(%esp) + jne L_abort$stub + addl $12, %esp + ret + +This can be applied to any no-return function call that takes no arguments etc. +Alternatively, the stack save/restore logic could be shrink-wrapped, producing +something like this: + +_test: + cmpl $0, 4(%esp) + jne LBB1_1 + ret +LBB1_1: + subl $12, %esp + call L_abort$stub + +Both are useful in different situations. Finally, it could be shrink-wrapped +and tail called, like this: + +_test: + cmpl $0, 4(%esp) + jne LBB1_1 + ret +LBB1_1: + pop %eax # realign stack. + call L_abort$stub + +Though this probably isn't worth it. + +//===---------------------------------------------------------------------===// + +We need to teach the codegen to convert two-address INC instructions to LEA +when the flags are dead. For example, on X86-64, compile: + +int foo(int A, int B) { + return A+1; +} + +to: + +_foo: + leal 1(%edi), %eax + ret + +instead of: + +_foo: + incl %edi + movl %edi, %eax + ret + +Another example is: + +;; X's live range extends beyond the shift, so the register allocator +;; cannot coalesce it with Y. Because of this, a copy needs to be +;; emitted before the shift to save the register value before it is +;; clobbered. However, this copy is not needed if the register +;; allocator turns the shift into an LEA. This also occurs for ADD. + +; Check that the shift gets turned into an LEA. +; RUN: llvm-upgrade < %s | llvm-as | llc -march=x86 -x86-asm-syntax=intel | \ +; RUN: not grep {mov E.X, E.X} + +%G = external global int + +int %test1(int %X, int %Y) { + %Z = add int %X, %Y + volatile store int %Y, int* %G + volatile store int %Z, int* %G + ret int %X +} + +int %test2(int %X) { + %Z = add int %X, 1 ;; inc + volatile store int %Z, int* %G + ret int %X +} + +//===---------------------------------------------------------------------===// + +This: +#include +unsigned test(float f) { + return _mm_cvtsi128_si32( (__m128i) _mm_set_ss( f )); +} + +Compiles to: +_test: + movss 4(%esp), %xmm0 + movd %xmm0, %eax + ret + +it should compile to a move from the stack slot directly into eax. DAGCombine +has this xform, but it is currently disabled until the alignment fields of +the load/store nodes are trustworthy. + +//===---------------------------------------------------------------------===// + +Sometimes it is better to codegen subtractions from a constant (e.g. 7-x) with +a neg instead of a sub instruction. Consider: + +int test(char X) { return 7-X; } + +we currently produce: +_test: + movl $7, %eax + movsbl 4(%esp), %ecx + subl %ecx, %eax + ret + +We would use one fewer register if codegen'd as: + + movsbl 4(%esp), %eax + neg %eax + add $7, %eax + ret + +Note that this isn't beneficial if the load can be folded into the sub. In +this case, we want a sub: + +int test(int X) { return 7-X; } +_test: + movl $7, %eax + subl 4(%esp), %eax + ret + +//===---------------------------------------------------------------------===// + +For code like: +phi (undef, x) + +We get an implicit def on the undef side. If the phi is spilled, we then get: +implicitdef xmm1 +store xmm1 -> stack + +It should be possible to teach the x86 backend to "fold" the store into the +implicitdef, which just deletes the implicit def. + +These instructions should go away: +#IMPLICIT_DEF %xmm1 +movaps %xmm1, 192(%esp) +movaps %xmm1, 224(%esp) +movaps %xmm1, 176(%esp) + +//===---------------------------------------------------------------------===// + +This is a "commutable two-address" register coallescing deficiency: + +define <4 x float> @test1(<4 x float> %V) { +entry: + %tmp8 = shufflevector <4 x float> %V, <4 x float> undef, <4 x i32> < i32 3, i32 2, i32 1, i32 0 > ; <<4 x float>> [#uses=1] + %add = add <4 x float> %tmp8, %V ; <<4 x float>> [#uses=1] + ret <4 x float> %add +} + +this codegens to: + +_test1: + pshufd $27, %xmm0, %xmm1 + addps %xmm0, %xmm1 + movaps %xmm1, %xmm0 + ret + +instead of: + +_test1: + pshufd $27, %xmm0, %xmm1 + addps %xmm1, %xmm0 + ret +