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

« back to all changes in this revision

Viewing changes to lib/compiler/src/cerl_inline.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:
14
14
%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
15
15
%% AB. All Rights Reserved.''
16
16
%% 
17
 
%%     $Id: cerl_inline.erl,v 1.41 2002/11/07 10:00:55 richardc Exp $
 
17
%%     $Id$
18
18
%%
19
19
%% Core Erlang inliner.
20
20
 
37
37
-export([core_transform/2, transform/1, transform/2]).
38
38
 
39
39
-import(cerl, [abstract/1, alias_pat/1, alias_var/1, apply_args/1,
40
 
               apply_op/1, atom_name/1, atom_val/1, bin_seg_val/1,
41
 
               bin_seg_size/1, bin_seg_unit/1, bin_seg_type/1,
42
 
               bin_seg_flags/1, binary_segs/1, update_c_alias/3,
43
 
               update_c_apply/3, update_c_binary/2, update_c_bin_seg/6,
 
40
               apply_op/1, atom_name/1, atom_val/1, bitstr_val/1,
 
41
               bitstr_size/1, bitstr_unit/1, bitstr_type/1,
 
42
               bitstr_flags/1, binary_segments/1, update_c_alias/3,
 
43
               update_c_apply/3, update_c_binary/2, update_c_bitstr/6,
44
44
               update_c_call/4, update_c_case/3, update_c_catch/2,
45
45
               update_c_clause/4, c_fun/2, c_int/1, c_let/3,
46
46
               update_c_let/4, update_c_letrec/3, update_c_module/5,
104
104
 
105
105
default_effort() -> 150.
106
106
default_size() -> 24.
 
107
default_unroll() -> 1.
107
108
 
108
109
%% Base costs/weights for different kinds of expressions. If these are
109
110
%% modified, the size limits above may have to be adjusted.
126
127
weight(call) -> 3;      % Assume remote-calls as efficient as `apply'.
127
128
weight(primop) -> 2;    % Assume more efficient than `apply'.
128
129
weight(binary) -> 4;    % Initialisation base cost.
129
 
weight(bin_seg) -> 3;   % Coding/decoding a value; like a primop.
 
130
weight(bitstr) -> 3;   % Coding/decoding a value; like a primop.
130
131
weight(module) -> 1.    % Like a letrec with a constant body
131
132
 
132
133
%% These "reference" structures are used for variables and function
176
177
    %% about cluttering the process dictionary with debugging info, or
177
178
    %% proper deallocation of ets-tables.
178
179
    Opts1 = Opts ++ [{inline_size, default_size()},
179
 
                     {inline_effort, default_effort()}],
 
180
                     {inline_effort, default_effort()},
 
181
                     {inline_unroll, default_unroll()}],
180
182
    Reply = self(),
181
183
    Pid = spawn_link(fun () -> start(Reply, Tree, Ctxt, Opts1) end),
182
184
    receive
187
189
start(Reply, Tree, Ctxt, Opts) ->
188
190
    init_debug(),
189
191
    case debug_runtime() of
190
 
        true ->
191
 
            put(inline_start_time,
192
 
                element(1, erlang:statistics(runtime)));
193
 
        _ ->
 
192
        %% true ->
 
193
        %%     put(inline_start_time,
 
194
        %%         element(1, erlang:statistics(runtime)));
 
195
        false ->
194
196
            ok
195
197
    end,
196
198
    Size = max(1, proplists:get_value(inline_size, Opts)),
197
199
    Effort = max(1, proplists:get_value(inline_effort, Opts)),
 
200
    Unroll = max(1, proplists:get_value(inline_unroll, Opts)),
198
201
    case proplists:get_bool(verbose, Opts) of
199
202
        true ->
200
203
            io:fwrite("Inlining: inline_size=~w inline_effort=~w\n",
204
207
    end,
205
208
 
206
209
    %% Note that the counters of the new state are passive.
207
 
    S = st__new(Effort, Size),
 
210
    S = st__new(Effort, Size, Unroll),
208
211
 
209
212
%%% Initialization is not needed at present. Note that the code in
210
213
%%% `inline_init' is not up-to-date with this module.
216
219
 
217
220
init_debug() ->
218
221
    case debug_counters() of
219
 
        true ->
220
 
            put(counter_effort_triggers, 0),
221
 
            put(counter_effort_max, 0),
222
 
            put(counter_size_triggers, 0),
223
 
            put(counter_size_max, 0);
224
 
        _ ->
 
222
        %% true ->
 
223
        %%     put(counter_effort_triggers, 0),
 
224
        %%     put(counter_effort_max, 0),
 
225
        %%     put(counter_size_triggers, 0),
 
226
        %%     put(counter_size_max, 0);
 
227
        false ->
225
228
            ok
226
229
    end.
227
230
 
228
231
report_debug() ->
229
232
    case debug_runtime() of
230
 
        true ->
231
 
            {Time, _} = erlang:statistics(runtime),
232
 
            report("Total run time for inlining: ~.2.0f s.\n",
233
 
                   [(Time - get(inline_start_time))/1000]);
234
 
        _ ->
 
233
        %% true ->
 
234
        %%     {Time, _} = erlang:statistics(runtime),
 
235
        %%     report("Total run time for inlining: ~.2.0f s.\n",
 
236
        %%         [(Time - get(inline_start_time))/1000]);
 
237
        false ->
235
238
            ok
236
239
    end,
237
240
    case debug_counters() of
238
 
        true ->
239
 
            counter_stats();
240
 
        _ ->
 
241
        %% true ->
 
242
        %%     counter_stats();
 
243
        false ->
241
244
            ok
242
245
    end.
243
246
 
244
 
counter_stats() ->
245
 
    T1 = get(counter_effort_triggers),
246
 
    T2 = get(counter_size_triggers),
247
 
    E = get(counter_effort_max),
248
 
    S = get(counter_size_max),
249
 
    M1 = io_lib:fwrite("\tNumber of triggered "
250
 
                       "effort counters: ~p.\n", [T1]),
251
 
    M2 = io_lib:fwrite("\tNumber of triggered "
252
 
                       "size counters: ~p.\n", [T2]),
253
 
    M3 = io_lib:fwrite("\tLargest active effort counter: ~p.\n",
254
 
                       [E]),
255
 
    M4 = io_lib:fwrite("\tLargest active size counter: ~p.\n",
256
 
                       [S]),
257
 
    report("Counter statistics:\n~s", [[M1, M2, M3, M4]]).
 
247
%% counter_stats() ->
 
248
%%     T1 = get(counter_effort_triggers),
 
249
%%     T2 = get(counter_size_triggers),
 
250
%%     E = get(counter_effort_max),
 
251
%%     S = get(counter_size_max),
 
252
%%     M1 = io_lib:fwrite("\tNumber of triggered "
 
253
%%                        "effort counters: ~p.\n", [T1]),
 
254
%%     M2 = io_lib:fwrite("\tNumber of triggered "
 
255
%%                        "size counters: ~p.\n", [T2]),
 
256
%%     M3 = io_lib:fwrite("\tLargest active effort counter: ~p.\n",
 
257
%%                        [E]),
 
258
%%     M4 = io_lib:fwrite("\tLargest active size counter: ~p.\n",
 
259
%%                        [S]),
 
260
%%     report("Counter statistics:\n~s", [[M1, M2, M3, M4]]).
258
261
 
259
262
 
260
263
%% =====================================================================
1276
1279
i_binary(E, Ren, Env, S) ->
1277
1280
    %% Visit the segments for value.
1278
1281
    {Es, S1} = mapfoldl(fun (E, S) ->
1279
 
                                i_bin_seg(E, Ren, Env, S)
 
1282
                                i_bitstr(E, Ren, Env, S)
1280
1283
                        end,
1281
 
                        S, binary_segs(E)),
 
1284
                        S, binary_segments(E)),
1282
1285
    S2 = count_size(weight(binary), S1),
1283
1286
    {update_c_binary(E, Es), S2}.
1284
1287
 
1285
 
i_bin_seg(E, Ren, Env, S) ->
 
1288
i_bitstr(E, Ren, Env, S) ->
1286
1289
    %% It is not necessary to visit the Unit, Type and Flags fields,
1287
1290
    %% since these are always literals.
1288
 
    {Val, S1} = i(bin_seg_val(E), value, Ren, Env, S),
1289
 
    {Size, S2} = i(bin_seg_size(E), value, Ren, Env, S1),
1290
 
    Unit = bin_seg_unit(E),
1291
 
    Type = bin_seg_type(E),
1292
 
    Flags = bin_seg_flags(E),
1293
 
    S3 = count_size(weight(bin_seg), S2),
1294
 
    {update_c_bin_seg(E, Val, Size, Unit, Type, Flags), S3}.
 
1291
    {Val, S1} = i(bitstr_val(E), value, Ren, Env, S),
 
1292
    {Size, S2} = i(bitstr_size(E), value, Ren, Env, S1),
 
1293
    Unit = bitstr_unit(E),
 
1294
    Type = bitstr_type(E),
 
1295
    Flags = bitstr_flags(E),
 
1296
    S3 = count_size(weight(bitstr), S2),
 
1297
    {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
1295
1298
 
1296
1299
%% This is a simplified version of `i_pattern', for lists of parameter
1297
1300
%% variables only. It does not modify the state.
1346
1349
            end;
1347
1350
        binary ->
1348
1351
            {Es, S1} = mapfoldl(fun (E, S) ->
1349
 
                                        i_bin_seg_pattern(E, Ren, Env,
 
1352
                                        i_bitstr_pattern(E, Ren, Env,
1350
1353
                                                          Ren0, Env0, S)
1351
1354
                                end,
1352
 
                                S, binary_segs(E)),
 
1355
                                S, binary_segments(E)),
1353
1356
            S2 = count_size(weight(binary), S1),
1354
1357
            {update_c_binary(E, Es), S2};
1355
1358
        _ ->
1371
1374
            end
1372
1375
    end.
1373
1376
 
1374
 
i_bin_seg_pattern(E, Ren, Env, Ren0, Env0, S) ->
 
1377
i_bitstr_pattern(E, Ren, Env, Ren0, Env0, S) ->
1375
1378
    %% It is not necessary to visit the Unit, Type and Flags fields,
1376
1379
    %% since these are always literals. The Value field is a limited
1377
1380
    %% pattern - either a literal or an unbound variable. The Size field
1378
1381
    %% is a limited expression - either a literal or a variable bound in
1379
1382
    %% the environment of the containing expression.
1380
 
    {Val, S1} = i_pattern(bin_seg_val(E), Ren, Env, Ren0, Env0, S),
1381
 
    {Size, S2} = i(bin_seg_size(E), value, Ren0, Env0, S1),
1382
 
    Unit = bin_seg_unit(E),
1383
 
    Type = bin_seg_type(E),
1384
 
    Flags = bin_seg_flags(E),
1385
 
    S3 = count_size(weight(bin_seg), S2),
1386
 
    {update_c_bin_seg(E, Val, Size, Unit, Type, Flags), S3}.
 
1383
    {Val, S1} = i_pattern(bitstr_val(E), Ren, Env, Ren0, Env0, S),
 
1384
    {Size, S2} = i(bitstr_size(E), value, Ren0, Env0, S1),
 
1385
    Unit = bitstr_unit(E),
 
1386
    Type = bitstr_type(E),
 
1387
    Flags = bitstr_flags(E),
 
1388
    S3 = count_size(weight(bitstr), S2),
 
1389
    {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
1387
1390
 
1388
1391
 
1389
1392
%% ---------------------------------------------------------------------
1417
1420
    if length(Opnds) /= length(Vs) ->
1418
1421
            report_error("function called with wrong number "
1419
1422
                         "of arguments!\n"),
 
1423
            %% TODO: should really just residualise the call...
1420
1424
            exit(error);
1421
1425
       true ->
1422
1426
            ok
2329
2333
    C = st__get_effort(S),
2330
2334
    C1 = counter__add(N, C, effort, S),
2331
2335
    case debug_counters() of
2332
 
        true ->
2333
 
            case counter__is_active(C1) of
2334
 
                true ->
2335
 
                    V = counter__value(C1),
2336
 
                    case V > get(counter_effort_max) of
2337
 
                        true ->
2338
 
                            put(counter_effort_max, V);
2339
 
                        false ->
2340
 
                            ok
2341
 
                    end;
2342
 
                false ->
2343
 
                    ok
2344
 
            end;
2345
 
        _ ->
 
2336
        %% true ->
 
2337
        %%     case counter__is_active(C1) of
 
2338
        %%         true ->
 
2339
        %%             V = counter__value(C1),
 
2340
        %%             case V > get(counter_effort_max) of
 
2341
        %%                 true ->
 
2342
        %%                     put(counter_effort_max, V);
 
2343
        %%                 false ->
 
2344
        %%                     ok
 
2345
        %%             end;
 
2346
        %%         false ->
 
2347
        %%             ok
 
2348
        %%     end;
 
2349
        false ->
2346
2350
            ok
2347
2351
    end,
2348
2352
    st__set_effort(C1, S).
2351
2355
    C = st__get_size(S),
2352
2356
    C1 = counter__add(N, C, size, S),
2353
2357
    case debug_counters() of
2354
 
        true ->
2355
 
            case counter__is_active(C1) of
2356
 
                true ->
2357
 
                    V = counter__value(C1),
2358
 
                    case V > get(counter_size_max) of
2359
 
                        true ->
2360
 
                            put(counter_size_max, V);
2361
 
                        false ->
2362
 
                            ok
2363
 
                    end;
2364
 
                false ->
2365
 
                    ok
2366
 
            end;
2367
 
        _ ->
 
2358
        %% true ->
 
2359
        %%     case counter__is_active(C1) of
 
2360
        %%         true ->
 
2361
        %%             V = counter__value(C1),
 
2362
        %%             case V > get(counter_size_max) of
 
2363
        %%                 true ->
 
2364
        %%                     put(counter_size_max, V);
 
2365
        %%                 false ->
 
2366
        %%                     ok
 
2367
        %%             end;
 
2368
        %%         false ->
 
2369
        %%             ok
 
2370
        %%     end;
 
2371
        false ->
2368
2372
            ok
2369
2373
    end,
2370
2374
    st__set_size(C1, S).
2496
2500
    rec_env:new_key(Env).
2497
2501
 
2498
2502
env__new_fname(A, N, Env) ->
2499
 
    rec_env:new_custom_key(fun (X) ->
2500
 
                                   S = integer_to_list(X),
2501
 
                                   {list_to_atom(atom_to_list(A) ++ "_"
2502
 
                                                 ++ S),
2503
 
                                    N}
2504
 
                           end,
2505
 
                           Env).
 
2503
    rec_env:new_key(fun (X) ->
 
2504
                        S = integer_to_list(X),
 
2505
                        {list_to_atom(atom_to_list(A) ++ "_" ++ S),
 
2506
                         N}
 
2507
                    end, Env).
2506
2508
 
2507
2509
 
2508
2510
%% =====================================================================
2511
2513
-record(state, {free,           % next free location
2512
2514
                size,           % size counter
2513
2515
                effort,         % effort counter
 
2516
                unroll,         % inner/outer-pending initial value
2514
2517
                cache,          % operand expression cache
2515
2518
                var_flags,      % flags for variables (#ref-structures)
2516
2519
                opnd_flags,     % flags for operands
2535
2538
%% flag whether we are in the process of inlining a propagated
2536
2539
%% functional value. The "pending flags" are really counters limiting
2537
2540
%% the number of times an operand may be inlined recursively, causing
2538
 
%% loop unrolling; however, unrolling more than one iteration does not
2539
 
%% work offhand in the present implementation. (TODO: find out why.)
2540
 
%% Note that the initial value must be greater than zero in order for
2541
 
%% any inlining at all to be done.
 
2541
%% loop unrolling. Note that the initial value must be greater than zero
 
2542
%% in order for any inlining at all to be done.
2542
2543
 
2543
2544
%% Flags are stored in ETS-tables, one table for each class. The second
2544
2545
%% element in each stored tuple is the key (the "label").
2548
2549
                     effect = false}).
2549
2550
-record(app_flags, {lab, inlined = false}).
2550
2551
 
2551
 
st__new(Effort, Size) ->
 
2552
st__new(Effort, Size, Unroll) ->
2552
2553
    #state{free = 0,
2553
2554
           size = counter__new_passive(Size),
2554
 
           effort = counter__new_passive(Effort),
 
2555
           effort = counter__new_passive(Effort),
 
2556
           unroll = Unroll,
2555
2557
           cache = dict:new(),
2556
2558
           var_flags = ets:new(var, [set, private, {keypos, 2}]),
2557
2559
           opnd_flags = ets:new(opnd, [set, private, {keypos, 2}]),
2658
2660
 
2659
2661
st__new_opnd_loc(S) ->
2660
2662
    V = {L, _S1} = st__new_loc(S),
2661
 
    ets:insert(S#state.opnd_flags, #opnd_flags{lab = L}),
 
2663
    N = S#state.unroll,
 
2664
    ets:insert(S#state.opnd_flags,
 
2665
               #opnd_flags{lab = L,
 
2666
                           inner_pending = N,
 
2667
                           outer_pending = N}),
2662
2668
    V.
2663
2669
 
2664
2670
 
2669
2675
%% resulting counter value would exceed the limit for the counter in
2670
2676
%% question (`Type' and `Data' are given by the user).
2671
2677
 
2672
 
-record(counter, {active, value, limit}).
2673
 
 
2674
2678
counter__new_passive(Limit) when Limit > 0 ->
2675
2679
    {0, Limit}.
2676
2680
 
2698
2702
    N1 = V - N,
2699
2703
    if V > 0, N1 =< 0 ->
2700
2704
            case debug_counters() of
2701
 
                true ->
2702
 
                    case Type of
2703
 
                        effort ->
2704
 
                            put(counter_effort_triggers,
2705
 
                                get(counter_effort_triggers) + 1);
2706
 
                        size ->
2707
 
                            put(counter_size_triggers,
2708
 
                                get(counter_size_triggers) + 1)
2709
 
                    end;
2710
 
                _ ->
 
2705
                %% true ->
 
2706
                %%     case Type of
 
2707
                %%      effort ->
 
2708
                %%          put(counter_effort_triggers,
 
2709
                %%              get(counter_effort_triggers) + 1);
 
2710
                %%      size ->
 
2711
                %%          put(counter_size_triggers,
 
2712
                %%              get(counter_size_triggers) + 1)
 
2713
                %%     end;
 
2714
                false ->
2711
2715
                    ok
2712
2716
            end,
2713
2717
            throw({counter_exceeded, Type, Data});
2728
2732
report_error(D) ->
2729
2733
    report_error(D, []).
2730
2734
    
2731
 
report_error({F, L, D}, Vs) ->
2732
 
    report({F, L, {error, D}}, Vs);
2733
2735
report_error(D, Vs) ->
2734
2736
    report({error, D}, Vs).
2735
2737
 
2736
2738
report_warning(D) ->
2737
2739
    report_warning(D, []).
2738
2740
 
2739
 
report_warning({F, L, D}, Vs) ->
2740
 
    report({F, L, {warning, D}}, Vs);
2741
2741
report_warning(D, Vs) ->
2742
2742
    report({warning, D}, Vs).
2743
2743
 
2756
2756
    [io_lib:fwrite("~s:~w: ", [filename(F), L]), format(D, Vs)];
2757
2757
format({F, _L, D}, Vs) ->
2758
2758
    [io_lib:fwrite("~s: ", [filename(F)]), format(D, Vs)];
2759
 
format({_F, _L, D}, Vs) ->
2760
 
    format(D, Vs);
2761
2759
format(S, Vs) when list(S) ->
2762
2760
    [io_lib:fwrite(S, Vs), $\n].
2763
2761