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

« back to all changes in this revision

Viewing changes to lib/hipe/sparc/hipe_sparc_pre_ra_prop.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
 
%% Copyright (c) 2001 by Erik Johansson.  All Rights Reserved 
3
 
%% -*- erlang-indent-level: 2 -*-
4
 
%% ====================================================================
5
 
%%  Filename :  hipe_sparc_prop.erl
6
 
%%  Module   :  hipe_sparc_prop
7
 
%%  Purpose  :  
8
 
%%  Notes    : 
9
 
%%  History  :  * 2001-12-04 Erik Johansson (happi@csd.uu.se): 
10
 
%%               Created.
11
 
%%  CVS      :
12
 
%%              $Author: richardc $
13
 
%%              $Date: 2002/10/01 12:47:16 $
14
 
%%              $Revision: 1.5 $
15
 
%% ====================================================================
16
 
%%  Exports  :
17
 
%%
18
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
19
 
 
20
 
-module(hipe_sparc_pre_ra_prop).
21
 
-export([cfg/1]).
22
 
-include("../main/hipe.hrl").
23
 
 
24
 
cfg(CFG) ->
25
 
  %%  hipe_sparc_cfg:pp(CFG),
26
 
  Lbls = [hipe_sparc_cfg:start(CFG)],
27
 
  {CFG0,GEnv0} = prop_bbs(Lbls, CFG, new_genv(CFG),[]),
28
 
  %% hipe_sparc_cfg:pp(CFG0),
29
 
  CFG1 = prop(Lbls, CFG0, GEnv0,100),
30
 
  CFG2 = remove_dead(CFG1),
31
 
  CFG2.
32
 
 
33
 
remove_dead(CFG) ->
34
 
  Liveness = hipe_sparc_liveness:analyze(CFG),
35
 
  Lbls = hipe_sparc_cfg:labels(CFG),
36
 
  bwd_prop(Lbls, CFG, Liveness).
37
 
 
38
 
bwd_prop([L|Lbls], CFG, Liveness) ->
39
 
  BB = hipe_sparc_cfg:bb(CFG, L),
40
 
  LiveOut = hipe_sparc_liveness:liveout(Liveness, L),
41
 
  {NewCode,_} = bwd_prop_bb(hipe_bb:code(BB),LiveOut),
42
 
  NewBB = hipe_bb:code_update(BB, NewCode),
43
 
  NewCFG = hipe_sparc_cfg:bb_update(CFG, L, NewBB),
44
 
  bwd_prop(Lbls, NewCFG, Liveness);
45
 
bwd_prop([],CFG,_) ->
46
 
  CFG.
47
 
 
48
 
bwd_prop_bb([I|Is], LiveOut) ->
49
 
  {NewIs, NewLiveOut} = bwd_prop_bb(Is,LiveOut),
50
 
  {NewI,Out} = bwd_prop_i(I,NewLiveOut),
51
 
  {[NewI|NewIs], Out};
52
 
bwd_prop_bb([], LiveOut) -> {[], LiveOut}.
53
 
 
54
 
bwd_prop_i(I,Live) ->
55
 
  Uses = ordsets:from_list(hipe_sparc:uses(I)),
56
 
  Defines = 
57
 
    ordsets:from_list(
58
 
      case hipe_sparc:type(I) of
59
 
        call_link -> 
60
 
          [hipe_sparc:mk_reg(X) 
61
 
           || X <- hipe_sparc_registers:allocatable()];
62
 
        _ -> hipe_sparc:defines(I)
63
 
      end),
64
 
  
65
 
  case ordsets:union(Defines,Live) of
66
 
    [] ->
67
 
      %% Nothing defined is live -- potentialy dead
68
 
      case can_kill(I) of
69
 
        true ->
70
 
          {hipe_sparc:comment_create({"Removed instr",I},[I]),
71
 
           Live};
72
 
        false ->
73
 
          {I,
74
 
           ordsets:union(ordsets:subtract(Live,Defines),Uses)}
75
 
      end;
76
 
    _ -> %% The result is needed.
77
 
       {I,ordsets:union(ordsets:subtract(Live,Defines),Uses)}
78
 
  end.
79
 
 
80
 
can_kill(I) ->
81
 
  %% TODO: Expand this function.
82
 
  case hipe_sparc:type(I) of
83
 
    pseudo_unspill ->
84
 
      Dest = hipe_sparc:reg_nr(hipe_sparc:pseudo_spill_reg(I)),
85
 
      case hipe_sparc_registers:is_precolored(Dest) of
86
 
        true -> false;
87
 
        _ -> true
88
 
      end;
89
 
    move ->
