MLIR DAG rewriter w/ SSA IR, dominance and CFG analysis passes
1

Configure Feed

Select the types of activity you want to include in your feed.

nemo / lib / dominance.ml
3.3 kB 115 lines
1open Ir 2open Cfg 3 4module IntMap = Map.Make(Int) 5module IntSet = Set.Make(Int) 6 7let rev_postorder cfg = 8 let visited = ref IntSet.empty in 9 let order = ref [] in 10 let rec dfs id = 11 if IntSet.mem id !visited then () 12 else begin 13 visited := IntSet.add id !visited; 14 let b = IntMap.find id cfg.blocks in 15 List.iter dfs b.succs; 16 order := id :: !order 17 end 18 in 19 dfs cfg.entry; 20 let remaining = IntMap.fold (fun k _ acc -> 21 if IntSet.mem k !visited then acc else k :: acc 22 ) cfg.blocks [] in 23 !order @ remaining 24 25let dominators cfg = 26 let rpo = rev_postorder cfg in 27 let rpo_idx = Hashtbl.create 64 in 28 List.iteri (fun i x -> Hashtbl.add rpo_idx x i) rpo; 29 let idom = ref IntMap.empty in 30 let get_rank v = 31 try Hashtbl.find rpo_idx v with Not_found -> max_int in 32 List.iter (fun w -> 33 if w = cfg.entry then () 34 else 35 let b = IntMap.find w cfg.blocks in 36 match b.preds with 37 | [] -> () 38 | p0 :: ps -> 39 let find_best v = 40 try IntMap.find v !idom with Not_found -> v 41 in 42 let best = ref (find_best p0) in 43 let best_rank = ref (get_rank !best) in 44 List.iter (fun p -> 45 let candidate = find_best p in 46 let r = get_rank candidate in 47 if r < !best_rank then begin best := candidate; best_rank := r end 48 ) ps; 49 let semi_w = !best in 50 let rec walk cur best_id = 51 if cur = w then best_id 52 else 53 let r = get_rank cur in 54 let best_id = if r < get_rank best_id then cur else best_id in 55 try 56 let parent = IntMap.find cur !idom in 57 walk parent best_id 58 with Not_found -> best_id 59 in 60 let idom_w = walk semi_w w in 61 idom := IntMap.add w idom_w !idom; 62 ignore semi_w 63 ) rpo; 64 let doms = ref IntMap.empty in 65 List.iter (fun id -> 66 let rec collect v acc = 67 if IntSet.mem v acc then acc 68 else 69 let acc = IntSet.add v acc in 70 try collect (IntMap.find v !idom) acc with Not_found -> acc 71 in 72 doms := IntMap.add id (collect id IntSet.empty) !doms 73 ) rpo; 74 !doms 75 76let dominates doms a b = 77 IntSet.mem a (IntMap.find b doms) 78 79let idom_from_doms doms id = 80 let s = IntMap.find id doms in 81 let without = IntSet.diff s (IntSet.singleton id) in 82 if IntSet.is_empty without then None 83 else 84 let strict_doms = IntSet.elements without in 85 let rec find = function 86 | [] -> None 87 | d :: rest -> 88 if List.for_all (fun m -> m = d || IntSet.mem d (IntMap.find m doms)) strict_doms 89 then Some d 90 else find rest 91 in 92 find strict_doms 93 94let dominance_frontiers cfg doms = 95 let df = ref IntMap.empty in 96 IntMap.iter (fun id _ -> df := IntMap.add id IntSet.empty !df) cfg.blocks; 97 IntMap.iter (fun id b -> 98 match b.preds with 99 | [] | [_] -> () 100 | _ -> 101 let idom_y = idom_from_doms doms id in 102 List.iter (fun p -> 103 let rec walk cur = 104 if Some cur = idom_y then () 105 else begin 106 df := IntMap.add cur (IntSet.add id (IntMap.find cur !df)) !df; 107 (match idom_from_doms doms cur with 108 | None -> () 109 | Some n -> walk n) 110 end 111 in 112 walk p 113 ) b.preds 114 ) cfg.blocks; 115 !df