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

« back to all changes in this revision

Viewing changes to lib/hipe/rtl/hipe_rtl_ssapre.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: 2 -*-
 
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
3
%% File        : hipe_rtl_ssapre.erl
 
4
%% Author      : He Bingwen and Fr�d�ric Haziza
 
5
%% Description : Performs Partial Redundancy Elimination on SSA form.
 
6
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
7
%% $Id$
 
8
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
9
%% @doc
 
10
%%
 
11
%% This module implements the <a href="http://cs.wheaton.edu/%7Etvandrun/writings/spessapre.pdf">Anticipation-SSAPRE algorithm</a>,
 
12
%% with several modifications for Partial Redundancy Elimination on SSA form.
 
13
%% We actually found problems in this algorithm, so
 
14
%% we implement another version with several advantages:
 
15
%% - No loop for Xsi insertions
 
16
%% - No fix point iteration for the downsafety part
 
17
%% - Less computations for Will Be Available part
 
18
%% - Complexity of the overall algorithm is improved
 
19
%%
 
20
%% We were supposed to publish these results anyway :D
 
21
%%
 
22
%% @end
 
23
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
24
 
 
25
-module(hipe_rtl_ssapre).
 
26
 
 
27
-export([rtl_ssapre/2]).
 
28
 
 
29
-include("../main/hipe.hrl").
 
30
-include("hipe_rtl.hrl").
 
31
 
 
32
%%-define(SSAPRE_DEBUG, true        ). %% When uncommented, produces debug printouts
 
33
-define(        SETS, ordsets       ). %% Which set implementation module to use
 
34
-define(         CFG, hipe_rtl_cfg  ).
 
35
-define(         RTL, hipe_rtl      ).
 
36
-define(          BB, hipe_bb       ).
 
37
-define(        ARCH, hipe_rtl_arch ).
 
38
-define(       GRAPH, digraph       ).
 
39
 
 
40
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
41
%% Records / Structures
 
42
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
43
 
 
44
-record(xsi_link,{number}). %% Number is the index of the temporary (a Key into the Xsi Tree)
 
45
-record(temp,{key,var}).
 
46
-record(bottom,{key,var}).
 
47
-record(xsi, { inst,   %% Associated instruction
 
48
                def,   %% Hypothetical temporary variable
 
49
                       %% that stores the result of the computation
 
50
                label, %% Block Label where the xsi is inserted
 
51
                opList,%% List of operands
 
52
                cba,   %%
 
53
                later, %%
 
54
                wba
 
55
               }).
 
56
 
 
57
-record(pre_candidate, {alu,def}).
 
58
-record(xsi_op, {pred,op}).
 
59
 
 
60
-record(mp, {xsis,maps,preds,defs,uses,ndsSet}).
 
61
-record(block, {type,attributes}).
 
62
 
 
63
-record(eop, {expr,var,stopped_by}).
 
64
-record(insertion, {code,from}).
 
65
 
 
66
-record(const_expr, {var,value}).
 
67
 
 
68
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
69
%% Main function
 
70
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
71
 
 
72
rtl_ssapre(RtlSSACfg, Options) ->
 
73
  %% io:format("\n################ Original CFG ################\n"),
 
74
  %% hipe_rtl_cfg:pp(RtlSSACfg),
 
75
  %% io:format("\n\n############ SSA-Form CHECK ==> ~w\n",[hipe_rtl_ssa:check(RtlSSACfg)]),
 
76
 
 
77
  {CFG2,XsiGraph,CFGGraph,MPs} = perform_Xsi_insertion(RtlSSACfg,Options),
 
78
  %%pp_debug("~n~n################ Xsi CFG ################\n",[]),pp_cfg(CFG2,XsiGraph),
 
79
  XsiList = ?GRAPH:vertices(XsiGraph),
 
80
  case XsiList of
 
81
    [] ->
 
82
      %% No Xsi
 
83
      ?option_time(pp_debug("~n~n################ No Xsi Inserted ################~n",[]),"RTL A-SSAPRE No Xsi inserted (skip Downsafety and Will Be Available)",Options),
 
84
      ok;
 
85
    _ ->
 
86
      pp_debug("~n############ Downsafety ##########~n",[]),
 
87
      ?option_time(perform_downsafety(MPs,CFGGraph,XsiGraph),"RTL A-SSAPRE Downsafety",Options),
 
88
      pp_debug("~n~n################ CFG Graph ################~n",[]),pp_cfggraph(CFGGraph),
 
89
      pp_debug("~n############ Will Be Available ##########~n",[]),
 
90
      ?option_time(perform_will_be_available(XsiGraph,CFGGraph,Options),"RTL A-SSAPRE WillBeAvailable",Options)
 
91
  end,
 
92
  
 
93
  pp_debug("~n############ No more need for the CFG Graph....Deleting...",[]),?GRAPH:delete(CFGGraph),
 
94
  pp_debug("~n~n################ Xsi Graph ################~n",[]),pp_xsigraph(XsiGraph),
 
95
  
 
96
  pp_debug("~n############ Code Motion ##########~n",[]),
 
97
  Labels = ?CFG:preorder(CFG2),
 
98
 
 
99
  pp_debug("~n~n################ Xsi CFG ################~n",[]),pp_cfg(CFG2,XsiGraph),
 
100
 
 
101
  init_redundancy_count(),
 
102
  ?option_time(FinalCFG=perform_code_motion(Labels,CFG2,XsiGraph),"RTL A-SSAPRE Code Motion",Options),
 
103
  
 
104
  pp_debug("\n############ No more need for the Xsi Graph....Deleting...",[]),?GRAPH:delete(XsiGraph),
 
105
 
 
106
  %% io:format("\n################ Final CFG ################\n"),
 
107
  %% hipe_rtl_cfg:pp(FinalCFG),
 
108
  %% io:format("\n\n############ SSA-Form CHECK ==> ~w\n",
 
109
  %%           [hipe_rtl_ssa:check(FinalCFG)]),
 
110
  pp_debug("\nSSAPRE : ~w redundancies were found\n",[get_redundancy_count()]),
 
111
 
 
112
  FinalCFG.
 
113
 
 
114
%% ##########################################################################
 
115
%% ######################## XSI INSERTION ###################################
 
116
%% ##########################################################################
 
117
 
 
118
perform_Xsi_insertion(Cfg, Options)->
 
119
  init_counters(), %% Init counters for Bottoms and Temps
 
120
  XsiGraph = digraph:new([cyclic,private]),
 
121
  %% Be carefull, the digraph component is NOT garbage collected,
 
122
  %% so don't create 20 millions of instances!
 
123
  %% finds the longest depth
 
124
  %% Depth-first, preorder traversal over Basic Blocks.
 
125
  %%Labels = ?CFG:reverse_postorder(Cfg), 
 
126
  Labels = ?CFG:preorder(Cfg), 
 
127
 
 
128
  pp_debug("~n~n############# Finding definitions for computation~n~n",[]),
 
129
  ?option_time({Cfg2,XsiGraph} = find_definition_for_computations(Labels,Cfg,XsiGraph),"RTL A-SSAPRE Xsi Insertion, searching from instructions",Options),
 
130
 
 
131
  %% Active List creation
 
132
  GeneratorXsiList = lists:sort(?GRAPH:vertices(XsiGraph)),
 
133
  pp_debug("~n~n############# Inserted Xsis ~w",[GeneratorXsiList]),
 
134
  pp_debug("~n~n############# Finding operands~n",[]),
 
135
  ?option_time({Cfg3,XsiGraph} = find_operands(Cfg2,XsiGraph,GeneratorXsiList,0),"RTL A-SSAPRE Xsi Insertion, finding operands",Options),
 
136
 
 
137
  %% Creating the CFGGraph
 
138
  pp_debug("~n~n############# Creating CFG Graph",[]),
 
139
  pp_debug("~n############# Labels = ~w",[Labels]),
 
140
  CFGGraph = digraph:new([cyclic,private]),
 
141
  [StartLabel|Others] = Labels,   % adding the start label as a leaf
 
142
  pp_debug("~nAdding a vertex for the start label: ~w",[StartLabel]),
 
