~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/hipe/x86/hipe_x86_ra_naive.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%%% -*- erlang-indent-level: 4 -*-
 
2
%%% $Id$
 
3
%%% simple local x86 regalloc
 
4
 
 
5
-ifdef(HIPE_AMD64).
 
6
-define(HIPE_X86_RA_NAIVE, hipe_amd64_ra_naive).
 
7
-define(HIPE_X86_REGISTERS, hipe_amd64_registers).
 
8
-define(HIPE_X86_SPECIFIC_FP, hipe_amd64_specific_sse2).
 
9
-define(ECX, rcx).
 
10
-else.
 
11
-define(HIPE_X86_RA_NAIVE, hipe_x86_ra_naive).
 
12
-define(HIPE_X86_REGISTERS, hipe_x86_registers).
 
13
-define(HIPE_X86_SPECIFIC_FP, hipe_x86_specific_x87).
 
14
-define(ECX, ecx).
 
15
-endif.
 
16
 
 
17
-module(?HIPE_X86_RA_NAIVE).
 
18
-export([ra/3]).
 
19
 
 
20
-include("../x86/hipe_x86.hrl").
 
21
-define(HIPE_INSTRUMENT_COMPILER, true). % enable instrumentation
 
22
-include("../main/hipe.hrl").
 
23
 
 
24
ra(X86Defun, Coloring_fp, Options) ->
 
25
    #defun{code=Code0} = X86Defun,
 
26
    Code1 = do_insns(Code0),
 
27
    NofSpilledFloats = count_non_float_spills(Coloring_fp),
 
28
    NofFloats = length(Coloring_fp),
 
29
    ?add_spills(Options, hipe_gensym:get_var(x86) -
 
30
                ?HIPE_X86_REGISTERS:first_virtual()-
 
31
                NofSpilledFloats -
 
32
                NofFloats),
 
33
    TempMap = [],
 
34
    {X86Defun#defun{code=Code1,
 
35
                    var_range={0, hipe_gensym:get_var(x86)}},
 
36
     TempMap}.
 
37
 
 
38
count_non_float_spills(Coloring_fp)->
 
39
    count_non_float_spills(Coloring_fp,0).
 
40
count_non_float_spills([{_,To}|Tail], Num)->
 
41
    case ?HIPE_X86_SPECIFIC_FP:is_precoloured(To) of
 
42
        true ->
 
43
            count_non_float_spills(Tail, Num);
 
44
        _ ->
 
45
            count_non_float_spills(Tail, Num+1)
 
46
    end;
 
47
count_non_float_spills([],Num) ->
 
48
    Num.
 
49
 
 
50
do_insns([I|Insns]) ->
 
51
    do_insn(I) ++ do_insns(Insns);
 
52
do_insns([]) ->
 
53
    [].
 
54
 
 
55
do_insn(I) ->   % Insn -> Insn list
 
56
    case I of
 
57
        #alu{} ->
 
58
            do_alu(I);
 
59
        #cmp{} ->
 
60
            do_cmp(I);
 
61
        #jmp_switch{} ->
 
62
            do_jmp_switch(I);
 
63
        #lea{} ->
 
64
            do_lea(I);
 
65
        #move{} ->
 
66
            do_move(I);
 
67
        #move64{} ->
 
68
            do_move64(I);
 
69
        #movzx{} ->
 
70
            do_movx(I);
 
71
        #movsx{} ->
 
72
            do_movx(I);
 
73
        #fmove{} ->
 
74
            do_fmove(I);
 
75
        #fp_unop{} ->
 
76
            do_fp_unop(I);
 
77
        #fp_binop{} ->
 
78
            do_fp_binop(I);
 
79
        #shift{} ->
 
80
            do_shift(I);
 
81
        #label{} ->
 
82
            [I];
 
83
        #pseudo_jcc{} ->
 
84
            [I]; 
 
85
        #pseudo_call{} ->
 
86
            [I];
 
87
        #ret{} ->
 
88
            [I];
 
89
        #pseudo_tailcall_prepare{} ->
 
90
            [I];
 
91
        #pseudo_tailcall{} ->      
 
92
            [I];
 
93
        #push{} ->     
 
94
            [I];
 
95
        #jmp_label{} ->     
 
96
            [I];
 
97
        #comment{} ->     
 
98
            [I];
 
99
        _ ->
 
100
            io:format("Unknown Instruction = ~w\n", [I]),
 
101
            exit({?MODULE, unknown_instruction, I})
 
