~emersion/minic

cf499df24fe0c0ed11fdae47fcbb55db14f1c308 — emersion 2 years ago 0351a85
Liveness: extract liveness from Ertltree to its own module
4 files changed, 88 insertions(+), 72 deletions(-)

M ertltree.ml
A liveness.ml
A liveness.mli
M ltl.ml
M ertltree.ml => ertltree.ml +1 -67
@@ 103,60 103,6 @@ let succ = function
  | Ereturn ->
      []

type live_info = {
         instr: instr;
          succ: Label.t list;    (* successeurs *)
  mutable pred: Label.set;       (* prédécesseurs *)
          defs: Register.set;    (* définitions *)
          uses: Register.set;    (* utilisations *)
  mutable  ins: Register.set;    (* variables vivantes en entrée *)
  mutable outs: Register.set;    (* variables vivantes en sortie *)
}

let rec kildall lg s =
  if not (Label.S.is_empty s) then (
    let lbl = Label.S.choose s in
    let s = Label.S.remove lbl s in
    let li = Label.M.find lbl !lg in
    let old_ins = li.ins in
    li.outs <- List.fold_left (fun rs succ_lbl ->
      let succ_li = Label.M.find succ_lbl !lg in
      Register.S.union rs succ_li.ins
    ) Register.S.empty li.succ;
    li.ins <- Register.S.union li.uses (Register.S.diff li.outs li.defs);
    let s = if Register.S.compare li.ins old_ins <> 0 then
      Label.S.union s li.pred
    else
      s
    in
    kildall lg s
  )

let liveness g =
  let lg = ref Label.M.empty in
  Label.M.iter (fun lbl instr ->
    let (defs, uses) = def_use instr in
    let li = {
      instr;
      succ = succ instr;
      pred = Label.S.empty;
      defs = Register.set_of_list defs;
      uses = Register.set_of_list uses;
      ins = Register.S.empty;
      outs = Register.S.empty
    } in
    lg := Label.M.add lbl li !lg
  ) g;
  Label.M.iter (fun lbl li ->
    List.iter (fun succ_lbl ->
      let succ_li = Label.M.find succ_lbl !lg in
      succ_li.pred <- Label.S.add lbl succ_li.pred
    ) li.succ
  ) !lg;
  let s = Label.M.fold (fun lbl _ s -> Label.S.add lbl s) !lg Label.S.empty in
  kildall lg s;
  !lg

