Module RTLpargen

Coalescing and RTLpar generation

Require Import Coqlib.
Require Import Errors.
Require Import Maps.
Require Import AST.
Require Import Globalenvs.
Require Import Smallstep.
Require Import Dom.
Require Import Op.
Require Import SSA.
Require Import SSAutils.
Require Import Utils.
Require Import CSSA.
Require RTLpar.
Require Import Kildall.
Require Import KildallComp.
Require Import DLib.
Require Import CSSAutils.
Require CSSAlive.
Require Import Registers.

Section TRANSFORMATION.

Notation "a @@ f" := (f a)
    (at level 50, left associativity).

compute variables definition point


Definition defined_var ins :=
  match ins with
  | Iop _ _ r _ => Some r
  | Iload _ _ _ r _ => Some r
  | Icall _ _ _ r _ => Some r
  | Ibuiltin _ _ (BR r) _ => Some r
  | _ => None
  end.

Definition compute_code_def (f : function) :=
  PTree.fold
    (fun acc pc ins =>
      match defined_var ins with
      | Some r => PTree.set r pc acc
      | None => acc
      end)
    (fn_code f).

Definition compute_phi_def (f : function) :=
  PTree.fold
   (fun acc pc phib =>
     fold_left
       (fun acc phi =>
       match phi with
       | Iphi args dst =>
           PTree.set dst pc acc
       end)
       phib acc)
   (fn_phicode f).

Definition compute_parc_def (f : function) :=
  PTree.fold
   (fun acc pc parcb =>
     fold_left
       (fun acc parc =>
       match parc with
       | Iparcopy src dst =>
           PTree.set dst pc acc
       end)
       parcb acc)
   (fn_parcopycode f).

Definition get_all_def f :=
  PTree.empty node
  @@ compute_code_def f
  @@ compute_phi_def f
  @@ compute_parc_def f.

Definition compute_def (f : function) all_defs :=
  fun r =>
    match PTree.get r all_defs with
    | Some d => d
    | None => fn_entrypoint f
    end.

gather extern parameters

Definition def_set defs :=
  List.fold_right SSARegSet.add SSARegSet.empty defs.

Definition get_ext_params f (all_defs : PTree.t positive) :=
  SSARegSet.union
    (SSARegSet.diff
      (search_used f)
      (def_set (map fst (PTree.elements all_defs))))
    (param_set f).

Coalescing classes construction in OCaml. Validated.

Parameter build_coalescing_classes_extern :
  function -> (reg -> reg -> bool) -> (reg -> reg) * (PTree.t (list reg)).

Checker for CSSA value computation

Definition check_cssaval_ins (elems : list (node * instruction)) (get_cssaval : reg -> reg) : bool :=
  fold_left
    (fun acc pcins =>
      if negb acc then false
      else match snd pcins with
      | Iop Omove (src :: nil) dst _ => peq (get_cssaval src) (get_cssaval dst)
      | Iop _ _ dst _ => peq (get_cssaval dst) dst
      | Iload _ _ _ dst _ => peq (get_cssaval dst) dst
      | Icall _ _ _ dst _ => peq (get_cssaval dst) dst
      | Ibuiltin _ _ (BR dst) _ => peq (get_cssaval dst) dst
      | _ => true
      end)
    elems true.

Definition check_cssaval_parcb (parcbs : list (node * parcopyblock)) (get_cssaval : reg -> reg) : bool :=
  fold_left
    (fun acc pcparcb =>
      if negb acc then false
      else forallb
        (fun parc =>
          match parc with
          | Iparcopy src dst =>
              peq (get_cssaval src) (get_cssaval dst)
          end)
        (snd pcparcb))
    parcbs
    true.

Definition check_cssaval_phib (phibs : list (node * phiblock)) (get_cssaval : reg -> reg) : bool :=
  fold_left
    (fun acc pcphib =>
      if negb acc then false
      else forallb
        (fun phi =>
          match phi with
          | Iphi args dst => peq (get_cssaval dst) dst
          end)
        (snd pcphib))
    phibs
    true.

Definition check_cssaval_ext_params (ext_params : list reg) (get_cssaval : reg -> reg) : bool :=
  forallb (fun param => peq (get_cssaval param) param) ext_params.

Definition check_cssaval (f : function)
    (get_cssaval : reg -> reg) ext_params : bool :=
  check_cssaval_ins (PTree.elements (fn_code f)) get_cssaval
  && check_cssaval_parcb (PTree.elements (fn_parcopycode f)) get_cssaval
  && check_cssaval_phib (PTree.elements (fn_phicode f)) get_cssaval
  && check_cssaval_ext_params (SSARegSet.elements ext_params) get_cssaval.

Parameter compute_cssaval_function : function -> (reg -> reg).

Definition compute_ninterfere f all_defs ext_params :=
  let def := compute_def f all_defs in
  match CSSAlive.analyze f with
  | None => Errors.Error (Errors.msg "live analysis failed")
  | Some live =>
      let cssaval := compute_cssaval_function f in
      if negb (check_cssaval f cssaval ext_params)
      then Errors.Error (Errors.msg "compute_cssaval")
      else
        Errors.OK
          (fun r1 r2 =>
            peq (cssaval r1) (cssaval r2)
            ||
              let '(d1, d2) := (def r1, def r2) in
              negb
                (peq d1 d2
                     || SSARegSet.mem r1 (PMap.get d2 live)
                     || SSARegSet.mem r2 (PMap.get d1 live)))
  end.