102
    end.
 
103
 
 
104
%%% Fix an alu op.
 
105
 
 
106
do_alu(I) ->
 
107
    #alu{src=Src0,dst=Dst0} = I,
 
108
    {FixSrc,Src,FixDst,Dst} = do_binary(Src0, Dst0),
 
109
    FixSrc ++ FixDst ++ [I#alu{src=Src,dst=Dst}].
 
110
 
 
111
%%% Fix a cmp op.
 
112
 
 
113
do_cmp(I) ->
 
114
    #cmp{src=Src0,dst=Dst0} = I,
 
115
    {FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
 
116
    FixSrc ++ FixDst ++ [I#cmp{src=Src,dst=Dst}].
 
117
 
 
118
%%% Fix a jmp_switch op.
 
119
 
 
120
-ifdef(HIPE_AMD64).
 
121
do_jmp_switch(I) ->
 
122
    #jmp_switch{temp=Temp, jtab=Tab} = I,
 
123
    case temp_is_pseudo(Temp) of
 
124
        false ->
 
125
            case temp_is_pseudo(Tab) of
 
126
                false ->
 
127
                    [I];
 
128
                true ->
 
129
                    Reg = hipe_x86:mk_temp(hipe_amd64_registers:temp0(),
 
130
                                           'untagged'),
 
131
                    [hipe_x86:mk_move(Temp, Reg), I#jmp_switch{jtab=Reg}]
 
132
            end;
 
133
        true ->
 
134
            Reg = hipe_x86:mk_temp(hipe_amd64_registers:temp1(),
 
135
                                   'untagged'),
 
136
            case temp_is_pseudo(Tab) of
 
137
                false ->
 
138
                    [hipe_x86:mk_move(Temp, Reg), I#jmp_switch{temp=Reg}];
 
139
                true ->
 
140
                    Reg2 = hipe_x86:mk_temp(hipe_amd64_registers:temp0(),
 
141
                                            'untagged'),
 
142
                    [hipe_x86:mk_move(Temp, Reg),
 
143
                     hipe_x86:mk_move(Tab, Reg2),
 
144
                     I#jmp_switch{temp=Reg, jtab=Reg2}]
 
145
            end
 
146
    end.
 
147
-else.
 
148
do_jmp_switch(I) ->
 
149
    #jmp_switch{temp=Temp} = I,
 
150
    case temp_is_pseudo(Temp) of
 
151
        false ->
 
152
            [I];
 
153
        true ->
 
154
            Reg = hipe_x86:mk_temp(?HIPE_X86_REGISTERS:temp0(), 'untagged'),
 
155
            [hipe_x86:mk_move(Temp, Reg), I#jmp_switch{temp=Reg}]
 
156
    end.
 
157
-endif.
 
158
 
 
159
%%% Fix a lea op.
 
160
 
 
161
do_lea(I) ->
 
162
    #lea{temp=Temp} = I,
 
163
    case temp_is_pseudo(Temp) of
 
164
        false ->
 
165
            [I];
 
166
        true ->
 
167
            Reg = hipe_x86:mk_temp(?HIPE_X86_REGISTERS:temp0(), 'untagged'),
 
168
            [I#lea{temp=Reg}, hipe_x86:mk_move(Reg, Temp)]
 
169
    end.
 
170
 
 
171
%%% Fix a move op.
 
172
 
 
173
do_move(I) ->
 
174
    #move{src=Src0,dst=Dst0} = I,
 
175
    {FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
 
176
    FixSrc ++ FixDst ++ [I#move{src=Src,dst=Dst}].
 
177
 
 
178
-ifdef(HIPE_AMD64).
 
179
do_move64(I) ->
 
180
    #move64{dst=Dst} = I,
 
181
    case is_mem_opnd(Dst) of
 
182
        false ->
 
183
            [I];
 
184
        true ->     
 
185
            Reg = hipe_amd64_registers:temp1(),
 
186
            NewDst = clone(Dst, Reg),
 
187
            [I#move64{dst=NewDst}, hipe_x86:mk_move(NewDst, Dst)]
 
188
    end.
 
189
-else.
 
190
do_move64(I) -> exit({?MODULE, I}).
 
191
-endif.
 
192
 
 
193
do_movx(I) ->
 
194
    {FixSrc, Src} =
 
195
        case I of
 
196
            #movsx{src=Src0,dst=Dst0} ->
 
197
                fix_src_operand(Src0);
 
198
            #movzx{src=Src0,dst=Dst0} ->
 
199
                fix_src_operand(Src0)
 
200
        end,
 
201
    {FixDst, Dst} = fix_dst_operand(Dst0),
 
202
    Reg = ?HIPE_X86_REGISTERS:temp0(),
 
203
    Dst2 = clone(Dst, Reg),
 
204
    I2 =
 
205
        case is_mem_opnd(Dst) of
 
206
            true ->
 
207
                Reg = ?HIPE_X86_REGISTERS:temp0(),
 
208
                Dst2 = clone(Dst, Reg),
 
209
                case I of
 
210
                    #movsx{} ->
 
211
                        [hipe_x86:mk_movsx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)];
 
212
                    #movzx{} ->
 
213
                        [hipe_x86:mk_movzx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)]
 
214
                end;
 
215
            false ->
 
216
                case I of
 
217
                    #movsx{} ->
 
218
                        [hipe_x86:mk_movsx(Src, Dst)];
 
219
                    #movzx{} ->
 
220
                        [hipe_x86:mk_movzx(Src, Dst)]
 
221
                end
 
222
        end,
 
223
 
 
224
    FixSrc ++ FixDst ++ I2.
 
225
 
 
226
 
 
227
 
 
228
%%% Fix a fmove op.
 
229
%% conv_to_float
 
230
do_fmove(I=#fmove{src=#x86_temp{type=untagged},
 
231
                  dst=#x86_temp{type=double}}) ->
 
232
  #fmove{src=Src0,dst=Dst0} = I,
 
233
  Src = clone(Src0, ?HIPE_X86_REGISTERS:temp0()),
 
234
  Dst = clone(Dst0, ?HIPE_X86_REGISTERS:temp1()),
 
235
  [hipe_x86:mk_move(Src0, Src),
 
236
   I#fmove{src=Src, dst=Dst},
 
237
   hipe_x86:mk_fmove(Dst, Dst0)];
 
238
%% fmove
 
239
do_fmove(I) ->
 
240
    #fmove{src=Src0,dst=Dst0} = I,
 
241
    {FixSrc, Src, FixDst, Dst} = do_binary(Src0, Dst0),
 
242
    FixSrc ++ FixDst ++ [I#fmove{src=Src,dst=Dst}].
 
243
 
 
244
do_fp_unop(I) ->
 
245
    #fp_unop{arg=Arg} = I,
 
246
    case is_mem_opnd(Arg) of
 
247
        false ->
 
248
            [I];
 
249
        true ->
 
250
            Reg = ?HIPE_X86_REGISTERS:temp1(),
 
251
            NewArg = clone(Arg, Reg),
 
252
            [hipe_x86:mk_fmove(Arg, NewArg),
 
253
             I#fp_unop{arg=NewArg},
 
254
             hipe_x86:mk_fmove(NewArg, Arg)]
 
255
    end.
 
256
 
 
257
do_fp_binop(I) ->
 
258
    #fp_binop{src=Src0, dst=Dst0} = I,
 
259
    {FixSrc, Src} = fix_src_operand(Src0),
 
260
    {FixDst, Dst} = fix_dst_operand(Dst0),
 
261
    Reg = ?HIPE_X86_REGISTERS:temp1(),
 
262
    Dst2 = clone(Dst, Reg),
 
263
    FixSrc ++ FixDst ++ [hipe_x86:mk_fmove(Dst, Dst2),
 
264
                         I#fp_binop{src=Src, dst=Dst2},
 
265
                         hipe_x86:mk_fmove(Dst2, Dst)].
 
266
 
 
267
do_shift(I) ->
 
268
    #shift{src=Src0,dst=Dst0} = I,
 
269
    {FixDst, Dst} = fix_dst_operand(Dst0),
 
270
    Reg = ?HIPE_X86_REGISTERS:?ECX(),
 
271
    case Src0 of
 
272
        #x86_imm{} ->
 
273
            FixDst ++ [I#shift{dst=Dst}];
 
274
        #x86_temp{reg=Reg}  ->
 
275
            FixDst ++ [I#shift{dst=Dst}]
 
276
    end.
 
277
 
 
278
%%% Fix the operands of a binary op.
 
279
%%% 1. remove pseudos from any explicit memory operands
 
280
%%% 2. if both operands are (implicit or explicit) memory operands,
 
281
%%%    move src to a reg and use reg as src in the original insn
 
282
 
 
283
do_binary(Src0, Dst0) ->
 
284
    {FixSrc, Src} = fix_src_operand(Src0),
 
285
    {FixDst, Dst} = fix_dst_operand(Dst0),
 
286
    {FixSrc3, Src3} =
 
287
        case is_mem_opnd(Src) of
 
288
            false ->
 
289
                {FixSrc, Src};
 
290
            true ->
 
291
                case is_mem_opnd(Dst) of
 
292
                    false ->
 
293
                        {FixSrc, Src};
 
294
                    true ->
 
295
                        Reg = ?HIPE_X86_REGISTERS:temp0(),
 
296
                        Src2 = clone(Src, Reg),
 
297
                        FixSrc2 = FixSrc ++ [mk_move(Src, Src2)],
 
298
                        {FixSrc2, Src2}
 
299
                end
 
300
        end,
 
301
    {FixSrc3, Src3, FixDst, Dst}.
 
302
 
 
303
%%% Fix any x86_mem operand to not refer to any pseudos.
 
304
%%% The fixup may use additional instructions and registers.
 
305
%%% 'src' operands may clobber '%temp0'.
 
306
%%% 'dst' operands may clobber '%temp1'.
 
307
 
 
308
fix_src_operand(Opnd) ->
 
309
    fix_mem_operand(Opnd, ?HIPE_X86_REGISTERS:temp0()).
 
310
 
 
311
fix_dst_operand(Opnd) ->
 
312
    fix_mem_operand(Opnd, ?HIPE_X86_REGISTERS:temp1()).
 
313
 
 
314
fix_mem_operand(Opnd, Reg) ->   % -> {[fixupcode], newop}
 
315
    case Opnd of
 
316
        #x86_mem{base=Base,off=Off} ->
 
317
            case is_mem_opnd(Base) of
 
318
                false ->
 
319
                    case src_is_pseudo(Off) of
 
320
                        false ->
 
321
                            {[], Opnd};
 
322
                        true ->         % pseudo(reg)
 
323
                            Temp = clone(Off, Reg),
 
324
                            {[hipe_x86:mk_move(Off, Temp)],
 
325
                             Opnd#x86_mem{off=Temp}}
 
326
                    end;
 
327
                true ->
 
328
                    Temp = clone(Base, Reg),
 
329
                    case src_is_pseudo(Off) of
 
330
                        false ->        % imm/reg(pseudo)
 
331
                            {[hipe_x86:mk_move(Base, Temp)],
 
332
                             Opnd#x86_mem{base=Temp}};
 
333
                        true ->         % pseudo1(pseudo0)
 
334
                            {[hipe_x86:mk_move(Base, Temp),
 
335
                              hipe_x86:mk_alu('add', Off, Temp)],
 
336
                             Opnd#x86_mem{base=Temp, off=hipe_x86:mk_imm(0)}}
 
337
                    end
 
338
            end;
 
339
        _ ->
 
340
            {[], Opnd}
 
341
    end.
 
342
 
 
343
%%% Check if an operand denotes a memory cell (mem or pseudo).
 
344
 
 
345
is_mem_opnd(Opnd) ->
 
346
    case Opnd of
 
347
        #x86_mem{} -> true;
 
348
        #x86_temp{} -> temp_is_pseudo(Opnd);
 
349
        _ -> false
 
350
    end.
 
351
 
 
352
%%% Check if an operand is a pseudo-Temp.
 
353
 
 
354
src_is_pseudo(Src) ->
 
355
    case hipe_x86:is_temp(Src) of
 
356
        true -> temp_is_pseudo(Src);
 
357
        false -> false
 
358
    end.
 
359
 
 
360
temp_is_pseudo(Temp) ->
 
361
    not(?HIPE_X86_REGISTERS:is_precoloured(hipe_x86:temp_reg(Temp))).
 
362
 
 
363
%%% Make Reg a clone of Dst (attach Dst's type to Reg).
 
364
 
 
365
clone(Dst, Reg) ->
 
366
    Type =
 
367
        case Dst of
 
368
            #x86_mem{} -> hipe_x86:mem_type(Dst);
 
369
            #x86_temp{} -> hipe_x86:temp_type(Dst)
 
370
        end,
 
371
    hipe_x86:mk_temp(Reg, Type).
 
372
 
 
373
mk_move(Src, Dst=#x86_temp{type=double}) ->
 
374
    hipe_x86:mk_fmove(Src, Dst);
 
375
mk_move(Src, Dst) ->
 
376
    hipe_x86:mk_move(Src, Dst).