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

« back to all changes in this revision

Viewing changes to lib/hipe/x86/hipe_x86_ra_ls_postconditions.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
 
%% ====================================================================
2
 
%%  Filename :  hipe_x86_ra_ls_postconditions.erl
3
 
%%  Module   :  hipe_x86_ra_ls_postconditions
4
 
%%  Purpose  :  
5
 
%%  Notes    : 
6
 
%%  History  :  * 2001-07-24 Erik Johansson (happi@csd.uu.se): 
7
 
%%               Created.
8
 
%%  CVS      :
9
 
%%              $Author: pergu $
10
 
%%              $Date: 2003/04/10 15:40:39 $
11
 
%%              $Revision: 1.8 $
12
 
%% ====================================================================
13
 
%%  Exports  :
14
 
%%
15
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16
 
 
17
 
-module(hipe_x86_ra_ls_postconditions).
18
 
-export([check_and_rewrite/4]).
19
 
-include("hipe_x86.hrl").
20
 
-define(HIPE_INSTRUMENT_COMPILER, true).
21
 
-include("../main/hipe.hrl").
22
 
-define(count_temp(T), ?cons_counter(counter_mfa_mem_temps, T)).
23
 
 
24
 
 
25
 
check_and_rewrite(X86Defun, Coloring, DontSpill, _Options) ->  
26
 
  %% io:format("Converting\n"),
27
 
  TempMap = hipe_temp_map:cols2tuple(Coloring,hipe_x86_specific),
28
 
  %% io:format("Rewriting\n"),
29
 
  #defun{code=Code0} = X86Defun,
30
 
  {Code1, NewDontSpill} = do_insns(Code0, TempMap, [], DontSpill),
31
 
  {X86Defun#defun{code=Code1,
32
 
                  var_range={0, hipe_gensym:get_var()}}, 
33
 
   Coloring, NewDontSpill}.
34
 
 
35
 
do_insns([I|Insns], TempMap, Is, DontSpill) ->
36
 
  {NewIs, NewDontSpill} = do_insns(Insns, TempMap, Is, DontSpill),
37
 
  {NewI, FinalDontSpill} = do_insn(I, TempMap, NewDontSpill),
38
 
  {NewI ++ NewIs, FinalDontSpill};
39
 
do_insns([],_, Is, DontSpill) ->
40
 
  {Is, DontSpill}.
41
 
 
42
 
do_insn(I, TempMap, DontSpill) ->       % Insn -> Insn list
43
 
  case I of
44
 
    #alu{} ->
45
 
      do_alu(I, TempMap, DontSpill);
46
 
    #cmp{} ->
47
 
      do_cmp(I, TempMap, DontSpill);
48
 
    #jmp_switch{} ->
49
 
      do_jmp_switch(I, TempMap, DontSpill);
50
 
    #lea{} ->
51
 
      do_lea(I, TempMap, DontSpill);
52
 
    #move{} ->
53
 
      do_move(I, TempMap, DontSpill);
54
 
    #movsx{} ->
55
 
      do_movx(I, TempMap, DontSpill);
56
 
    #movzx{} ->
57
 
      do_movx(I, TempMap, DontSpill);
58
 
    #fmov{} ->
59
 
      do_fmov(I, TempMap, DontSpill);
60
 
    #shift{} ->
61
 
      do_shift(I, TempMap, DontSpill);
62
 
    _ ->
63
 
      %% comment, jmp*, label, pseudo_call, pseudo_jcc, pseudo_tailcall,
64
 
      %% pseudo_tailcall_prepare, push, ret
65
 
      {[I], DontSpill}
66
 
  end.
67
 
 
68
 
%%% Fix an alu op.
69
 
 
70
 
do_alu(I, TempMap, DontSpill) ->
71
 
  #alu{src=Src0,dst=Dst0} = I,
72
 
  {FixSrc,Src,FixDst,Dst, NewDontSpill} = 
73
 
    do_binary(Src0, Dst0, TempMap, DontSpill),