90
 
      Dest = hipe_sparc:reg_nr(hipe_sparc:move_dest(I)),
91
 
      case hipe_sparc_registers:is_precolored(Dest) of
92
 
        true -> false;
93
 
        _ -> true
94
 
      end;
95
 
    _ -> 
96
 
      false
97
 
  end.
98
 
 
99
 
 
100
 
 
101
 
prop(Start,CFG,Env,0) ->
102
 
  io:format("Limit hit\n"),
103
 
  CFG;
104
 
prop(Start,CFG,Env,N) ->
105
 
  case changed(Env) of
106
 
    true ->
107
 
      {CFG0,GEnv0} = prop_bbs(Start, CFG, clear_changed(Env), []),
108
 
      prop(Start,CFG0, GEnv0, N-1);
109
 
    false ->
110
 
      CFG
111
 
  end.
112
 
 
113
 
%%
114
 
%% Iterate over the basic blocks of a cfg.
115
 
%%
116
 
 
117
 
prop_bbs([], CFG, GEnv,_) ->
118
 
  {CFG,GEnv};
119
 
prop_bbs([BB|BBs], CFG, GEnv,Vis) ->
120
 
  {Succs, CFG0,GEnv0, NewVis} = prop_bb(BB, GEnv, CFG,Vis),
121
 
  prop_bbs(BBs++Succs, CFG0, GEnv0, NewVis).
122
 
  
123
 
  
124
 
 
125
 
%%
126
 
%% If Lbl is a member of the extended block Ebb. Then propagate info 
127
 
%% and continue with its successors.
128
 
%%
129
 
 
130
 
prop_bb(Lbl, GEnv, CFG, Vis) ->
131
 
  case lists:member(Lbl, Vis) of
132
 
    true -> {[],CFG, GEnv, Vis};
133
 
    false ->
134
 
      BB = hipe_sparc_cfg:bb(CFG, Lbl),
135
 
      %% io:format("\n~w:\n========\n~p\n",[Lbl,env(set_active_block(Lbl,GEnv))]),
136
 
      {NewCode, NewGEnv} = prop_instrs(hipe_bb:code(BB), 
137
 
                                       set_active_block(Lbl,GEnv)),
138
 
      NewBB = hipe_bb:code_update(BB, NewCode),
139
 
      NewCFG = hipe_sparc_cfg:bb_update(CFG, Lbl, NewBB),
140
 
      Succ = succ(NewGEnv),
141
 
      %% io:format("Succs: ~w\n",[Succ]),
142
 
      {Succ, NewCFG, NewGEnv,[Lbl|Vis]}
143
 
  end.
144
 
 
145
 
 
146
 
% prop_succ([], GEnv, CFG, Vis) ->
147
 
%   {CFG,GEnv, Vis};
148
 
% prop_succ([BB|BBs], GEnv, CFG, Vis) ->
149
 
%   {NewCFG,NewGEnv, NewVis} = prop_bb(BB, GEnv, CFG, Vis),
150
 
%   prop_succ(BBs, NewGEnv, NewCFG, NewVis).
151
 
 
152
 
 
153
 
prop_instrs([], GEnv) ->
154
 
  {[], end_of_bb(GEnv)};
155
 
prop_instrs([I|Is], GEnv) ->
156
 
  {NewI, Env0} = prop_instr(I, GEnv),
157
 
%%  if I =/= NewI ->
158
 
%%            io:format("REWRITE\n"),
159
 
%%        hipe_sparc_pp:pp_instr(NewI),
160
 
%%      ok;
161
 
%%     true -> ok
162
 
%%  end,
163
 
  GEnv0 = set_env(Env0,GEnv),
164
 
  {NewIs, NewEnv} = prop_instrs(Is, GEnv0),
165
 
 
166
 
  case NewI of
167
 
    [_|_] -> {NewI++NewIs, NewEnv};     %% alub -> [move, goto]
168
 
    _ -> {[NewI|NewIs], NewEnv}
169
 
  end.
170
 
 
171
 
 
172
 
%%
173
 
%% Propagate copies and constants for one instruction.
174
 
%%
175
 
 
176
 
prop_instr(I, Env) ->
177
 
%%   pp_lenv(Env),
178
 
%%   hipe_sparc_pp:pp_instr(I),
179
 
 
180
 
 
181
 
  case hipe_sparc:type(I) of
182
 
    move ->
183
 
      Srcs = [hipe_sparc:move_src(I)],
184
 
      Dsts = [hipe_sparc:move_dest(I)],
185
 
      {I0,Env0} = bind_all(Srcs, Dsts, I, env(Env)),
186
 
      {I, kill_uses(hipe_sparc:defines(I0), Env0)};
187
 
    multimove ->
