diff options
Diffstat (limited to 'lib/hipe/icode/hipe_icode_instruction_counter.erl')
-rw-r--r-- | lib/hipe/icode/hipe_icode_instruction_counter.erl | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/lib/hipe/icode/hipe_icode_instruction_counter.erl b/lib/hipe/icode/hipe_icode_instruction_counter.erl new file mode 100644 index 0000000000..92658d294a --- /dev/null +++ b/lib/hipe/icode/hipe_icode_instruction_counter.erl @@ -0,0 +1,135 @@ +%% -*- erlang-indent-level: 2 -*- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%------------------------------------------------------------------- +%% File : icode_instruction_counter.erl +%% Author : Andreas Hasselberg <[email protected]> +%% Purpose : This module counts the number of different instructions +%% in a function. It is useful when you want to know if +%% your Icode analysis or specialization is good, bad or +%% simply unlucky :) +%% +%% Created : 2 Oct 2006 by Andreas Hasselberg <[email protected]> +%%------------------------------------------------------------------- + +-module(hipe_icode_instruction_counter). + +-export([cfg/3, compare/3]). + +-include("../main/hipe.hrl"). +-include("hipe_icode.hrl"). +-include("../flow/cfg.hrl"). + +%%------------------------------------------------------------------- +%% A general CFG instruction walktrough +%%------------------------------------------------------------------- + +-spec cfg(#cfg{}, mfa(), comp_options()) -> [_]. + +cfg(Cfg, _IcodeFun, _Options) -> + Labels = hipe_icode_cfg:labels(Cfg), + %% Your Info init function goes here + InitInfo = counter__init_info(), + Info = lists:foldl(fun (Label, InfoAcc) -> + BB = hipe_icode_cfg:bb(Cfg, Label), + Code = hipe_bb:code(BB), + walktrough_bb(Code, InfoAcc) + end, InitInfo, Labels), + %% counter__output_info(IcodeFun, Info), + Info. + +walktrough_bb(BB, Info) -> + lists:foldl(fun (Insn, InfoAcc) -> + %% Your analysis function here + counter__analys_insn(Insn, InfoAcc) + end, Info, BB). + +%%------------------------------------------------------------------- +%% The counter specific functions +%%------------------------------------------------------------------- + +-spec compare(gb_tree(), gb_tree(), gb_tree()) -> gb_tree(). + +compare(Name, Old, New) -> + NewList = gb_trees:to_list(New), + OldList = gb_trees:to_list(Old), + TempTree = compare_one_way(NewList, Old, added, gb_trees:empty()), + DiffTree = compare_one_way(OldList, New, removed, TempTree), + DiffList = gb_trees:to_list(DiffTree), + if DiffList =:= [] -> + ok; + true -> + io:format("~p: ~p ~n", [Name, DiffList]) + end, + DiffTree. + +compare_one_way(List, Tree, Key, Fold_tree) -> + lists:foldl(fun({Insn, ListCount}, DiffAcc) when is_integer(ListCount) -> + DiffCount = + case gb_trees:lookup(Insn, Tree) of + {value, TreeCount} when is_integer(TreeCount) -> + ListCount - TreeCount; + none -> + ListCount + end, + if DiffCount > 0 -> + gb_trees:insert({Key, Insn}, DiffCount, DiffAcc); + true -> + DiffAcc + end + end, + Fold_tree, + List). + +counter__init_info() -> + gb_trees:empty(). + +counter__analys_insn(Insn, Info) -> + Key = counter__insn_get_key(Insn), + counter__increase_key(Key, Info). + +counter__insn_get_key(If = #icode_if{}) -> {'if', hipe_icode:if_op(If)}; +counter__insn_get_key(Call = #icode_call{}) -> {call, hipe_icode:call_fun(Call)}; +counter__insn_get_key(#icode_enter{}) -> enter; +counter__insn_get_key(#icode_return{}) -> return; +counter__insn_get_key(#icode_type{}) -> type; +counter__insn_get_key(#icode_switch_val{}) -> switch_val; +counter__insn_get_key(#icode_switch_tuple_arity{}) -> switch_tuple_arity; +counter__insn_get_key(#icode_goto{}) -> goto; +counter__insn_get_key(#icode_move{}) -> move; +counter__insn_get_key(#icode_phi{}) -> phi; +counter__insn_get_key(#icode_begin_try{}) -> begin_try; +counter__insn_get_key(#icode_end_try{}) -> end_try; +counter__insn_get_key(#icode_begin_handler{}) -> begin_handler; +counter__insn_get_key(#icode_fail{}) -> fail; +counter__insn_get_key(#icode_comment{}) -> comment. + +counter__increase_key(Key, Info) -> + NewCounter = + case gb_trees:lookup(Key, Info) of + {value, Counter} when is_integer(Counter) -> + Counter + 1; + none -> + 1 + end, + gb_trees:enter(Key, NewCounter, Info). + +%%counter__output_info(IcodeFun, Info) -> +%% InfoList = gb_trees:to_list(Info), +%% io:format("~p instructions : ~p ~n", [IcodeFun, InfoList]). |