Fixed some bugs.
[llvm/zpu.git] / lib / Target / X86 / README-X86-64.txt
blob78c4dc00ee729047167991aff50435e8fb94ff41
1 //===- README_X86_64.txt - Notes for X86-64 code gen ----------------------===//
3 AMD64 Optimization Manual 8.2 has some nice information about optimizing integer
4 multiplication by a constant. How much of it applies to Intel's X86-64
5 implementation? There are definite trade-offs to consider: latency vs. register
6 pressure vs. code size.
8 //===---------------------------------------------------------------------===//
10 Are we better off using branches instead of cmove to implement FP to
11 unsigned i64?
13 _conv:
14         ucomiss LC0(%rip), %xmm0
15         cvttss2siq      %xmm0, %rdx
16         jb      L3
17         subss   LC0(%rip), %xmm0
18         movabsq $-9223372036854775808, %rax
19         cvttss2siq      %xmm0, %rdx
20         xorq    %rax, %rdx
21 L3:
22         movq    %rdx, %rax
23         ret
25 instead of
27 _conv:
28         movss LCPI1_0(%rip), %xmm1
29         cvttss2siq %xmm0, %rcx
30         movaps %xmm0, %xmm2
31         subss %xmm1, %xmm2
32         cvttss2siq %xmm2, %rax
33         movabsq $-9223372036854775808, %rdx
34         xorq %rdx, %rax
35         ucomiss %xmm1, %xmm0
36         cmovb %rcx, %rax
37         ret
39 Seems like the jb branch has high likelyhood of being taken. It would have
40 saved a few instructions.
42 //===---------------------------------------------------------------------===//
44 Poor codegen:
46 int X[2];
47 int b;
48 void test(void) {
49   memset(X, b, 2*sizeof(X[0]));
52 llc:
53         movq _b@GOTPCREL(%rip), %rax
54         movzbq (%rax), %rax
55         movq %rax, %rcx
56         shlq $8, %rcx
57         orq %rax, %rcx
58         movq %rcx, %rax
59         shlq $16, %rax
60         orq %rcx, %rax
61         movq %rax, %rcx
62         shlq $32, %rcx
63         movq _X@GOTPCREL(%rip), %rdx
64         orq %rax, %rcx
65         movq %rcx, (%rdx)
66         ret
68 gcc:
69         movq    _b@GOTPCREL(%rip), %rax
70         movabsq $72340172838076673, %rdx
71         movzbq  (%rax), %rax
72         imulq   %rdx, %rax
73         movq    _X@GOTPCREL(%rip), %rdx
74         movq    %rax, (%rdx)
75         ret
77 And the codegen is even worse for the following
78 (from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33103):
79   void fill1(char *s, int a)
80   {
81     __builtin_memset(s, a, 15);
82   }
84 For this version, we duplicate the computation of the constant to store.
86 //===---------------------------------------------------------------------===//
88 It's not possible to reference AH, BH, CH, and DH registers in an instruction
89 requiring REX prefix. However, divb and mulb both produce results in AH. If isel
90 emits a CopyFromReg which gets turned into a movb and that can be allocated a
91 r8b - r15b.
93 To get around this, isel emits a CopyFromReg from AX and then right shift it
94 down by 8 and truncate it. It's not pretty but it works. We need some register
95 allocation magic to make the hack go away (e.g. putting additional constraints
96 on the result of the movb).
98 //===---------------------------------------------------------------------===//
100 The x86-64 ABI for hidden-argument struct returns requires that the
101 incoming value of %rdi be copied into %rax by the callee upon return.
103 The idea is that it saves callers from having to remember this value,
104 which would often require a callee-saved register. Callees usually
105 need to keep this value live for most of their body anyway, so it
106 doesn't add a significant burden on them.
108 We currently implement this in codegen, however this is suboptimal
109 because it means that it would be quite awkward to implement the
110 optimization for callers.
112 A better implementation would be to relax the LLVM IR rules for sret
113 arguments to allow a function with an sret argument to have a non-void
114 return type, and to have the front-end to set up the sret argument value
115 as the return value of the function. The front-end could more easily
116 emit uses of the returned struct value to be in terms of the function's
117 lowered return value, and it would free non-C frontends from a
118 complication only required by a C-based ABI.
120 //===---------------------------------------------------------------------===//
122 We get a redundant zero extension for code like this:
124 int mask[1000];
125 int foo(unsigned x) {
126  if (x < 10)
127    x = x * 45;
128  else
129    x = x * 78;
130  return mask[x];
133 _foo:
134 LBB1_0: ## entry
135         cmpl    $9, %edi
136         jbe     LBB1_3  ## bb
137 LBB1_1: ## bb1
138         imull   $78, %edi, %eax
139 LBB1_2: ## bb2
140         movl    %eax, %eax                    <----
141         movq    _mask@GOTPCREL(%rip), %rcx
142         movl    (%rcx,%rax,4), %eax
143         ret
144 LBB1_3: ## bb
145         imull   $45, %edi, %eax
146         jmp     LBB1_2  ## bb2
147   
148 Before regalloc, we have:
150         %reg1025<def> = IMUL32rri8 %reg1024, 45, %EFLAGS<imp-def>
151         JMP mbb<bb2,0x203afb0>
152     Successors according to CFG: 0x203afb0 (#3)
154 bb1: 0x203af60, LLVM BB @0x1e02310, ID#2:
155     Predecessors according to CFG: 0x203aec0 (#0)
156         %reg1026<def> = IMUL32rri8 %reg1024, 78, %EFLAGS<imp-def>
157     Successors according to CFG: 0x203afb0 (#3)
159 bb2: 0x203afb0, LLVM BB @0x1e02340, ID#3:
160     Predecessors according to CFG: 0x203af10 (#1) 0x203af60 (#2)
161         %reg1027<def> = PHI %reg1025, mbb<bb,0x203af10>,
162                             %reg1026, mbb<bb1,0x203af60>
163         %reg1029<def> = MOVZX64rr32 %reg1027
165 so we'd have to know that IMUL32rri8 leaves the high word zero extended and to
166 be able to recognize the zero extend.  This could also presumably be implemented
167 if we have whole-function selectiondags.
169 //===---------------------------------------------------------------------===//
171 Take the following C code
172 (from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43640):
174 struct u1
176         float x;
177         float y;
180 float foo(struct u1 u)
182         return u.x + u.y;
185 Optimizes to the following IR:
186 define float @foo(double %u.0) nounwind readnone {
187 entry:
188   %tmp8 = bitcast double %u.0 to i64              ; <i64> [#uses=2]
189   %tmp6 = trunc i64 %tmp8 to i32                  ; <i32> [#uses=1]
190   %tmp7 = bitcast i32 %tmp6 to float              ; <float> [#uses=1]
191   %tmp2 = lshr i64 %tmp8, 32                      ; <i64> [#uses=1]
192   %tmp3 = trunc i64 %tmp2 to i32                  ; <i32> [#uses=1]
193   %tmp4 = bitcast i32 %tmp3 to float              ; <float> [#uses=1]
194   %0 = fadd float %tmp7, %tmp4                    ; <float> [#uses=1]
195   ret float %0
198 And current llvm-gcc/clang output:
199         movd    %xmm0, %rax
200         movd    %eax, %xmm1
201         shrq    $32, %rax
202         movd    %eax, %xmm0
203         addss   %xmm1, %xmm0
204         ret
206 We really shouldn't move the floats to RAX, only to immediately move them
207 straight back to the XMM registers.
209 There really isn't any good way to handle this purely in IR optimizers; it
210 could possibly be handled by changing the output of the fronted, though.  It
211 would also be feasible to add a x86-specific DAGCombine to optimize the
212 bitcast+trunc+(lshr+)bitcast combination.
214 //===---------------------------------------------------------------------===//
216 Take the following code
217 (from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34653):
218 extern unsigned long table[];
219 unsigned long foo(unsigned char *p) {
220   unsigned long tag = *p;
221   return table[tag >> 4] + table[tag & 0xf];
224 Current code generated:
225         movzbl  (%rdi), %eax
226         movq    %rax, %rcx
227         andq    $240, %rcx
228         shrq    %rcx
229         andq    $15, %rax
230         movq    table(,%rax,8), %rax
231         addq    table(%rcx), %rax
232         ret
234 Issues:
235 1. First movq should be movl; saves a byte.
236 2. Both andq's should be andl; saves another two bytes.  I think this was
237    implemented at one point, but subsequently regressed.
238 3. shrq should be shrl; saves another byte.
239 4. The first andq can be completely eliminated by using a slightly more
240    expensive addressing mode.
242 //===---------------------------------------------------------------------===//
244 Consider the following (contrived testcase, but contains common factors):
246 #include <stdarg.h>
247 int test(int x, ...) {
248   int sum, i;
249   va_list l;
250   va_start(l, x);
251   for (i = 0; i < x; i++)
252     sum += va_arg(l, int);
253   va_end(l);
254   return sum;
257 Testcase given in C because fixing it will likely involve changing the IR
258 generated for it.  The primary issue with the result is that it doesn't do any
259 of the optimizations which are possible if we know the address of a va_list
260 in the current function is never taken:
261 1. We shouldn't spill the XMM registers because we only call va_arg with "int".
262 2. It would be nice if we could scalarrepl the va_list.
263 3. Probably overkill, but it'd be cool if we could peel off the first five
264 iterations of the loop.
266 Other optimizations involving functions which use va_arg on floats which don't
267 have the address of a va_list taken:
268 1. Conversely to the above, we shouldn't spill general registers if we only
269    call va_arg on "double".
270 2. If we know nothing more than 64 bits wide is read from the XMM registers,
271    we can change the spilling code to reduce the amount of stack used by half.
273 //===---------------------------------------------------------------------===//