188
 
      NewEnv = unbind(hipe_sparc:defines(I), env(Env)),
189
 
      Srcs = hipe_sparc:multimove_src(I),
190
 
      Dsts = hipe_sparc:multimove_dest(I),
191
 
      bind_all(Srcs, Dsts, I, NewEnv);
192
 
    _ ->
193
 
      %% Uses = hipe_sparc:uses(I),
194
 
      %% %% Map = [{U, lookup(U, Env)} || U <- Uses],
195
 
      %% Map = map_all(Uses, env(Env)),
196
 
      %% NewI = hipe_sparc:subst_uses(I,Map),
197
 
      %% eval(NewI, env(Env))
198
 
      eval(I, env(Env))
199
 
  end.
200
 
 
201
 
 
202
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203
 
%%
204
 
%% Evaluate an instruction. Returns {NewI, NewEnv}.
205
 
%%
206
 
 
207
 
eval(I, Env) ->
208
 
  case hipe_sparc:type(I) of
209
 
    store -> prop_store(I,Env);
210
 
    load ->  prop_load(I,Env);
211
 
    pseudo_spill -> prop_spill(I,Env);
212
 
    pseudo_unspill -> prop_unspill(I,Env);
213
 
%    cmov_cc -> prop_cmov_cc(I,Env);
214
 
%    cmov_r -> prop_cmov_r(I,Env);
215
 
    alu -> prop_alu(I,Env);
216
 
%    alu_cc -> prop_alu_cc(I,Env);
217
 
%    sethi ->  prop_sethi(I,Env);
218
 
 
219
 
%    load_atom ->  prop_load_atom(I,Env);
220
 
%    load_word_index ->  prop_word_index(I,Env);
221
 
%    load_address ->  prop_load_address(I,Env);
222
 
 
223
 
 
224
 
%    b ->  prop_b(I,Env);
225
 
%    br ->  prop_br(I,Env);
226
 
%    goto ->  prop_got(I,Env);
227
 
%    jmp ->  prop_jmp(I,Env);
228
 
 
229
 
    call_link ->  prop_call_link(I,Env);
230
 
 
231
 
    nop ->  {I,Env};
232
 
    align ->  {I,Env};
233
 
 
234
 
    _ -> 
235
 
      NewEnv = unbind(hipe_sparc:defines(I), Env),
236
 
      {I,NewEnv};
237
 
 
238
 
    comment -> {I,Env}
239
 
 
240
 
end.    
241
 
 
242
 
prop_store(I,Env) ->
243
 
  Base = hipe_sparc:store_dest(I),
244
 
  Offset = hipe_sparc:store_off(I),
245
 
  Src = hipe_sparc:store_src(I),
246
 
  SP = hipe_sparc:mk_reg(hipe_sparc_registers:stack_pointer()),
247
 
  HP = hipe_sparc:mk_reg(hipe_sparc_registers:heap_pointer()),
248
 
  if
249
 
    Base =:= SP ->
250
 
      prop_stack_store(I,Env,Offset,Src);
251
 
    Base =:= HP ->
252
 
      prop_heap_store(I,Env,Offset,Src);
253
 
    Offset =:= SP ->
254
 
      ?EXIT({dont_use_sp_as_offset,I});
255
 
    Offset =:= HP ->
256
 
      ?EXIT({dont_use_hp_as_offset,I});
257
 
    true ->
258
 
      %% A store off stack and heap (Probably PCB).
259
 
      %% We assume there is no interference here!!!
260
 
      {I,Env}
261
 
  end.
262
 
 
263
 
prop_spill(I,Env) ->
264
 
  Pos = hipe_sparc:imm_value(hipe_sparc:pseudo_spill_pos(I))*4,
265
 
  Src = hipe_sparc:pseudo_spill_reg(I),
266
 
  case find_spos(Pos, Env) of
267
 
    Src ->
268
 
      %% Already spilled.
269
 
      NewI = hipe_sparc:comment_create({"Removed spill",I},[]),
270
 
      {NewI, Env};
271
 
    _ ->
272
 
      %% Not spilled.
273
 
      NewEnv = bind_spos(Pos, Src, Env),
274
 
      {I, NewEnv}
275
 
  end.
276
 
 
277
 
prop_unspill(I,Env) ->
278
 
  Pos = hipe_sparc:imm_value(hipe_sparc:pseudo_unspill_pos(I))*4,
279
 
  Dest = hipe_sparc:pseudo_unspill_reg(I),
280
 
  case find_spos(Pos, Env) of
281
 
    undefined ->
282
 
      {I, kill(Dest,Env)};
283
 
    Val ->
284
 
      bind_all([Val],[Dest],I,Env)
