Skip to content

Commit 8f01333

Browse files
author
Shale Xiong
committed
[gen] Allowed Id in resolving input relax.
Rework on the `resolve_edge` function in `edge.ml`. The new version will merge all annotations to immediate left and right hand side edges. This means the `merge_annotation` in `cycle.ml` become unnecessary.
1 parent b81fc28 commit 8f01333

File tree

2 files changed

+135
-224
lines changed

2 files changed

+135
-224
lines changed

gen/common/edge.ml

Lines changed: 135 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ and module RMW = A.RMW = struct
267267

268268
type edge = { edge: tedge; a1:atom option; a2: atom option; }
269269

270+
let can_merge e = not @@ is_insert_store e.edge
271+
270272
open Printf
271273

272274
let plain_edge e = { a1=None; a2=None; edge=e; }
@@ -367,16 +369,12 @@ let pp_dp_default tag sd e = sprintf "%s%s%s" tag (pp_sd sd) (pp_extr e)
367369
| CRf|CWs -> Dir W
368370
| CFr -> Dir R
369371

370-
exception NotThat of string
371-
372-
let not_that e msg = raise (NotThat (sprintf "%s: %s" msg (pp_tedge e)))
373-
374372
let do_dir_tgt e = match e with
375373
| Po(_,_,e)| Fenced(_,_,_,e)|Dp (_,_,e) -> e
376374
| Rf _| Hat -> Dir R
377375
| Ws _|Fr _|Rmw _ -> Dir W
378376
| Leave c|Back c -> do_dir_tgt_com c
379-
| Id -> not_that e "do_dir_tgt"
377+
| Id -> NoDir
380378
| Insert _ -> NoDir
381379
| Store -> Dir W
382380
| Node d -> Dir d
@@ -387,7 +385,7 @@ let pp_dp_default tag sd e = sprintf "%s%s%s" tag (pp_sd sd) (pp_extr e)
387385
| Dp _|Fr _|Hat|Rmw _ -> Dir R
388386
| Ws _|Rf _ -> Dir W
389387
| Leave c|Back c -> do_dir_src_com c
390-
| Id -> not_that e "do_dir_src"
388+
| Id -> NoDir
391389
| Insert _ -> NoDir
392390
| Store -> Dir W
393391
| Node d -> Dir d
@@ -530,12 +528,9 @@ let fold_tedges f r =
530528
let dir_tgt e = do_dir_tgt e.edge
531529
and dir_src e = do_dir_src e.edge
532530
and safe_dir e =
533-
try
534-
begin match do_dir_src e.edge with
535-
| Dir d -> Some d
536-
| NoDir|Irr -> None
537-
end
538-
with NotThat _ -> None
531+
match do_dir_src e.edge with
532+
| Dir d -> Some d
533+
| NoDir|Irr -> None
539534

540535
(***************)
541536
(* Atom lexing *)
@@ -803,15 +798,13 @@ let fold_tedges f r =
803798
let expand_edges es f = do_expand_edges (List.rev es) f []
804799

805800
(* resolve *)
806-
let rec find_non_insert_store = function
801+
let rec find_next_merge = function
807802
| [] -> raise Not_found
808-
| e::es -> begin match e.edge with
809-
| Insert _|Store ->
810-
let bef,ni,aft = find_non_insert_store es in
811-
e::bef,ni,aft
812-
| _ ->
813-
[],e,es
814-
end
803+
| e::es -> (* `Node` or Non-pseudo can be merged *)
804+
if can_merge e then [],e,es
805+
else
806+
let bef,ni,aft = find_next_merge es in
807+
e::bef,ni,aft
815808

816809
let set_a1 e a = match e.edge with
817810
| Node _|Id -> { e with a1=a; a2=a;}
@@ -821,120 +814,65 @@ let fold_tedges f r =
821814
| Node _|Id -> { e with a1=a; a2=a;}
822815
| _ -> { e with a2=a;}
823816

