aboutsummaryrefslogtreecommitdiffstats
path: root/src/SoftwarePipelining/SPBasic.ml
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2021-11-18 22:10:55 +0000
committerYann Herklotz <git@yannherklotz.com>2021-11-18 22:10:55 +0000
commit82d69d247c7de8387b92936086abdc3d441c8628 (patch)
tree227f7db7e785f1c3affa2028bc2484e0771d54f4 /src/SoftwarePipelining/SPBasic.ml
parentfea7ee4d30aa7597ff5b8e2a2954ed452a1a7a57 (diff)
downloadvericert-82d69d247c7de8387b92936086abdc3d441c8628.tar.gz
vericert-82d69d247c7de8387b92936086abdc3d441c8628.zip
Rename pipelining
Diffstat (limited to 'src/SoftwarePipelining/SPBasic.ml')
-rw-r--r--src/SoftwarePipelining/SPBasic.ml819
1 files changed, 0 insertions, 819 deletions
diff --git a/src/SoftwarePipelining/SPBasic.ml b/src/SoftwarePipelining/SPBasic.ml
deleted file mode 100644
index 32234b8..0000000
--- a/src/SoftwarePipelining/SPBasic.ml
+++ /dev/null
@@ -1,819 +0,0 @@
-(***********************************************************************)
- (* *)
-(* Compcert Extensions *)
-(* *)
-(* Jean-Baptiste Tristan *)
-(* *)
-(* All rights reserved. This file is distributed under the terms *)
-(* described in file ../../LICENSE. *)
-(* *)
-(***********************************************************************)
-
-
-open RTL
-open Camlcoq
-open Graph.Pack.Digraph
-open Op
-open Registers
-open Memory
-open Mem
-open AST
-open SPBase_types
-open SPSymbolic_evaluation
-
-type node = instruction * int
-module G = Graph.Persistent.Digraph.AbstractLabeled
- (struct type t = node end)
- (struct type t = int let compare = compare let default = 0 end)
-module Topo = Graph.Topological.Make (G)
-module Dom = Graph.Dominator.Make (G)
-module Index = Map.Make (struct type t = int let compare = compare end)
-
-let string_of_instruction node =
- match G.V.label node with
- | (Inop,n) -> Printf.sprintf "%i nop" n
- | (Iop (op, args, dst),n) -> Printf.sprintf "%i r%i := %s %s" n (to_int dst) (string_of_op op) (string_of_args args)
- | (Iload (chunk, mode, args, dst),n) -> Printf.sprintf "%i r%i := load %s" n (to_int dst) (string_of_args args)
- | (Istore (chunk, mode, args, src),n) -> Printf.sprintf "%i store %i %s" n (to_int src) (string_of_args args)
- | (Icall (sign, id, args, dst),n) -> Printf.sprintf "%i call" n
- | (Itailcall (sign, id, args),n) -> Printf.sprintf "%i tailcall" n
- (* | (Ialloc (dst, size),n) -> Printf.sprintf "%i %i := alloc" n (to_int dst) *)
- | (Icond (cond, args),n) -> Printf.sprintf "%i cond %s %s" n (string_of_cond cond) (string_of_args args)
- | (Ireturn (res),n) -> Printf.sprintf "%i return" n
-
-let string_of_node = string_of_instruction
-
-module Display = struct
- include G
- let vertex_name v = print_inst (V.label v)
- let graph_attributes _ = []
- let default_vertex_attributes _ = []
- let vertex_attributes v = [`Label (string_of_instruction v)]
- let default_edge_attributes _ = []
- let edge_attributes e = [`Label (string_of_int (G.E.label e))]
- let get_subgraph _ = None
-end
-module Dot_ = Graph.Graphviz.Dot(Display)
-
-let dot_output g f =
- let oc = open_out f in
- Dot_.output_graph oc g;
- close_out oc
-
-let display g name =
- let addr = SPDebug.name ^ name in
- dot_output g addr ;
- ignore (Sys.command ("(dot -Tpng " ^ addr ^ " -o " ^ addr ^ ".png ; rm -f " ^ addr ^ ") & "))
-
-(******************************************)
-
-type cfg = {graph : G.t; start : G.V.t}
-
-(* convert traduit un graphe RTL compcert en un graphe RTL ocamlgraph*)
-
-let convert f =
-
- let make_node inst key =
- let inst = inst_coq_to_caml inst in
- G.V.create (inst, to_int key)
- in
-
- let (graph, index) = Maps.PTree.fold (fun (g,m) key inst ->
- let node = make_node inst key in
- (G.add_vertex g node, Index.add (to_int key) node m)
- ) f.fn_code (G.empty,Index.empty)
- in
-
- let succ = RTL.successors_map f in
- let rec link n succs g =
- match succs with
- | [] -> g
- | pos::[] ->
- G.add_edge g (Index.find (to_int n) index) (Index.find (to_int pos) index)
- | pos1::pos2::[] ->
- let g = G.add_edge_e g (G.E.create (Index.find (to_int n) index) 1 (Index.find (to_int pos1) index)) in
- G.add_edge_e g (G.E.create (Index.find (to_int n) index) 2 (Index.find (to_int pos2) index))
- | _ -> failwith "convert : trop de successeurs"
-
- in
-
- let graph = Maps.PTree.fold ( fun g key inst ->
- link key (match Maps.PTree.get key succ with
- Some x -> x | _ -> failwith "Could not index") g
- ) f.fn_code graph
- in
-
- {graph = graph; start = Index.find (to_int (f.fn_entrypoint)) index}
-
-
-let convert_back g =
-
- G.fold_vertex (fun node m ->
- let v = G.V.label node in
- match (fst v) with
- | Icond (_,_) ->
- begin
- let l =
- match G.succ_e g node with
- | [e1;e2] ->
- if G.E.label e1 > G.E.label e2
- then [G.E.dst e2;G.E.dst e1]
- else [G.E.dst e1;G.E.dst e2]
- | _ -> failwith "convert_back: nombre de successeurs incoherent"
- in
- let succs = List.map (fun s -> to_binpos (snd (G.V.label s))) l in
- Maps.PTree.set (to_binpos (snd v)) (inst_caml_to_coq (fst v) succs) m
- end
- | _ ->
- let succs = List.map (fun s -> to_binpos (snd (G.V.label s))) (G.succ g node) in
- Maps.PTree.set (to_binpos (snd v)) (inst_caml_to_coq (fst v) succs) m
- ) g Maps.PTree.empty
-
-
-
-
-(* dominator_tree calcule l'arbre de domination grace au code de FP *)
-let dominator_tree f =
- Dom.compute_idom f.graph f.start
-
-(* detect_loops, find the loops in the graph and returns the list of nodes in it,
- in dominating order !!! This is of great importance, we suppose that it is ordered
- when we build the dependency graph *)
-let detect_loops graph dom_tree =
- let rec is_dominating v1 v2 l = (* does v1 dominate v2 *)
- match dom_tree v2 with
- | v -> if v1 = v then Some (v :: l)
- else is_dominating v1 v (v :: l)
- | exception (Not_found) -> None
- in
-
- G.fold_edges (fun v1 v2 loops ->
- match is_dominating v2 v1 [v1] with
- | None -> loops
- | Some loop -> (v2,loop) :: loops
- ) graph []
-
-let print_index node =
- Printf.printf "%i " (snd (G.V.label node))
-
-let print_instruction node =
- match G.V.label node with
- | (Inop,n) -> Printf.printf "%i : Inop \n" n
- | (Iop (op, args, dst),n) -> Printf.printf "%i : Iop \n" n
- | (Iload (chunk, mode, args, dst),n) -> Printf.printf "%i : Iload \n" n
- | (Istore (chunk, mode, args, src),n) -> Printf.printf "%i : Istore \n" n
- | (Icall (sign, id, args, dst),n) -> Printf.printf "%i : Icall \n" n
- | (Itailcall (sign, id, args),n) -> Printf.printf "%i : Itailcall \n" n
- (*| (Ialloc (dst, size),n) -> Printf.printf "%i : Ialloc \n" n *)
- | (Icond (cond, args),n) -> Printf.printf "%i : Icond \n" n
- | (Ireturn (res),n) -> Printf.printf "%i : Ireturn \n" n
-
-let is_rewritten node r =
- match fst (G.V.label node) with
- | Inop -> false
- | Iop (op, args, dst) -> if dst = r then true else false
- | Iload (chunk, mode, args, dst) -> if dst = r then failwith "J'ai degote une boucle ZARBI !!!" else false
- | Istore (chunk, mode, args, src) -> false
- | Icall (sign, id, args, dst) -> failwith "call in a loop"
- | Itailcall (sign, id, args) -> failwith "tailcall in a loop"
- (* | Ialloc (dst, size) -> if dst = r then failwith "J'ai degote une boucle ZARBI !!!" else false *)
- | Icond (cond, args) -> false
- | Ireturn (res) -> failwith "return in a loop"
-
-let is_variant r loop =
- List.fold_right (fun node b ->
- is_rewritten node r || b
- ) loop false
-
-
-let is_pipelinable loop = (* true if loop is innermost and without control *)
-
- let is_acceptable node =
- match fst (G.V.label node) with
- | Icall _ | Itailcall _ | Ireturn _ | Icond _ (*| Ialloc _*) | Iop ((Ocmp _),_,_)-> false
- | _ -> true
- in
-
- let is_branching node =
- match fst (G.V.label node) with
- | Icond _ -> true
- | _ -> false
- in
-
- let is_nop node =
- match fst (G.V.label node) with
- | Inop -> true
- | _ -> false
- in
-
- let is_OK_aux l =
- List.fold_right (fun n b -> is_acceptable n && b) l true
- in
-
- let is_bounded node loop =
- match G.V.label node with
- | (Icond (cond, args),n) ->
- let args = to_caml_list args in
- begin
- match args with
- | [] -> false
- | r :: [] -> is_variant r loop (* used to be not *)
- | r1 :: r2 :: [] ->
- begin
- match is_variant r1 loop, is_variant r2 loop with
- | true, true -> false
- | false, true -> true
- | true, false -> true
- | false, false -> false
- end
- | _ -> false
- end
- | _ -> false
- in
-
- match List.rev loop with
- | v2 :: v1 :: l -> ((*Printf.printf "is_nop: %s | " (is_nop v1 |> string_of_bool);*)
- Printf.printf "is_branching: %s | " (is_branching v2 |> string_of_bool);
- Printf.printf "is_OK_aux: %s | " (is_OK_aux l |> string_of_bool);
- Printf.printf "is_bounded: %s\n" (is_bounded v2 loop |> string_of_bool);
- (*is_nop v1 && *)is_branching v2 && is_OK_aux l && is_bounded v2 loop)
- | _ -> false
-
-let print_loops loops =
- List.iter (fun loop -> print_index (fst(loop));
- print_newline ();
- List.iter print_index (snd(loop));
- print_newline ();
- if is_pipelinable (snd(loop)) then print_string "PIPELINABLE !" else print_string "WASTE";
- print_newline ();
- List.iter print_instruction (snd(loop));
- print_newline ()
- ) loops
-
-(* type resource = Reg of reg | Mem *)
-module Sim = Map.Make (struct type t = resource let compare = compare end)
-
-let map_get key map =
- try Some (Sim.find key map)
- with
- | Not_found -> None
-
-let rec to_res l =
- match l with
- | [] -> []
- | e :: l -> Reg e :: to_res l
-
-let resources_reads_of node =
- match fst (G.V.label node) with
- | Inop -> []
- | Iop (op, args, dst) -> to_res args
- | Iload (chunk, mode, args, dst) -> Mem :: (to_res args)
- | Istore (chunk, mode, args, src) -> Mem :: Reg src :: (to_res args)
- | Icall (sign, id, args, dst) -> failwith "Resource read of call"
- | Itailcall (sign, id, args) -> failwith "Resource read of tailcall"
- (*| Ialloc (dst, size) -> [Mem] *)
- | Icond (cond, args) -> to_res args
- | Ireturn (res) -> failwith "Resource read of return"
-
-let resources_writes_of node =
- match fst (G.V.label node) with
- | Inop -> []
- | Iop (op, args, dst) -> [Reg dst]
- | Iload (chunk, mode, args, dst) -> [Reg dst]
- | Istore (chunk, mode, args, src) -> [Mem]
- | Icall (sign, id, args, dst) -> failwith "Resource read of call"
- | Itailcall (sign, id, args) -> failwith "Resource read of tailcall"
- (*| Ialloc (dst, size) -> (Reg dst) :: [Mem]*)
- | Icond (cond, args) -> []
- | Ireturn (res) -> failwith "Resource read of return"
-
-let build_intra_dependency_graph loop =
-
- let rec build_aux graph read write l =
- match l with
- | [] -> (graph,(read,write))
- | v :: l->
- let g = G.add_vertex graph v in
- let reads = resources_reads_of v in
- let writes = resources_writes_of v in
- (* dependances RAW *)
- let g = List.fold_right (fun r g ->
- match map_get r write with
- | Some n -> G.add_edge_e g (G.E.create n 1 v)
- | None -> g
- ) reads g in
- (* dependances WAR *)
- let g = List.fold_right (fun r g ->
- match map_get r read with
- | Some l -> List.fold_right (fun n g -> G.add_edge_e g (G.E.create n 2 v)) l g
- | None -> g
- ) writes g in
- (* dependances WAW *)
- let g = List.fold_right (fun r g ->
- match map_get r write with
- | Some n -> G.add_edge_e g (G.E.create n 3 v)
- | None -> g
- ) writes g in
- let write = List.fold_right (fun r m -> Sim.add r v m) writes write in
- let read_tmp = List.fold_right (fun r m ->
- match map_get r read with
- | Some al -> Sim.add r (v :: al) m
- | None -> Sim.add r (v :: []) m
- ) reads read
- in
- let read = List.fold_right (fun r m -> Sim.add r [] m) writes read_tmp in
-
- build_aux g read write l
- in
-
- build_aux G.empty Sim.empty Sim.empty (List.tl loop)
-
-let build_inter_dependency_graph loop =
-
- let rec build_aux2 graph read write l =
- match l with
- | [] -> graph
- | v :: l->
- let g = graph in
- let reads = resources_reads_of v in
- let writes = resources_writes_of v in
- (* dependances RAW *)
- let g = List.fold_right (fun r g ->
- match map_get r write with
- | Some n -> (* if n = v then g else *) G.add_edge_e g (G.E.create n 4 v)
- | None -> g
- ) reads g in
- (* dependances WAR *)
- let g = List.fold_right (fun r g ->
- match map_get r read with
- | Some l -> List.fold_right
- (fun n g -> (* if n = v then g else *) G.add_edge_e g (G.E.create n 5 v)) l g
- | None -> g
- ) writes g in
- (* dependances WAW *)
- let g = List.fold_right (fun r g ->
- match map_get r write with
- | Some n -> (* if n = v then g else *) G.add_edge_e g (G.E.create n 6 v)
- | None -> g
- ) writes g in
- let write = List.fold_right (fun r m -> Sim.remove r m) writes write in
- let read = List.fold_right (fun r m -> Sim.remove r m) writes read in
-
-
- build_aux2 g read write l
- in
-
- let (g,(r,w)) = build_intra_dependency_graph loop in
- build_aux2 g r w (List.tl loop)
-
-(* patch_graph prepare le graphe pour la boucle commencant au noeud entry
- qui a une borne de boucle bound et pour un software pipelining
- de au minimum min tours et de deroulement ur *)
-(* this is rather technical so we give many comments *)
-
-(* let n1 = G.V.create (Iop ((Ointconst ur),to_coq_list [],r1),next_pc) in *)
-(* let next_pc = next_pc + 1 in *)
-(* let n2 = G.V.create (Iop (Odiv,to_coq_list [bound;r1],r2),next_pc) in *)
-(* let next_pc = next_pc + 1 in *)
-(* let n3 = G.V.create (Iop ((Omulimm ur),to_coq_list [r2],r3),next_pc) in *)
-(* let next_pc = next_pc + 1 in *)
-(* let n4 = G.V.create (Iop (Osub,to_coq_list [bound;r3],r4),next_pc) in *)
-(* let next_pc = next_pc + 1 in *)
-(* let n5 = G.V.create (Iop (Omove,to_coq_list [r3],bound),next_pc) in (\* retouchee, [r3],bound *\) *)
-
-
-let patch_graph graph entry lastone loop bound min ur r1 r2 r3 r4 next_pc prolog epilog ramp_up ramp_down =
-
- (* 1. Break the edge that enters the loop, except for the backedge *)
- let preds_e = G.pred_e graph entry in
- let wannabes = List.map G.E.src preds_e in
- let wannabes = List.filter (fun e -> not (e = lastone)) wannabes in
- let graph = List.fold_right (fun e g -> G.remove_edge_e g e) preds_e graph in
- let graph = G.add_edge graph lastone entry in
-
- (* 2. Add the test for minimal iterations and link it*)
-
- let cond = G.V.create (Icond ((Ccompimm (Integers.Cle,min)),to_coq_list [bound]), next_pc) in
- let graph = G.add_vertex graph cond in
- let next_pc = next_pc + 1 in
-
- (* 3. Link its predecessors and successors *)
- (* It is false in case there is a condition that points to the entry:
- inthis case, the edge should not be labeled with 0 !*)
-
- let graph = List.fold_right (fun n g -> G.add_edge g n cond) wannabes graph in
- let graph = G.add_edge_e graph (G.E.create cond 1 entry) in
-
-
- (* 4. Add the div and modulo code, link it *)
- let n1 = G.V.create (Iop ((Ointconst ur),to_coq_list [],r1),next_pc) in
- let next_pc = next_pc + 1 in
- let n2 = G.V.create (Iop (Odiv,to_coq_list [bound;r1],r2),next_pc) in
- let next_pc = next_pc + 1 in
- let n3 = G.V.create (Iop (Omove,to_coq_list [bound],r4),next_pc) in
- let next_pc = next_pc + 1 in
- let n4 = G.V.create (Iop ((Omulimm ur ),to_coq_list [r2],r3),next_pc) in
- let next_pc = next_pc + 1 in
- let n5 = G.V.create (Iop ((Olea (Aindexed (Z.of_sint (-1)))),to_coq_list [r3],bound),next_pc) in (* retouchee, [r3],bound *)
- let next_pc = next_pc + 1 in
- let graph = G.add_vertex graph n1 in
- let graph = G.add_vertex graph n2 in
- let graph = G.add_vertex graph n3 in
- let graph = G.add_vertex graph n4 in
- let graph = G.add_vertex graph n5 in
- let graph = G.add_edge_e graph (G.E.create cond 2 n1) in
- let graph = G.add_edge graph n1 n2 in
- let graph = G.add_edge graph n2 n3 in
- let graph = G.add_edge graph n3 n4 in
- let graph = G.add_edge graph n4 n5 in
-
- (* 5. Fabriquer la pipelined loop et la linker, sans la condition d entree *)
-
- let (graph,next_pc,l) = List.fold_right (fun e (g,npc,l) ->
- let n = G.V.create (e,npc) in
- (G.add_vertex g n, npc+1, n :: l)
- ) loop (graph,next_pc,[]) in
-
- let pipe_cond = List.hd l in
- let pipeline = List.tl l in
-
- let rec link l graph node =
- match l with
- | n1 :: n2 :: l -> link (n2 :: l) (G.add_edge graph n1 n2) node
- | n1 :: [] -> G.add_edge graph n1 node
- | _ -> graph
- in
-
- let graph = link pipeline graph pipe_cond in
-
- (* link de l entree de la boucle *)
-
- let (graph,next_pc,prolog) = List.fold_right (fun e (g,npc,l) ->
- let n = G.V.create (e,npc) in
- (G.add_vertex g n, npc+1, n :: l)
- ) prolog (graph,next_pc,[]) in
-
- let (graph,next_pc,epilog) = List.fold_right (fun e (g,npc,l) ->
- let n = G.V.create (e,npc) in
- (G.add_vertex g n, npc+1, n :: l)
- ) epilog (graph,next_pc,[]) in
-
- (* 6. Creation du reste et branchement et la condition *)
- let n6 = G.V.create (Iop (Omove,to_coq_list [r4],bound),next_pc) in (* Iop (Omove,to_coq_list [r4],bound) *)
- let next_pc = next_pc + 1 in
-
- (* 7. Creation du ramp up *)
- let ramp_up = List.map (fun (a,b) -> Iop (Omove, [b], a)) ramp_up in
- let (graph,next_pc,ramp_up) = List.fold_right (fun e (g,npc,l) ->
- let n = G.V.create (e,npc) in
- (G.add_vertex g n, npc+1, n :: l)
- ) ramp_up (graph,next_pc,[]) in
-
- let next_pc = next_pc + 1 in
-
- let ramp_down = List.map (fun (a,b) -> Iop (Omove,[b],a)) ramp_down in
- let (graph,next_pc,ramp_down) = List.fold_right (fun e (g,npc,l) ->
- let n = G.V.create (e,npc) in
- (G.add_vertex g n, npc+1, n :: l)
- ) ramp_down (graph,next_pc,[]) in
-
- (* let next_pc = next_pc + 1 in *)
-
- (* Creation des proloque et epilogue *)
-
- let graph = link prolog graph pipe_cond in
- let graph = link ramp_up graph (List.hd prolog) in
- let graph = link epilog graph (List.hd ramp_down) in
- let graph = link ramp_down graph n6 in
-
- let graph = G.add_edge graph n5 (List.hd ramp_up) in
- let graph = G.add_edge_e graph (G.E.create pipe_cond 1 (List.hd epilog)) in
- let graph = G.add_edge_e graph (G.E.create pipe_cond 2 (List.hd pipeline)) in
-
- (* 8. Retour sur la boucle classique *)
- let graph = G.add_edge graph n6 entry in
-
- graph
-
-let regs_of_node node =
- match G.V.label node with
- | (Inop,n) -> []
- | (Iop (op, args, dst),n) -> dst :: (to_caml_list args)
- | (Iload (chunk, mode, args, dst),n) -> dst :: (to_caml_list args)
- | (Istore (chunk, mode, args, src),n) -> src :: (to_caml_list args)
- | (Icall (sign, id, args, dst),n) -> dst :: (to_caml_list args)
- | (Itailcall (sign, id, args),n) -> (to_caml_list args)
- (*| (Ialloc (dst, size),n) -> [dst]*)
- | (Icond (cond, args),n) -> (to_caml_list args)
- | (Ireturn (res),n) -> match res with Some res -> [res] | _ -> []
-
-let max_reg_of_graph graph params =
- Printf.fprintf SPDebug.dc "Calcul du registre de depart.\n";
- let regs = G.fold_vertex (fun node regs ->
- (regs_of_node node) @ regs
- ) graph [] in
- let regs = regs @ params in
- let max_reg = List.fold_right (fun reg max ->
- Printf.fprintf SPDebug.dc "%i " (P.to_int reg);
- if Int32.compare (P.to_int32 reg) max > 0
- then (P.to_int32 reg)
- else max
- ) regs Int32.zero in
-
- Printf.fprintf SPDebug.dc "MAX REG = %i\n" (Int32.to_int max_reg);
- BinPos.Pos.succ (P.of_int32 max_reg)
-
-let get_bound node loop =
- match G.V.label node with
- | (Icond (cond, args),n) ->
- let args = to_caml_list args in
- begin
- match args with
- | [] -> failwith "get_bound: condition sans variables"
- | r :: [] -> if is_variant r loop then failwith "Pas de borne dans la boucle" else r (* Modified false to true condition. *)
- | r1 :: r2 :: [] ->
- begin
- match is_variant r1 loop, is_variant r2 loop with
- | true, true -> failwith "Pas de borne dans la boucle "
- | false, true -> r1
- | true, false -> r2
- | false, false -> failwith "deux bornes possibles dans la boucle"
- end
- | _ -> failwith "get_bound: condition avec nombre de variables superieur a 2"
- end
- | _ -> failwith "get_bound: the node I was given is not a condition\n"
-
-let get_nextpc graph =
- (G.fold_vertex (fun node max ->
- if (snd (G.V.label node)) > max
- then (snd (G.V.label node))
- else max
- ) graph 0) + 1
-
-let substitute_pipeline graph loop steady_state prolog epilog min unrolling ru rd params =
- let n1 = max_reg_of_graph graph params in
- let n2 = (BinPos.Pos.succ n1) in
- let n3 = (BinPos.Pos.succ n2) in
- let n4 = (BinPos.Pos.succ n3) in
- let way_in = (List.hd loop) in
- let way_out = (List.hd (List.rev loop)) in
- let bound = (get_bound way_out loop) in
- let min = Z.of_sint min in
- let unrolling = Z.of_sint unrolling in
- let next_pc = get_nextpc graph in
- patch_graph graph way_in way_out steady_state bound min unrolling n1 n2 n3 n4 next_pc prolog epilog ru rd
-
-let get_loops cfg =
- let domi = dominator_tree cfg in
- let loops = detect_loops cfg.graph domi in
- print_loops loops;
- let loops = List.filter (fun loop -> is_pipelinable (snd (loop))) loops in
- loops
-
-type pipeline = {steady_state : G.V.t list; prolog : G.V.t list; epilog : G.V.t list;
- min : int; unrolling : int; ramp_up : (reg * reg) list; ramp_down : (reg * reg) list}
-
-let delete_indexes l = List.map (fun e -> fst (G.V.label e) ) l
-
-type reg = Registers.reg
-
-let fresh = ref BinNums.Coq_xH
-
-let distance e =
- match G.E.label e with
- | 1 | 2 | 3 -> 0
- | _ -> 1
-
-type et = IntraRAW | IntraWAW | IntraWAR | InterRAW | InterWAW | InterWAR
-
-let edge_type e =
- match G.E.label e with
- | 1 -> IntraRAW
- | 2 -> IntraWAR
- | 3 -> IntraWAW
- | 4 -> InterRAW
- | 5 -> InterWAR
- | 6 -> InterWAW
- | _ -> failwith "Unknown edge type"
-
-let latency n = (* A raffiner *)
- match fst (G.V.label n) with
- | Iop (op,args, dst) ->
- begin
- match op with
- | Omove -> 1
- (*| Oaddimm _ -> 1*)
- (*| Oadd -> 2*)
- | Omul -> 4
- | Odiv -> 30
- | Omulimm _ -> 4
- | _ -> 2
- end
- | Iload _ -> 1
- (* | Ialloc _ -> 20*)
- | _ -> 1
-
-let reforge_writes inst r =
- G.V.create ((match fst (G.V.label inst) with
- | Inop -> Inop
- | Iop (op, args, dst) -> Iop (op, args, r)
- | Iload (chunk, mode, args, dst) -> Iload (chunk, mode, args, r)
- | Istore (chunk, mode, args, src) -> Istore (chunk, mode, args, src)
- | Icall (sign, id, args, dst) -> failwith "reforge_writes: call"
- | Itailcall (sign, id, args) -> failwith "reforge_writes: tailcall"
- (* | Ialloc (dst, size) -> Ialloc (r, size)*)
- | Icond (cond, args) -> Icond (cond, args)
- | Ireturn (res) -> failwith "reforge_writes: return")
- , snd (G.V.label inst))
-
-let rec reforge_args args oldr newr =
- match args with
- | [] -> []
- | e :: l -> (if e = oldr then newr else e) :: (reforge_args l oldr newr)
-
-let rec mem_args args r =
- match args with
- | [] -> false
- | e :: l -> if e = r then true else mem_args l r
-
-let check_read_exists inst r =
- match fst (G.V.label inst) with
- | Inop -> false
- | Iop (op, args, dst) -> mem_args args r
- | Iload (chunk, mode, args, dst) -> mem_args args r
- | Istore (chunk, mode, args, src) -> src = r || mem_args args r
- | Icall (sign, id, args, dst) -> mem_args args r
- | Itailcall (sign, id, args) -> false
- (*| Ialloc (dst, size) -> false*)
- | Icond (cond, args) -> mem_args args r
- | Ireturn (res) -> false
-
-let reforge_reads inst oldr newr =
- assert (check_read_exists inst oldr);
- G.V.create ((match fst (G.V.label inst) with
- | Inop -> Inop
- | Iop (op, args, dst) -> Iop (op, reforge_args args oldr newr, dst)
- | Iload (chunk, mode, args, dst) -> Iload (chunk, mode, reforge_args args oldr newr, dst)
- | Istore (chunk, mode, args, src) -> Istore (chunk, mode, reforge_args args oldr newr , if src = oldr then newr else src)
- | Icall (sign, id, args, dst) -> failwith "reforge_reads: call"
- | Itailcall (sign, id, args) -> failwith "reforge_reads: tailcall"
- (*| Ialloc (dst, size) -> Ialloc (dst, size)*)
- | Icond (cond, args) -> Icond (cond, reforge_args args oldr newr)
- | Ireturn (res) -> failwith "reforge_reads: return")
- , snd (G.V.label inst))
-
-let get_succs_raw ddg node =
- let succs = G.succ_e ddg node in
- let succs = List.filter (fun succ ->
- match G.E.label succ with
- | 1 | 4 -> true
- | _ -> false
- ) succs in
- List.map (fun e -> G.E.dst e) succs
-
-let written inst =
- match fst (G.V.label inst) with
- | Inop -> None
- | Iop (op, args, dst) -> Some dst
- | Iload (chunk, mode, args, dst) -> Some dst
- | Istore (chunk, mode, args, src) -> None
- | Icall (sign, id, args, dst) -> failwith "written: call"
- | Itailcall (sign, id, args) -> failwith "written: tailcall"
- (*| Ialloc (dst, size) -> Some dst*)
- | Icond (cond, args) -> None
- | Ireturn (res) -> failwith "written: return"
-
-let fresh_regs n =
- let t = Array.make n (BinNums.Coq_xH) in
- for i = 0 to (n - 1) do
- Array.set t i (!fresh);
- fresh := BinPos.Pos.succ !fresh
- done;
- t
-
-let print_reg r = Printf.fprintf SPDebug.dc "%i " (P.to_int r)
-
-let is_cond node =
- match fst (G.V.label node) with
- | Icond _ -> true
- | _ -> false
-
-
-(*******************************************)
-
-let watch_regs l = List.fold_right (fun (a,b) l ->
- if List.mem a l then l else a :: l
- ) l []
-
-let make_moves = List.map (fun (a,b) -> Iop (Omove,[b],a))
-
-let rec repeat l n =
- match n with
- | 0 -> []
- | n -> l @ repeat l (n-1)
-
-let fv = ref 0
-
-let apply_pipeliner f p ?(debug=false) =
- Printf.fprintf SPDebug.dc "******************** NEW FUNCTION ***********************\n";
- let cfg = convert f in
- incr fv;
- if debug then display cfg.graph ("input" ^ (string_of_int !fv));
- let loops = get_loops cfg in
- Printf.fprintf SPDebug.dc "Loops: %d\n" (List.length loops);
- let ddgs = List.map (fun (qqch,loop) -> (loop,build_inter_dependency_graph loop)) loops in
-
- let lv = ref 0 in
-
- let graph = List.fold_right (fun (loop,ddg) graph ->
- Printf.fprintf SPDebug.dc "__________________ NEW LOOP ____________________\n";
- Printf.printf "Pipelinable loop: ";
- incr lv;
- fresh := (BinPos.Pos.succ
- (BinPos.Pos.succ
- (BinPos.Pos.succ
- (BinPos.Pos.succ
- (BinPos.Pos.succ
- (max_reg_of_graph graph (to_caml_list f.fn_params)
- ))))));
- Printf.fprintf SPDebug.dc "FRESH = %i \n"
- (P.to_int !fresh);
- match p ddg with
- | Some pipe ->
- Printf.printf "Rock On ! Min = %i - Unroll = %i\n" pipe.min pipe.unrolling;
- let p = (make_moves pipe.ramp_up) @ (delete_indexes pipe.prolog) in
- let e = (delete_indexes pipe.epilog) @ (make_moves pipe.ramp_down) in
- let b = delete_indexes (List.tl (List.rev loop)) in
- let bt = (List.tl (delete_indexes pipe.steady_state)) in
- let cond1 = fst (G.V.label (List.hd (List.rev loop))) in
- let cond2 = (List.hd (delete_indexes pipe.steady_state)) in
-
- let bu = symbolic_evaluation (repeat b (pipe.min + 1)) in
- let pe = symbolic_evaluation (p @ e) in
- let bte = symbolic_evaluation (bt @ e) in
- let ebu = symbolic_evaluation (e @ repeat b pipe.unrolling) in
- let regs = watch_regs pipe.ramp_down in
- let c1 = symbolic_condition cond1 (repeat b pipe.unrolling) in
- let d1 = symbolic_condition cond1 (repeat b (pipe.min + 1)) in
- (*let c2 = symbolic_condition cond2 p in
- let d2 = symbolic_condition cond2 ((make_moves pipe.ramp_up) @ bt) in*)
-
-
-
- let sbt = symbolic_evaluation (bt) in
- let sep = symbolic_evaluation (e @ repeat b (pipe.unrolling - (pipe.min + 1)) @ p) in (* er @ pr *)
-
- Printf.printf "Initialisation : %s \n"
- (if symbolic_equivalence bu pe regs then "OK" else "FAIL");
- Printf.printf "Etat stable : %s \n"
- (if symbolic_equivalence bte ebu regs then "OK" else "FAIL");
- Printf.printf "Egalite fondamentale : %s \n"
- (if symbolic_equivalence sbt sep (watch_regs pipe.ramp_up) then "OK" else "FAIL");
- (* Printf.printf "Condition initiale : %s \n"
- (if c1 = c2 then "OK" else "FAIL");
- Printf.printf "Condition stable : %s \n"
- (if d1 = d2 then "OK" else "FAIL");
-
-
- Printf.fprintf SPDebug.dc "pbte\n";*)
- List.iter (fun e ->
- Printf.fprintf SPDebug.dc "%s\n"
- (string_of_node (G.V.create (e,0)))
- ) (p @ bt @ e);
- Printf.fprintf SPDebug.dc "bu\n";
- List.iter (fun e -> Printf.fprintf SPDebug.dc "%s\n"
- (string_of_node (G.V.create (e,0)))
- ) (repeat b (pipe.unrolling + pipe.min));
-
-
-
- if debug then
- display_st ("pbte"^ (string_of_int !fv) ^ (string_of_int !lv)) (p @ bt @ e) (watch_regs pipe.ramp_down);
- if debug then
- display_st ("bu"^ (string_of_int !fv) ^ (string_of_int !lv)) (repeat b (pipe.min + pipe.unrolling)) (watch_regs pipe.ramp_down);
-
- if debug then display_st ("bt"^ (string_of_int !fv) ^ (string_of_int !lv)) (bt) (watch_regs pipe.ramp_up);
- if debug then display_st ("ep"^ (string_of_int !fv) ^ (string_of_int !lv)) (e @ repeat b (pipe.unrolling - (pipe.min + 1)) @ p) (watch_regs pipe.ramp_up);
-
- substitute_pipeline graph loop
- (delete_indexes pipe.steady_state) (delete_indexes pipe.prolog)
- (delete_indexes pipe.epilog) (pipe.min + pipe.unrolling)
- pipe.unrolling pipe.ramp_up
- pipe.ramp_down
- (to_caml_list f.fn_params)
- | None -> Printf.printf "Damn It ! \n"; graph
- ) ddgs cfg.graph in
-
- if debug then display graph ("output"^ (string_of_int !fv));
- let tg = convert_back graph in
-
- let tg_to_type = {fn_sig = f.fn_sig;
- fn_params = f.fn_params;
- fn_stacksize = f.fn_stacksize;
- fn_code = tg;
- fn_entrypoint = f.fn_entrypoint;
- (*fn_nextpc = P.of_int ((get_nextpc (graph)))*)
- } in
- (*SPTyping.type_function tg_to_type;*)
-
- tg_to_type