285
 
  end.
286
 
 
287
 
 
288
 
 
289
 
 
290
 
prop_stack_store(I,Env,Offset,Src) ->
291
 
  case sp(Env) of
292
 
    unknown ->
293
 
       %% We are updating via unknown SP.
294
 
        {I, zap_stack(Env)};
295
 
    SOff ->
296
 
      case hipe_sparc:is_imm(Offset) of
297
 
        false ->
298
 
          %% We are updating the stack via a reg...
299
 
          %% TODO: Check wehter the the reg is bound to a const...
300
 
          %% We have to zap the stack...
301
 
          {I, zap_stack(Env)};
302
 
        true ->
303
 
          Pos = hipe_sparc:imm_value(Offset) + SOff,
304
 
          NewEnv = bind_spos(Pos, Src, Env),
305
 
          %% TODO: Indicate that Src is copied on stack.
306
 
          {I, NewEnv}
307
 
      end
308
 
  end.
309
 
 
310
 
prop_heap_store(I,Env,Offset,Src) ->
311
 
 
312
 
    case hp(Env) of
313
 
      unknown ->
314
 
        %% We are updating via unknown HP.    
315
 
        {I, zap_heap(Env)};     
316
 
      HOff ->
317
 
        case hipe_sparc:is_imm(Offset) of
318
 
          false ->
319
 
            %% We are updating the heap via a reg...
320
 
            %% TODO: Check wehter the the reg is bound to a const...
321
 
            %% We have to zap the heap...
322
 
            {I, zap_heap(Env)};
323
 
          true ->
324
 
            Pos = hipe_sparc:imm_value(Offset) + HOff,
325
 
            NewEnv = bind_hpos(Pos, Src, Env),
326
 
            %% TODO: Indicate that Src is copied on heap.
327
 
            {I, NewEnv}
328
 
        end
329
 
    end.
330
 
 
331
 
prop_load(I,Env) ->
332
 
  Base = hipe_sparc:load_src(I),
333
 
  Offset = hipe_sparc:load_off(I),
334
 
  Dest = hipe_sparc:load_dest(I),
335
 
  SP = hipe_sparc:mk_reg(hipe_sparc_registers:stack_pointer()),
336
 
  HP = hipe_sparc:mk_reg(hipe_sparc_registers:heap_pointer()),
337
 
  if
338
 
    Base =:= SP ->
339
 
      prop_stack_load(I,Env,Offset,Dest);
340
 
    Base =:= HP ->
341
 
      prop_heap_load(I,Env,Offset,Dest);
342
 
    Offset =:= SP ->
343
 
      ?EXIT({dont_use_sp_as_offset,I});
344
 
    Offset =:= HP ->
345
 
      ?EXIT({dont_use_hp_as_offset,I});
346
 
    true ->
347
 
      %% A load off stack and heap (Probably PCB).
348
 
      %% We assume there is no interference here!!!
349
 
      NewEnv = kill(Dest,Env),
350
 
      {I,NewEnv}
351
 
  end.
352
 
 
353
 
prop_stack_load(I,Env,Offset,Dest) ->
354
 
  case sp(Env) of
355
 
    unknown ->
356
 
      {I, kill(Dest,Env)};
357
 
    SOff ->
358
 
      case hipe_sparc:is_imm(Offset) of
359
 
        false ->
360
 
          %% We are reading the stack via a reg...
361
 
          %% TODO: Check wehter the the reg is bound to a const...
362
 
          {I, kill(Dest,Env)};
363
 
        true ->
364
 
          Pos = hipe_sparc:imm_value(Offset) + SOff,
365
 
          
366
 
          case find_spos(Pos, Env) of
367
 
            undefined ->
368
 
              {I, kill(Dest,Env)};
369
 
            Val ->
370
 
              bind_all([Val],[Dest],I,kill_uses([Dest],Env))
371
 
          end
372
 
      end
373
 
  end.
374
 
 
375
 
prop_heap_load(I,Env,Offset,Dest) ->
376
 
  case hp(Env) of
377
 
    unknown ->
378
 
      {I, kill(Dest,Env)};
379
 
    HOff ->
380
 
      case hipe_sparc:is_imm(Offset) of
381
 
        false ->
382
 
          %% We are reading the heap via a reg...
383
 
          %% TODO: Check wehter the the reg is bound to a const...
384
 
          {I, kill(Dest,Env)};
385
 
        true ->
386
 
          Pos = hipe_sparc:imm_value(Offset) + HOff,
387
 
          
388
 
          case find_hpos(Pos, Env) of
389
 
            undefined ->
390
 
              {I, kill(Dest,Env)};
391
 
            Val ->