824-
let merge_id e1 e2 = match e1.edge,e2.edge with
825-
| Id,Id ->
826-
begin
827-
let a1 = e1.a2 and a2 = e2.a1 in
828-
match a1,a2 with
829-
| None,None -> Some e1
830-
| (None,(Some _ as a))|((Some _ as a),None) ->
831-
Some { e1 with a1=a; a2=a; }
832-
| Some a1,Some a2 ->
833-
begin
834-
match merge_atoms a1 a2 with
835-
| None -> None (* Merge impossible, will fail later *)
836-
| Some _ as a ->
837-
Some { e1 with a1=a; a2=a; }
838-
end
839-
end
840-
| _ -> None
841-
842-
let merge_ids =
843-
let rec do_rec fst = function
844-
| [] -> fst,[]
845-
| [lst] ->
846-
begin
847-
match merge_id lst fst with
848-
| None -> fst,[lst]
849-
| Some e -> e,[]
850-
end
851-
| e1::(e2::es as k) ->
852-
begin
853-
match merge_id e1 e2 with
854-
| None ->
855-
let fst,k = do_rec fst k in
856-
fst,e1::k
857-
| Some e -> do_rec fst (e::es)
858-
end in
859-
let rec do_fst = function
860-
| []|[_] as es -> es
861-
| e1::(e2::es as k) ->
862-
begin
863-
match merge_id e1 e2 with
864-
| None ->
865-
let fst,k = do_rec e1 k in
866-
fst::k
867-
| Some e -> do_fst (e::es)
868-
end in
869-
do_fst
870-
871-
(*
872-
resolve_pair e1 e2, merges the end annotation of e1 with
873-
the start annotation of e2.
874-
Warning: resolve_pair cannot fail, instead it must leave
875-
e1 and e2 as they are...
876-
*)
877-
let resolve_pair e1 e2 =
878-
if dbg > 0 then
879-
eprintf
880-
"Resolve pair <%s,%s> -> " (debug_edge e1) (debug_edge e2) ;
881-
let e1,e2 =
882-
try
883-
let d1 = dir_tgt e1 and d2 = dir_src e2 in
884-
match d1,d2 with
885-
| Irr,Dir d -> set_tgt d e1,e2
886-
| Dir d,Irr -> e1,set_src d e2
887-
| _,_ -> e1,e2
888-
with NotThat _ -> e1,e2 in
889-
let a1 = e1.a2 and a2 = e2.a1 in
890-
let r =
817+
(* Merges the end annotation and direction of `e1`
818+
with the start of `e2`. *)
819+
let merge_pair e1 e2 =
820+
let update_dir (e1,e2) =
821+
let d1 = dir_tgt e1 and d2 = dir_src e2 in
822+
match d1,d2 with
823+
| Irr,Dir d -> Some(set_tgt d e1,e2)
824+
| Dir d,Irr -> Some(e1,set_src d e2)
825+
| _,_ -> None in
826+
let update_annotation (e1,e2) =
827+
let a1 = e1.a2 and a2 = e2.a1 in
891828
match a1,a2 with
892-
| None,None -> e1,e2
829+
| None,None -> None
893830
| None,Some a
894-
| Some a,None when is_ifetch (Some a)-> e1, e2
895-
| None,Some _ -> set_a2 e1 a2,e2
896-
| Some _,None -> e1, set_a1 e2 a1
831+
| Some a,None when is_ifetch (Some a)-> None
832+
| None,Some _ -> Some(set_a2 e1 a2,e2)
833+
| Some _,None -> Some(e1, set_a1 e2 a1)
897834
| Some a1,Some a2 ->
898-
begin match merge_atoms a1 a2 with
899-
| None -> e1,e2
900-
| Some _ as a ->
901-
set_a2 e1 a,set_a1 e2 a
902-
end in
835+
match merge_atoms a1 a2 with
836+
| None -> None
837+
| Some _ as a ->
838+
Some(set_a2 e1 a,set_a1 e2 a) in
839+
let input = (e1,e2) in
840+
let r = update_dir input
841+
|> Option.fold ~none:(update_annotation input)
842+
(* Propagate result `f e` if changed *)
843+
~some:(fun e ->
844+
Some(Option.value (update_annotation e) ~default:e)) in
903845
if dbg > 0 then begin
904-
let e1,e2 = r in
905-
eprintf "<%s,%s>\n" (debug_edge e1) (debug_edge e2)
846+
let i1,i2 = input in
847+
let r1,r2 = Option.value ~default:input r in
848+
eprintf "Merge pair <%s,%s> -> <%s,%s>\n"
849+
(debug_edge i1) (debug_edge i2) (debug_edge r1) (debug_edge r2)
906850
end ;
907851
r
908852

