X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FREADME.txt;h=073e2dacef183b26bab7ac32332d4a19f2702471;hb=c59e52108bbfca50b23c5d10706484d4b012c344;hp=09d9bb6ef866f5ce88bae47ab6fe708886dd18e8;hpb=6a6d354d4c33e435c15a70e1f3946984ae194445;p=oota-llvm.git diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt index 09d9bb6ef86..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,58 +26,36 @@ long long test(int X, int Y) { return (long long)X*Y; } ... which should only be one imul instruction. -//===---------------------------------------------------------------------===// - -This should be one DIV/IDIV instruction, not a libcall: +or: -unsigned test(unsigned long long X, unsigned Y) { - return X/Y; +unsigned long long int t2(unsigned int a, unsigned int b) { + return (unsigned long long)a * b; } -This can be done trivially with a custom legalizer. What about overflow -though? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224 +... which should be one mul instruction. -//===---------------------------------------------------------------------===// -Some targets (e.g. athlons) prefer freep to fstp ST(0): -http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00659.html +This can be done with a custom expander, but it would be nice to move this to +generic code. //===---------------------------------------------------------------------===// -This should use fiadd on chips where it is profitable: -double foo(double P, int *I) { return P+*I; } - -We have fiadd patterns now but the followings have the same cost and -complexity. We need a way to specify the later is more profitable. - -def FpADD32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, - [(set RFP:$dst, (fadd RFP:$src1, - (extloadf64f32 addr:$src2)))]>; - // ST(0) = ST(0) + [mem32] - -def FpIADD32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, - [(set RFP:$dst, (fadd RFP:$src1, - (X86fild addr:$src2, i32)))]>; - // ST(0) = ST(0) + [mem32int] +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. //===---------------------------------------------------------------------===// -The FP stackifier needs to be global. Also, it should handle simple permutates -to reduce number of shuffle instructions, e.g. turning: - -fld P -> fld Q -fld Q fld P -fxch - -or: - -fxch -> fucomi -fucomi jl X -jg X +This should be one DIV/IDIV instruction, not a libcall: -Ideas: -http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02410.html +unsigned test(unsigned long long X, unsigned Y) { + return X/Y; +} +This can be done trivially with a custom legalizer. What about overflow +though? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224 //===---------------------------------------------------------------------===// @@ -87,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: @@ -122,20 +122,6 @@ allocator. Delay codegen until post register allocation. //===---------------------------------------------------------------------===// -Add a target specific hook to DAG combiner to handle SINT_TO_FP and -FP_TO_SINT when the source operand is already in memory. - -//===---------------------------------------------------------------------===// - -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); } @@ -153,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. //===---------------------------------------------------------------------===// @@ -167,24 +160,6 @@ flags. //===---------------------------------------------------------------------===// -Open code rint,floor,ceil,trunc: -http://gcc.gnu.org/ml/gcc-patches/2004-08/msg02006.html -http://gcc.gnu.org/ml/gcc-patches/2004-08/msg02011.html - -//===---------------------------------------------------------------------===// - -Combine: a = sin(x), b = cos(x) into a,b = sincos(x). - -Expand these to calls of sin/cos and stores: - double sincos(double x, double *sin, double *cos); - float sincosf(float x, float *sin, float *cos); - long double sincosl(long double x, long double *sin, long double *cos); - -Doing so could allow SROA of the destination pointers. See also: -http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17687 - -//===---------------------------------------------------------------------===// - The instruction selector sometimes misses folding a load into a compare. The pattern is written as (cmp reg, (load p)). Because the compare isn't commutative, it is not matched with the load on both sides. The dag combiner @@ -193,141 +168,17 @@ when it can invert the result of the compare for free. //===---------------------------------------------------------------------===// -LSR should be turned on for the X86 backend and tuned to take advantage of its -addressing modes. +How about intrinsics? An example is: + *res = _mm_mulhi_epu16(*A, _mm_mul_epu32(*B, *C)); -//===---------------------------------------------------------------------===// - -When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and -other fast SSE modes. - -//===---------------------------------------------------------------------===// +compiles to + pmuludq (%eax), %xmm0 + movl 8(%esp), %eax + movdqa (%eax), %xmm1 + pmulhuw %xmm0, %xmm1 -Think about doing i64 math in SSE regs. - -//===---------------------------------------------------------------------===// - -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. :) - -//===---------------------------------------------------------------------===// - -This testcase should have no SSE instructions in it, and only one load from -a constant pool: - -double %test3(bool %B) { - %C = select bool %B, double 123.412, double 523.01123123 - ret double %C -} - -Currently, the select is being lowered, which prevents the dag combiner from -turning 'select (load CPI1), (load CPI2)' -> 'load (select CPI1, CPI2)' - -The pattern isel got this one right. - -//===---------------------------------------------------------------------===// - -We need to lower switch statements to tablejumps when appropriate instead of -always into binary branch trees. - -//===---------------------------------------------------------------------===// - -SSE doesn't have [mem] op= reg instructions. If we have an SSE instruction -like this: - - X += y - -and the register allocator decides to spill X, it is cheaper to emit this as: - -Y += [xslot] -store Y -> [xslot] - -than as: - -tmp = [xslot] -tmp += y -store tmp -> [xslot] - -..and this uses one fewer register (so this should be done at load folding -time, not at spiller time). *Note* however that this can only be done -if Y is dead. Here's a testcase: - -%.str_3 = external global [15 x sbyte] ; <[15 x sbyte]*> [#uses=0] -implementation ; Functions: -declare void %printf(int, ...) -void %main() { -build_tree.exit: - br label %no_exit.i7 -no_exit.i7: ; preds = %no_exit.i7, %build_tree.exit - %tmp.0.1.0.i9 = phi double [ 0.000000e+00, %build_tree.exit ], [ %tmp.34.i18, %no_exit.i7 ] ; [#uses=1] - %tmp.0.0.0.i10 = phi double [ 0.000000e+00, %build_tree.exit ], [ %tmp.28.i16, %no_exit.i7 ] ; [#uses=1] - %tmp.28.i16 = add double %tmp.0.0.0.i10, 0.000000e+00 - %tmp.34.i18 = add double %tmp.0.1.0.i9, 0.000000e+00 - br bool false, label %Compute_Tree.exit23, label %no_exit.i7 -Compute_Tree.exit23: ; preds = %no_exit.i7 - tail call void (int, ...)* %printf( int 0 ) - store double %tmp.34.i18, double* null - ret void -} - -We currently emit: - -.BBmain_1: - xorpd %XMM1, %XMM1 - addsd %XMM0, %XMM1 -*** movsd %XMM2, QWORD PTR [%ESP + 8] -*** addsd %XMM2, %XMM1 -*** movsd QWORD PTR [%ESP + 8], %XMM2 - jmp .BBmain_1 # no_exit.i7 - -This is a bugpoint reduced testcase, which is why the testcase doesn't make -much sense (e.g. its an infinite loop). :) - -//===---------------------------------------------------------------------===// - -None of the FPStack instructions are handled in -X86RegisterInfo::foldMemoryOperand, which prevents the spiller from -folding spill code into the instructions. +The transformation probably requires a X86 specific pass or a DAG combiner +target specific hook. //===---------------------------------------------------------------------===// @@ -344,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 @@ -353,53 +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. - -//===---------------------------------------------------------------------===// - -SSE should implement 'select_cc' using 'emulated conditional moves' that use -pcmp/pand/pandn/por to do a selection instead of a conditional branch: - -double %X(double %Y, double %Z, double %A, double %B) { - %C = setlt double %A, %B - %z = add double %Z, 0.0 ;; select operand is not a load - %D = select bool %C, double %Y, double %z - ret double %D -} - -We currently emit: - -_X: - subl $12, %esp - xorpd %xmm0, %xmm0 - addsd 24(%esp), %xmm0 - movsd 32(%esp), %xmm1 - movsd 16(%esp), %xmm2 - ucomisd 40(%esp), %xmm1 - jb LBB_X_2 -LBB_X_1: - movsd %xmm0, %xmm2 -LBB_X_2: - movsd %xmm2, (%esp) - fldl (%esp) - addl $12, %esp - ret - -//===---------------------------------------------------------------------===// - We should generate bts/btr/etc instructions on targets where they are cheap or when codesize is important. e.g., for: @@ -429,12 +233,6 @@ when we can spare a register. It reduces code size. //===---------------------------------------------------------------------===// -It's not clear whether we should use pxor or xorps / xorpd to clear XMM -registers. The choice may depend on subtarget information. We should do some -more experiments on different x86 machines. - -//===---------------------------------------------------------------------===// - Evaluate what the best way to codegen sdiv X, (2^C) is. For X/8, we currently get this: @@ -466,36 +264,6 @@ which is probably slower, but it's interesting at least :) //===---------------------------------------------------------------------===// -Currently the x86 codegen isn't very good at mixing SSE and FPStack -code: - -unsigned int foo(double x) { return x; } - -foo: - subl $20, %esp - movsd 24(%esp), %xmm0 - movsd %xmm0, 8(%esp) - fldl 8(%esp) - fisttpll (%esp) - movl (%esp), %eax - addl $20, %esp - ret - -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() @@ -526,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 @@ -549,45 +301,6 @@ stores, TLB preheating, etc) //===---------------------------------------------------------------------===// -Lower memcpy / memset to a series of SSE 128 bit move instructions when it's -feasible. - -//===---------------------------------------------------------------------===// - -Teach the coalescer to commute 2-addr instructions, allowing us to eliminate -the reg-reg copy in this example: - -float foo(int *x, float *y, unsigned c) { - float res = 0.0; - unsigned i; - for (i = 0; i < c; i++) { - float xx = (float)x[i]; - xx = xx * y[i]; - xx += res; - res = xx; - } - return res; -} - -LBB_foo_3: # no_exit - cvtsi2ss %XMM0, DWORD PTR [%EDX + 4*%ESI] - mulss %XMM0, DWORD PTR [%EAX + 4*%ESI] - addss %XMM0, %XMM1 - inc %ESI - cmp %ESI, %ECX -**** movaps %XMM1, %XMM0 - jb LBB_foo_3 # no_exit - -//===---------------------------------------------------------------------===// - -Codegen: - if (copysign(1.0, x) == copysign(1.0, y)) -into: - if (x^y & mask) -when using SSE. - -//===---------------------------------------------------------------------===// - Optimize this into something reasonable: x * copysign(1.0, y) * copysign(1.0, z) @@ -649,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. @@ -665,5 +423,693 @@ directly %esp[0] if there are no other uses. //===---------------------------------------------------------------------===// -Use movhps to update upper 64-bits of a v4sf value. Also movlps on lower half -of a v4sf value. +Adding to the list of cmp / test poor codegen issues: + +int test(__m128 *A, __m128 *B) { + if (_mm_comige_ss(*A, *B)) + return 3; + else + return 4; +} + +_test: + movl 8(%esp), %eax + movaps (%eax), %xmm0 + movl 4(%esp), %eax + movaps (%eax), %xmm1 + comiss %xmm0, %xmm1 + setae %al + movzbl %al, %ecx + movl $3, %eax + movl $4, %edx + cmpl $0, %ecx + cmove %edx, %eax + ret + +Note the setae, movzbl, cmpl, cmove can be replaced with a single cmovae. There +are a number of issues. 1) We are introducing a setcc between the result of the +intrisic call and select. 2) The intrinsic is expected to produce a i32 value +so a any extend (which becomes a zero extend) is added. + +We probably need some kind of target DAG combine hook to fix this. + +//===---------------------------------------------------------------------===// + +We generate significantly worse code for this than GCC: +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21150 +http://gcc.gnu.org/bugzilla/attachment.cgi?id=8701 + +There is also one case we do worse on PPC. + +//===---------------------------------------------------------------------===// + +If shorter, we should use things like: +movzwl %ax, %eax +instead of: +andl $65535, %EAX + +The former can also be used when the two-addressy nature of the 'and' would +require a copy to be inserted (in X86InstrInfo::convertToThreeAddress). + +//===---------------------------------------------------------------------===// + +Consider this: + +typedef struct pair { float A, B; } pair; +void pairtest(pair P, float *FP) { + *FP = P.A+P.B; +} + +We currently generate this code with llvmgcc4: + +_pairtest: + 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: +_pairtest: + movss 4(%esp), %xmm0 + movl 12(%esp), %eax + addss 8(%esp), %xmm0 + movss %xmm0, (%eax) + ret + +The issue is that llvmgcc4 is forcing the struct to memory, then passing it as +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. + +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). + +//===---------------------------------------------------------------------===// + +Another instruction selector deficiency: + +void %bar() { + %tmp = load int (int)** %foo + %tmp = tail call int %tmp( int 3 ) + ret void +} + +_bar: + subl $12, %esp + movl L_foo$non_lazy_ptr, %eax + movl (%eax), %eax + call *%eax + addl $12, %esp + ret + +The current isel scheme will not allow the load to be folded in the call since +the load's chain result is read by the callseq_start. + +//===---------------------------------------------------------------------===// + +Don't forget to find a way to squash noop truncates in the JIT environment. + +//===---------------------------------------------------------------------===// + +Implement anyext in the same manner as truncate that would allow them to be +eliminated. + +//===---------------------------------------------------------------------===// + +How about implementing truncate / anyext as a property of machine instruction +operand? i.e. Print as 32-bit super-class register / 16-bit sub-class register. +Do this for the cases where a truncate / anyext is guaranteed to be eliminated. +For IA32 that is truncate from 32 to 16 and anyext from 16 to 32. + +//===---------------------------------------------------------------------===// + +For this: + +int test(int a) +{ + return a * 3; +} + +We currently emits + imull $3, 4(%esp), %eax + +Perhaps this is what we really should generate is? Is imull three or four +cycles? Note: ICC generates this: + movl 4(%esp), %eax + leal (%eax,%eax,2), %eax + +The current instruction priority is based on pattern complexity. The former is +more "complex" because it folds a load so the latter will not be emitted. + +Perhaps we should use AddedComplexity to give LEA32r a higher priority? We +should always try to match LEA first since the LEA matching code does some +estimate to determine whether the match is profitable. + +However, if we care more about code size, then imull is better. It's two bytes +shorter than movl + leal. + +//===---------------------------------------------------------------------===// + +Implement CTTZ, CTLZ with bsf and bsr. + +//===---------------------------------------------------------------------===// + +It appears gcc place string data with linkonce linkage in +.section __TEXT,__const_coal,coalesced instead of +.section __DATA,__const_coal,coalesced. +Take a look at darwin.h, there are other Darwin assembler directives that we +do not make use of. + +//===---------------------------------------------------------------------===// + +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 +} + +is pessimized by -loop-reduce and -indvars + +//===---------------------------------------------------------------------===// + +u32 to float conversion improvement: + +float uint32_2_float( unsigned u ) { + float fl = (int) (u & 0xffff); + float fh = (int) (u >> 16); + fh *= 0x1.0p16f; + return fh + fl; +} + +00000000 subl $0x04,%esp +00000003 movl 0x08(%esp,1),%eax +00000007 movl %eax,%ecx +00000009 shrl $0x10,%ecx +0000000c cvtsi2ss %ecx,%xmm0 +00000010 andl $0x0000ffff,%eax +00000015 cvtsi2ss %eax,%xmm1 +00000019 mulss 0x00000078,%xmm0 +00000021 addss %xmm1,%xmm0 +00000025 movss %xmm0,(%esp,1) +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 +