392
 
              bind_all([Val],[Dest],I,kill_uses([Dest],Env))
393
 
          end
394
 
      end
395
 
  end.
396
 
 
397
 
 
398
 
%% ____________________________________________________________________
399
 
%% 
400
 
prop_alu(I,Env) ->
401
 
  OP = hipe_sparc:alu_operator(I),
402
 
  Src1 = hipe_sparc:alu_src1(I),
403
 
  Src2 = hipe_sparc:alu_src2(I),
404
 
  Dest = hipe_sparc:alu_dest(I),
405
 
  SP = hipe_sparc:mk_reg(hipe_sparc_registers:stack_pointer()),
406
 
  HP = hipe_sparc:mk_reg(hipe_sparc_registers:heap_pointer()),
407
 
  if
408
 
    Dest =:= SP ->
409
 
      case Src1 of
410
 
        SP ->
411
 
          prop_sp_op(I,Env,OP,Src2);
412
 
        _ ->
413
 
          %% TODO: handle SP = x op SP
414
 
          %% unknown update of SP.
415
 
          {I,kill_sp(zap_stack(Env))}
416
 
      end;
417
 
    Dest =:= HP ->
418
 
      case Src1 of
419
 
        HP ->
420
 
          prop_hp_op(I,Env,OP,Src2);
421
 
        _ ->
422
 
          %% TODO: handle HP = x op HP
423
 
          %% unknown update of HP.
424
 
          {I,kill_hp(zap_heap(Env))}
425
 
      end;
426
 
    true ->
427
 
      %% TODO: Fold consts ...
428
 
      {I, kill(Dest,Env)}
429
 
  end.
430
 
 
431
 
prop_sp_op(I,Env,'+',Src) ->
432
 
  case hipe_sparc:is_imm(Src) of
433
 
    true ->
434
 
      {I, inc_sp(Env,hipe_sparc:imm_value(Src))};
435
 
    false ->
436
 
      {I,kill_sp(zap_stack(Env))}
437
 
  end;
438
 
prop_sp_op(I,Env,'-',Src) ->
439
 
  case hipe_sparc:is_imm(Src) of
440
 
    true ->
441
 
      {I, inc_sp(Env, - hipe_sparc:imm_value(Src))};
442
 
    false ->
443
 
      {I,kill_sp(zap_stack(Env))}
444
 
  end;
445
 
prop_sp_op(I,Env,Op,Src) ->
446
 
  %% Dont know how to handle other ops...
447
 
  {I,kill_sp(zap_stack(Env))}.
448
 
 
449
 
prop_hp_op(I,Env,'+',Src) ->
450
 
  case hipe_sparc:is_imm(Src) of
451
 
    true ->
452
 
      {I,inc_hp(Env,hipe_sparc:imm_value(Src))};
453
 
    false ->
454
 
      {I,kill_sp(zap_stack(Env))}
455
 
  end;
456
 
prop_hp_op(I,Env,'-',Src) ->
457
 
  case hipe_sparc:is_imm(Src) of
458
 
    true ->
459
 
      {I, inc_hp(Env, - hipe_sparc:imm_value(Src))};
460
 
    false ->
461
 
      {I,kill_sp(zap_stack(Env))}
462
 
  end;
463
 
prop_hp_op(I,Env,Op,Src) ->
464
 
  %% Dont know how to handle other ops...
465
 
  {I,kill_hp(zap_heap(Env))}.
466
 
 
467
 
%% ____________________________________________________________________
468
 
%% 
469
 
prop_call_link(I,Env) ->
470
 
  Dests = hipe_sparc:call_link_dests(I),
471
 
  Env1 = kill_uses(Dests,kill_phys_regs(Env)),
472
 
  {I,Env1}.
473
 
 
474
 
 
475
 
%% ____________________________________________________________________
476
 
%% 
477
 
% map_all([], Env) ->
478
 
%   [];
479
 
% map_all([V|Vs], Env) ->
480
 
%   [{V, lookup(V, Env)} | map_all(Vs, Env)].
481
 
 
482
 
 
483
 
bind_all(Srcs, Dsts, I, Env) ->
484
 
  bind_all(Srcs, Dsts, I, Env, Env).
485
 
 
486
 
%%%
487
 
%% We have two envs, Env where we do lookups and
488
 
%%                   NewEnv where the new bindings are entered.
489
 
bind_all([Src|Srcs], [Dst|Dsts], I, Env, NewEnv) ->
490
 
  case hipe_sparc:is_imm(Src) of
491
 
    true ->
492
 
      bind_all(Srcs, Dsts, I, Env, bind(NewEnv, Dst, Src));
493
 
    false ->  %% its a variable
