... which should only be one imul instruction.
+This can be done with a custom expander, but it would be nice to move this to
+generic code.
+
//===---------------------------------------------------------------------===//
This should be one DIV/IDIV instruction, not a libcall:
This can be done trivially with a custom legalizer. What about overflow
though? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
-//===---------------------------------------------------------------------===//
-
-Some targets (e.g. athlons) prefer freep to fstp ST(0):
-http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00659.html
-
-//===---------------------------------------------------------------------===//
-
-This should use fiadd on chips where it is profitable:
-double foo(double P, int *I) { return P+*I; }
-
-//===---------------------------------------------------------------------===//
-
-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
-
-Ideas:
-http://gcc.gnu.org/ml/gcc-patches/2004-11/msg02410.html
-
-
//===---------------------------------------------------------------------===//
Improvements to the multiply -> shift/add algorithm:
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:
//===---------------------------------------------------------------------===//
-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); }
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.
//===---------------------------------------------------------------------===//
//===---------------------------------------------------------------------===//
-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
+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
+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.
//===---------------------------------------------------------------------===//
-Combine: a = sin(x), b = cos(x) into a,b = sincos(x).
+How about intrinsics? An example is:
+ *res = _mm_mulhi_epu16(*A, _mm_mul_epu32(*B, *C));
-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);
+compiles to
+ pmuludq (%eax), %xmm0
+ movl 8(%esp), %eax
+ movdqa (%eax), %xmm1
+ pmulhuw %xmm0, %xmm1
-Doing so could allow SROA of the destination pointers. See also:
-http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17687
+The transformation probably requires a X86 specific pass or a DAG combiner
+target specific hook.
//===---------------------------------------------------------------------===//
-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
-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.
+In many cases, LLVM generates code like this:
-//===---------------------------------------------------------------------===//
+_test:
+ movl 8(%esp), %eax
+ cmpl %eax, 4(%esp)
+ setl %al
+ movzbl %al, %eax
+ ret
-LSR should be turned on for the X86 backend and tuned to take advantage of its
-addressing modes.
+on some processors (which ones?), it is more efficient to do this:
-//===---------------------------------------------------------------------===//
+_test:
+ movl 8(%esp), %ebx
+ xor %eax, %eax
+ cmpl %ebx, 4(%esp)
+ setl %al
+ ret
-When compiled with unsafemath enabled, "main" should enable SSE DAZ mode and
-other fast SSE modes.
+Doing this correctly is tricky though, as the xor clobbers the flags.
//===---------------------------------------------------------------------===//
-Think about doing i64 math in SSE regs.
+We should generate bts/btr/etc instructions on targets where they are cheap or
+when codesize is important. e.g., for:
+
+void setbit(int *target, int bit) {
+ *target |= (1 << bit);
+}
+void clearbit(int *target, int bit) {
+ *target &= ~(1 << bit);
+}
//===---------------------------------------------------------------------===//
-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.
+Instead of the following for memset char*, 1, 10:
-.ll:
+ movl $16843009, 4(%edx)
+ movl $16843009, (%edx)
+ movw $257, 8(%edx)
-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
-}
+It might be better to generate
-dag isel:
+ movl $16843009, %eax
+ movl %eax, 4(%edx)
+ movl %eax, (%edx)
+ movw al, 8(%edx)
+
+when we can spare a register. It reduces code size.
-_test:
+//===---------------------------------------------------------------------===//
+
+Evaluate what the best way to codegen sdiv X, (2^C) is. For X/8, we currently
+get this:
+
+int %test1(int %X) {
+ %Y = div int %X, 8
+ ret int %Y
+}
+
+_test1:
movl 4(%esp), %eax
- movl (%eax), %eax
- movl 8(%esp), %ecx
- movl (%ecx), %ecx
- addl %ecx, %eax
- movl 12(%esp), %ecx
- movl (%ecx), %ecx
+ movl %eax, %ecx
+ sarl $31, %ecx
+ shrl $29, %ecx
addl %ecx, %eax
+ sarl $3, %eax
ret
-pattern isel:
+GCC knows several different ways to codegen it, one of which is this:
-_test:
- movl 12(%esp), %ecx
- movl 4(%esp), %edx
- movl 8(%esp), %eax
- movl (%eax), %eax
- addl (%edx), %eax
- addl (%ecx), %eax
+_test1:
+ movl 4(%esp), %eax
+ cmpl $-1, %eax
+ leal 7(%eax), %ecx
+ cmovle %ecx, %eax
+ sarl $3, %eax
ret
-This is bad for register pressure, though the dag isel is producing a
-better schedule. :)
+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?
//===---------------------------------------------------------------------===//
-This testcase should have no SSE instructions in it, and only one load from
-a constant pool:
+The first BB of this code:
-double %test3(bool %B) {
- %C = select bool %B, double 123.412, double 523.01123123
- ret double %C
+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
}
-Currently, the select is being lowered, which prevents the dag combiner from
-turning 'select (load CPI1), (load CPI2)' -> 'load (select CPI1, CPI2)'
+compiles to:
-The pattern isel got this one right.
+_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.
+
+//===---------------------------------------------------------------------===//
+
+Enable X86InstrInfo::convertToThreeAddress().
//===---------------------------------------------------------------------===//
-We need to lower switch statements to tablejumps when appropriate instead of
-always into binary branch trees.
+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
+stores, TLB preheating, etc)
//===---------------------------------------------------------------------===//
-SSE doesn't have [mem] op= reg instructions. If we have an SSE instruction
-like this:
+Optimize this into something reasonable:
+ x * copysign(1.0, y) * copysign(1.0, z)
- X += y
+//===---------------------------------------------------------------------===//
-and the register allocator decides to spill X, it is cheaper to emit this as:
+Optimize copysign(x, *y) to use an integer load from y.
-Y += [xslot]
-store Y -> [xslot]
+//===---------------------------------------------------------------------===//
-than as:
+%X = weak global int 0
-tmp = [xslot]
-tmp += y
-store tmp -> [xslot]
+void %foo(int %N) {
+ %N = cast int %N to uint
+ %tmp.24 = setgt int %N, 0
+ br bool %tmp.24, label %no_exit, label %return
-..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:
+no_exit:
+ %indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ]
+ %i.0.0 = cast uint %indvar to int
+ volatile store int %i.0.0, int* %X
+ %indvar.next = add uint %indvar, 1
+ %exitcond = seteq uint %indvar.next, %N
+ br bool %exitcond, label %return, label %no_exit
-%.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 ] ; <double> [#uses=1]
- %tmp.0.0.0.i10 = phi double [ 0.000000e+00, %build_tree.exit ], [ %tmp.28.i16, %no_exit.i7 ] ; <double> [#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
+return:
+ ret void
}
-We currently emit:
+compiles into:
-.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
+ .text
+ .align 4
+ .globl _foo
+_foo:
+ movl 4(%esp), %eax
+ cmpl $1, %eax
+ jl LBB_foo_4 # return
+LBB_foo_1: # no_exit.preheader
+ xorl %ecx, %ecx
+LBB_foo_2: # no_exit
+ movl L_X$non_lazy_ptr, %edx
+ movl %ecx, (%edx)
+ incl %ecx
+ cmpl %eax, %ecx
+ jne LBB_foo_2 # no_exit
+LBB_foo_3: # return.loopexit
+LBB_foo_4: # return
+ ret
-This is a bugpoint reduced testcase, which is why the testcase doesn't make
-much sense (e.g. its an infinite loop). :)
+We should hoist "movl L_X$non_lazy_ptr, %edx" out of the loop after
+remateralization is implemented. This can be accomplished with 1) a target
+dependent LICM pass or 2) makeing SelectDAG represent the whole function.
//===---------------------------------------------------------------------===//
-None of the FPStack instructions are handled in
-X86RegisterInfo::foldMemoryOperand, which prevents the spiller from
-folding spill code into the instructions.
+The following tests perform worse with LSR:
+
+lambda, siod, optimizer-eval, ackermann, hash2, nestedloop, strcat, and Treesor.
//===---------------------------------------------------------------------===//
-In many cases, LLVM generates code like this:
+Teach the coalescer to coalesce vregs of different register classes. e.g. FR32 /
+FR64 to VR128.
-_test:
- movl 8(%esp), %eax
- cmpl %eax, 4(%esp)
- setl %al
- movzbl %al, %eax
- ret
+//===---------------------------------------------------------------------===//
-on some processors (which ones?), it is more efficient to do this:
+mov $reg, 48(%esp)
+...
+leal 48(%esp), %eax
+mov %eax, (%esp)
+call _foo
+
+Obviously it would have been better for the first mov (or any op) to store
+directly %esp[0] if there are no other uses.
+
+//===---------------------------------------------------------------------===//
+
+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), %ebx
- xor %eax, %eax
- cmpl %ebx, 4(%esp)
- setl %al
- ret
+ 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
-Doing this correctly is tricky though, as the xor clobbers the flags.
+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 should generate 'test' instead of 'cmp' in various cases, e.g.:
+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
-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
-}
+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
-This may just be a matter of using 'test' to write bigger patterns for X86cmp.
+The former can also be used when the two-addressy nature of the 'and' would
+require a copy to be inserted (in X86InstrInfo::convertToThreeAddress).
//===---------------------------------------------------------------------===//
-SSE should implement 'select_cc' using 'emulated conditional moves' that use
-pcmp/pand/pandn/por to do a selection instead of a conditional branch:
+Bad codegen:
-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
+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;
+void pairtest(pair P, float *FP) {
+ *FP = P.A+P.B;
}
-We currently emit:
+We currently generate this code with llvmgcc4:
-_X:
+_pairtest:
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)
+ 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
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.
+
//===---------------------------------------------------------------------===//
-The x86 backend currently supports dynamic-no-pic. Need to add asm
-printer support for static and PIC.
+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.
//===---------------------------------------------------------------------===//
-We should generate bts/btr/etc instructions on targets where they are cheap or
-when codesize is important. e.g., for:
+Don't forget to find a way to squash noop truncates in the JIT environment.
-void setbit(int *target, int bit) {
- *target |= (1 << bit);
+//===---------------------------------------------------------------------===//
+
+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;
}
-void clearbit(int *target, int bit) {
- *target &= ~(1 << bit);
+
+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.
+
+//===---------------------------------------------------------------------===//
+
+We should handle __attribute__ ((__visibility__ ("hidden"))).
+
+//===---------------------------------------------------------------------===//
+
+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 ; <int> [#uses=1]
+ %tmp5 = add int %t_addr.0.0, %x.0.0 ; <int> [#uses=1]
+ %tmp7 = add int %tmp5, %tmp3 ; <int> [#uses=2]
+ %tmp9 = add int %x.0.0, 1 ; <int> [#uses=2]
+ %tmp = setgt int %tmp9, 39 ; <bool> [#uses=1]
+ br bool %tmp, label %bb12, label %cond_true
+
+bb12: ; preds = %cond_true
+ ret int %tmp7
}
+is pessimized by -loop-reduce and -indvars
+
//===---------------------------------------------------------------------===//
-Easy: Global addresses are not always allowed as immediates. For this:
+u32 to float conversion improvement:
-int dst = 0; int *ptr = 0;
-void foo() { ptr = &dst; }
+float uint32_2_float( unsigned u ) {
+ float fl = (int) (u & 0xffff);
+ float fh = (int) (u >> 16);
+ fh *= 0x1.0p16f;
+ return fh + fl;
+}
-we get this:
+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
-_foo:
- movl $_dst, %eax
- movl %eax, _ptr
+//===---------------------------------------------------------------------===//
+
+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
-When: "movl $_dst, _ptr" is sufficient.
+it could be:
+_f:
+ movl 4(%esp), %eax
+ sarl $31, %eax
+ notl %eax
+ addl $14, %eax
+ movl %eax, _G
+ ret
+
+etc.
//===---------------------------------------------------------------------===//
-Use fisttp to do FP to integer conversion whenever it is available.
+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.
//===---------------------------------------------------------------------===//
-Instead of the following for memset char*, 1, 10:
+We generate really bad code in some cases due to lowering SETCC/SELECT at
+legalize time, which prevents the post-legalize dag combine pass from
+understanding the code. As a silly example, this prevents us from folding
+stuff like this:
- movl $16843009, 4(%edx)
- movl $16843009, (%edx)
- movw $257, 8(%edx)
+bool %test(ulong %x) {
+ %tmp = setlt ulong %x, 4294967296
+ ret bool %tmp
+}
-It might be better to generate
+into x.h == 0
- movl $16843009, %eax
- movl %eax, 4(%edx)
- movl %eax, (%edx)
- movw al, 8(%edx)
-
-when we can spare a register. It reduces code size.
+//===---------------------------------------------------------------------===//
+
+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
//===---------------------------------------------------------------------===//
-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.
+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?
+