1
//===- README_X86_64.txt - Notes for X86-64 code gen ----------------------===//
3
Implement different PIC models? Right now we only support Mac OS X with small
6
//===---------------------------------------------------------------------===//
21
We need to do the tailcall optimization as well.
23
//===---------------------------------------------------------------------===//
25
AMD64 Optimization Manual 8.2 has some nice information about optimizing integer
26
multiplication by a constant. How much of it applies to Intel's X86-64
27
implementation? There are definite trade-offs to consider: latency vs. register
28
pressure vs. code size.
30
//===---------------------------------------------------------------------===//
32
Are we better off using branches instead of cmove to implement FP to
36
ucomiss LC0(%rip), %xmm0
37
cvttss2siq %xmm0, %rdx
39
subss LC0(%rip), %xmm0
40
movabsq $-9223372036854775808, %rax
41
cvttss2siq %xmm0, %rdx
50
movss LCPI1_0(%rip), %xmm1
51
cvttss2siq %xmm0, %rcx
54
cvttss2siq %xmm2, %rax
55
movabsq $-9223372036854775808, %rdx
61
Seems like the jb branch has high likelyhood of being taken. It would have
62
saved a few instructions.
64
//===---------------------------------------------------------------------===//
71
memset(X, b, 2*sizeof(X[0]));
75
movq _b@GOTPCREL(%rip), %rax
85
movq _X@GOTPCREL(%rip), %rdx
91
movq _b@GOTPCREL(%rip), %rax
92
movabsq $72340172838076673, %rdx
95
movq _X@GOTPCREL(%rip), %rdx
99
//===---------------------------------------------------------------------===//
101
Vararg function prologue can be further optimized. Currently all XMM registers
102
are stored into register save area. Most of them can be eliminated since the
103
upper bound of the number of XMM registers used are passed in %al. gcc produces
104
something like the following:
107
leaq 0(,%rdx,4), %rax
108
leaq 4+L2(%rip), %rdx
111
movaps %xmm7, -15(%rax)
112
movaps %xmm6, -31(%rax)
113
movaps %xmm5, -47(%rax)
114
movaps %xmm4, -63(%rax)
115
movaps %xmm3, -79(%rax)
116
movaps %xmm2, -95(%rax)
117
movaps %xmm1, -111(%rax)
118
movaps %xmm0, -127(%rax)
121
It jumps over the movaps that do not need to be stored. Hard to see this being
122
significant as it added 5 instruciton (including a indirect branch) to avoid
123
executing 0 to 8 stores in the function prologue.
125
Perhaps we can optimize for the common case where no XMM registers are used for
126
parameter passing. i.e. is %al == 0 jump over all stores. Or in the case of a
127
leaf function where we can determine that no XMM input parameter is need, avoid
128
emitting the stores at all.
130
//===---------------------------------------------------------------------===//
132
AMD64 has a complex calling convention for aggregate passing by value:
134
1. If the size of an object is larger than two eightbytes, or in C++, is a non-
135
POD structure or union type, or contains unaligned fields, it has class
137
2. Both eightbytes get initialized to class NO_CLASS.
138
3. Each field of an object is classified recursively so that always two fields
139
are considered. The resulting class is calculated according to the classes
140
of the fields in the eightbyte:
141
(a) If both classes are equal, this is the resulting class.
142
(b) If one of the classes is NO_CLASS, the resulting class is the other
144
(c) If one of the classes is MEMORY, the result is the MEMORY class.
145
(d) If one of the classes is INTEGER, the result is the INTEGER.
146
(e) If one of the classes is X87, X87UP, COMPLEX_X87 class, MEMORY is used as
148
(f) Otherwise class SSE is used.
149
4. Then a post merger cleanup is done:
150
(a) If one of the classes is MEMORY, the whole argument is passed in memory.
151
(b) If SSEUP is not preceeded by SSE, it is converted to SSE.
153
Currently llvm frontend does not handle this correctly.
156
typedef struct { int i; double d; } QuadWordS;
157
It is currently passed in two i64 integer registers. However, gcc compiled
158
callee expects the second element 'd' to be passed in XMM0.
161
typedef struct { int32_t i; float j; double d; } QuadWordS;
162
The size of the first two fields == i64 so they will be combined and passed in
163
a integer register RDI. The third field is still passed in XMM0.
166
typedef struct { int64_t i; int8_t j; int64_t d; } S;
168
The size of this aggregate is greater than two i64 so it should be passed in
169
memory. Currently llvm breaks this down and passed it in three integer
173
Taking problem 3 one step ahead where a function expects a aggregate value
174
in memory followed by more parameter(s) passed in register(s).
175
void test(S s, int b)
177
LLVM IR does not allow parameter passing by aggregates, therefore it must break
178
the aggregates value (in problem 3 and 4) into a number of scalar values:
179
void %test(long %s.i, byte %s.j, long %s.d);
181
However, if the backend were to lower this code literally it would pass the 3
182
values in integer registers. To force it be passed in memory, the frontend
183
should change the function signiture to:
184
void %test(long %undef1, long %undef2, long %undef3, long %undef4,
185
long %undef5, long %undef6,
186
long %s.i, byte %s.j, long %s.d);
187
And the callee would look something like this:
188
call void %test( undef, undef, undef, undef, undef, undef,
189
%tmp.s.i, %tmp.s.j, %tmp.s.d );
190
The first 6 undef parameters would exhaust the 6 integer registers used for
191
parameter passing. The following three integer values would then be forced into
194
For problem 4, the parameter 'd' would be moved to the front of the parameter
195
list so it will be passed in register:
197
long %undef1, long %undef2, long %undef3, long %undef4,
198
long %undef5, long %undef6,
199
long %s.i, byte %s.j, long %s.d);
201
//===---------------------------------------------------------------------===//
203
Right now the asm printer assumes GlobalAddress are accessed via RIP relative
204
addressing. Therefore, it is not possible to generate this:
205
movabsq $__ZTV10polynomialIdE+16, %rax
207
That is ok for now since we currently only support small model. So the above
209
leaq __ZTV10polynomialIdE+16(%rip), %rax
211
This is probably slightly slower but is much shorter than movabsq. However, if
212
we were to support medium or larger code models, we need to use the movabs
213
instruction. We should probably introduce something like AbsoluteAddress to
214
distinguish it from GlobalAddress so the asm printer and JIT code emitter can
217
//===---------------------------------------------------------------------===//
219
It's not possible to reference AH, BH, CH, and DH registers in an instruction
220
requiring REX prefix. However, divb and mulb both produce results in AH. If isel
221
emits a CopyFromReg which gets turned into a movb and that can be allocated a
224
To get around this, isel emits a CopyFromReg from AX and then right shift it
225
down by 8 and truncate it. It's not pretty but it works. We need some register
226
allocation magic to make the hack go away (e.g. putting additional constraints
227
on the result of the movb).
229
//===---------------------------------------------------------------------===//
231
The x86-64 ABI for hidden-argument struct returns requires that the
232
incoming value of %rdi be copied into %rax by the callee upon return.
234
The idea is that it saves callers from having to remember this value,
235
which would often require a callee-saved register. Callees usually
236
need to keep this value live for most of their body anyway, so it
237
doesn't add a significant burden on them.
239
We currently implement this in codegen, however this is suboptimal
240
because it means that it would be quite awkward to implement the
241
optimization for callers.
243
A better implementation would be to relax the LLVM IR rules for sret
244
arguments to allow a function with an sret argument to have a non-void
245
return type, and to have the front-end to set up the sret argument value
246
as the return value of the function. The front-end could more easily
247
emit uses of the returned struct value to be in terms of the function's
248
lowered return value, and it would free non-C frontends from a
249
complication only required by a C-based ABI.
251
//===---------------------------------------------------------------------===//
253
We get a redundant zero extension for code like this:
256
int foo(unsigned x) {
269
imull $78, %edi, %eax
271
movl %eax, %eax <----
272
movq _mask@GOTPCREL(%rip), %rcx
273
movl (%rcx,%rax,4), %eax
276
imull $45, %edi, %eax
279
Before regalloc, we have:
281
%reg1025<def> = IMUL32rri8 %reg1024, 45, %EFLAGS<imp-def>
282
JMP mbb<bb2,0x203afb0>
283
Successors according to CFG: 0x203afb0 (#3)
285
bb1: 0x203af60, LLVM BB @0x1e02310, ID#2:
286
Predecessors according to CFG: 0x203aec0 (#0)
287
%reg1026<def> = IMUL32rri8 %reg1024, 78, %EFLAGS<imp-def>
288
Successors according to CFG: 0x203afb0 (#3)
290
bb2: 0x203afb0, LLVM BB @0x1e02340, ID#3:
291
Predecessors according to CFG: 0x203af10 (#1) 0x203af60 (#2)
292
%reg1027<def> = PHI %reg1025, mbb<bb,0x203af10>,
293
%reg1026, mbb<bb1,0x203af60>
294
%reg1029<def> = MOVZX64rr32 %reg1027
296
so we'd have to know that IMUL32rri8 leaves the high word zero extended and to
297
be able to recognize the zero extend. This could also presumably be implemented
298
if we have whole-function selectiondags.
300
//===---------------------------------------------------------------------===//