(** {2 Fonctions d'impression, pour debugger} *)

open Format


@@ 217,24 163,12 @@ let visit f g entry =
let print_graph fmt g =
  visit (fun l i -> fprintf fmt "%a: %a@\n" Label.print l print_instr i) g

let print_live_info fmt li =
  fprintf fmt "def={%a}@ use={%a}@ in={%a}@ out={%a}"
    Register.print_set li.defs Register.print_set li.uses
    Register.print_set li.ins Register.print_set li.outs

let print_graph_with_liveness fmt g =
  let lg = liveness g in
  visit (fun l i ->
    let li = Label.M.find l lg in
    fprintf fmt "@[<hov 2>%a: %a@ @[%a@]@]@\n" Label.print l print_instr i print_live_info li
  ) g

let print_deffun fmt f =
  fprintf fmt "%s(%d)@\n" f.fun_name f.fun_formals;
  fprintf fmt "  @[";
  fprintf fmt "entry : %a@\n" Label.print f.fun_entry;
  fprintf fmt "locals: @[%a@]@\n" Register.print_set f.fun_locals;
  print_graph_with_liveness fmt f.fun_body f.fun_entry;
  print_graph fmt f.fun_body f.fun_entry;
  fprintf fmt "@]@."

let print_file fmt p =

A liveness.ml => liveness.ml +68 -0
@@ 0,0 1,68 @@
open Ertltree
open Format

type live_info = {
         instr: instr;
          succ: Label.t list;    (* successeurs *)
  mutable pred: Label.set;       (* prédécesseurs *)
          defs: Register.set;    (* définitions *)
          uses: Register.set;    (* utilisations *)
  mutable  ins: Register.set;    (* variables vivantes en entrée *)
  mutable outs: Register.set;    (* variables vivantes en sortie *)
}

let rec kildall lg s =
  if not (Label.S.is_empty s) then (
    let lbl = Label.S.choose s in
    let s = Label.S.remove lbl s in
    let li = Label.M.find lbl !lg in
    let old_ins = li.ins in
    li.outs <- List.fold_left (fun rs succ_lbl ->
      let succ_li = Label.M.find succ_lbl !lg in
      Register.S.union rs succ_li.ins
    ) Register.S.empty li.succ;
    li.ins <- Register.S.union li.uses (Register.S.diff li.outs li.defs);
    let s = if Register.S.compare li.ins old_ins <> 0 then
      Label.S.union s li.pred
    else
      s
    in
    kildall lg s
  )

let liveness g =
  let lg = ref Label.M.empty in
  Label.M.iter (fun lbl instr ->
    let (defs, uses) = def_use instr in
    let li = {
      instr;
      succ = succ instr;
      pred = Label.S.empty;
      defs = Register.set_of_list defs;
      uses = Register.set_of_list uses;
      ins = Register.S.empty;
      outs = Register.S.empty
    } in
    lg := Label.M.add lbl li !lg
  ) g;
  Label.M.iter (fun lbl li ->
    List.iter (fun succ_lbl ->
      let succ_li = Label.M.find succ_lbl !lg in
      succ_li.pred <- Label.S.add lbl succ_li.pred
    ) li.succ
  ) !lg;
  let s = Label.M.fold (fun lbl _ s -> Label.S.add lbl s) !lg Label.S.empty in
  kildall lg s;
  !lg

let print_live_info fmt li =
  fprintf fmt "def={%a}@ use={%a}@ in={%a}@ out={%a}"
    Register.print_set li.defs Register.print_set li.uses
    Register.print_set li.ins Register.print_set li.outs

let print_graph fmt g =
  let lg = liveness g in
  visit (fun l i ->
    let li = Label.M.find l lg in
    fprintf fmt "@[<hov 2>%a: %a@ @[%a@]@]@\n" Label.print l print_instr i print_live_info li
  ) g

A liveness.mli => liveness.mli +13 -0
@@ 0,0 1,13 @@
open Ertltree

type live_info = {
         instr: instr;
          succ: Label.t list;    (* successeurs *)
  mutable pred: Label.set;       (* prédécesseurs *)
          defs: Register.set;    (* définitions *)
          uses: Register.set;    (* utilisations *)
  mutable  ins: Register.set;    (* variables vivantes en entrée *)
  mutable outs: Register.set;    (* variables vivantes en sortie *)
}

val liveness : instr Label.M.t -> live_info Label.M.t

M ltl.ml => ltl.ml +6 -5
@@ 1,5 1,6 @@
open Ops
open Ltltree
open Liveness

type arcs = {
  prefs: Register.set;


@@ 57,13 58,13 @@ let make lg =
  let ig = ref Register.M.empty in
  Label.M.iter (fun lbl li ->
    Register.S.iter (fun def ->
      match li.Ertltree.instr with
      match li.instr with
      | Ertltree.Embinop (Mmov, r1, r2, _) ->
        Register.S.iter (fun out -> add_intf ig def out) (Register.S.remove r1 li.Ertltree.outs);
        Register.S.iter (fun out -> add_intf ig def out) (Register.S.remove r1 li.outs);
        add_pref ig r1 r2
      | _ ->
        Register.S.iter (fun out -> add_intf ig def out) li.Ertltree.outs
    ) li.Ertltree.defs
        Register.S.iter (fun out -> add_intf ig def out) li.outs
    ) li.defs
  ) lg;
  (* print_ig !ig; Format.printf "@\n"; *)
  !ig


@@ 301,7 302,7 @@ let process_instr graph col ns lblin instr =
  graph := Label.M.add lblin i !graph

let process_deffun df =
  let lg = Ertltree.liveness df.Ertltree.fun_body in
  let lg = liveness df.Ertltree.fun_body in
  let ig = make lg in
  let (c, ns) = color ig in
  let graph = ref Label.M.empty in