Validation of congruence classes, naive algorithm

Fixpoint check_interference_with_class (r : reg) (class : list reg) ninterf :=
  match class with
  | nil => true
  | a :: t =>
      ninterf r a && check_interference_with_class r t ninterf
  end.

Fixpoint check_interference_in_class (class : list reg) ninterf :=
  match class with
  | nil => true
  | a :: t =>
      check_interference_with_class a t ninterf &&
      check_interference_in_class t ninterf
  end.

Definition mem_class_reg regrepr classes r : bool :=
  match PTree.get (regrepr r) classes with
  | Some class => In_reg r class
  | None => peq r (regrepr r)
  end.

Definition mem_class_regs regrepr classes reglist :=
  forallb (mem_class_reg regrepr classes) reglist.

Definition check_coalescing_classes regrepr classes ninterf (all_defs : PTree.t positive) ext_params :=
  forallb (fun class => check_interference_in_class class ninterf) (map snd (PTree.elements classes)) &&
  mem_class_regs regrepr classes (map fst (PTree.elements all_defs)) &&
  mem_class_regs regrepr classes (SSARegSet.elements ext_params).

Check that phi_ressources are correctly mapped to destinations

Definition check_phi_ressources_coalescing regrepr phi :=
  match phi with
  | Iphi args dst =>
      forallb (fun arg => peq (regrepr arg) (regrepr dst)) args
  end.

Definition check_cssa_coalescing_in_phib regrepr phib :=
  forallb (check_phi_ressources_coalescing regrepr) phib.

Definition check_cssa_coalescing_in_phicode regrepr f :=
  forallb (check_cssa_coalescing_in_phib regrepr)
    (map snd (PTree.elements (fn_phicode f))).

RTLpar generation functions


Definition compute_regrepr (f : function) :=
  let all_defs := get_all_def f in
  let ext_params := get_ext_params f all_defs in
  match compute_ninterfere f all_defs ext_params with
  | Errors.Error m => Errors.Error m
  | Errors.OK ninterf =>
      match build_coalescing_classes_extern f ninterf with
      | (regrepr, classes) =>
          if check_coalescing_classes regrepr classes ninterf all_defs ext_params &&
            check_cssa_coalescing_in_phicode regrepr f
          then Errors.OK regrepr
          else Errors.Error (Errors.msg "check_coalescing_classes")
      end
  end.

Definition transl_instruction regrepr ins :=
  match ins with
  | Inop s => Inop s
  | Iop op args res s => Iop op (map regrepr args) (regrepr res) s
  | Iload chunk addr args dst s => Iload chunk addr (map regrepr args) (regrepr dst) s
  | Istore chunk addr args src s => Istore chunk addr (map regrepr args) (regrepr src) s
  | Icall sig (inl r) args res s => Icall sig (inl (regrepr r)) (map regrepr args) (regrepr res) s
  | Icall sig os args res s => Icall sig os (map regrepr args) (regrepr res) s
  | Itailcall sig (inl r) args => Itailcall sig (inl (regrepr r)) (map (regrepr) args)
  | Itailcall sig os args => Itailcall sig os (map regrepr args)
  | Ibuiltin ef args res s => Ibuiltin ef (map (map_builtin_arg regrepr) args) (map_builtin_res regrepr res) s
  | Icond cond args ifso ifnot => Icond cond (map regrepr args) ifso ifnot
  | Ijumptable arg tbl => Ijumptable (regrepr arg) tbl
  | Ireturn None => Ireturn None
  | Ireturn (Some arg) => Ireturn (Some (regrepr arg))
  end.

Definition transl_parcb regrepr (parcb : parcopyblock) :=
  map (fun parc =>
    match parc with
    | Iparcopy src dst =>
        Iparcopy (regrepr src) (regrepr dst)
    end)
    parcb.

Definition transl_code (regrepr : reg -> reg) (code : code) :=
  PTree.map1 (transl_instruction regrepr) code.

Definition transl_parcopycode (regrepr : reg -> reg) (parcode : parcopycode) :=
  PTree.map1 (transl_parcb regrepr) parcode.

Post processing


Fixpoint parcb_cleanup (parcb : parcopyblock) :=
  match parcb with
  | nil => nil
  | Iparcopy src dst :: parcb =>
      if peq src dst then parcb_cleanup parcb
      else Iparcopy src dst :: parcb_cleanup parcb
  end.

Definition parcopycode_cleanup (parcode : parcopycode) :=
  PTree.map1 parcb_cleanup parcode.

The transformation


Definition transl_function (f : CSSA.function) :=
  match compute_regrepr f with
  | Errors.Error m => Errors.Error m
  | Errors.OK regrepr =>
      Errors.OK
        (RTLpar.mkfunction
          f.(fn_sig)
          (map regrepr f.(fn_params))
          f.(fn_stacksize)
          (transl_code regrepr f.(fn_code))
          (parcopycode_cleanup (transl_parcopycode regrepr f.(fn_parcopycode)))
          f.(fn_entrypoint))
  end.

Definition transl_fundef :=
  transf_partial_fundef transl_function.

Definition transl_program (p: CSSA.program) : Errors.res RTLpar.program :=
  transform_partial_program transl_fundef p.

End TRANSFORMATION.