From 59fd6ed1e0f451672923e26009bf30d5cbef48c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Thu, 10 Oct 2024 07:24:12 +0200
Subject: [PATCH] [region] refactor squash

---
 src/plugins/region/memory.ml  | 64 ++++++++++++++++++++---------------
 src/plugins/region/ranges.ml  |  7 ++--
 src/plugins/region/ranges.mli |  5 ++-
 3 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/src/plugins/region/memory.ml b/src/plugins/region/memory.ml
index bbe223c15de..d8c360b49f0 100644
--- a/src/plugins/region/memory.ml
+++ b/src/plugins/region/memory.ml
@@ -254,13 +254,16 @@ let labels (m: map) (r: node) =
 (* -------------------------------------------------------------------------- *)
 
 type queue = (node * node) Queue.t
+type cell = { mutable size : int ; mutable ptr : node option }
+let new_cell ?(size=0) ?ptr () = { size ; ptr }
+let cell_layout { size ; ptr } =
+  if size = 0 && ptr = None then Blob else Cell(size,ptr)
 
-let singleton ~size = function
-  | None -> Ranges.empty
-  | Some r -> Ranges.range ~length:size r
+let merge_push (m: map) (q: queue) (a: node) (b: node) : unit =
+  if not @@ Ufind.eq m.store a b then Queue.push (a,b) q
 
 let merge_node (m: map) (q: queue) (a: node) (b: node) : node =
-  if not @@ Ufind.eq m.store a b then Queue.push (a,b) q ;
+  merge_push m q a b ;
   Ufind.find m.store (min a b)
 
 let merge_opt (m: map) (q: queue)
@@ -269,6 +272,16 @@ let merge_opt (m: map) (q: queue)
   | None, p | p, None -> p
   | Some pa, Some pb -> Some (merge_node m q pa pb)
 
+let merge_cell (m:map) (q:queue) cell root r =
+  let node = Ufind.get m.store r in
+  let s = sizeof node.clayout in
+  let p = cpointed node.clayout in
+  begin
+    merge_push m q root r ;
+    cell.size <- Ranges.gcd cell.size s ;
+    cell.ptr <- merge_opt m q cell.ptr p ;
+  end
+
 let merge_range (m: map) (q: queue) (ra : rg) (rb : rg) : node =
   let na = ra.data in
   let nb = rb.data in
@@ -283,7 +296,7 @@ let merge_range (m: map) (q: queue) (ra : rg) (rb : rg) : node =
   if size = sa && size = sb then data else
     merge_node m q (new_chunk m ~size ()) data
 
-let merge_ranges (m: map) (q: queue)
+let merge_ranges (m: map) (q: queue) (root: node)
     (sa : int) (fa : Fields.domain) (wa : node Ranges.t)
     (sb : int) (fb : Fields.domain) (wb : node Ranges.t)
   : layout =
@@ -292,32 +305,29 @@ let merge_ranges (m: map) (q: queue)
     Compound(sa, fields, Ranges.merge (merge_range m q) wa wb)
   else
     let size = Ranges.gcd sa sb in
-    let ra = Ranges.squash (merge_node m q) wa in
-    let rb = Ranges.squash (merge_node m q) wb in
-    Compound(size, fields, singleton ~size @@ merge_opt m q ra rb)
+    let cell = new_cell ~size () in
+    Ranges.iter (merge_cell m q cell root) wa ;
+    Ranges.iter (merge_cell m q cell root) wb ;
+    cell_layout cell
 
-let merge_layout (m: map) (q: queue) (a : layout) (b : layout) : layout =
+let merge_layout (m:map) (q:queue) (root:node) (a:layout) (b:layout) : layout =
   match a, b with
   | Blob, c | c, Blob -> c
 
   | Cell(sa,pa) , Cell(sb,pb) -> Cell(Ranges.gcd sa sb, merge_opt m q pa pb)
 
   | Compound(sa,fa,wa), Compound(sb,fb,wb) ->
-    merge_ranges m q sa fa wa sb fb wb
+    merge_ranges m q root sa fa wa sb fb wb
 
-  | Compound(sr,fr,wr), Cell(sx,None)
-  | Cell(sx,None), Compound(sr,fr,wr) ->
+  | Compound(sr,_,wr), Cell(sx,ptr)
+  | Cell(sx,ptr), Compound(sr,_,wr) ->
     let size = Ranges.gcd sx sr in