494
 
      SrcVal = lookup(Src, Env),
495
 
      %% Uncomment this and only constants will be propagated
496
 
      %% case hipe_rtl:is_imm(SrcVal) of
497
 
      %%   true ->
498
 
      NewI = hipe_sparc:subst_uses(I,[{Src, SrcVal}]),
499
 
      bind_all(Srcs, Dsts, NewI, Env, bind(NewEnv, Dst, SrcVal))
500
 
      %%  false ->
501
 
      %%     bind_all(Srcs, Dsts, I, Env, NewEnv)
502
 
      %% end
503
 
  end;
504
 
bind_all([], [], I, _, Env) ->
505
 
  {I, Env}.
506
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507
 
 
508
 
 
509
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511
 
%%
512
 
%% the environment, Rewrite if we go global.
513
 
%% {Regs,SP,HP, Stack, Heap}
514
 
-record(genv,{block,cfg,succ_map,pred_map,env,envs,changed}).
515
 
new_genv(CFG)->  
516
 
  #genv{cfg=CFG,
517
 
        succ_map=hipe_sparc_cfg:succ_map(CFG),
518
 
        pred_map=hipe_sparc_cfg:pred_map(CFG),
519
 
        env=new_env(),
520
 
        envs=[],
521
 
        changed=false
522
 
       }.
523
 
set_env(Env,GEnv) ->
524
 
  GEnv#genv{env=Env}.
525
 
env(GEnv) ->
526
 
  GEnv#genv.env.
527
 