143
  ?GRAPH:add_vertex(CFGGraph,StartLabel,#block{type=top}),
 
144
                                                % Doing the others
 
145
  ?option_time(MPs=create_cfggraph(Others,Cfg3,CFGGraph,[],[],[],XsiGraph),"RTL A-SSAPRE Xsi Insertion, creating intermediate 'SSAPRE Graph'",Options),
 
146
 
 
147
  %% Return the bloody collected information
 
148
  {Cfg3,XsiGraph,CFGGraph,MPs}.
 
149
 
 
150
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
151
 
 
152
find_definition_for_computations([], Cfg, XsiGraph) ->
 
153
  {Cfg,XsiGraph}; %% No more block to inspect in the depth-first order
 
154
find_definition_for_computations([Label|Rest], Cfg, XsiGraph) ->
 
155
  Code = ?BB:code(?CFG:bb(Cfg,Label)),
 
156
  {NewCfg,XsiGraph} = find_definition_for_computations_in_block(Label,Code,Cfg,[],XsiGraph),
 
157
  find_definition_for_computations(Rest, NewCfg, XsiGraph).
 
158
 
 
159
%%===========================================================================
 
160
%% Searches from instruction for one block BlockLabel.
 
161
%% We process forward over instructions.
 
162
 
 
163
find_definition_for_computations_in_block(BlockLabel,[],Cfg,
 
164
                                          VisitedInstructions,XsiGraph)->
 
165
  Code = lists:reverse(VisitedInstructions),
 
166
  NewBB = ?BB:mk_bb(Code),
 
167
  NewCfg = ?CFG:bb_add(Cfg,BlockLabel,NewBB),
 
168
  {NewCfg,XsiGraph}; %% No more instructions to inspect in this block
 
169
find_definition_for_computations_in_block(BlockLabel,[Inst|Rest],Cfg,
 
170
                                          VisitedInstructions,XsiGraph) ->
 
171
  %%  pp_debug(" Inspecting instruction: ",[]),pp_instr(Inst,nil),
 
172
  case Inst of
 
173
    #alu{} ->
 
174
      %% Is Inst interesting for SSAPRE?
 
175
      %% i.e., is Inst an arithmetic operation which doesn't deal with precoloured?
 
176
      %% Note that since we parse forward, we have no 'pre_candidate'-type so far.
 
177
      case check_definition(Inst,VisitedInstructions,BlockLabel,Cfg,XsiGraph) of
 
178
        {def_found,Def} ->
 
179
          %% Replacing Inst in Cfg
 
180
          NewInst = #pre_candidate{alu=Inst,def=Def},
 
181
          NewVisited = [NewInst|VisitedInstructions],
 
182
          %% Recurse forward over instructions, same CFG, same XsiGraph
 
183
          find_definition_for_computations_in_block(BlockLabel,Rest,Cfg,
 
184
                                                    NewVisited,XsiGraph);
 
185
        {merge_point,Xsi} ->
 
186
          Def = Xsi#xsi.def,
 
187
          Key = Def#temp.key,
 
188
          NewInst = #pre_candidate{alu=Inst,def=Def},
 
189
          XsiLink = #xsi_link{number=Key},
 
190
 
 
191
          %% Add a vertex to the Xsi Graph
 
192
          ?GRAPH:add_vertex(XsiGraph,Key,Xsi),
 
193
          pp_debug(" Inserting Xsi: ",[]),pp_xsi(Xsi),
 
194
 
 
195
          Label = Xsi#xsi.label,
 
196
          case BlockLabel == Label of
 
197
            false ->
 
198
              %% Insert the Xsi in the appropriate block
 
199
              Code = hipe_bb:code(?CFG:bb(Cfg,Label)),
 
200
              {BeforeCode,AfterCode} = split_for_xsi(lists:reverse(Code),[]),
 
201
              NewCode = BeforeCode++[XsiLink|AfterCode],
 
202
              NewBB = hipe_bb:mk_bb(NewCode),
 
203
              NewCfg = ?CFG:bb_add(Cfg,Label,NewBB),
 
204
              NewVisited = [NewInst|VisitedInstructions];
 
205
            _->
 
206
              {BeforeCode,AfterCode} = split_for_xsi(VisitedInstructions,[]),
 
207
              TempVisited = BeforeCode++[XsiLink|AfterCode],
 
208
              TempVisited2 = lists:reverse(TempVisited),
 
209
              NewVisited = [NewInst|TempVisited2],
 
210
              NewCfg = Cfg
 
211
          end,
 
212
          find_definition_for_computations_in_block(BlockLabel, Rest, NewCfg,
 
213
                                                    NewVisited, XsiGraph)
 
214
      end;
 
215
    _ ->
 
216
      %%pp_debug("~n [L~w] Not concerned with: ~w",[BlockLabel,Inst]),
 
217
      %% If the instruction is not a SSAPRE candidate, we skip it and keep on
 
218
      %% processing instructions
 
219
      %% Prepend Inst, so that we have all in reverse order.
 
220
      %% Easy to parse backwards
 
221
      find_definition_for_computations_in_block(BlockLabel, Rest, Cfg,
 
222
                                                [Inst|VisitedInstructions], XsiGraph)
 
223
  end.
 
224
 
 
225
%% ############################################################################
 
226
%% We have E as an expression, I has an alu (arithmetic operation), and
 
227
%% we inspect backwards the previous instructions to find a definition for E.
 
228
%% Since we parse in forward order, we know that the previous SSAPRE 
 
229
%% instruction will have a definition.
 
230
 
 
231
check_definition(E,[],BlockLabel,Cfg,XsiGraph)->
 
232
  %% No more instructions in that block
 
233
  %% No definition found in that block
 
234
  %% Search is previous blocks
 
235
  Preds = ?CFG:pred(?CFG:pred_map(Cfg),BlockLabel),
 
236
  %%  pp_debug("~n CHECKING DEFINITION  ####### Is L~w a merge block? It has ~w preds. So far E=",[BlockLabel,length(Preds)]),pp_expr(E),
 
237
  case Preds of
 
238
    [] ->
 
239
      %% Entry Point
 
240
      {def_found,bottom};
 
241
    [P] ->
 
242
      %% One predecessor only, we just keep looking for a definition in that block
 
243
      VisitedInstructions = lists:reverse(hipe_bb:code(?CFG:bb(Cfg,P))),
 
244
      check_definition(E,VisitedInstructions,P,Cfg,XsiGraph);
 
245
    _ ->
 
246
      Temp = new_temp(),
 
247
      %% It's a merge point
 
248
      OpList = [#xsi_op{pred=X} || X<-Preds],
 
249
      Xsi = #xsi{inst=E,def=Temp,label=BlockLabel,opList=OpList},
 
250
      {merge_point,Xsi} 
 
251
  end;
 
252
check_definition(E,[CC|Rest],BlockLabel,Cfg,XsiGraph) ->
 
253
  SRC1 = ?RTL:alu_src1(E),
 
254
  SRC2 = ?RTL:alu_src2(E),
 
255
  case CC of
 
256
    #alu{} ->
 
257
      exit({?MODULE,should_not_be_an_alu,
 
258
            {"Why the hell do we still have an alu???",CC}});
 
259
    #pre_candidate{} ->
 
260
      %% C is the previous instruction
 
261
      C = CC#pre_candidate.alu,
 
262
      DST = ?RTL:alu_dst(C),
 
263
      case DST==SRC1 orelse DST==SRC2 of
 
264
        false ->
 
265
          case check_match(E,C) of
 
266
            true -> %% It's a computation of E!
 
267
              %% Get the dst of the alu
 
268
              {def_found,DST};
 
269
            _->
 
270
              check_definition(E,Rest,BlockLabel,Cfg,XsiGraph)
 
271
          end;
 
272
        true ->
 
273
          %% Get the definition of C, since C is PRE-candidate AND has been processed before
 
274
          DEF = CC#pre_candidate.def,
 
275
          case DEF of
 
276
            bottom -> 
 
277
              %% Def(E)=bottom, STOP
 
278
              {def_found,bottom};
 
279
            _ -> 
 
280
              %% Emend E with this def(C)
 
281
              %%pp_debug("Parameters are E=~w, DST=~w, DEF=~w",[E,DST,DEF]),
 
282
              F=emend(E,DST,DEF),
 
283
              check_definition(F,Rest,BlockLabel,Cfg,XsiGraph) %% Continue the search
 
284
          end
 
285
      end;
 
286
    #move{} ->
 
287
      %% It's a move, we emend E, and continue the definition search
 
288
      DST = ?RTL:move_dst(CC),
 
289
      F = case SRC1==DST orelse SRC2==DST of
 
290
            true ->
 
291
              SRC = ?RTL:move_src(CC),
 
292
              emend(E,DST,SRC);
 
293
            _ ->
 
294
              E
 
295
          end,
 
296
      check_definition(F,Rest,BlockLabel,Cfg,XsiGraph); %% Continue the search
 
297
    #xsi_link{} ->
 
298
      {_K,Xsi} = ?GRAPH:vertex(XsiGraph,CC#xsi_link.number),
 
299
      C = Xsi#xsi.inst,
 
300
      case check_match(C,E) of
 
301
        true -> %% There is a Xsi already with a computation of E!
 
302
          %% fetch definition of C, and give it to E
 
303
          {def_found,Xsi#xsi.def};
 
304
        _->
 
305
          check_definition(E,Rest,BlockLabel,Cfg,XsiGraph)
 
306
      end;
 
307
    #phi{} -> 
 
308
      %% skip them. NOTE: Important to separate this case from the next one
 
309
      check_definition(E,Rest,BlockLabel,Cfg,XsiGraph);
 
310
    _ ->
 
311
      %% Note: the function calls or some other instructions can change the pre-coloured registers
 
312
      %% which are able to be redefined. This breaks of course the SSA form.
 
313
      %% If there is a redefinition we can give bottom to the computation, and no xsi will be inserted.
 
314
      %% (In some sens, the result of the computation is new at that point.)
 
315
      PreColouredTest = ?ARCH:is_precoloured(SRC1) orelse ?ARCH:is_precoloured(SRC2),
 
316
 
 
317
      %%RegisterTest = ?RTL:is_reg(?RTL:alu_dst(E)) orelse ?RTL:is_reg(SRC1) orelse ?RTL:is_reg(SRC2),
 
318
      RegisterTest = ?RTL:is_reg(?RTL:alu_dst(E)), %% That means we cannot reuse the result held in this register...
 
319
 
 
320
      case PreColouredTest orelse RegisterTest of
 
321
        true ->
 
322
          {def_found,bottom};
 
323
        false ->
 
324
          DC = ?RTL:defines(CC),
 
325
          case lists:member(SRC1,DC) orelse lists:member(SRC2,DC) of
 
326
            true ->
 
327
              {def_found,bottom};
 
328
            false ->
 
329
              %% Orthogonal to E, we continue the search
 
330
              check_definition(E,Rest,BlockLabel,Cfg,XsiGraph)
 
331
          end
 
332
      end
 
333
  end.
 
334
 
 
335
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
336
 
 
337
check_match(E, C) ->
 
338
  OpE = ?RTL:alu_op(E),
 
339
  OpC = ?RTL:alu_op(C),
 
340
  case OpE == OpC of
 
341
    false ->
 
342
      false;
 
343
    true ->
 
344
      Src1E = ?RTL:alu_src1(E),
 
345
      Src2E = ?RTL:alu_src2(E),
 
346
      Src1C = ?RTL:alu_src1(C),
 
347
      Src2C = ?RTL:alu_src2(C),
 
348
      case Src1E == Src1C of
 
349
        true ->
 
350
          Src2E == Src2C;
 
351
        false ->
 
352
          case Src1E == Src2C of
 
353
            true ->
 
354
              Src2E == Src1C;
 
355
            false ->
 
356
              false
 
357
          end
 
358
      end
 
359
  end.
 
360
 
 
361
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
362
 
 
363
expr_is_constant(E) ->
 
364
  ?RTL:is_imm(?RTL:alu_src1(E)) andalso ?RTL:is_imm(?RTL:alu_src2(E)).
 
365
%%  is_number(?RTL:alu_src1(E)) andalso is_number(?RTL:alu_src2(E)).
 
366
 
 
367
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
368
%% Must be an arithmetic operation, i.e. #alu{}
 
369
emend(Expr, S, Var) ->
 
370
  SRC1 = ?RTL:alu_src1(Expr),
 
371
  NewExpr = case SRC1 == S of
 
372
              true  -> ?RTL:alu_src1_update(Expr,Var);
 
373
              false -> Expr
 
374
            end,
 
375
  SRC2 = ?RTL:alu_src2(NewExpr),
 
376
  NewExpr2 = case SRC2 == S of
 
377
               true  -> ?RTL:alu_src2_update(NewExpr,Var);
 
378
               false -> NewExpr
 
379
             end,
 
380
  NewExpr2.
 
381
 
 
382
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
383
 
 
384
split_for_xsi([], Acc) ->
 
385
  {[],Acc};  %  no_xsi_no_phi_found;
 
386
split_for_xsi([I|Rest], Acc) -> %% [I|Rest] in backward order, Acc in order
 
387
  case I of
 
388
    #xsi_link{} ->
 
389
      BeforeCode = [I|Rest],
 
390
      {lists:reverse(BeforeCode), Acc};
 
391
    #phi{} ->
 
392
      BeforeCode = [I|Rest],
 
393
      {lists:reverse(BeforeCode), Acc};
 
394
    _ ->
 
395
      split_for_xsi(Rest,[I|Acc])
 
396
  end.
 
397
 
 
398
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
399
%% Phase 1.B : Search for operands
 
400
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
401
 
 
402
find_operands(Cfg,XsiGraph,[],_Count) ->
 
403
  {Cfg,XsiGraph};
 
404
find_operands(Cfg,XsiGraph,ActiveList,Count) ->
 
405
  {NewCfg,TempActiveList} = find_operands_for_active_list(Cfg,XsiGraph,ActiveList,[]),
 
406
  NewActiveList = lists:reverse(TempActiveList),
 
407
  pp_debug("~n################ Finding operands (iteration ~w): ~w have been introduced. Now ~w in total~n",
 
408
           [Count+1, length(NewActiveList), length(?GRAPH:vertices(XsiGraph))]),
 
409
  find_operands(NewCfg,XsiGraph,NewActiveList,Count+1).
 
410
 
 
411
find_operands_for_active_list(Cfg,_XsiGraph,[],ActiveListAcc) ->
 
412
  {Cfg,ActiveListAcc};
 
413
find_operands_for_active_list(Cfg,XsiGraph,[K|Ks],ActiveListAcc) ->
 
414
  {_Key,Xsi} = ?GRAPH:vertex(XsiGraph,K),
 
415
  pp_debug("~n Inspecting operands of : ~n",[]),pp_xsi(Xsi),
 
416
  Preds = ?CFG:pred(?CFG:pred_map(Cfg),Xsi#xsi.label),
 
417
  {NewCfg,NewActiveListAcc}=determine_operands(Xsi,Preds,Cfg,K,XsiGraph,ActiveListAcc),
 
418
  {_Key2,Xsi2} = ?GRAPH:vertex(XsiGraph,K),
 
419
  pp_debug("~n ** Final Xsi: ~n",[]),pp_xsi(Xsi2),
 
420
  pp_debug("~n #####################################################~n",[]),
 
421
  find_operands_for_active_list(NewCfg,XsiGraph,Ks,NewActiveListAcc).
 
422
 
 
423
determine_operands(_Xsi,[],Cfg,_K,_XsiGraph,ActiveAcc) ->
 
424
  %% All operands have been determined.
 
425
  %% The CFG is not updated, only the XsiGraph
 
426
  {Cfg,ActiveAcc};
 
427
determine_operands(Xsi,[P|Ps],Cfg,K,XsiGraph,ActiveAcc) ->
 
428
  Label = Xsi#xsi.label,
 
429
  ReverseCode = lists:reverse(hipe_bb:code(?CFG:bb(Cfg,Label))),
 
430
  VisitedInstructions = get_visited_instructions(Xsi,ReverseCode),
 
431
  Res = determine_e_prime(Xsi#xsi.inst,VisitedInstructions,P,XsiGraph),
 
432
 
 
433
  case Res of
 
434
    operand_is_bottom ->
 
435
      NewXsi = xsi_arg_update(Xsi,P,new_bottom()),
 
436
      ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
437
      determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);
 
438
    operand_is_const_expr ->
 
439
      NewXsi = xsi_arg_update(Xsi,P,new_bottom()),
 
440
      ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
441
      determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);
 
442
    {sharing_operand,Op} ->
 
443
      NewXsi = xsi_arg_update(Xsi,P,Op),
 
444
      ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
445
      determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);  
 
446
    {revised_expression,E_prime} ->
 
447
      pp_debug(" E' is determined : ",[]),pp_expr(E_prime),
 
448
      pp_debug(" and going along the edge L~w~n",[P]),
 
449
      %% Go along the edge P
 
450
      RevCode = lists:reverse(hipe_bb:code(?CFG:bb(Cfg,P))),
 
451
      case check_one_operand(E_prime,RevCode,P,Cfg,K,XsiGraph) of
 
452
        {def_found,Def}->
 
453
          NewXsi = xsi_arg_update(Xsi,P,Def),
 
454
          ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
455
          determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);
 
456
 
 
457
        {expr_found,ChildExpr}->
 
458
          NewXsi = xsi_arg_update(Xsi,P,ChildExpr),
 
459
          ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
460
          determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);
 
461
 
 
462
        {expr_is_constant,Op}->
 
463
          %% We detected that the expression is of the form: 'N op M'
 
464
          %% where N and M are constant.
 
465
          NewXsi = xsi_arg_update(Xsi,P,Op),
 
466
          ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
467
          determine_operands(NewXsi,Ps,Cfg,K,XsiGraph,ActiveAcc);
 
468
 
 
469
        {merge_point,XsiChild}->
 
470
          %% Update that Xsi, give its definition as Operand for the
 
471
          %% search, and go on
 
472
          XsiChildDef = XsiChild#xsi.def,
 
473
          NewXsi = xsi_arg_update(Xsi,P,XsiChildDef),
 
474
          ?GRAPH:add_vertex(XsiGraph,K,NewXsi),
 
475
 
 
476
          KeyChild = XsiChildDef#temp.key,
 
477
          XsiChildLink = #xsi_link{number=KeyChild},
 
478
          ?GRAPH:add_vertex(XsiGraph,KeyChild,XsiChild),
 
479
 
 
480
          %% Should not be the same block !!!!!!!
 
481
          RCode = lists:reverse(hipe_bb:code(?CFG:bb(Cfg,XsiChild#xsi.label))),
 
482
          {BCode,ACode}=split_code_for_xsi(RCode,[]),
 
483
 
 
484
          NewCode = BCode++[XsiChildLink|ACode],
 
485
          NewBB = hipe_bb:mk_bb(NewCode),
 
486
          NewCfg = ?CFG:bb_add(Cfg, XsiChild#xsi.label, NewBB),
 
487
 
 
488
          pp_debug(" -- ",[]),pp_arg(Xsi#xsi.def),pp_debug(" causes insertion of: ~n",[]),pp_xsi(XsiChild),
 
489
          pp_debug(" -- Adding an edge ",[]),pp_arg(Xsi#xsi.def),pp_debug(" -> ",[]),pp_arg(XsiChild#xsi.def),
 
490
 
 
491
          %% Adding an edge...
 
492
          %%?GRAPH:add_edge(XsiGraph,K,KeyChild,"family"),
 
493
          ?GRAPH:add_edge(XsiGraph,K,KeyChild),
 
494
          determine_operands(NewXsi,Ps,NewCfg,K,XsiGraph,[KeyChild|ActiveAcc])
 
495
      end
 
496
  end.
 
497
 
 
498
determine_e_prime(Expr,VisitedInstructions,Pred,XsiGraph) ->
 
499
  %% MUST FETCH FROM THE XSI TREE, since Xsis are not updated yet in the CFG
 
500
  NewExpr=emend_with_phis(Expr,VisitedInstructions,Pred),
 
501
  emend_with_processed_xsis(NewExpr,VisitedInstructions,Pred,XsiGraph).
 
502
 
 
503
emend_with_phis(EmendedE, [], _) ->
 
504
  EmendedE;
 
505
emend_with_phis(E, [I|Rest], Pred) ->
 
506
  case I of
 
507
    #phi{} ->
 
508
      Dst = ?RTL:phi_dst(I),
 
509
      UE = ?RTL:uses(E), %% Should we get SRC1 and SRC2 instead?
 
510
      case lists:member(Dst, UE) of
 
511
        false ->
 
512
          emend_with_phis(E, Rest, Pred);
 
513
        true ->
 
514
          NewE = emend(E, Dst, ?RTL:phi_arg(I,Pred)),
 
515
          emend_with_phis(NewE, Rest, Pred)
 
516
      end;
 
517
    _ ->
 
518
      emend_with_phis(E, Rest, Pred)
 
519
  end.
 
520
 
 
521
emend_with_processed_xsis(EmendedE, [], _, _) ->
 
522
  {revised_expression,EmendedE};  
 
523
emend_with_processed_xsis(E, [I|Rest], Pred, XsiGraph) ->
 
524
  case I of
 
525
    #xsi_link{} ->
 
526
      Key = I#xsi_link.number,
 
527
      {_KK,Xsi} = ?GRAPH:vertex(XsiGraph,Key),
 
528
      Def = Xsi#xsi.def,
 
529
      UE = ?RTL:uses(E), %% Should we get SRC1 and SRC2 instead?
 
530
      case lists:member(Def,UE) of
 
531
        false ->
 
532
          CE = Xsi#xsi.inst,
 
533
          case check_match(E,CE) of
 
534
            true -> %% It's a computation of E!
 
535
              case xsi_arg(Xsi,Pred) of
 
536
                undetermined_operand ->
 
537
                  exit({?MODULE,check_operand_sharing,"######## �h Dear, we trusted Kostis !!!!!!!!! #############"});
 
538
                XsiOp ->
 
539
                  {sharing_operand,XsiOp} %% They share operands
 
540
              end;
 
541
            _->
 
542
              emend_with_processed_xsis(E,Rest,Pred,XsiGraph)
 
543
          end;
 
544
        true ->
 
545
          A=xsi_arg(Xsi,Pred),
 
546
          %%pp_debug(" ######### xsi_arg(I:~w,Pred:~w) = ~w~n",[I,Pred,A]),
 
547
          case A of
 
548
            #bottom{} ->
 
549
              operand_is_bottom;
 
550
            #const_expr{} ->
 
551
              operand_is_const_expr;
 
552
            #eop{} ->
 
553
              NewE = emend(E,Def,A#eop.var),
 
554
              emend_with_processed_xsis(NewE,Rest,Pred,XsiGraph);
 
555
            undetermined_operand ->
 
556
              exit({?MODULE,emend_with_processed_xsis,"######## �h Dear, we trusted Kostis, again !!!!!!!!! #############"});
 
557
            XsiOp ->
 
558
              NewE = emend(E,Def,XsiOp),
 
559
              emend_with_processed_xsis(NewE,Rest,Pred,XsiGraph)
 
560
          end
 
561
      end;
 
562
    _ ->
 
563
      emend_with_processed_xsis(E,Rest,Pred,XsiGraph)
 
564
  end.
 
565
 
 
566
%% get_visited_instructions(Xsi,[]) ->
 
567
%%   pp_debug("~nWe don't find this xsi with def ",[]),pp_arg(Xsi#xsi.def),pp_debug(" in L~w : ",[Xsi#xsi.label]),
 
568
%%   exit({?MODULE,no_such_xsi_in_block,"We didn't find that Xsi in the block"});
 
569
get_visited_instructions(Xsi,[I|Rest]) ->
 
570
  case I of
 
571
    #xsi_link{} ->
 
572
      XsiDef = Xsi#xsi.def,
 
573
      Key = XsiDef#temp.key,
 
574
      case I#xsi_link.number == Key of
 
575
        true ->
 
576
          Rest;
 
577
        false ->
 
578
          get_visited_instructions(Xsi,Rest)
 
579
      end;
 
580
    _ ->
 
581
      get_visited_instructions(Xsi,Rest)
 
582
  end.
 
583
 
 
584
split_code_for_xsi([], Acc) ->
 
585
  {[],Acc};
 
586
split_code_for_xsi([I|Rest], Acc) ->
 
587
  case I of
 
588
    #xsi_link{} ->
 
589
      {lists:reverse([I|Rest]),Acc};
 
590
    #phi{} ->
 
591
      {lists:reverse([I|Rest]),Acc};
 
592
    _ ->
 
593
      split_code_for_xsi(Rest,[I|Acc])
 
594
  end.
 
595
 
 
596
check_one_operand(E, [], BlockLabel, Cfg, XsiKey, XsiGraph) ->
 
597
  %% No more instructions in that block
 
598
  %% No definition found in that block
 
599
  %% Search is previous blocks
 
600
  Preds = ?CFG:pred(?CFG:pred_map(Cfg), BlockLabel),
 
601
  case Preds of
 
602
    [] ->
 
603
      %% Entry Point
 
604
      {def_found,new_bottom()};
 
605
    [P] ->
 
606
      %% One predecessor only, we just keep looking for a definition in that block
 
607
      case expr_is_constant(E) of
 
608
        true ->
 
609
          pp_debug("\n\n############## Wow expr is constant: ~w",[E]),
 
610
          Var = ?RTL:mk_new_var(),
 
611
          Value = eval_expr(E),
 
612
          Op = #const_expr{var=Var,value=Value},
 
613
          {expr_is_constant,Op};
 
614
        false ->
 
615
          VisitedInstructions = lists:reverse(?BB:code(?CFG:bb(Cfg,P))),
 
616
          check_one_operand(E,VisitedInstructions,P,Cfg,XsiKey,XsiGraph)
 
617
      end;
 
618
    _ ->
 
619
      %% It's a merge point
 
620
      case expr_is_constant(E) of
 
621
        true ->
 
622
          pp_debug("\n\n############## Wow expr is constant at merge point: ~w",[E]),
 
623
          Var = ?RTL:mk_new_var(),
 
624
          Value = eval_expr(E),
 
625
          Op = #const_expr{var=Var,value=Value},
 
626
          {expr_is_constant,Op};
 
627
        false ->
 
628
          Temp = new_temp(),
 
629
          OpList = [#xsi_op{pred=X} || X <- Preds],
 
630
          Xsi = #xsi{inst=E,def=Temp,label=BlockLabel,opList=OpList},
 
631
          {merge_point,Xsi}
 
632
      end
 
633
  end;
 
634
check_one_operand(E,[CC|Rest],BlockLabel,Cfg,XsiKey,XsiGraph) ->
 
635
  SRC1 = ?RTL:alu_src1(E),
 
636
  SRC2 = ?RTL:alu_src2(E),
 
637
  %% C is the previous instruction
 
638
  case CC of
 
639
    #alu{} ->
 
640
      exit({?MODULE,should_not_be_an_alu,
 
641
            {"Why the hell do we still have an alu???",CC}});
 
642
    #xsi{} ->
 
643
      exit({?MODULE,should_not_be_a_xsi,
 
644
            {"Why the hell do we still have a xsi???",CC}});
 
645
    #pre_candidate{} ->
 
646
      C = CC#pre_candidate.alu,
 
647
      DST = ?RTL:alu_dst(C),
 
648
      case DST==SRC1 orelse DST==SRC2 of
 
649
        true ->
 
650
          %% Get the definition of C, since C is PRE-candidate AND has
 
651
          %% been processed before
 
652
          DEF = CC#pre_candidate.def,
 
653
          case DEF of
 
654
            bottom -> 
 
655
              %% Def(E)=bottom, STOP
 
656
              %% No update of the XsiGraph
 
657
              {def_found,new_bottom()};
 
658
            _->
 
659
              %% Simply emend
 
660
              F = emend(E,DST,DEF),
 
661
              pp_debug("~nEmendation : E= ",[]),pp_expr(E),pp_debug(" ==> E'= ",[]),pp_expr(F),pp_debug("~n",[]),
 
662
              check_one_operand(F,Rest,BlockLabel,Cfg,XsiKey,XsiGraph)
 
663
          end;
 
664
        false ->
 
665
          case check_match(C,E) of
 
666
            true -> %% It's a computation of E!
 
667
              %% It should give DST and not Def
 
668
              %% No update of the XsiGraph, cuz we use DST and not Def
 
669
              %% The operand is therefore gonna be a real variable
 
670
              {def_found,DST};
 
671
            _->
 
672
              %% Nothing to do with E
 
673
              check_one_operand(E,Rest,BlockLabel,Cfg,XsiKey,XsiGraph)
 
674
          end
 
675
      end;
 
676
    #move{} ->
 
677
      %% It's a move, we emend E, and continue the definition search
 
678
      DST = ?RTL:move_dst(CC),
 
679
      case SRC1==DST orelse SRC2==DST of
 
680
        true ->
 
681
          SRC = ?RTL:move_src(CC),
 
682
          F = emend(E,DST,SRC),
 
683
          check_one_operand(F,Rest,BlockLabel,Cfg,XsiKey,XsiGraph); %% Continue the search
 
684
        _ ->
 
685
          check_one_operand(E,Rest,BlockLabel,Cfg,XsiKey,XsiGraph) %% Continue the search
 
686
      end;
 
687
    #xsi_link{} ->
 
688
      Key = CC#xsi_link.number,
 
689
      %% Is Key a family member of XsiDef ?
 
690
      {_KK,Xsi} = ?GRAPH:vertex(XsiGraph,Key),
 
691
      C = Xsi#xsi.inst,
 
692
      case check_match(E,C) of
 
693
        true -> %% There is a Xsi already with a computation of E!
 
694
          %% fetch definition of C, and give it to E
 
695
          %% Must update an edge in the XsiGraph, and here, we know it's a Temp
 
696
          %% Note: this can create a loop (= a cycle of length 1)
 
697
          pp_debug(" -- Found a cycle with match: Adding an edge t~w -> t~w",[XsiKey,Key]),
 
698
          ?GRAPH:add_edge(XsiGraph,XsiKey,Key),
 
699
          {def_found,Xsi#xsi.def};
 
700
        _ ->
 
701
          case ?GRAPH:get_path(XsiGraph,Key,XsiKey) of 
 
702
            false ->
 
703
              %% Is it a loop back to itself???
 
704
              case Key==XsiKey of 
 
705
                false ->
 
706
                  check_one_operand(E,Rest,BlockLabel,Cfg,XsiKey,XsiGraph);
 
707
                _ ->
 
708
                  {expr_found,#eop{expr=E,var=?RTL:mk_new_var(),stopped_by=Key}}
 
709
              end;
 
710
            _ ->
 
711
              %% Returning the expression instead of looping
 
712
              %% And in case of no match
 
713
              ExprOp = #eop{expr=E,var=?RTL:mk_new_var(),stopped_by=Key},
 
714
              {expr_found,ExprOp}
 
715
          end
 
716
      end;
 
717
    #phi{} -> %% skip them
 
718
      check_one_operand(E,Rest,BlockLabel,Cfg,XsiKey,XsiGraph);
 
719
    _ ->
 
720
      PreColouredTest = ?ARCH:is_precoloured(SRC1) orelse ?ARCH:is_precoloured(SRC2),
 
721
 
 
722
      %%RegisterTest = ?RTL:is_reg(?RTL:alu_dst(E)) orelse ?RTL:is_reg(SRC1) orelse ?RTL:is_reg(SRC2),
 
723
      RegisterTest = ?RTL:is_reg(?RTL:alu_dst(E)),
 
724
 
 
725
      case PreColouredTest orelse RegisterTest of
 
726
        true ->
 
727
          {def_found,new_bottom()};
 
728
        _->
 
729
          DC = ?RTL:defines(CC),
 
730
          case lists:member(SRC1,DC) orelse lists:member(SRC2,DC) of
 
731
            true ->
 
732
              {def_found,new_bottom()};
 
733
            _ ->
 
734
              %% Orthogonal to E, we continue the search
 
735
              check_one_operand(E,Rest,BlockLabel,Cfg,XsiKey,XsiGraph)
 
736
          end
 
737
      end
 
738
  end.
 
739
 
 
740
eval_expr(E) ->
 
741
  pp_debug("~n Evaluating the result of ~w~n", [E]),
 
742
  Op1 = ?RTL:alu_src1(E),
 
743
  Op2 = ?RTL:alu_src2(E),
 
744
  Val1 = case ?RTL:is_imm(Op1) of
 
745
           true -> ?RTL:imm_value(Op1)
 
746
         end,    
 
747
  Val2 = case ?RTL:is_imm(Op2) of
 
748
           true -> ?RTL:imm_value(Op2)
 
749
         end,    
 
750
  {Result, _Sign, _Zero, _Overflow, _Carry} = ?ARCH:eval_alu(?RTL:alu_op(E), Val1, Val2),
 
751
  pp_debug("~n Result is then ~w~n", [Result]),
 
752
  ?RTL:mk_imm(Result).
 
753
 
 
754
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
755
%%%%%%%%%%%%%%%%%%%%%%%%%%  CREATTING CFGGRAPH  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
756
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
757
 
 
758
create_cfggraph([],_Cfg,CFGGraph,ToBeFactorizedAcc,MPAcc,LateEdges,_XsiGraph) ->
 
759
  pp_debug("~n~n ############# PostProcessing ~n~w~n",[LateEdges]),
 
760
  post_process(LateEdges,CFGGraph),
 
761
  pp_debug("~n~n ############# Factorizing ~n~w~n",[ToBeFactorizedAcc]),
 
762
  factorize(ToBeFactorizedAcc,CFGGraph),
 
763
  MPAcc;
 
764
create_cfggraph([Label|Ls],Cfg,CFGGraph,ToBeFactorizedAcc,MPAcc,LateEdges,XsiGraph) ->
 
765
  Preds = ?CFG:pred(?CFG:pred_map(Cfg),Label),
 
766
  case Preds of
 
767
    [] ->
 
768
      exit({?MODULE,do_not_call_on_top,{"Why the hell do we call that function on the start label???",Label}});
 
769
    [P] ->
 
770
      Code = ?BB:code(?CFG:bb(Cfg,Label)),
 
771
      Defs = get_defs_in_non_merge_block(Code,[]),
 
772
      pp_debug("~nAdding a vertex for ~w",[Label]),
 
773
      Succs = ?CFG:succ(?CFG:succ_map(Cfg),Label),
 
774
      case Succs of
 
775
        [] -> %% Exit point
 
776
          ?GRAPH:add_vertex(CFGGraph,Label,#block{type=exit}),
 
777
          NewToBeFactorizedAcc=ToBeFactorizedAcc;
 
778
        _ -> %% Split point
 
779
          ?GRAPH:add_vertex(CFGGraph,Label,#block{type=not_mp,attributes={P,Succs}}),
 
780
          NewToBeFactorizedAcc=[Label|ToBeFactorizedAcc]
 
781
      end,
 
782
      pp_debug("~nAdding an edge ~w -> ~w (~w)",[P,Label,Defs]),
 
783
      case ?GRAPH:add_edge(CFGGraph,P,Label,Defs) of
 
784
        {error,Reason} ->
 
785
          exit({?MODULE,forget_that_for_christs_sake_bingwen_please,{"Bad edge",Reason}});
 
786
        _ ->
 
787
          ok
 
788
      end,
 
789
      create_cfggraph(Ls,Cfg,CFGGraph,NewToBeFactorizedAcc,MPAcc,LateEdges,XsiGraph);
 
790
    _ -> %% Merge point
 
791
      Code = ?BB:code(?CFG:bb(Cfg,Label)),
 
792
      {Defs,Xsis,Maps,Uses} = get_info_in_merge_block(Code,XsiGraph,[],[],gb_trees:empty(),gb_trees:empty()),
 
793
      Attributes = #mp{preds=Preds,xsis=Xsis,defs=Defs,maps=Maps,uses=Uses},
 
794
      MergeBlock = #block{type=mp,attributes=Attributes},
 
795
      pp_debug("~nAdding a vertex for ~w with Defs= ~w",[Label,Defs]),
 
796
      ?GRAPH:add_vertex(CFGGraph,Label,MergeBlock),
 
797
      %% Add edges
 
798
      NewLateEdges = add_edges_for_mp(Preds,Label,LateEdges),
 
799
      create_cfggraph(Ls,Cfg,CFGGraph,ToBeFactorizedAcc,[Label|MPAcc],NewLateEdges,XsiGraph)
 
800
  end.
 
801
 
 
802
get_defs_in_non_merge_block([], Acc) ->
 
803
  ?SETS:from_list(Acc);
 
804
get_defs_in_non_merge_block([Inst|Rest], Acc) ->
 
805
  case Inst of
 
806
    #pre_candidate{} ->
 
807
      Def = Inst#pre_candidate.def,
 
808
      case Def of
 
809
        #temp{}->
 
810
          %%        {temp,Key,_Var}->
 
811
          %%          get_defs_in_non_merge_block(Rest,[Key|Acc]);
 
812
          get_defs_in_non_merge_block(Rest,[Def#temp.key|Acc]);
 
813
        _-> %% Real variables or bottom
 
814
          get_defs_in_non_merge_block(Rest,Acc)
 
815
      end;
 
816
    _  ->
 
817
      get_defs_in_non_merge_block(Rest,Acc)
 
818
  end.
 
819
 
 
820
get_info_in_merge_block([],_XsiGraph,Defs,Xsis,Maps,Uses) ->
 
821
  {?SETS:from_list(Defs),Xsis,Maps,Uses}; %% Xsis are in backward order
 
822
get_info_in_merge_block([Inst|Rest],XsiGraph,Defs,Xsis,Maps,Uses) ->
 
823
  case Inst of
 
824
    #pre_candidate{} ->
 
825
      Def = Inst#pre_candidate.def,
 
826
      case Def of
 
827
        #temp{} ->
 
828
          get_info_in_merge_block(Rest,XsiGraph,[Def#temp.key|Defs],Xsis,Maps,Uses);
 
829
        _ ->
 
830
          get_info_in_merge_block(Rest,XsiGraph,Defs,Xsis,Maps,Uses)
 
831
      end;
 
832
    #xsi_link{} ->
 
833
      Key = Inst#xsi_link.number,
 
834
      {_Key,Xsi} = ?GRAPH:vertex(XsiGraph,Key),
 
835
      OpList = xsi_oplist(Xsi),
 
836
      {NewMaps,NewUses} = add_map_and_uses(OpList,Key,Maps,Uses),
 
837
      get_info_in_merge_block(Rest,XsiGraph,Defs,[Key|Xsis],NewMaps,NewUses);
 
838
    _  ->
 
839
      get_info_in_merge_block(Rest,XsiGraph,Defs,Xsis,Maps,Uses)
 
840
  end.
 
841
 
 
842
add_edges_for_mp([], _Label, LateEdges) ->
 
843
  LateEdges;
 
844
add_edges_for_mp([P|Ps], Label, LateEdges) ->
 
845
  add_edges_for_mp(Ps,Label,[{P,Label}|LateEdges]).
 
846
 
 
847
%% Doesn't do anything so far
 
848
add_map_and_uses([], _Key, Maps, Uses) ->
 
849
  {Maps,Uses};
 
850
add_map_and_uses([XsiOp|Ops], Key, Maps, Uses) ->
 
851
  case XsiOp#xsi_op.op of
 
852
    #bottom{} ->
 
853
      Set = case gb_trees:lookup(XsiOp,Maps) of
 
854
              {value,V} ->
 
855
                ?SETS:add_element(Key,V);
 
856
              none ->
 
857
                ?SETS:from_list([Key])
 
858
            end,
 
859
      NewMaps = gb_trees:enter(XsiOp,Set,Maps),
 
860
      NewUses = Uses;
 
861
    #temp{} ->
 
862
      Set = case gb_trees:lookup(XsiOp,Maps) of
 
863
              {value,V}->
 
864
                ?SETS:add_element(Key,V);
 
865
              none ->
 
866
                ?SETS:from_list([Key])
 
867
            end,
 
868
      NewMaps = gb_trees:enter(XsiOp,Set,Maps),
 
869
      Pred = XsiOp#xsi_op.pred,
 
870
      OOP = XsiOp#xsi_op.op,
 
871
      SSet = case gb_trees:lookup(Pred,Uses) of
 
872
               {value,VV} ->
 
873
                 ?SETS:add_element(OOP#temp.key,VV);
 
874
               none ->
 
875
                 ?SETS:from_list([OOP#temp.key])
 
876
             end,
 
877
      NewUses = gb_trees:enter(Pred,SSet,Uses);
 
878
    #eop{} ->
 
879
      Set = case gb_trees:lookup(XsiOp,Maps) of
 
880
              {value,V} ->
 
881
                ?SETS:add_element(Key,V);
 
882
              none ->
 
883
                ?SETS:from_list([Key])
 
884
            end,
 
885
      NewMaps = gb_trees:enter(XsiOp,Set,Maps),
 
886
      Pred = XsiOp#xsi_op.pred,
 
887
      Op = XsiOp#xsi_op.op,
 
888
      SSet = case gb_trees:lookup(Pred,Uses) of
 
889
               {value,VV}->
 
890
                 ?SETS:add_element(Op#eop.stopped_by,VV);
 
891
               none ->
 
892
                 ?SETS:from_list([Op#eop.stopped_by])
 
893
             end,
 
894
      NewUses = gb_trees:enter(Pred,SSet,Uses);
 
895
    _->
 
896
      NewMaps = Maps,
 
897
      NewUses = Uses
 
898
  end,
 
899
  add_map_and_uses(Ops, Key, NewMaps, NewUses).
 
900
 
 
901
post_process([], _CFGGraph) -> ok;
 
902
post_process([E|Es], CFGGraph) ->
 
903
  {Pred,Label} = E,
 
904
  {_PP,Block} = ?GRAPH:vertex(CFGGraph,Label),
 
905
  Att = Block#block.attributes,
 
906
  Uses = Att#mp.uses,
 
907
  SetToAdd = case gb_trees:lookup(Pred,Uses) of
 
908
               {value,Set}->
 
909
                 Set;
 
910
               none ->
 
911
                 ?SETS:new()
 
912
             end,
 
913
  %%pp_debug("~nAdding an edge ~w -> ~w (~w)",[Pred,Label,SetToAdd]),
 
914
  ?GRAPH:add_edge(CFGGraph, Pred, Label, SetToAdd),
 
915
  post_process(Es, CFGGraph).
 
916
 
 
917
factorize([], _CFGGraph) -> ok;
 
918
factorize([P|Ps], CFGGraph) ->
 
919
  [OE|OEs] = ?GRAPH:out_edges(CFGGraph,P),
 
920
  %%pp_debug("~nIn_degrees ~w : ~w",[P,?GRAPH:in_degree(CFGGraph,P)]),
 
921
  [InEdge] = ?GRAPH:in_edges(CFGGraph,P),
 
922
  {E,V1,V2,Label} = ?GRAPH:edge(CFGGraph,InEdge),
 
923
  {_OEE,_OEV1,_OEV2,LOE} = ?GRAPH:edge(CFGGraph,OE),
 
924
  List = shoot_info_upwards(OEs,LOE,CFGGraph),
 
925
  NewLabel = ?SETS:union(Label,List),
 
926
  ?GRAPH:add_edge(CFGGraph,E,V1,V2,NewLabel),
 
927
  factorize(Ps, CFGGraph).
 
928
 
 
929
shoot_info_upwards([], Acc, _CFGGraph) -> Acc;
 
930
shoot_info_upwards([E|Es], Acc, CFGGraph) ->
 
931
  {_E,_V1,_V2,Set} = ?GRAPH:edge(CFGGraph,E),
 
932
  NewAcc = ?SETS:intersection(Acc, Set),
 
933
  case ?SETS:size(NewAcc) of
 
934
    0 -> NewAcc;
 
935
    _ -> shoot_info_upwards(Es,NewAcc,CFGGraph)
 
936
  end.
 
937
 
 
938
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
939
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  DOWNSAFETY   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
940
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
941
 
 
942
perform_downsafety([],_G,_XsiG) ->
 
943
  ok;
 
944
perform_downsafety([MP|MPs],G,XG) ->
 
945
  {V,Block} = ?GRAPH:vertex(G,MP),
 
946
  NDS = ?SETS:new(),
 
947
  Att = Block#block.attributes,
 
948
  Maps = Att#mp.maps,
 
949
  Defs = Att#mp.defs,
 
950
  OutEdges = ?GRAPH:out_edges(G,MP),
 
951
  %%pp_debug("~n Inspection Maps : ~w",[Maps]),
 
952
  NewNDS = parse_keys(gb_trees:keys(Maps),Maps,OutEdges,G,Defs,NDS,XG),
 
953
  NewAtt = Att#mp{ndsSet=NewNDS},
 
954
  ?GRAPH:add_vertex(G,V,Block#block{attributes=NewAtt}),
 
955
  pp_debug("~n Not Downsafe at L~w: ~w",[V,NewNDS]),
 
956
  %%io:format(standard_io,"~n Not Downsafe at L~w: ~w",[V,NewNDS]),
 
957
  perform_downsafety(MPs,G,XG).
 
958
 
 
959
parse_keys([], _Maps, _OutEdges, _G, _Defs, NDS, _XsiG) ->
 
960
  NDS;
 
961
parse_keys([M|Ms], Maps, OutEdges, G, Defs, NDS, XsiG) ->
 
962
  KillerSet = gb_trees:get(M,Maps),
 
963
  %%pp_debug("~n Inspection ~w -> ~w",[M,KillerSet]),
 
964
  TempSet = ?SETS:intersection(KillerSet,Defs),
 
965
  NewNDS = case ?SETS:size(TempSet) of
 
966
             0 -> getNDS(M,KillerSet,NDS,OutEdges,G,XsiG);
 
967
             _ ->
 
968
               %% One Xsi which has M as operand has killed it
 
969
               %% M is then Downsafe
 
970
               %% and is not added to the NotDownsafeSet (NDS)
 
971
               NDS
 
972
           end,
 
973
  parse_keys(Ms, Maps, OutEdges, G, Defs, NewNDS, XsiG).
 
974
 
 
975
getNDS(_M,_KillerSet,NDS,[],_G,_XsiG) ->
 
976
  NDS;
 
977
getNDS(M,KillerSet,NDS,[E|Es],G,XsiG) ->
 
978
  {_EE,_V1,_V2,Label} = ?GRAPH:edge(G,E),
 
979
  Set = ?SETS:intersection(KillerSet,Label),
 
980
  %%   pp_debug("~n ######## Intersection between KillerSet: ~w and Label: ~w",[KillerSet,Label]),
 
981
  %%   pp_debug("~n ######## ~w",[Set]),
 
982
  case ?SETS:size(Set) of
 
983
    0 ->
 
984
      %% M is not downsafe
 
985
      ?SETS:add_element(M,NDS);
 
986
    _ ->
 
987
      %% Try the other edges
 
988
      getNDS(M,KillerSet,NDS,Es,G,XsiG)
 
989
  end.
 
990
 
 
991
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
992
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  WILL BE AVAILABLE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
993
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
994
 
 
995
perform_will_be_available(XsiGraph,CFGGraph,Options) ->
 
996
  Keys = ?GRAPH:vertices(XsiGraph),
 
997
  pp_debug("~n############ Can Be Available ##########~n",[]),
 
998
  ?option_time(perform_can_be_available(Keys,XsiGraph,CFGGraph),"RTL A-SSAPRE WillBeAvailable - Compute CanBeAvailable",Options),
 
999
  pp_debug("~n############ Later ##########~n",[]),
 
1000
  ?option_time(perform_later(Keys,XsiGraph),"RTL A-SSAPRE WillBeAvailable - Compute Later",Options).
 
1001
 
 
1002
perform_can_be_available([],_XsiGraph,_CFGGraph) -> ok;
 
1003
perform_can_be_available([Key|Keys],XsiGraph,CFGGraph) ->
 
1004
  {V,Xsi} = ?GRAPH:vertex(XsiGraph,Key),
 
1005
  case Xsi#xsi.cba of
 
1006
    undefined ->
 
1007
      {_VV,Block} = ?GRAPH:vertex(CFGGraph,Xsi#xsi.label),
 
1008
      Att = Block#block.attributes,
 
1009
      NDS = Att#mp.ndsSet,
 
1010
      OpList = ?SETS:from_list(xsi_oplist(Xsi)),
 
1011
      Set = ?SETS:intersection(NDS,OpList),
 
1012
      case ?SETS:size(Set) of
 
1013
        0 ->
 
1014
          ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{cba=true}),
 
1015
          perform_can_be_available(Keys,XsiGraph,CFGGraph);
 
1016
        _ ->
 
1017
          LIST = [X || #temp{key=X} <- ?SETS:to_list(Set)],
 
1018
          case LIST of
 
1019
            [] ->
 
1020
              ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{cba=false}),
 
1021
              ImmediateParents = ?GRAPH:in_neighbours(XsiGraph,Key),
 
1022
              propagate_cba(ImmediateParents,XsiGraph,Xsi#xsi.def,CFGGraph);
 
1023
            _ ->
 
1024
              ok
 
1025
          end,
 
1026
          perform_can_be_available(Keys,XsiGraph,CFGGraph)
 
1027
      end;
 
1028
    _ -> %% True or False => recurse
 
1029
      perform_can_be_available(Keys,XsiGraph,CFGGraph)
 
1030
  end.
 
1031
 
 
1032
propagate_cba([],_XG,_Def,_CFGG) -> ok;
 
1033
propagate_cba([IPX|IPXs],XsiGraph,XsiDef,CFGGraph) ->
 
1034
  {V,IPXsi} = ?GRAPH:vertex(XsiGraph,IPX),
 
1035
  {_VV,Block} = ?GRAPH:vertex(CFGGraph,IPXsi#xsi.label),
 
1036
  Att = Block#block.attributes,
 
1037
  NDS = Att#mp.ndsSet,
 
1038
  List = ?SETS:to_list(?SETS:intersection(NDS,?SETS:from_list(xsi_oplist(IPXsi)))),
 
1039
  case IPXsi#xsi.cba of
 
1040
    false -> ok;
 
1041
    _ ->
 
1042
      case lists:keymember(XsiDef,#xsi_op.op,List) of
 
1043
        true ->
 
1044
          ?GRAPH:add_vertex(XsiGraph,V,IPXsi#xsi{cba=false}),
 
1045
          ImmediateParents = ?GRAPH:in_neighbours(XsiGraph,IPX),
 
1046
          propagate_cba(ImmediateParents,XsiGraph,IPXsi#xsi.def,CFGGraph);
 
1047
        _ ->
 
1048
          ok
 
1049
      end
 
1050
  end,
 
1051
  propagate_cba(IPXs,XsiGraph,XsiDef,CFGGraph).
 
1052
 
 
1053
perform_later([], _XsiGraph) -> ok;
 
1054
perform_later([Key|Keys], XsiGraph) ->
 
1055
  {V,Xsi} = ?GRAPH:vertex(XsiGraph,Key),
 
1056
  %% pp_debug("~n DEBUG : inspecting later of ~w (~w)~n",[Key,Xsi#xsi.later]),
 
1057
  case Xsi#xsi.later of
 
1058
    undefined ->
 
1059
      OpList = xsi_oplist(Xsi),
 
1060
      case parse_ops(OpList,fangpi) of  %% It means "fart" in chinese :D
 
1061
        has_temp ->
 
1062
          perform_later(Keys,XsiGraph);
 
1063
        has_real ->
 
1064
          case Xsi#xsi.cba of
 
1065
            true ->
 
1066
              ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{later=false,wba=true});
 
1067
            undefined ->
 
1068
              ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{later=false,wba=true});
 
1069
            _ ->
 
1070
              ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{later=false,wba=false})
 
1071
          end,
 
1072
          AllParents = digraph_utils:reaching([Key],XsiGraph),
 
1073
          pp_debug("~nPropagating to all parents of t~w: ~w",[Key,AllParents]),
 
1074
          propagate_later(AllParents,XsiGraph),
 
1075
          perform_later(Keys,XsiGraph);
 
1076
        _ -> %% Just contains bottoms and/or expressions
 
1077
          ?GRAPH:add_vertex(XsiGraph,V,Xsi#xsi{later=true}),
 
1078
          perform_later(Keys,XsiGraph)
 
1079
      end;
 
1080
    _ -> %% True or False => recurse
 
1081
      perform_later(Keys,XsiGraph)
 
1082
  end.
 
1083
 
 
1084
propagate_later([], _XG) -> ok;
 
1085
propagate_later([IPX|IPXs], XsiGraph) ->
 
1086
  {V,IPXsi} = ?GRAPH:vertex(XsiGraph,IPX),
 
1087
  case IPXsi#xsi.later of
 
1088
    false ->
 
1089
      pp_debug("~nThrough propagation, later of t~w is already reset",[IPX]),
 
1090
      propagate_later(IPXs,XsiGraph);
 
1091
    _ ->
 
1092
      pp_debug("~nThrough propagation, resetting later of t~w",[IPX]),
 
1093
      case IPXsi#xsi.cba of
 
1094
        true ->
 
1095
          ?GRAPH:add_vertex(XsiGraph,V,IPXsi#xsi{later=false,wba=true});
 
1096
        undefined ->
 
1097
          ?GRAPH:add_vertex(XsiGraph,V,IPXsi#xsi{later=false,wba=true});
 
1098
        _ ->
 
1099
          ?GRAPH:add_vertex(XsiGraph,V,IPXsi#xsi{later=false,wba=false})
 
1100
      end,
 
1101
      propagate_later(IPXs,XsiGraph)
 
1102
  end.
 
1103
 
 
1104
parse_ops([], Res) ->
 
1105
  Res;
 
1106
parse_ops([Op|Ops], Res) ->
 
1107
  case Op#xsi_op.op of
 
1108
    #temp{}->
 
1109
      NewRes = has_temp,
 
1110
      parse_ops(Ops,NewRes);
 
1111
    #bottom{} ->
 
1112
      parse_ops(Ops,Res);
 
1113
    #eop{} ->
 
1114
      parse_ops(Ops,Res);
 
1115
    _ ->
 
1116
      has_real
 
1117
  end.
 
1118
 
 
1119
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1120
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  CODE MOTION  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1121
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1122
 
 
1123
perform_code_motion([], Cfg, _XsiG) ->
 
1124
  Cfg;
 
1125
perform_code_motion([L|Labels], Cfg, XsiG) ->
 
1126
  Code=?BB:code(?CFG:bb(Cfg,L)),
 
1127
  pp_debug("~n################  Code Motion in L~w~n",[L]),
 
1128
  pp_debug("~nCode to move ~n",[]),
 
1129
  pp_instrs(Code,XsiG),
 
1130
  NewCfg = code_motion_in_block(L,Code,Cfg,XsiG,[],gb_trees:empty()),
 
1131
  pp_debug("~n################  Code Motion successful in L~w~n",[L]),
 
1132
  perform_code_motion(Labels,NewCfg,XsiG).
 
1133
 
 
1134
code_motion_in_block(Label,[],Cfg,_XsiG,Visited,InsertionsAcc) ->
 
1135
  InsertionsAlong = gb_trees:keys(InsertionsAcc),
 
1136
  Code = lists:reverse(Visited),
 
1137
  NewBB = ?BB:mk_bb(Code),
 
1138
  Cfg2 = ?CFG:bb_add(Cfg,Label,NewBB),
 
1139
  %% Must come after the bb_add, since redirect will update the Phis too...
 
1140
  Cfg3 = make_insertions(Label,InsertionsAlong,InsertionsAcc,Cfg2),
 
1141
  %%pp_debug("~nChecking the Code at L~w:~n~p",[Label,?BB:code(?CFG:bb(Cfg3,Label))]),
 
1142
  Cfg3;
 
1143
code_motion_in_block(L,[Inst|Insts],Cfg,XsiG,Visited,InsertionsAcc) ->
 
1144
  pp_debug("~nInspecting Inst : ~n",[]),pp_instr(Inst,XsiG),
 
1145
  case Inst of
 
1146
    #pre_candidate{} ->
 
1147
      Def = Inst#pre_candidate.def,
 
1148
      Alu = Inst#pre_candidate.alu,
 
1149
      case Def of
 
1150
        bottom ->
 
1151
          InstToAdd = Alu;
 
1152
        #temp{} ->
 
1153
          Key = Def#temp.key,
 
1154
          {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
 
1155
          case Xsi#xsi.wba of
 
1156
            true ->
 
1157
              %% Turn into a move
 
1158
              Dst = ?RTL:alu_dst(Alu),
 
1159
              Move = ?RTL:mk_move(Dst,Def#temp.var),
 
1160
              pp_instr(Inst#pre_candidate.alu,nil),pp_debug(" ==> ",[]),pp_instr(Move,nil),
 
1161
              %% Counting redundancies
 
1162
              redundancy_add(),
 
1163
              InstToAdd = Move;
 
1164
            _ ->
 
1165
              InstToAdd = Alu
 
1166
          end;
 
1167
        _ -> %% Def is a real variable
 
1168
          %% Turn into a move
 
1169
          Dst = ?RTL:alu_dst(Alu),
 
1170
          Move = ?RTL:mk_move(Dst,Def),
 
1171
          pp_instr(Alu,nil), pp_debug(" ==> ",[]),pp_instr(Move,nil),
 
1172
          %% Counting redundancies
 
1173
          redundancy_add(),
 
1174
          InstToAdd = Move
 
1175
      end,
 
1176
      code_motion_in_block(L,Insts,Cfg,XsiG,[InstToAdd|Visited],InsertionsAcc);
 
1177
    #xsi_link{} ->
 
1178
      Key = Inst#xsi_link.number,
 
1179
      {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),      
 
1180
      case Xsi#xsi.wba of
 
1181
        true ->
 
1182
          %% Xsi is a WBA, it might trigger insertions
 
1183
          OpList = xsi_oplist(Xsi),
 
1184
          pp_debug(" This Xsi is a 'Will be available'",[]),
 
1185
          %% Cleaning the instruction
 
1186
          Expr = prepare_inst(Xsi#xsi.inst),
 
1187
          {NewOpList,NewInsertionsAcc} = get_insertions(OpList,[],InsertionsAcc,Visited,Expr,XsiG),
 
1188
          %% Making Xsi a Phi with Oplist
 
1189
          PhiOpList = [{Pred,Var} || #xsi_op{pred=Pred,op=Var} <- NewOpList],
 
1190
          Def = Xsi#xsi.def,
 
1191
          Phi = ?RTL:phi_arglist_update(?RTL:mk_phi(Def#temp.var),PhiOpList),
 
1192
          pp_debug("~n Xsi is turned into Phi : ~w",[Phi]),
 
1193
          code_motion_in_block(L,Insts,Cfg,XsiG,[Phi|Visited],NewInsertionsAcc);
 
1194
        _ ->
 
1195
          pp_debug(" This Xsi is not a 'Will be available'",[]),
 
1196
          code_motion_in_block(L,Insts,Cfg,XsiG,Visited,InsertionsAcc)
 
1197
      end;
 
1198
%%     phi ->
 
1199
%%       code_motion_in_block(L,Insts,Cfg,XsiG,[Inst|Visited],InsertionsAcc);
 
1200
    _ ->
 
1201
      %% Other instructions.... Phis too
 
1202
      code_motion_in_block(L,Insts,Cfg,XsiG,[Inst|Visited],InsertionsAcc)
 
1203
  end.
 
1204
 
 
1205
prepare_inst(Expr) ->
 
1206
  S1 = ?RTL:alu_src1(Expr),
 
1207
  S2 = ?RTL:alu_src2(Expr),
 
1208
  NewInst = case S1 of
 
1209
              #temp{} -> ?RTL:alu_src1_update(Expr,S1#temp.var);
 
1210
              _ -> Expr
 
1211
            end,
 
1212
  NewExpr = case S2 of
 
1213
              #temp{} -> ?RTL:alu_src2_update(NewInst,S2#temp.var);
 
1214
              _ -> NewInst
 
1215
            end,
 
1216
  NewExpr.
 
1217
 
 
1218
get_insertions([],OpAcc,InsertionsAcc,_Visited,_Expr,_XsiG) ->
 
1219
  {OpAcc,InsertionsAcc};
 
1220
get_insertions([XsiOp|Ops],OpAcc,InsertionsAcc,Visited,Expr,XsiG) ->
 
1221
  Pred = XsiOp#xsi_op.pred,
 
1222
  Op = XsiOp#xsi_op.op,
 
1223
  case Op of
 
1224
    #bottom{} ->
 
1225
      case gb_trees:lookup(Pred,InsertionsAcc) of
 
1226
        {value,Insertion} ->
 
1227
          From = Insertion#insertion.from,
 
1228
          case lists:keysearch(Op,1,From) of
 
1229
            false -> 
 
1230
              pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
 
1231
              Dst = Op#bottom.var,
 
1232
              Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1233
              Inst = manufacture_computation(Pred,Expr2,Visited),
 
1234
              Code = Insertion#insertion.code,
 
1235
              NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
 
1236
              NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
 
1237
            {value,{_,Val}} ->
 
1238
              pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
 
1239
              Dst = Val,
 
1240
              NewInsertionsAcc = InsertionsAcc
 
1241
          end;
 
1242
        none ->
 
1243
          pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
 
1244
          Dst = Op#bottom.var,
 
1245
          Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1246
          Inst = manufacture_computation(Pred,Expr2,Visited),
 
1247
          NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
 
1248
          NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
 
1249
      end;
 
1250
    #const_expr{} ->
 
1251
      case gb_trees:lookup(Pred,InsertionsAcc) of
 
1252
        {value,Insertion} ->
 
1253
          From = Insertion#insertion.from,
 
1254
          case lists:keysearch(Op,1,From) of
 
1255
            false -> 
 
1256
              pp_debug("~nThere have been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
 
1257
              Dst = Op#const_expr.var,
 
1258
              Val = Op#const_expr.value,
 
1259
              Inst = ?RTL:mk_move(Dst,Val),
 
1260
              Code = Insertion#insertion.code,
 
1261
              NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
 
1262
              NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
 
1263
            {value,{_,Val}} ->
 
1264
              pp_debug("~nThere have been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
 
1265
              Dst = Val,
 
1266
              NewInsertionsAcc = InsertionsAcc
 
1267
          end;
 
1268
        none ->
 
1269
          pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
 
1270
          Dst = Op#const_expr.var,
 
1271
          Val = Op#const_expr.value,
 
1272
          Inst = ?RTL:mk_move(Dst,Val),
 
1273
          NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
 
1274
          NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
 
1275
      end;
 
1276
    #eop{} ->
 
1277
      %% We treat expressions like bottoms
 
1278
      %% The value must be recomputed, and therefore not available...
 
1279
      case gb_trees:lookup(Pred,InsertionsAcc) of
 
1280
        {value,Insertion} ->
 
1281
          From = Insertion#insertion.from,
 
1282
          case lists:keysearch(Op,1,From) of
 
1283
            false -> 
 
1284
              pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
 
1285
              Dst = Op#eop.var,
 
1286
              Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1287
              Inst = manufacture_computation(Pred,Expr2,Visited),
 
1288
              Code = Insertion#insertion.code,
 
1289
              NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
 
1290
              NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc);
 
1291
            {value,{_,Val}} ->
 
1292
              pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too | Op=",[Pred]),pp_arg(Op),
 
1293
              Dst = Val,
 
1294
              NewInsertionsAcc = InsertionsAcc
 
1295
          end;
 
1296
        none ->
 
1297
          pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course)| Op=",[Pred]),pp_arg(Op),
 
1298
          Dst = Op#eop.var,
 
1299
          Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1300
          Inst = manufacture_computation(Pred,Expr2,Visited),
 
1301
          NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
 
1302
          NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
 
1303
      end;
 
1304
    #temp{} ->
 
1305
      case gb_trees:lookup(Pred,InsertionsAcc) of
 
1306
        {value,Insertion} ->
 
1307
          From = Insertion#insertion.from,
 
1308
          case lists:keysearch(Op,1,From) of
 
1309
            false -> 
 
1310
              pp_debug("~nThere has been insertions along the edge L~w already, but not for that operand | Op=",[Pred]),pp_arg(Op),
 
1311
              Key = Op#temp.key,
 
1312
              {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),      
 
1313
              case Xsi#xsi.wba of
 
1314
                true ->
 
1315
                  pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
 
1316
                  Dst = Op#temp.var,
 
1317
                  NewInsertionsAcc = InsertionsAcc;
 
1318
                _ ->
 
1319
                  pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
 
1320
                  Dst = ?RTL:mk_new_var(),
 
1321
                  Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1322
                  Inst = manufacture_computation(Pred,Expr2,Visited),
 
1323
                  Code = Insertion#insertion.code,
 
1324
                  NewInsertion = Insertion#insertion{from=[{Op,Dst}|From],code=[Inst|Code]},
 
1325
                  NewInsertionsAcc = gb_trees:update(Pred,NewInsertion,InsertionsAcc)
 
1326
              end;
 
1327
            {value,{_,Val}} ->
 
1328
              pp_debug("~nThere has been insertions along the edge L~w already, and for that operand too (Op=~w)",[Pred,Op]),
 
1329
              pp_debug("~nThis means, this temp is a WBA Xsi's definition",[]),
 
1330
              Dst = Val,
 
1331
              NewInsertionsAcc = InsertionsAcc
 
1332
          end;
 
1333
        none ->
 
1334
          pp_debug("~nThere has been no insertion along the edge L~w, (and not for that operand, of course | Op=",[Pred]),pp_arg(Op),
 
1335
          Key = Op#temp.key,
 
1336
          {_V,Xsi} = ?GRAPH:vertex(XsiG,Key),
 
1337
          case Xsi#xsi.wba of
 
1338
            true ->
 
1339
              pp_debug("~nBut the operand is a WBA Xsi: no need for insertion",[]),
 
1340
              Dst = Op#temp.var,
 
1341
              NewInsertionsAcc = InsertionsAcc;
 
1342
            _ ->
 
1343
              pp_debug("~nBut the operand is a NOT WBA Xsi: we must make an insertion",[]),
 
1344
              Dst = ?RTL:mk_new_var(),
 
1345
              Expr2 = ?RTL:alu_dst_update(Expr,Dst),
 
1346
              Inst = manufacture_computation(Pred,Expr2,Visited),
 
1347
              NewInsertion = #insertion{from=[{Op,Dst}],code=[Inst]},
 
1348
              NewInsertionsAcc = gb_trees:insert(Pred,NewInsertion,InsertionsAcc)
 
1349
          end
 
1350
      end;
 
1351
    _ ->
 
1352
      pp_debug("~nThe operand (Op=",[]),pp_arg(Op),pp_debug(") is a real variable, no need for insertion along L~w",[Pred]),
 
1353
      Dst = Op,
 
1354
      NewInsertionsAcc = InsertionsAcc
 
1355
  end,
 
1356
  NewXsiOp = XsiOp#xsi_op{op=Dst},
 
1357
  get_insertions(Ops, [NewXsiOp|OpAcc], NewInsertionsAcc, Visited, Expr, XsiG).
 
1358
 
 
1359
manufacture_computation(_Pred, Expr, []) ->
 
1360
  pp_debug("~n Manufactured computation : ~w", [Expr]),
 
1361
  Expr;
 
1362
manufacture_computation(Pred, Expr, [I|Rest]) ->
 
1363
  %%pp_debug("~n Expr = ~w",[Expr]),
 
1364
  SRC1 = ?RTL:alu_src1(Expr),
 
1365
  SRC2 = ?RTL:alu_src2(Expr),
 
1366
  case I of
 
1367
    #xsi_link{} ->
 
1368
      exit({?MODULE,should_not_be_a_xsi_link,{"Why the hell do we still have a xsi link???",I}});
 
1369
    #xsi{} ->
 
1370
      exit({?MODULE,should_not_be_a_xsi,{"Why the hell do we still have a xsi ???",I}});
 
1371
    #phi{} ->
 
1372
      DST = ?RTL:phi_dst(I),
 
1373
      Arg = ?RTL:phi_arg(I,Pred),
 
1374
      NewInst = case DST==SRC1 of
 
1375
                  true -> ?RTL:alu_src1_update(Expr,Arg);
 
1376
                  false -> Expr
 
1377
                end,
 
1378
      NewExpr = case DST==SRC2 of
 
1379
                  true -> ?RTL:alu_src2_update(NewInst,Arg);
 
1380
                  false -> NewInst
 
1381
                end,
 
1382
      manufacture_computation(Pred,NewExpr,Rest)
 
1383
  end.
 
1384
 
 
1385
make_insertions(_L, [], _ITree, Cfg) ->
 
1386
  Cfg; 
 
1387
make_insertions(L, [OldPred|Is], ITree, Cfg) ->
 
1388
  NewPred      = ?RTL:label_name(?RTL:mk_new_label()),
 
1389
  I            = gb_trees:get(OldPred, ITree),
 
1390
  CodeToInsert = lists:reverse([?RTL:mk_goto(L)|I#insertion.code]),
 
1391
  BBToInsert   = ?BB:mk_bb(CodeToInsert),
 
1392
  NewCfg       = ?CFG:bb_insert_between(Cfg, NewPred, BBToInsert, OldPred, L),
 
1393
  make_insertions(L, Is, ITree, NewCfg).
 
1394
 
 
1395
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1396
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  XSI INTERFACE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1397
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1398
 
 
1399
xsi_oplist(#xsi{opList=OpList}) ->
 
1400
  case OpList of undefined -> [] ; _ -> OpList end.
 
1401
xsi_arg(Xsi, Pred) ->
 
1402
  case lists:keysearch(Pred, #xsi_op.pred ,xsi_oplist(Xsi)) of
 
1403
    false ->
 
1404
      undetermined_operand;
 
1405
    {value,R} ->
 
1406
      R#xsi_op.op
 
1407
  end.
 
1408
xsi_arg_update(Xsi, Pred, Op) ->
 
1409
  NewOpList = lists:keyreplace(Pred, #xsi_op.pred, xsi_oplist(Xsi), 
 
1410
                               #xsi_op{pred=Pred,op=Op}),
 
1411
  Xsi#xsi{opList=NewOpList}.
 
1412
 
 
1413
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1414
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PRETTY-PRINTING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1415
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1416
 
 
1417
-ifndef(SSAPRE_DEBUG).
 
1418
 
 
1419
pp_debug(_,_) -> ok.
 
1420
%%pp_cfg(Cfg,_) -> ?CFG:pp(Cfg).
 
1421
pp_cfg(_,_) -> ok.
 
1422
pp_instr(_,_) -> ok.
 
1423
pp_instrs(_,_) -> ok.
 
1424
pp_expr(_) -> ok.
 
1425
pp_xsi(_) -> ok.
 
1426
pp_arg(_) -> ok.
 
1427
pp_xsigraph(_) -> ok.
 
1428
pp_cfggraph(_) -> ok.
 
1429
%% pp_xsigraph(G) ->
 
1430
%%   Vertices = lists:sort(?GRAPH:vertices(G)),
 
1431
%%   io:format(standard_io, "Size of the Xsi Graph: ~w", [length(Vertices)]).
 
1432
%% pp_cfggraph(G) ->
 
1433
%%   Vertices = lists:sort(?GRAPH:vertices(G)),
 
1434
%%   io:format(standard_io, "Size of the CFG Graph: ~w", [length(Vertices)]).
 
1435
 
 
1436
-else.
 
1437
 
 
1438
pp_debug(Str, Args) ->
 
1439
  io:format(standard_io, Str, Args).
 
1440
 
 
1441
pp_cfg(Cfg, Graph) ->
 
1442
  Labels = ?CFG:preorder(Cfg),
 
1443
  pp_blocks(Labels, Cfg, Graph).
 
1444
 
 
1445
pp_blocks([], _, _) ->
 
1446
  ok;
 
1447
pp_blocks([L|Ls], Cfg, Graph) ->
 
1448
  Code = hipe_bb:code(?CFG:bb(Cfg,L)),
 
1449
  io:format(standard_io,"~n########## Label L~w~n", [L]),
 
1450
  pp_instrs(Code, Graph),
 
1451
  pp_blocks(Ls, Cfg, Graph).
 
1452
 
 
1453
pp_instrs([], _) ->
 
1454
  ok;
 
1455
pp_instrs([I|Is], Graph) ->
 
1456
  pp_instr(I, Graph),
 
1457
  pp_instrs(Is, Graph).
 
1458
 
 
1459
pp_xsi_link(Key, Graph) ->
 
1460
  {_Key,Xsi} = ?GRAPH:vertex(Graph, Key),
 
1461
  pp_xsi(Xsi).
 
1462
 
 
1463
pp_xsi(Xsi) ->
 
1464
  io:format(standard_io, "    [L~w] ", [Xsi#xsi.label]),
 
1465
  io:format(standard_io, "[", []), pp_expr(Xsi#xsi.inst),
 
1466
  io:format(standard_io, "] Xsi(", []), pp_xsi_args(xsi_oplist(Xsi)),
 
1467
  io:format(standard_io, ") (", []), pp_xsi_def(Xsi#xsi.def),
 
1468
  io:format(standard_io, ") cba=~w, later=~w | wba=~w~n", [Xsi#xsi.cba,Xsi#xsi.later,Xsi#xsi.wba]).
 
1469
 
 
1470
pp_instr(I,Graph) ->
 
1471
  case I of
 
1472
    #alu{} ->
 
1473
      io:format(standard_io, "    ", []),
 
1474
      pp_arg(?RTL:alu_dst(I)),
 
1475
      io:format(standard_io, " <- ", []),
 
1476
      pp_expr(I),
 
1477
      io:format(standard_io, "~n", []);
 
1478
    _ ->
 
1479
      case catch ?RTL:pp_instr(standard_io, I) of
 
1480
        {'EXIT', _} -> 
 
1481
          case I of
 
1482
            #pre_candidate{} ->
 
1483
              pp_pre(I);
 
1484
            #xsi{} ->
 
1485
              pp_xsi(I);
 
1486
            #xsi_link{} ->
 
1487
              pp_xsi_link(I#xsi_link.number,Graph);
 
1488
            _->
 
1489
              io:format(standard_io,"*** ~w ***~n", [I])
 
1490
          end;
 
1491
        _ ->
 
1492
          ok
 
1493
      end
 
1494
  end.
 
1495
 
 
1496
pp_pre(I) ->
 
1497
  A = I#pre_candidate.alu,
 
1498
  io:format(standard_io, "    ", []),
 
1499
  pp_arg(?RTL:alu_dst(A)),
 
1500
  io:format(standard_io, " <- ", []),pp_expr(A),
 
1501
  io:format(standard_io, " [ ", []),pp_arg(I#pre_candidate.def),
 
1502
  %%io:format(standard_io, "~w", [I#pre_candidate.def]),
 
1503
  io:format(standard_io, " ]~n",[]).
 
1504
 
 
1505
pp_expr(I) ->
 
1506
  pp_arg(?RTL:alu_dst(I)),
 
1507
  io:format(standard_io, " <- ", []),
 
1508
  pp_arg(?RTL:alu_src1(I)),
 
1509
  io:format(standard_io, " ~w ", [?RTL:alu_op(I)]),
 
1510
  pp_arg(?RTL:alu_src2(I)).
 
1511
 
 
1512
pp_arg(Arg) ->
 
1513
  case Arg of
 
1514
    bottom ->
 
1515
      io:format(standard_io, "_|_", []);
 
1516
    #bottom{} ->
 
1517
      io:format(standard_io, "_|_:~w (", [Arg#bottom.key]),pp_arg(Arg#bottom.var),io:format(standard_io,")",[]);
 
1518
    #temp{} ->
 
1519
      pp_xsi_def(Arg);
 
1520
    #eop{} ->
 
1521
      io:format(standard_io,"#",[]),pp_expr(Arg#eop.expr),io:format(standard_io,"(",[]),pp_arg(Arg#eop.var),io:format(standard_io,")#",[]);
 
1522
    #const_expr{} ->
 
1523
      io:format(standard_io,"*",[]),pp_arg(Arg#const_expr.var),io:format(standard_io," -> ",[]),pp_arg(Arg#const_expr.value),io:format(standard_io,"*",[]);
 
1524
    undefined ->
 
1525
      io:format(standard_io, "...", []); %%"undefined", []);
 
1526
    _->
 
1527
      case Arg of
 
1528
        #alu{} ->
 
1529
          pp_expr(Arg);      
 
1530
        _->
 
1531
          ?RTL:pp_arg(standard_io, Arg)
 
1532
      end
 
1533
  end.
 
1534
 
 
1535
pp_args([]) ->
 
1536
  ok;
 
1537
pp_args(undefined) ->
 
1538
  io:format(standard_io, "...,...,...", []);
 
1539
pp_args([A]) ->
 
1540
  pp_arg(A);
 
1541
pp_args([A|As]) ->
 
1542
  pp_arg(A),
 
1543
  io:format(standard_io, ", ", []),
 
1544
  pp_args(As).
 
1545
 
 
1546
pp_xsi_args([]) -> ok;
 
1547
pp_xsi_args([XsiOp]) ->
 
1548
  io:format(standard_io, "{~w| ", [XsiOp#xsi_op.pred]),
 
1549
  pp_arg(XsiOp#xsi_op.op),
 
1550
  io:format(standard_io, "}", []);
 
1551
pp_xsi_args([XsiOp|Args]) ->
 
1552
  io:format(standard_io, "{~w| ", [XsiOp#xsi_op.pred]),
 
1553
  pp_arg(XsiOp#xsi_op.op),
 
1554
  io:format(standard_io, "}, ", []),
 
1555
  pp_xsi_args(Args);
 
1556
pp_xsi_args(Args) ->
 
1557
  pp_args(Args).
 
1558
 
 
1559
pp_xsi_def(Arg) ->
 
1560
  D = Arg#temp.key,
 
1561
  V = Arg#temp.var,
 
1562
  io:format(standard_io, "t~w (", [D]),pp_arg(V),io:format(standard_io,")",[]).
 
1563
 
 
1564
pp_cfggraph(G) ->
 
1565
  Vertices = lists:sort(?GRAPH:vertices(G)),
 
1566
  io:format(standard_io, "Size of the CFG Graph: ~w ~n", [length(Vertices)]),
 
1567
  pp_cfgvertex(Vertices, G).
 
1568
 
 
1569
pp_xsigraph(G) ->
 
1570
  Vertices = lists:sort(?GRAPH:vertices(G)),
 
1571
  io:format(standard_io, "Size of the Xsi Graph: ~w ~n", [length(Vertices)]),
 
1572
  pp_xsivertex(Vertices,G).
 
1573
 
 
1574
pp_xsivertex([], _G) ->
 
1575
  ok;
 
1576
pp_xsivertex([Key|Keys], G) ->
 
1577
  {V,Xsi} = ?GRAPH:vertex(G, Key),
 
1578
  OutNeighbours = ?GRAPH:out_neighbours(G, V),
 
1579
  pp_debug(" ~w -> ~w", [V,OutNeighbours]), pp_xsi(Xsi),
 
1580
  pp_xsivertex(Keys, G).
 
1581
 
 
1582
pp_cfgvertex([], _G) ->
 
1583
  ok;
 
1584
pp_cfgvertex([Key|Keys], G) ->
 
1585
  {V,Block} = ?GRAPH:vertex(G,Key),
 
1586
  case Block#block.type of
 
1587
    mp ->
 
1588
      pp_debug("~n Block ~w's attributes: ~n", [V]),
 
1589
      pp_attributes(Block),
 
1590
      pp_debug("~n Block ~w's edges: ~n", [V]),
 
1591
      pp_edges(G, ?GRAPH:in_edges(G,Key), ?GRAPH:out_edges(G,Key));
 
1592
    _->
 
1593
      ok
 
1594
  end,
 
1595
  pp_cfgvertex(Keys, G).
 
1596
 
 
1597
pp_attributes(Block) ->
 
1598
  Att = Block#block.attributes,
 
1599
  case Att of
 
1600
    undefined ->
 
1601
      ok;
 
1602
    _ ->
 
1603
      pp_debug("        Maps: ~n",[]),pp_maps(gb_trees:keys(Att#mp.maps),Att#mp.maps),
 
1604
      pp_debug("        Uses: ~n",[]),pp_uses(gb_trees:keys(Att#mp.uses),Att#mp.uses),
 
1605
      pp_debug("        Defs: ~w~n",[Att#mp.defs]),
 
1606
      pp_debug("        Xsis: ~w~n",[Att#mp.xsis]),
 
1607
      pp_debug("        NDS : ",[]),pp_nds(?SETS:to_list(Att#mp.ndsSet))
 
1608
  end.
 
1609
 
 
1610
pp_maps([], _Maps) -> ok;
 
1611
pp_maps([K|Ks], Maps) ->
 
1612
  pp_debug("              ",[]),pp_arg(K#xsi_op.op),pp_debug("-> ~w~n",[?SETS:to_list(gb_trees:get(K,Maps))]),
 
1613
  pp_maps(Ks, Maps).
 
1614
 
 
1615
pp_uses([], _Maps) -> ok;
 
1616
pp_uses([K|Ks], Maps) ->
 
1617
  pp_debug("              ~w -> ~w~n",[K,?SETS:to_list(gb_trees:get(K,Maps))]),
 
1618
  pp_uses(Ks, Maps).
 
1619
 
 
1620
pp_nds([]) -> pp_debug("~n",[]);
 
1621
pp_nds(undefined) -> pp_debug("None",[]);
 
1622
pp_nds([K]) ->
 
1623
  pp_arg(K#xsi_op.op), pp_debug("~n",[]);
 
1624
pp_nds([K|Ks]) ->
 
1625
  pp_arg(K#xsi_op.op), pp_debug(", ",[]),
 
1626
  pp_nds(Ks).
 
1627
 
 
1628
pp_edges(_G, [], []) -> ok;
 
1629
pp_edges(G, [], [OUT|OUTs]) ->
 
1630
  {_E,V1,V2,Label} = ?GRAPH:edge(G,OUT),
 
1631
  pp_debug(" Out edge ~w -> ~w (~w)~n", [V1,V2,?SETS:to_list(Label)]),
 
1632
  pp_edges(G, [], OUTs);
 
1633
pp_edges(G, [IN|INs], Outs) ->
 
1634
  {_E,V1,V2,Label} = ?GRAPH:edge(G,IN),
 
1635
  pp_debug("  In edge ~w -> ~w (~w)~n", [V1,V2,?SETS:to_list(Label)]),
 
1636
  pp_edges(G, INs, Outs).
 
1637
 
 
1638
-endif.
 
1639
 
 
1640
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1641
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% COUNTERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1642
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1643
 
 
1644
init_counters() ->
 
1645
  put({ssapre_temp,temp_count}, 0),
 
1646
  put({ssapre_index,index_count}, 0).
 
1647
 
 
1648
new_bottom() ->
 
1649
  V = get({ssapre_index,index_count}),
 
1650
  put({ssapre_index,index_count}, V+1),
 
1651
  #bottom{key=V,var=?RTL:mk_new_var()}.
 
1652
 
 
1653
new_temp() ->
 
1654
  V = get({ssapre_temp,temp_count}),
 
1655
  put({ssapre_temp,temp_count}, V+1),
 
1656
  #temp{key=V,var=?RTL:mk_new_var()}.
 
1657
 
 
1658
init_redundancy_count() ->
 
1659
  put({ssapre_redundancy,redundancy_count}, 0).
 
1660
 
 
1661
redundancy_add() ->
 
1662
  V = get({ssapre_redundancy,redundancy_count}),
 
1663
  put({ssapre_redundancy,redundancy_count}, V+1).
 
1664
 
 
1665
get_redundancy_count() ->
 
1666
  get({ssapre_redundancy,redundancy_count}).
 
1667
 
 
1668
%% //////////////////
 
1669
%% // End of the file