909-
(* Function merge_pair merges two versions of the same edge with
910-
different annotations and direction resolution.
911-
It cannot fail *)
912-
let merge_dir d1 d2 = match d1,d2 with
913-
| (Irr,Dir d)|(Dir d,Irr) -> d
914-
| Dir d1,Dir d2 -> assert (d1=d2) ; d1
915-
| (Irr,Irr)|(NoDir,_)|(_,NoDir) -> assert false
916-
917-
let merge_atomo a1 a2 = match a1,a2 with
918-
| None,Some _ -> a2
919-
| Some _,None -> a1
920-
| None,None -> None
921-
| Some a1,Some a2 ->
922-
begin match merge_atoms a1 a2 with
923-
| None ->
924-
Warn.fatal
925-
"Atoms %s and %s *must* be mergeable"
926-
(pp_atom a1) (pp_atom a2)
927-
| Some _ as a -> a
928-
end
929-
930-
let merge_pair e1 e2 = match e1.edge,e2.edge with
931-
| (Id,Id) -> e1
932-
| (Insert _,_)|(_,Insert _) -> assert false
933-
| _,_ ->
934-
let tgt = merge_dir (dir_tgt e1) (dir_tgt e2)
935-
and src = merge_dir (dir_src e1) (dir_src e2) in
936-
let e = set_tgt tgt (set_src src e1) in
937-
{ e with a1 = merge_atomo e1.a1 e2.a1; a2 = merge_atomo e1.a2 e2.a2; }
853+
(* Assume `e` is not `Store` nor `Insert`,
854+
merge annotations and direction from the head of `es`
855+
into `e` until no more possibility. *)
856+
let rec merge_left e es =
857+
let is_default e = e = { edge=Id; a1=None; a2=None; } in
858+
try
859+
let store_insert,next,rest = find_next_merge es in
860+
(* throw away a default annotation *)
861+
if is_default e then true, None, store_insert @ next :: rest
862+
else if is_default next then merge_left e (store_insert @ rest)
863+
(* Merge `e` and `next` *)
864+
else match merge_pair e next with
865+
| None -> true, Some e, (store_insert @ next :: rest)
866+
| Some (e, next) ->
867+
match is_id e.edge, is_id next.edge with
868+
(* Erase `next` and continue merging *)
869+
| _,true -> merge_left e (store_insert @ rest)
870+
(* Indicate erasing `e` *)
871+
| true,false -> true, None, (store_insert @ next :: rest)
872+
(* Two non-`Id` *)
873+
| false,false -> true, Some(e), (store_insert @ next :: rest)
874+
(* find_next_merge fails, no more node to process *)
875+
with Not_found -> false, Some e, es
938876

939877
let default_access = Cfg.naturalsize,0
940878

@@ -947,69 +885,78 @@ let fold_tedges f r =
947885
and a2 = replace_plain_atom e.a2 in
948886
{ e with a1; a2; }
949887

950-
let remove_id = List.filter (fun e -> not (is_id e.edge))
951-
952-
let check_mixed =
953-
if not do_mixed || do_disjoint then fun _ -> ()
954-
else
955-
List.iter
956-
(fun e ->
957-
if not (ok_mixed e.edge e.a1 e.a2) then begin
958-
match e.edge with
959-
| Rmw _ ->
960-
Warn.fatal
961-
"Illegal mixed-size Rmw edge: %s"
962-
(pp_edge e)
963-
| _ ->
964-
if same_access_atoms e.a1 e.a2 then
965-
Warn.fatal
966-
"Identical mixed access in %s and `-variant MixedStrictOverlap` mode"
967-
(pp_edge e)
968-
else
969-
Warn.fatal
970-
"Non overlapping accesses in %s, allow with `-variant MixedDisjoint`"
971-
(pp_edge e)
972-
end)
888+
let validity_edges es =
889+
(* Check mixed size memory access annotation *)
890+
let check_mixed e =
891+
if not (not do_mixed || do_disjoint || (ok_mixed e.edge e.a1 e.a2)) then
892+
Warn.fatal
893+
( match e.edge,(same_access_atoms e.a1 e.a2) with
894+
| Rmw _,_ -> "Illegal mixed-size Rmw edge: %s"
895+
| _,true ->
896+
"Identical mixed access in %s and `-variant MixedStrictOverlap` mode"
897+
| _,false ->
898+
"Non overlapping accesses in %s, allow with `-variant MixedDisjoint`" )
899+
(pp_edge e) in
900+
(* Check `Id` edge are all pseudo annotation *)
901+
let check_pseudo_id e =
902+
if is_id e.edge then
903+
Warn.fatal "Invalid extra annotation %s" (pp_edge e) in
904+
List.iter (fun e -> check_mixed e; check_pseudo_id e) es;
905+
(* Match annotations between non-insert edges *)
906+
let last_non_insert_edge =
907+
List.rev es
908+
|> List.find ( fun e -> not @@ is_insert_store e.edge ) in
909+
List.fold_left (fun prev_annotation e ->
910+
match is_insert_store e.edge, prev_annotation = e.a1 with
911+
(* carry over the previous result if insert edges *)
912+
| true,_ -> prev_annotation
913+
| false,false -> Warn.fatal "Annotations mismatch"
914+
| false,true -> e.a2
915+
) last_non_insert_edge.a2 es
916+
|> ignore
917+
973918

