1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14 15-module(hipe_arm_cfg). 16 17-export([init/1, 18 labels/1, start_label/1, 19 succ/2, 20 map_bbs/2, fold_bbs/3, 21 bb/2, bb_add/3]). 22-export([postorder/1]). 23-export([linearise/1]). 24-export([params/1, reverse_postorder/1]). 25-export([arity/1]). % for linear scan 26%%-export([redirect_jmp/3]). 27-export([branch_preds/1]). 28 29%%% these tell cfg.inc what to define (ugly as hell) 30-define(BREADTH_ORDER,true). % for linear scan 31-define(PARAMS_NEEDED,true). 32-define(START_LABEL_UPDATE_NEEDED,true). 33-define(MAP_FOLD_NEEDED,true). 34 35-include("hipe_arm.hrl"). 36-include("../flow/cfg.hrl"). 37-include("../flow/cfg.inc"). 38 39init(Defun) -> 40 Code = hipe_arm:defun_code(Defun), 41 StartLab = hipe_arm:label_label(hd(Code)), 42 Data = hipe_arm:defun_data(Defun), 43 IsClosure = hipe_arm:defun_is_closure(Defun), 44 Name = hipe_arm:defun_mfa(Defun), 45 IsLeaf = hipe_arm:defun_is_leaf(Defun), 46 Formals = hipe_arm:defun_formals(Defun), 47 CFG0 = mk_empty_cfg(Name, StartLab, Data, IsClosure, IsLeaf, Formals), 48 take_bbs(Code, CFG0). 49 50is_branch(I) -> 51 case I of 52 #b_fun{} -> true; 53 #b_label{'cond'='al'} -> true; 54 #pseudo_bc{} -> true; 55 #pseudo_blr{} -> true; 56 #pseudo_bx{} -> true; 57 #pseudo_call{} -> true; 58 #pseudo_switch{} -> true; 59 #pseudo_tailcall{} -> true; 60 _ -> false 61 end. 62 63branch_successors(Branch) -> 64 case Branch of 65 #b_fun{} -> []; 66 #b_label{'cond'='al',label=Label} -> [Label]; 67 #pseudo_bc{true_label=TrueLab,false_label=FalseLab} -> [FalseLab,TrueLab]; 68 #pseudo_blr{} -> []; 69 #pseudo_bx{} -> []; 70 #pseudo_call{contlab=ContLab, sdesc=#arm_sdesc{exnlab=ExnLab}} -> 71 case ExnLab of 72 [] -> [ContLab]; 73 _ -> [ContLab,ExnLab] 74 end; 75 #pseudo_switch{labels=Labels} -> Labels; 76 #pseudo_tailcall{} -> [] 77 end. 78 79branch_preds(Branch) -> 80 case Branch of 81 #pseudo_bc{true_label=TrueLab,false_label=FalseLab,pred=Pred} -> 82 [{FalseLab, 1.0-Pred}, {TrueLab, Pred}]; 83 #pseudo_call{contlab=ContLab, sdesc=#arm_sdesc{exnlab=[]}} -> 84 %% A function can still cause an exception, even if we won't catch it 85 [{ContLab, 1.0-hipe_bb_weights:call_exn_pred()}]; 86 #pseudo_call{contlab=ContLab, sdesc=#arm_sdesc{exnlab=ExnLab}} -> 87 CallExnPred = hipe_bb_weights:call_exn_pred(), 88 [{ContLab, 1.0-CallExnPred}, {ExnLab, CallExnPred}]; 89 #pseudo_switch{labels=Labels} -> 90 Prob = 1.0/length(Labels), 91 [{L, Prob} || L <- Labels]; 92 _ -> 93 case branch_successors(Branch) of 94 [] -> []; 95 [Single] -> [{Single, 1.0}] 96 end 97 end. 98 99-ifdef(REMOVE_TRIVIAL_BBS_NEEDED). 100fails_to(_Instr) -> []. 101-endif. 102 103-ifdef(notdef). 104redirect_jmp(I, Old, New) -> 105 case I of 106 #b_label{label=Label} -> 107 if Old =:= Label -> I#b_label{label=New}; 108 true -> I 109 end; 110 #pseudo_bc{true_label=TrueLab, false_label=FalseLab} -> 111 I1 = if Old =:= TrueLab -> I#pseudo_bc{true_label=New}; 112 true -> I 113 end, 114 if Old =:= FalseLab -> I1#pseudo_bc{false_label=New}; 115 true -> I1 116 end; 117 %% handle pseudo_call too? 118 _ -> I 119 end. 120-endif. 121 122mk_goto(Label) -> 123 hipe_arm:mk_b_label(Label). 124 125is_label(I) -> 126 hipe_arm:is_label(I). 127 128label_name(Label) -> 129 hipe_arm:label_label(Label). 130 131mk_label(Name) -> 132 hipe_arm:mk_label(Name). 133 134linearise(CFG) -> % -> defun, not insn list 135 MFA = function(CFG), 136 Formals = params(CFG), 137 Code = linearize_cfg(CFG), 138 Data = data(CFG), 139 VarRange = hipe_gensym:var_range(arm), 140 LabelRange = hipe_gensym:label_range(arm), 141 IsClosure = is_closure(CFG), 142 IsLeaf = is_leaf(CFG), 143 hipe_arm:mk_defun(MFA, Formals, IsClosure, IsLeaf, 144 Code, Data, VarRange, LabelRange). 145 146arity(CFG) -> 147 {_M, _F, A} = function(CFG), 148 A. 149