env(L,GEnv) ->
528
 
  case plookup(L, GEnv#genv.envs) of
529
 
    undefined ->new_env();
530
 
    E -> E
531
 
  end.
532
 
      
533
 
preds(L,GEnv) ->
534
 
  hipe_sparc_cfg:pred(GEnv#genv.pred_map,L).
535
 
 
536
 
succ(GEnv) ->
537
 
  hipe_sparc_cfg:succ(GEnv#genv.succ_map, GEnv#genv.block).
538
 
 
539
 
end_of_bb(GEnv) ->
540
 
  Env = GEnv#genv.env,
541
 
  L = GEnv#genv.block,
542
 
  Envs =  GEnv#genv.envs,
543
 
  case plookup(L,Envs) of
544
 
    Env -> GEnv;
545
 
    Env0 ->
546
 
      GEnv#genv{envs=[{L,Env}|Envs], changed=true}
547
 
  end.
548
 
 
549
 
changed(GEnv) ->
550
 
   GEnv#genv.changed.
551
 
 
552
 
clear_changed(GEnv) ->
553
 
   GEnv#genv{changed=false}.
554
 
 
555
 
 
556
 
set_active_block(L, GEnv) ->
557
 
  case preds(L,GEnv) of
558
 
    [Pred] ->
559
 
      GEnv#genv{block=L, env=env(Pred,GEnv)};
560
 
    [Pred|Preds] ->
561
 
      case plookup(Pred, GEnv#genv.envs) of
562
 
        undefined -> GEnv#genv{block=L, env=new_env()};
563
 
        E ->
564
 
          %% io:format("Joining: L:~w\n",[Pred]),
565
 
          %% pp_env(E),
566
 
          Env = join(Preds,E, GEnv),
567
 
          GEnv#genv{block=L, env=Env}
568
 
      end;
569
 
    _ ->
570
 
      GEnv#genv{block=L, env=new_env()}
571
 
  end.
572
 
 
573
 
join([L|Ls], Env, GEnv) ->
574
 
%%  io:format("Joining: L:~w\n",[L]),
575
 
  case plookup(L, GEnv#genv.envs) of
576
 
    undefined -> new_env();
577
 
    E ->
578
 
  %%    pp_env(E),
579
 
      join(Ls,merge(E,Env), GEnv)
580
 
  end;
581
 
join([],Env,Genv) ->
582
 
 %% io:format("Join:\n"),
583
 
 %% pp_env(Env),
584
 
  Env.
585
 
 
586
 
%% ____________________________________________________________________
587
 
%% 
588
 
-record(env,{regs=[],sp=0,hp=0,stack=[],heap=[]}).
589
 
new_env()->  #env{}.
590
 
regs(Env)-> Env#env.regs.
591
 
sp(Env)-> Env#env.sp.
592
 
hp(Env)-> Env#env.hp.
593
 
stack(Env)-> Env#env.stack.
594
 
heap(Env)-> Env#env.heap.
595
 
 
596
 
merge(E1, E2) ->
597
 
  Env0 = #env{regs=m(regs(E1),regs(E2))},
598
 
  Env1 = 
599
 
    case sp(E1) =:= sp(E2) of
600
 
      true ->
601
 
        Stack = m(stack(E1),stack(E2)),
602
 
        Env0#env{sp=sp(E1),stack= Stack};
603
 
      false -> Env0
604
 
    end,
605
 
  Env2 = 
606
 
    case hp(E1) =:= hp(E2) of
607
 
      true ->
608
 
        Heap = m(heap(E1),heap(E2)),
609
 
        Env1#env{hp=hp(E1),heap=Heap};
610
 
      false -> Env1
611
 
    end,
612
 
  Env2.
613
 
    
614
 
m(R1,R2) ->
615
 
  [{X,Y} || {X,Y} <- R1, {value, {X,Y}} =:= lists:keysearch(X, 1, R2)].
616
 
 
617
 
 
618
 
pp_lenv(GEnv) ->
619
 
  Env = env(GEnv),
620
 
  pp_env(Env).
621
 
 
622
 
pp_env(Env) ->
623
 
  pp_regs(regs(Env)),
624
 
  pp_mem(sp(Env),stack(Env),"STACK"),
625
 
  pp_mem(hp(Env),heap(Env)," HEAP").
626
 
 
627
 
pp_regs([{X,Y}|Regs]) ->
628
 
  case hipe_sparc:is_reg(X) of
629
 
    false ->
630
 
      ?EXIT({bad_reg_in_environment,{X,Y}});
631
 
    true ->
632
 
      hipe_sparc_pp:pp_arg(standard_io,X),
633
 
      io:format(" <- "),
634
 
      hipe_sparc_pp:pp_arg(standard_io,Y),
635
 
      io:format("\n"),
636
 
      pp_regs(Regs)
637
 
  end;
638
 
pp_regs([]) -> ok.
639
 
 
640
 
pp_mem(unknown,_,_) ->
641
 
  ok;
642
 
pp_mem(_,[],_) ->
643
 
  ok;
644
 
pp_mem(Pointer,Mem,What) ->
645
 
  io:format("~s:\n",[What]),
646
 
  case lists:sort(Mem) of
647
 
    [] -> ok;
648
 
    [First|_] = Slots ->
649
 
      pp_slots(min(element(1,First),Pointer),Pointer,Slots,What),
650
 
      io:format("               |-----|\n")
651
 
  end.
652
 
 
653
 
min(X,Y) when X =< Y ->
654
 
  X;
655
 
min(_,Y) ->
656
 
  Y.
657
 
 
658
 
 
659
 
pp_slots(Cur, Pointer, Slots = [{Next,V}|Rest], What) ->
660
 
  if Cur =:= Pointer ->
661
 
      io:format("~s_P -> ",[What]);
662
 
     true ->
663
 
      io:format("           ")
664
 
  end,
665
 
  io:format("~3w | ",[Cur]),
666
 
  if Cur =:= Next ->
667
 
      hipe_sparc_pp:pp_arg(standard_io, V),
668
 
      io:format(" |\n"),
669
 
      pp_slots(Cur+4, Pointer, Rest, What);
670
 
     true ->
671
 
      io:format("           |\n"),
672
 
      pp_slots(Cur+4, Pointer, Slots, What)
673
 
  end;
674
 
pp_slots(Cur,Pointer,[],What) ->
675
 
  if Cur =< Pointer ->
676
 
      pp_empty_slots(Cur,Pointer,What);
677
 
     true ->
678
 
      ok
679
 
  end.
680
 
 
681
 
pp_empty_slots(Cur,Pointer,What) ->
682
 
  if Cur =:= Pointer ->
683
 
      io:format("~s_P -> ~3w |      |\n",[What,Cur]);
684
 
     Cur > Pointer ->
685
 
      ?EXIT(bad_env);
686
 
     true ->
687
 
      io:format("           ~3w |      |\n",[Cur]),
688
 
      pp_empty_slots(Cur+4,Pointer,What)
689
 
  end.
690
 
 
691
 
  
692
 
 
693
 
zap_stack(Env)-> Env#env{stack=[]}.
694
 
zap_heap(Env)-> Env#env{heap=[]}.
695
 
kill_sp(Env)->Env#env{sp=unknown}.
696
 
kill_hp(Env)->Env#env{hp=unknown}.
697
 
kill_phys_regs(Env)->
698
 
  Env0 = Env#env{regs=[{X,Y}||{X,Y} <- regs(Env),
699
 
                            not_physical(X), not_physical(Y)]},
700
 
  Env1 = Env0#env{stack=[{X,Y}||{X,Y} <- stack(Env0),
701
 
                                not_physical(Y)]},
702
 
  Env2 = Env1#env{heap=[{X,Y}||{X,Y} <- heap(Env1),
703
 
                               not_physical(Y)]}.