-    Compound(size, fr, singleton ~size @@ Ranges.squash (merge_node m q) wr)
-
-  | Compound(sr,fr,wr), Cell(sx,Some ptr)
-  | Cell(sx,Some ptr), Compound(sr,fr,wr) ->
-    let rp = new_chunk m ~size:sx ~ptr () in
-    let fx = Fields.empty in
-    let wx = Ranges.range ~length:sx rp in
-    merge_ranges m q sx fx wx sr fr wr
+    let cell = new_cell ~size ?ptr () in
+    Ranges.iter (merge_cell m q cell root) wr ;
+    cell_layout cell
 
-let merge_region (m: map) (q: queue) (a : chunk) (b : chunk) : chunk = {
+let merge_chunk (m: map) (q:queue) (root:node)
+    (a : chunk) (b : chunk) : chunk = {
   cparents = nodes m @@ Store.bag a.cparents b.cparents ;
   cpointed = nodes m @@ Store.bag a.cpointed b.cpointed ;
   clabels = Lset.union a.clabels b.clabels ;
@@ -325,16 +335,16 @@ let merge_region (m: map) (q: queue) (a : chunk) (b : chunk) : chunk = {
   creads = Access.Set.union a.creads b.creads ;
   cwrites = Access.Set.union a.cwrites b.cwrites ;
   cshifts = Access.Set.union a.cshifts b.cshifts ;
-  clayout = merge_layout m q a.clayout b.clayout ;
+  clayout = merge_layout m q root a.clayout b.clayout ;
 }
 
 let do_merge (m: map) (q: queue) (a: node) (b: node): unit =
   begin
-    let ra = Ufind.get m.store a in
-    let rb = Ufind.get m.store b in
-    let rx = Ufind.union m.store a b in
-    let rc = merge_region m q ra rb in
-    Ufind.set m.store rx rc ;
+    let ca = Ufind.get m.store a in
+    let cb = Ufind.get m.store b in
+    let rt = Ufind.union m.store a b in
+    let ck = merge_chunk m q rt ca cb in
+    Ufind.set m.store rt ck ;
   end
 
 let merge_all (m:map) = function
diff --git a/src/plugins/region/ranges.ml b/src/plugins/region/ranges.ml
index 3e9dbed60ea..f8a6e0d3e9d 100644
--- a/src/plugins/region/ranges.ml
+++ b/src/plugins/region/ranges.ml
@@ -83,12 +83,11 @@ let rec merge f ra rb =
 
 let merge f (R x) (R y) = R (merge f x y)
 
-let squash f = function
-  | R [] -> None
-  | R (x::xs) -> Some (List.fold_left (fun w r -> f w r.data) x.data xs)
-
 let iteri f (R xs) = List.iter f xs
+let foldi f w (R xs) = List.fold_left f w xs
 let iter f (R xs) = List.iter (fun r -> f r.data) xs
+let fold f w (R xs) = List.fold_left (fun w r -> f w r.data) w xs
+let mapi f (R xs) = R (List.map f xs)
 let map f (R xs) = R (List.map (fun r -> { r with data = f r.data }) xs)
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/region/ranges.mli b/src/plugins/region/ranges.mli
index b04c273feb0..7149b1cd7b3 100644
--- a/src/plugins/region/ranges.mli
+++ b/src/plugins/region/ranges.mli
@@ -36,9 +36,12 @@ val empty : 'a t
 val singleton : 'a range -> 'a t
 val range : ?offset:int -> ?length:int -> 'a -> 'a t
 val merge : ('a range -> 'a range -> 'a) -> 'a t -> 'a t -> 'a t
-val squash : ('a -> 'a -> 'a) -> 'a t -> 'a option
 
 val find : int -> 'a t -> 'a range
+
 val map : ('a -> 'b) -> 'a t -> 'b t
+val mapi : ('a range -> 'b range) -> 'a t -> 'b t
 val iter : ('a -> unit) -> 'a t -> unit
 val iteri : ('a range -> unit) -> 'a t -> unit
+val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
+val foldi : ('b -> 'a range -> 'b) -> 'b -> 'a t -> 'b
-- 
GitLab