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_ppc_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, params/1, reverse_postorder/1]). 24-export([redirect_jmp/3, arity/1]). 25-export([branch_preds/1]). 26 27%%% these tell cfg.inc what to define (ugly as hell) 28-define(BREADTH_ORDER,true). 29-define(PARAMS_NEEDED,true). 30-define(START_LABEL_UPDATE_NEEDED,true). 31-define(MAP_FOLD_NEEDED,true). 32 33-include("hipe_ppc.hrl"). 34-include("../flow/cfg.hrl"). 35-include("../flow/cfg.inc"). 36 37init(Defun) -> 38 Code = hipe_ppc:defun_code(Defun), 39 StartLab = hipe_ppc:label_label(hd(Code)), 40 Data = hipe_ppc:defun_data(Defun), 41 IsClosure = hipe_ppc:defun_is_closure(Defun), 42 Name = hipe_ppc:defun_mfa(Defun), 43 IsLeaf = hipe_ppc:defun_is_leaf(Defun), 44 Formals = hipe_ppc:defun_formals(Defun), 45 CFG0 = mk_empty_cfg(Name, StartLab, Data, IsClosure, IsLeaf, Formals), 46 take_bbs(Code, CFG0). 47 48is_branch(I) -> 49 case I of 50 #b_fun{} -> true; 51 #b_label{} -> true; 52 %% not bc 53 #bctr{} -> true; 54 %% not bctrl 55 %% not bl 56 #blr{} -> true; 57 #pseudo_bc{} -> true; 58 #pseudo_call{} -> true; 59 #pseudo_tailcall{} -> true; 60 _ -> false 61 end. 62 63branch_successors(Branch) -> 64 case Branch of 65 #b_fun{} -> []; 66 #b_label{label=Label} -> [Label]; 67 #bctr{labels=Labels} -> Labels; 68 #blr{} -> []; 69 #pseudo_bc{true_label=TrueLab,false_label=FalseLab} -> [FalseLab,TrueLab]; 70 #pseudo_call{contlab=ContLab, sdesc=#ppc_sdesc{exnlab=ExnLab}} -> 71 case ExnLab of 72 [] -> [ContLab]; 73 _ -> [ContLab,ExnLab] 74 end; 75 #pseudo_tailcall{} -> [] 76 end. 77 78branch_preds(Branch) -> 79 case Branch of 80 #bctr{labels=Labels} -> 81 Prob = 1.0/length(Labels), 82 [{L, Prob} || L <- Labels]; 83 #pseudo_bc{true_label=TrueLab,false_label=FalseLab,pred=Pred} -> 84 [{FalseLab, 1.0-Pred}, {TrueLab, Pred}]; 85 #pseudo_call{contlab=ContLab, sdesc=#ppc_sdesc{exnlab=[]}} -> 86 %% A function can still cause an exception, even if we won't catch it 87 [{ContLab, 1.0-hipe_bb_weights:call_exn_pred()}]; 88 #pseudo_call{contlab=ContLab, sdesc=#ppc_sdesc{exnlab=ExnLab}} -> 89 CallExnPred = hipe_bb_weights:call_exn_pred(), 90 [{ContLab, 1.0-CallExnPred}, {ExnLab, CallExnPred}]; 91 _ -> 92 case branch_successors(Branch) of 93 [] -> []; 94 [Single] -> [{Single, 1.0}] 95 end 96 end. 97 98-ifdef(REMOVE_TRIVIAL_BBS_NEEDED). 99fails_to(_Instr) -> []. 100-endif. 101 102redirect_jmp(I, Old, New) -> 103 case I of 104 #b_label{label=Label} -> 105 if Old =:= Label -> I#b_label{label=New}; 106 true -> I 107 end; 108 #pseudo_bc{true_label=TrueLab, false_label=FalseLab} -> 109 I1 = if Old =:= TrueLab -> I#pseudo_bc{true_label=New}; 110 true -> I 111 end, 112 if Old =:= FalseLab -> I1#pseudo_bc{false_label=New}; 113 true -> I1 114 end; 115 #pseudo_call{sdesc=SDesc0, contlab=ContLab0} -> 116 SDesc = case SDesc0 of 117 #ppc_sdesc{exnlab=Old} -> SDesc0#ppc_sdesc{exnlab=New}; 118 #ppc_sdesc{exnlab=_} -> SDesc0 119 end, 120 ContLab = if Old =:= ContLab0 -> New; 121 true -> ContLab0 122 end, 123 I#pseudo_call{sdesc=SDesc, contlab=ContLab} 124 end. 125 126mk_goto(Label) -> 127 hipe_ppc:mk_b_label(Label). 128 129is_label(I) -> 130 hipe_ppc:is_label(I). 131 132label_name(Label) -> 133 hipe_ppc:label_label(Label). 134 135mk_label(Name) -> 136 hipe_ppc:mk_label(Name). 137 138linearise(CFG) -> % -> defun, not insn list 139 MFA = function(CFG), 140 Formals = params(CFG), 141 Code = linearize_cfg(CFG), 142 Data = data(CFG), 143 VarRange = hipe_gensym:var_range(ppc), 144 LabelRange = hipe_gensym:label_range(ppc), 145 IsClosure = is_closure(CFG), 146 IsLeaf = is_leaf(CFG), 147 hipe_ppc:mk_defun(MFA, Formals, IsClosure, IsLeaf, 148 Code, Data, VarRange, LabelRange). 149 150arity(CFG) -> 151 {_M, _F, A} = function(CFG), 152 A. 153