74
 
  {FixSrc ++ FixDst ++ [I#alu{src=Src,dst=Dst}], NewDontSpill}.
75
 
 
76
 
 
77
 
%%% Fix a cmp op.
78
 
 
79
 
do_cmp(I, TempMap, DontSpill) ->
80
 
  #cmp{src=Src0,dst=Dst0} = I,
81
 
  {FixSrc, Src, FixDst, Dst, NewDontSpill} = 
82
 
    do_binary(Src0, Dst0, TempMap, DontSpill),
83
 
  {FixSrc ++ FixDst ++ [I#cmp{src=Src,dst=Dst}], NewDontSpill}.
84
 
 
85
 
%%% Fix a jmp_switch op.
86
 
 
87
 
do_jmp_switch(I, TempMap, DontSpill) ->
88
 
  #jmp_switch{temp=Temp} = I,
89
 
  case is_spilled(Temp, TempMap) of
90
 
    false ->
91
 
      {[I], DontSpill};
92
 
    true ->
93
 
 
94
 
      NewTmp = spill_temp('untagged'),
95
 
 
96
 
      {[hipe_x86:mk_move(Temp, NewTmp), I#jmp_switch{temp=NewTmp}],
97
 
       [NewTmp|DontSpill]}
98
 
  end.
99
 
 
100
 
%%% Fix a lea op.
101
 
 
102
 
do_lea(I, TempMap, DontSpill) ->
103
 
  #lea{temp=Temp} = I,
104
 
  case is_spilled(Temp, TempMap) of
105
 
    false ->
106
 
      {[I], DontSpill};
107
 
    true ->
108
 
      NewTmp = spill_temp('untagged'),
109
 
      {[I#lea{temp=NewTmp}, hipe_x86:mk_move(NewTmp, Temp)],
110
 
       [NewTmp| DontSpill]}
111
 
  end.
112
 
 
113
 
%%% Fix a move op.
114
 
 
115
 
do_move(I, TempMap, DontSpill) ->
116
 
  #move{src=Src0,dst=Dst0} = I,
117
 
  {FixSrc, Src, FixDst, Dst, NewDontSpill} = 
118
 
    case Dst0 of
119
 
      #x86_mem{type=byte} ->
120
 
        do_byte_move(Src0, Dst0,
121
 
                     TempMap, DontSpill);
122
 
      _ ->
123
 
        do_binary(Src0, Dst0,
124
 
                  TempMap, DontSpill)
125
 
    end,
126
 
  {FixSrc ++ FixDst ++ [I#move{src=Src,dst=Dst}],
127
 
   NewDontSpill}.
128
 
 
129
 
 
130
 
do_movx(I, TempMap, DontSpill) ->
131
 
  {FixSrc, Src, DontSpill1} =
132
 
    case I of
133
 
      #movsx{src=Src0,dst=Dst0} ->
134
 
        fix_src_operand(Src0, TempMap);
135
 
      #movzx{src=Src0,dst=Dst0} ->
136
 
        fix_src_operand(Src0, TempMap)
137
 
    end,
138
 
  {FixDst, Dst, DontSpill2} = fix_dst_operand(Dst0, TempMap),
139
 
  {I3, DontSpill3} =
140
 
    case is_spilled(Dst, TempMap) of
141
 
      false ->
142
 
        I2 = case I of
143
 
               #movsx{} ->
144
 
                 [hipe_x86:mk_movsx(Src, Dst)];
145
 
               #movzx{} ->
146
 
                 [hipe_x86:mk_movzx(Src, Dst)]
147
 
             end,
148
 
        {I2, []};
149
 
      true ->
150
 
        Dst2 = clone(Dst),
151
 
        I2 = 
152
 
          case I of
153
 
            #movsx{} ->
154
 
              [hipe_x86:mk_movsx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)];
155
 
            #movzx{} ->
156
 
              [hipe_x86:mk_movzx(Src, Dst2), hipe_x86:mk_move(Dst2, Dst)]
157
 
          end,
158
 
        {I2, [Dst2]}
159
 
    end,
160
 
  {FixSrc++FixDst++I3, 
161
 
   DontSpill3 ++ DontSpill2 ++
162
 
   DontSpill1 ++ DontSpill}.
163
 
 
164
 
%%% Fix a fmov op.
165
 
do_fmov(I, TempMap, DontSpill) ->
166
 
  #fmov{src=Src0,dst=Dst0} = I,
167
 
  {FixSrc, Src, FixDst, Dst, NewDontSpill} = 
168
 
    do_binary(Src0, Dst0,
169
 
              TempMap, DontSpill),
170
 
  {FixSrc ++ FixDst ++ [I#fmov{src=Src,dst=Dst}],
171
 
   NewDontSpill}.
172
 
 
173
 
%%% Fix a shift operation
174
 
%%% 1. remove pseudos from any explicit memory operands
175
 
%%% 2. if the source is a register or memory position
176
 
%%% make sure to move it to %ecx
177
 
 
178
 
do_shift(I, TempMap, DontSpill) ->
179
 
  #shift{src=Src0,dst=Dst0} = I,
180
 
  {FixDst, Dst, DontSpill2} = fix_dst_operand(Dst0, TempMap),
181
 
  DontSpill3 = DontSpill ++ DontSpill2,
182
 
  Reg =  hipe_x86_registers:ecx(),
183
 
  case Src0 of 
184
 
    #x86_imm{} ->
185
 
      {FixDst ++ [I#shift{dst=Dst}], DontSpill3};
186
 
    #x86_temp{reg=Reg}  ->
187
 
      {FixDst ++ [I#shift{dst=Dst}], DontSpill3}
188
 
  end.
189
 
 
190
 
do_byte_move(Src0, Dst0,TempMap, DontSpill) ->
191
 
  {FixSrc, Src, DontSpill1} = fix_src_operand(Src0, TempMap),
192
 
  {FixDst, Dst, DontSpill2} = fix_dst_operand(Dst0, TempMap),
193
 
  {FixSrc3, Src3, DontSpill3} =
194
 
    case Src of
195
 
      #x86_imm{} ->
196
 
        {FixSrc, Src, []};
197
 
      #x86_temp{reg=Reg} ->
198
 
        case Reg < 4 of
199
 
          true ->
200
 
            {FixSrc, Src, []};
201
 
          false ->        %hardcode a move to eax for all temps not in the four low regs
202
 
            Src2 = hipe_x86:mk_temp(hipe_x86_registers:eax(), untagged),
203
 
            FixSrc2 = FixSrc ++ [hipe_x86:mk_move(Src, Src2)],
204
 
            {FixSrc2, Src2, [Src2]}
205
 
        end
206
 
    end,
207
 
  {FixSrc3, Src3, FixDst, Dst, 
208
 
   DontSpill3 ++ DontSpill2 ++
209
 
   DontSpill1 ++ DontSpill}.
210
 
 
211
 
%%% Fix the operands of a binary op.
212
 
%%% 1. remove pseudos from any explicit memory operands
213
 
%%% 2. if both operands are (implicit or explicit) memory operands,
214
 
%%%    move src to a reg and use reg as src in the original insn
215
 
 
216
 
do_binary(Src0, Dst0, TempMap, DontSpill) ->
217
 
  {FixSrc, Src, DontSpill1} = fix_src_operand(Src0, TempMap),
218
 
  {FixDst, Dst, DontSpill2} = fix_dst_operand(Dst0, TempMap),
219
 
  {FixSrc3, Src3, DontSpill3} =
220
 
    case is_mem_opnd(Src, TempMap) of
221
 
      false ->
222
 
        {FixSrc, Src, []};
223
 
      true ->
224
 
        case is_mem_opnd(Dst, TempMap) of
225
 
          false ->
226
 
            {FixSrc, Src, []};
227
 
          true ->
228
 
            Src2 = clone(Src),
229
 
            FixSrc2 = FixSrc ++ [hipe_x86:mk_move(Src, Src2)],
230
 
            {FixSrc2, Src2, [Src2]}
231
 
        end
232
 
    end,
233
 
  {FixSrc3, Src3, FixDst, Dst, 
234
 
   DontSpill3 ++ DontSpill2 ++
235
 
   DontSpill1 ++ DontSpill}.
236
 
 
237
 
%%% Fix any x86_mem operand to not refer to any spilled temps.
238
 
 
239
 
fix_src_operand(Opnd,TmpMap) ->
240
 
  fix_mem_operand(Opnd, TmpMap, hipe_x86_registers:temp1()).
241
 
 
242
 
fix_dst_operand(Opnd, TempMap) ->
243
 
  fix_mem_operand(Opnd,TempMap, hipe_x86_registers:temp0()).
244
 
 
245
 
fix_mem_operand(Opnd, TempMap, Reg) ->  % -> {[fixupcode], newop, DontSpill}
246
 
  case Opnd of
247
 
    #x86_mem{base=Base,off=Off} ->
248
 
      case is_mem_opnd(Base, TempMap) of
249
 
        false ->
250
 
          %% XXX: (Mikael) this test looks wrong to me, since it will
251
 
          %% falsely trigger for temps that are actual registers.
252
 
          %% ra_dummy uses src_is_pseudo() here.
253
 
          %%
254
 
          %% The assembler can't handle reg offsets, so at the moment
255
 
          %% it is handled here. (Happi)
256
 
          case  hipe_x86:is_imm(Off) of
257
 
            true ->
258
 
              {[], Opnd, []};
259
 
            false ->            % pseudo(pseudo)
260
 
              Temp = clone(Off, Reg),
261
 
              {[hipe_x86:mk_move(Base, Temp),
262
 
                hipe_x86:mk_alu('add', Off, Temp)],
263
 
               Opnd#x86_mem{base=Temp, off=hipe_x86:mk_imm(0)},
264
 
               [Temp]}
265
 
 
266
 
          end;
267
 
        true ->
268
 
          Temp = clone(Base, Reg),
269
 
          case hipe_x86:is_imm(Off) of
270
 
            true ->             % imm/reg(pseudo)
271
 
              {[hipe_x86:mk_move(Base, Temp)],
272
 
               Opnd#x86_mem{base=Temp},
273
 
               [Temp]};
274
 
            false ->            % pseudo(pseudo)
275
 
              {[hipe_x86:mk_move(Base, Temp),
276
 
                hipe_x86:mk_alu('add', Off, Temp)],
277
 
               Opnd#x86_mem{base=Temp, off=hipe_x86:mk_imm(0)},
278
 
               [Temp]}
279
 
          end
280
 
      end;
281
 
    _ ->
282
 
      {[], Opnd, []}
283
 
  end.
284
 
 
285
 
%%% Check if an operand denotes a memory cell (mem or pseudo).
286
 
 
287
 
is_mem_opnd(Opnd, TempMap) ->
288
 
  R =
289
 
    case Opnd of
290
 
      #x86_mem{} -> true;
291
 
      #x86_temp{} -> 
292
 
        Reg = hipe_x86:temp_reg(Opnd),
293
 
        case hipe_x86:temp_is_allocatable(Opnd) of
294
 
          true -> 
295
 
            case size(TempMap) > Reg of 
296
 
              true ->
297
 
                case 
298
 
                  hipe_temp_map:is_spilled(Reg,
299
 
                                           TempMap) of
300
 
                  true ->
301
 
                    ?count_temp(Reg),
302
 
                    true;
303
 
                  false -> false
304
 
                end;
305
 
              _ -> true
306
 
            end;
307
 
          false -> true
308
 
        end;
309
 
      _ -> false
310
 
    end,
311
 
  %%  io:format("Op ~w mem: ~w\n",[Opnd,R]),
312
 
  R.
313
 
 
314
 
%%% Check if an operand is a spilled Temp.
315
 
 
316
 
                                                %src_is_spilled(Src, TempMap) ->
317
 
                                                %  case hipe_x86:is_temp(Src) of
318
 
                                                %    true ->
319
 
                                                %      Reg = hipe_x86:temp_reg(Src),
320
 
                                                %      case hipe_x86:temp_is_allocatable(Src) of
321
 
                                                %       true -> 
322
 
                                                %         case size(TempMap) > Reg of 
323
 
                                                %           true ->
324
 
                                                %             case hipe_temp_map:is_spilled(Reg, TempMap) of
325
 
                                                %               true ->
326
 
                                                %                 ?count_temp(Reg),
327
 
                                                %                 true;
328
 
                                                %               false ->
329
 
                                                %                 false
330
 
                                                %             end;
331
 
                                                %           false ->
332
 
                                                %             false
333
 
                                                %         end;
334
 
                                                %       false -> true
335
 
                                                %      end;
336
 
                                                %    false -> false
337
 
                                                %  end.
338
 
 
339
 
is_spilled(Temp, TempMap) ->
340
 
  case hipe_x86:temp_is_allocatable(Temp) of
341
 
    true -> 
342
 
      Reg = hipe_x86:temp_reg(Temp),
343
 
      case size(TempMap) > Reg of 
344
 
        true ->
345
 
          case hipe_temp_map:is_spilled(Reg, TempMap) of
346
 
            true ->
347
 
              ?count_temp(Reg),
348
 
              true;
349
 
            false ->
350
 
              false
351
 
          end;
352
 
        false ->
353
 
          false
354
 
      end;
355
 
    false -> true
356
 
  end.
357
 
 
358
 
 
359
 
%%% Make Reg a clone of Dst (attach Dst's type to Reg).
360
 
 
361
 
clone(Dst) ->
362
 
  Type =
363
 
    case Dst of
364
 
      #x86_mem{} -> hipe_x86:mem_type(Dst);
365
 
      #x86_temp{} -> hipe_x86:temp_type(Dst)
366
 
    end,
367
 
  spill_temp(Type).
368
 
 
369
 
spill_temp(Type) ->
370
 
  hipe_x86:mk_temp(hipe_x86_registers:temp1(),Type).
371
 
 
372
 
clone(Dst, Reg) ->
373
 
  Type =
374
 
    case Dst of
375
 
      #x86_mem{} -> hipe_x86:mem_type(Dst);
376
 
      #x86_temp{} -> hipe_x86:temp_type(Dst)
377
 
    end,
378
 
  hipe_x86:mk_temp(Reg,Type).