704
 
  
705
 
 
706
 
not_physical(R) ->
707
 
  case hipe_sparc:is_reg(R) of
708
 
    false -> true;
709
 
    true ->
710
 
      not hipe_sparc_registers:is_precolored(hipe_sparc:reg_nr(R))
711
 
  end.
712
 
                
713
 
inc_sp(Env, Val) ->  
714
 
  case sp(Env) of
715
 
    unknown ->
716
 
      Env;
717
 
    PrevVal ->
718
 
      Env#env{sp=PrevVal+Val}
719
 
  end.
720
 
inc_hp(Env, Val) ->  
721
 
  case hp(Env) of
722
 
    unknown ->
723
 
      Env;
724
 
    PrevVal ->
725
 
      Env#env{hp=PrevVal+Val}
726
 
  end.
727
 
 
728
 
 
729
 
%% Bind a value/reg to a stack position
730
 
bind_spos(Pos, Val, Env) ->
731
 
  Env#env{stack=[{Pos,Val}| lists:keydelete(Pos,1,Env#env.stack)]}.
732
 
 
733
 
%% Bind a value/reg to a heap position
734
 
bind_hpos(Pos, Val, Env) ->
735
 
  Env#env{heap=[{Pos,Val}| lists:keydelete(Pos,1,Env#env.heap)]}.
736
 
 
737
 
%% Find a value on a stackpos
738
 
find_spos(Pos, Env) ->
739
 
  plookup(Pos,Env#env.stack).
740
 
 
741
 
%% Find a value on a heappos
742
 
find_hpos(Pos, Env) ->
743
 
  plookup(Pos,Env#env.heap).
744
 
 
745
 
%%
746
 
%% Find what memory pos P is bound to.
747
 
%% As a last resort undefined is returned.
748
 
%%
749
 
plookup(P, []) ->
750
 
  undefined;
751
 
plookup(P, [{P, Y}|_]) ->
752
 
  Y;
753
 
plookup(P, [_|Map]) ->
754
 
  plookup(P, Map).
755
 
 
756
 
%%
757
 
%% Bind reg X to Y in Map
758
 
%%
759
 
 
760
 
bind(Map, X, Y) ->
761
 
  Regs = Map#env.regs,
762
 
  Map#env{regs=[{X, Y} | lists:keydelete(X,1,Regs)]}.
763
 
 
764
 
%%
765
 
%% Find what X is bound to (as a last restort varaibles are bound 
766
 
%% to themself).
767
 
%%
768
 
 
769
 
lookup(X, Env) ->
770
 
  mlookup(X,regs(Env)).
771
 
 
772
 
mlookup(X, []) ->
773
 
  X;
774
 
mlookup(X, [{X, Y}|_]) ->
775
 
  Y;
776
 
mlookup(X, [_|Map]) ->
777
 
  mlookup(X, Map).
778
 
 
779
 
%%
780
 
%% Kill bindings with references to register X
781
 
%%
782
 
kill(X, Env0)->
783
 
  Env1 = Env0#env{regs=mkill(X,regs(Env0))},
784
 
  Env2 = Env1#env{stack=mkill(X,stack(Env1))},
785
 
  Env3 = Env2#env{heap=mkill(X,heap(Env2))}.
786
 
 
787
 
mkill(X, []) ->
788
 
  [];
789
 
mkill(X, [{X,_}|Xs]) ->
790
 
  mkill(X, Xs);
791
 
mkill(X, [{_,X}|Xs]) ->
792
 
  mkill(X, Xs);
793
 
mkill(X, [D|Xs]) ->
794
 
  [D | mkill(X,Xs)].
795
 
 
796
 
unbind(X, Env)->
797
 
  Env#env{regs=munbind(X,regs(Env))}.
798
 
 
799
 
munbind([], Map) ->
800
 
  Map;
801
 
munbind([V|Vs], Map) ->
802
 
  munbind(Vs, mkill(V, Map)).
803
 
 
804
 
 
805
 
kill_use(X, []) ->
806
 
  [];
807
 
kill_use(X, [{_,X}|Xs]) ->
808
 
  kill_use(X, Xs);
809
 
kill_use(X, [D|Xs]) ->
810
 
  [D | kill_use(X,Xs)].
811
 
 
812
 
kill_uses([X|Xs],Env0) ->
813
 
  Env1 = Env0#env{regs=kill_use(X,regs(Env0))},
814
 
  Env2 = Env1#env{stack=kill_use(X,stack(Env1))},
815
 
  Env3 = Env2#env{heap=kill_use(X,heap(Env2))},
816
 
  kill_uses(Xs,Env3);
817
 
kill_uses([], Env) -> Env.