974919
let resolve_edges es0 =
975-
let es0 = merge_ids es0 in
976-
match es0 with
977-
| []|[_] -> es0
978-
| e::es ->
979-
let rec do_rec e es = match e.edge with
980-
| Insert _|Store ->
981-
let fst,nxt,es = do_recs es in
982-
fst,e,nxt::es
983-
| _ ->
984-
begin try
985-
let es0,e1,es1 = find_non_insert_store es in
986-
let e,e1 = resolve_pair e e1 in
987-
let fst,f,es = do_recs (es0@(e1::es1)) in
988-
fst,e,f::es
989-
with Not_found -> try
990-
let _,e1,_ = find_non_insert_store es0 in
991-
let e,e1 = resolve_pair e e1 in
992-
e1,e,es
993-
with Not_found -> Warn.user_error "No non-insert-store node in cycle"
994-
end
995-
and do_recs = function
996-
(* This case is handled by Not_found handler above *)
997-
| [] -> assert false
998-
| e::es -> do_rec e es in
999-
let fst,e,es = do_rec e es in
1000-
let e =
1001-
match e.edge with
1002-
| Insert _ -> e
1003-
| _ ->
1004-
try merge_pair fst e
1005-
with exn ->
1006-
eprintf "Failure <%s,%s>\n" (debug_edge fst) (debug_edge e) ;
1007-
raise exn in
1008-
let es = remove_id (e::es) in
1009-
let es = if do_mixed then List.map replace_plain es else es in
1010-
if dbg > 0 then eprintf "Check Mixed: %s\n" (pp_edges es) ;
1011-
check_mixed es ;
1012-
es
920+
(* Merge annotations until find a first node
921+
that is not `Id`, `Store` nor `Insert`. *)
922+
let rec find_first es =
923+
let before,fst,after =
924+
try find_next_merge es
925+
with Not_found -> Warn.user_error "No memory access node in cycle" in
926+
let continuation,fst,after = merge_left fst after in
927+
match continuation,fst with
928+
| false, _ ->
929+
Warn.user_error "Only one relaxation that is not store nor insert."
930+
| true, None ->
931+
let before',fst,after = find_first after in
932+
before @ before',fst,after
933+
| true, Some(fst) -> before,fst,after in
934+
(* merge annotations in `es`, where `fst` is used to merge both the hand and tail of `es` *)
935+
let rec merge_es fst es = match es with
936+
| [] -> fst, []
937+
| e::es ->
938+
if can_merge e then
939+
let continuation,e,es = merge_left e es in
940+
match continuation,e with
941+
| false, None -> assert false
942+
(* throw away `e` *)
943+
| true, None -> merge_es fst es
944+
| true, Some(e) ->
945+
let fst,es = merge_es fst es in
946+
fst,e::es
947+
| false, Some(e) ->
948+
(* Reach the last relax, will try to merge with `fst` *)
949+
let e,fst = merge_pair e fst |> Option.value ~default:(e,fst) in
950+
fst,e::es
951+
else
952+
let fst,es = merge_es fst es in fst,e::es in
953+
let before,fst,es = find_first es0 in
954+
let fst,es = merge_es fst es in
955+
let es = before @ fst :: es in
956+
let es = if do_mixed then List.map replace_plain es else es in
957+
if dbg > 0 then eprintf "Check Validity: %s\n" (pp_edges es) ;
958+
validity_edges es ;
959+
es
1013960

1014961
(********************)
1015962
(* Atomic variation *)

0 commit comments

Comments
 (0)