|
@@ -570,230 +570,6 @@ module CopyPropagation = DataFlow(struct
|
|
|
);
|
|
|
end)
|
|
|
|
|
|
-module CodeMotion = DataFlow(struct
|
|
|
- open Graph
|
|
|
- open BasicBlock
|
|
|
-
|
|
|
- let conditional = false
|
|
|
- let flag = FlagCodeMotion
|
|
|
- type t_def =
|
|
|
- | Top
|
|
|
- | Bottom
|
|
|
- | Const of tconstant
|
|
|
- | Local of tvar
|
|
|
- | Binop of binop * t * t
|
|
|
-
|
|
|
- and t = (t_def * Type.t * pos)
|
|
|
-
|
|
|
- let top = (Top,t_dynamic,null_pos)
|
|
|
- let bottom = (Bottom,t_dynamic,null_pos)
|
|
|
-
|
|
|
- let rec equals (lat1,_,_) (lat2,_,_) = match lat1,lat2 with
|
|
|
- | Top,Top
|
|
|
- | Bottom,Bottom ->
|
|
|
- true
|
|
|
- | Const ct1,Const ct2 ->
|
|
|
- ct1 = ct2
|
|
|
- | Local v1,Local v2 ->
|
|
|
- v1 == v2
|
|
|
- | Binop(op1,lat11,lat12),Binop(op2,lat21,lat22) ->
|
|
|
- op1 = op2 && equals lat11 lat21 && equals lat12 lat22
|
|
|
- | _ ->
|
|
|
- false
|
|
|
-
|
|
|
- let lattice = Hashtbl.create 0
|
|
|
-
|
|
|
- let get_cell i = try Hashtbl.find lattice i with Not_found -> top
|
|
|
- let set_cell i ct = Hashtbl.replace lattice i ct
|
|
|
-
|
|
|
- let rec transfer ctx bb e =
|
|
|
- let rec eval e = match e.eexpr with
|
|
|
- | TConst ct ->
|
|
|
- Const ct
|
|
|
- | TLocal v ->
|
|
|
- Local v
|
|
|
- | TBinop(op,e1,e2) ->
|
|
|
- let lat1 = transfer ctx bb e1 in
|
|
|
- let lat2 = transfer ctx bb e2 in
|
|
|
- Binop(op,lat1,lat2)
|
|
|
- | _ ->
|
|
|
- raise Exit
|
|
|
- in
|
|
|
- try
|
|
|
- (eval e,e.etype,e.epos)
|
|
|
- with Exit | Not_found ->
|
|
|
- bottom
|
|
|
-
|
|
|
- let init ctx =
|
|
|
- Hashtbl.clear lattice
|
|
|
-
|
|
|
- let commit ctx =
|
|
|
- let rec filter_loops lat loops = match lat with
|
|
|
- | Local v,_,_ ->
|
|
|
- let bb = match (get_var_info ctx.graph v).vi_writes with [bb] -> bb | _ -> raise Exit in
|
|
|
- let loops2 = List.filter (fun i -> not (List.mem i bb.bb_loop_groups)) loops in
|
|
|
- if loops2 = [] then filter_loops (get_cell v.v_id) loops else true,lat,loops2
|
|
|
- | Const _,_,_ ->
|
|
|
- false,lat,loops
|
|
|
- | Binop(op,lat1,lat2),t,p ->
|
|
|
- let has_local1,lat1,loops = filter_loops lat1 loops in
|
|
|
- let has_local2,lat2,loops = filter_loops lat2 loops in
|
|
|
- has_local1 || has_local2,(Binop(op,lat1,lat2),t,p),loops
|
|
|
- | _ ->
|
|
|
- raise Exit
|
|
|
- in
|
|
|
- let rec to_texpr (lat,t,p) =
|
|
|
- let def = match lat with
|
|
|
- | Local v -> TLocal v
|
|
|
- | Const ct -> TConst ct
|
|
|
- | Binop(op,lat1,lat2) -> TBinop(op,to_texpr lat1,to_texpr lat2)
|
|
|
- | _ -> raise Exit
|
|
|
- in
|
|
|
- { eexpr = def; etype = t; epos = p }
|
|
|
- in
|
|
|
- let cache = Hashtbl.create 0 in
|
|
|
- let replace decl bb v =
|
|
|
- let lat,t,p = get_cell v.v_id in
|
|
|
- match lat with
|
|
|
- | Binop(op,lat1,lat2) ->
|
|
|
- let has_local1,lat1,loops = filter_loops lat1 bb.bb_loop_groups in
|
|
|
- let has_local2,lat2,loops = filter_loops lat2 loops in
|
|
|
- if loops = [] || not (has_local1 || has_local2) then raise Exit;
|
|
|
- let lat = ((Binop(op,lat1,lat2)),t,p) in
|
|
|
- let bb_loop_pre = IntMap.find (List.hd loops) ctx.graph.g_loops in
|
|
|
- let v' = try
|
|
|
- let l = Hashtbl.find cache bb_loop_pre.bb_id in
|
|
|
- snd (List.find (fun (lat',e) -> equals lat lat') l)
|
|
|
- with Not_found ->
|
|
|
- let v' = if decl then begin
|
|
|
- v
|
|
|
- end else begin
|
|
|
- let v' = alloc_var ctx.temp_var_name v.v_type v.v_pos in
|
|
|
- declare_var ctx.graph v' bb_loop_pre;
|
|
|
- v'.v_meta <- [Meta.CompilerGenerated,[],p];
|
|
|
- v'
|
|
|
- end in
|
|
|
- let e = to_texpr lat in
|
|
|
- let e = mk (TVar(v',Some e)) ctx.com.basic.tvoid p in
|
|
|
- add_texpr bb_loop_pre e;
|
|
|
- set_var_value ctx.graph v' bb_loop_pre false (DynArray.length bb_loop_pre.bb_el - 1);
|
|
|
- Hashtbl.replace cache bb_loop_pre.bb_id ((lat,v') :: try Hashtbl.find cache bb_loop_pre.bb_id with Not_found -> []);
|
|
|
- v'
|
|
|
- in
|
|
|
- let ev' = mk (TLocal v') v'.v_type p in
|
|
|
- if decl then begin
|
|
|
- if v == v' then
|
|
|
- mk (TConst TNull) t p
|
|
|
- else
|
|
|
- mk (TVar(v,Some ev')) ctx.com.basic.tvoid p
|
|
|
- end else begin
|
|
|
- let ev = mk (TLocal v) v.v_type p in
|
|
|
- mk (TBinop(OpAssign,ev,ev')) t p
|
|
|
- end
|
|
|
- | _ ->
|
|
|
- raise Exit
|
|
|
- in
|
|
|
- let rec commit bb e = match e.eexpr with
|
|
|
- | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
|
|
|
- begin try
|
|
|
- replace false bb v
|
|
|
- with Exit ->
|
|
|
- {e with eexpr = TBinop(OpAssign,e1,commit bb e2)}
|
|
|
- end
|
|
|
- | TVar(v,Some e1) when Meta.has Meta.CompilerGenerated v.v_meta ->
|
|
|
- begin try
|
|
|
- replace true bb v
|
|
|
- with Exit ->
|
|
|
- {e with eexpr = TVar(v,Some (commit bb e1))}
|
|
|
- end
|
|
|
- | _ ->
|
|
|
- Type.map_expr (commit bb) e
|
|
|
- in
|
|
|
- Graph.iter_dom_tree ctx.graph (fun bb ->
|
|
|
- if bb.bb_loop_groups <> [] then dynarray_map (commit bb) bb.bb_el
|
|
|
- );
|
|
|
-end)
|
|
|
-
|
|
|
-module LoopInductionVariables = struct
|
|
|
- open Graph
|
|
|
-
|
|
|
- type book = {
|
|
|
- tvar : tvar;
|
|
|
- index : int;
|
|
|
- mutable lowlink : int;
|
|
|
- mutable on_stack : bool
|
|
|
- }
|
|
|
-
|
|
|
- let find_cycles g =
|
|
|
- let index = ref 0 in
|
|
|
- let s = ref [] in
|
|
|
- let book = ref IntMap.empty in
|
|
|
- let add_book_entry v =
|
|
|
- let entry = {
|
|
|
- tvar = v;
|
|
|
- index = !index;
|
|
|
- lowlink = !index;
|
|
|
- on_stack = true;
|
|
|
- } in
|
|
|
- incr index;
|
|
|
- book := IntMap.add v.v_id entry !book;
|
|
|
- entry
|
|
|
- in
|
|
|
- let rec strong_connect vi =
|
|
|
- let v_entry = add_book_entry vi.vi_var in
|
|
|
- s := v_entry :: !s;
|
|
|
- List.iter (fun (bb,is_phi,i) ->
|
|
|
- try
|
|
|
- let e = BasicBlock.get_texpr bb is_phi i in
|
|
|
- let w = match e.eexpr with
|
|
|
- | TVar(v,_) | TBinop(OpAssign,{eexpr = TLocal v},_) -> v
|
|
|
- | _ -> raise Exit
|
|
|
- in
|
|
|
- begin try
|
|
|
- let w_entry = IntMap.find w.v_id !book in
|
|
|
- if w_entry.on_stack then
|
|
|
- v_entry.lowlink <- min v_entry.lowlink w_entry.index
|
|
|
- with Not_found ->
|
|
|
- let w_entry = strong_connect (get_var_info g w) in
|
|
|
- v_entry.lowlink <- min v_entry.lowlink w_entry.lowlink;
|
|
|
- end
|
|
|
- with Exit ->
|
|
|
- ()
|
|
|
- ) vi.vi_ssa_edges;
|
|
|
- if v_entry.lowlink = v_entry.index then begin
|
|
|
- let rec loop acc entries = match entries with
|
|
|
- | w_entry :: entries ->
|
|
|
- w_entry.on_stack <- false;
|
|
|
- if w_entry == v_entry then w_entry :: acc,entries
|
|
|
- else loop (w_entry :: acc) entries
|
|
|
- | [] ->
|
|
|
- acc,[]
|
|
|
- in
|
|
|
- let scc,rest = loop [] !s in
|
|
|
- begin match scc with
|
|
|
- | [] | [_] ->
|
|
|
- ()
|
|
|
- | _ ->
|
|
|
- print_endline "SCC:";
|
|
|
- List.iter (fun entry -> print_endline (Printf.sprintf "%s<%i>" entry.tvar.v_name entry.tvar.v_id)) scc;
|
|
|
- (* now what? *)
|
|
|
- end;
|
|
|
- s := rest
|
|
|
- end;
|
|
|
- v_entry
|
|
|
- in
|
|
|
- DynArray.iter (fun vi -> match vi.vi_ssa_edges with
|
|
|
- | [] ->
|
|
|
- ()
|
|
|
- | _ ->
|
|
|
- if not (IntMap.mem vi.vi_var.v_id !book) then
|
|
|
- ignore(strong_connect vi)
|
|
|
- ) g.g_var_infos
|
|
|
-
|
|
|
- let apply ctx =
|
|
|
- find_cycles ctx.graph
|
|
|
-end
|
|
|
-
|
|
|
(*
|
|
|
LocalDce implements a mark & sweep dead code elimination. The mark phase follows the CFG edges of the graphs to find
|
|
|
variable usages and marks variables accordingly. If ConstPropagation was run before, only CFG edges which are
|
|
@@ -927,7 +703,6 @@ module Debug = struct
|
|
|
let s_edge_flag = function
|
|
|
| FlagExecutable -> "exe"
|
|
|
| FlagDce -> "dce"
|
|
|
- | FlagCodeMotion -> "motion"
|
|
|
| FlagCopyPropagation -> "copy"
|
|
|
in
|
|
|
let label = label ^ match edge.cfg_flags with
|
|
@@ -1189,7 +964,6 @@ module Run = struct
|
|
|
with_timer actx.config.detail_times ["optimize";"ssa-apply"] (fun () -> Ssa.apply actx);
|
|
|
if actx.config.const_propagation then with_timer actx.config.detail_times ["optimize";"const-propagation"] (fun () -> ConstPropagation.apply actx);
|
|
|
if actx.config.copy_propagation then with_timer actx.config.detail_times ["optimize";"copy-propagation"] (fun () -> CopyPropagation.apply actx);
|
|
|
- if actx.config.code_motion then with_timer actx.config.detail_times ["optimize";"code-motion"] (fun () -> CodeMotion.apply actx);
|
|
|
with_timer actx.config.detail_times ["optimize";"local-dce"] (fun () -> LocalDce.apply actx);
|
|
|
end;
|
|
|
back_again actx is_real_function
|