Skip to content

Commit b0b0d6c

Browse files
authored
Merge pull request #247 from ppedrot/saner-merge-types
Use sets rather than lists in compiler types
2 parents 89aa9bd + 272b3e5 commit b0b0d6c

File tree

5 files changed

+122
-66
lines changed

5 files changed

+122
-66
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Unreleased
2+
3+
- Compiler:
4+
- Improve performance of separate compilation
5+
6+
17
# v1.19.4 (July 2024)
28

39
Requires Menhir 20211230 and OCaml 4.08 or above.

src/compiler.ml

Lines changed: 99 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ type argmap = {
373373
n2t : (D.term * D.Constants.t) StrMap.t;
374374
n2i : int StrMap.t;
375375
}
376-
[@@ deriving show]
376+
[@@ deriving show, ord]
377377

378378
let empty_amap = {
379379
nargs = 0;
@@ -405,29 +405,29 @@ type preterm = {
405405
loc : Loc.t;
406406
spilling : bool;
407407
}
408-
[@@ deriving show]
408+
[@@ deriving show, ord]
409409

410410
type type_declaration = {
411411
tname : D.constant;
412412
ttype : preterm;
413413
tloc : Loc.t;
414414
}
415-
[@@ deriving show]
415+
[@@ deriving show, ord]
416416

417417
type type_abbrev_declaration = {
418418
taname : D.constant;
419419
tavalue : preterm;
420420
taparams : int;
421421
taloc : Loc.t;
422422
}
423-
[@@ deriving show]
423+
[@@ deriving show, ord]
424424

425425
type presequent = {
426426
peigen : D.term;
427427
pcontext : D.term;
428428
pconclusion : D.term;
429429
}
430-
[@@ deriving show]
430+
[@@ deriving show, ord]
431431
type prechr_rule = {
432432
pto_match : presequent list;
433433
pto_remove : presequent list;
@@ -438,7 +438,7 @@ type prechr_rule = {
438438
pifexpr : string option;
439439
pcloc : Loc.t;
440440
}
441-
[@@ deriving show]
441+
[@@ deriving show, ord]
442442

443443
(****************************************************************************
444444
Intermediate program representation
@@ -447,6 +447,64 @@ type prechr_rule = {
447447
open Data
448448
module C = Constants
449449

450+
module Types = struct
451+
452+
type typ = {
453+
tindex : Ast.Structured.tattribute;
454+
decl : type_declaration
455+
}
456+
[@@deriving show, ord]
457+
458+
module Set = Util.Set.Make(struct
459+
type t = typ
460+
let compare = compare_typ
461+
let show = show_typ
462+
let pp = pp_typ
463+
end)
464+
465+
type types = {
466+
set : Set.t;
467+
lst : typ list;
468+
def : typ;
469+
} [@@deriving show, ord]
470+
471+
let make t = { set = Set.singleton t; lst = [t]; def = t }
472+
473+
let merge t1 t2 =
474+
let l2 = List.filter (fun t -> not @@ Set.mem t t1.set) t2.lst in
475+
match l2 with
476+
| [] -> t1
477+
| _ :: _ ->
478+
{
479+
set = Set.union t1.set t2.set;
480+
lst = t1.lst @ l2;
481+
def = t2.def;
482+
}
483+
484+
let smart_map (f : typ -> typ) (t : types) : types =
485+
let fold t accu =
486+
let t' = f t in
487+
if t' == t then accu
488+
else Set.add t' (Set.remove t accu)
489+
in
490+
let set' = Set.fold fold t.set t.set in
491+
let lst' = smart_map f t.lst in
492+
let def' = f t.def in
493+
if set' == t.set && lst' == t.lst && def' == t.def then t
494+
else { set = set'; lst = lst'; def = def' }
495+
496+
let append x t = {
497+
set = Set.add x t.set;
498+
lst = x :: t.lst;
499+
def = t.def;
500+
}
501+
502+
let fold f accu t = List.fold_left f accu t.lst
503+
let iter f t = List.iter f t.lst
504+
let for_all f t = List.for_all f t.lst
505+
506+
end
507+
450508
module Structured = struct
451509

452510
type program = {
@@ -455,7 +513,7 @@ type program = {
455513
toplevel_macros : macro_declaration;
456514
}
457515
and pbody = {
458-
types : typ list C.Map.t;
516+
types : Types.types C.Map.t;
459517
type_abbrevs : type_abbrev_declaration C.Map.t;
460518
modes : (mode * Loc.t) C.Map.t;
461519
body : block list;
@@ -467,18 +525,14 @@ and block =
467525
| Namespace of string * pbody
468526
| Shorten of C.t Ast.Structured.shorthand list * pbody
469527
| Constraints of constant list * prechr_rule list * pbody
470-
and typ = {
471-
tindex : Ast.Structured.tattribute;
472-
decl : type_declaration
473-
}
474-
[@@deriving show]
528+
[@@deriving show, ord]
475529

476530
end
477531

478532
module Flat = struct
479533

480534
type program = {
481-
types : Structured.typ list C.Map.t;
535+
types : Types.types C.Map.t;
482536
type_abbrevs : type_abbrev_declaration C.Map.t;
483537
modes : (mode * Loc.t) C.Map.t;
484538
clauses : (preterm,Ast.Structured.attribute) Ast.Clause.t list;
@@ -495,7 +549,7 @@ end
495549
module Assembled = struct
496550

497551
type program = {
498-
types : Structured.typ list C.Map.t;
552+
types : Types.types C.Map.t;
499553
type_abbrevs : type_abbrev_declaration C.Map.t;
500554
modes : (mode * Loc.t) C.Map.t;
501555
clauses_rev : (preterm,attribute) Ast.Clause.t list;
@@ -538,7 +592,7 @@ module WithMain = struct
538592

539593
(* The entire program + query, but still in "printable" format *)
540594
type 'a query = {
541-
types : Structured.typ list C.Map.t;
595+
types : Types.types C.Map.t;
542596
type_abbrevs : type_abbrev_declaration C.Map.t;
543597
modes : mode C.Map.t;
544598
clauses_rev : (preterm,Assembled.attribute) Ast.Clause.t list;
@@ -859,10 +913,10 @@ module ToDBL : sig
859913
(* Exported since also used to flatten (here we "flatten" locals) *)
860914
val prefix_const : State.t -> string list -> C.t -> State.t * C.t
861915
val merge_modes : State.t -> (mode * Loc.t) Map.t -> (mode * Loc.t) Map.t -> (mode * Loc.t) Map.t
862-
val merge_types :
863-
Structured.typ list C.Map.t ->
864-
Structured.typ list C.Map.t ->
865-
Structured.typ list C.Map.t
916+
val merge_types : State.t ->
917+
Types.types C.Map.t ->
918+
Types.types C.Map.t ->
919+
Types.types C.Map.t
866920
val merge_type_abbrevs : State.t ->
867921
type_abbrev_declaration C.Map.t ->
868922
type_abbrev_declaration C.Map.t ->
@@ -1234,7 +1288,7 @@ let query_preterm_of_ast ~depth macros state (loc, t) =
12341288
let state, ttype =
12351289
preterms_of_ast ~on_type:true loc ~depth:lcs F.Map.empty state (fun ~depth:_ state x -> state, [loc,x]) ty in
12361290
let ttype = assert(List.length ttype = 1); List.hd ttype in
1237-
state, { Structured.tindex = attributes; decl = { tname; ttype; tloc = loc } }
1291+
state, { Types.tindex = attributes; decl = { tname; ttype; tloc = loc } }
12381292

12391293
let funct_of_ast state c =
12401294
try
@@ -1258,21 +1312,16 @@ let query_preterm_of_ast ~depth macros state (loc, t) =
12581312
state, C.Map.add mname (args,loc) modes
12591313

12601314
let merge_modes state m1 m2 =
1315+
if C.Map.is_empty m1 then m2 else
12611316
C.Map.fold (fun k v m ->
12621317
check_duplicate_mode state k v m;
12631318
C.Map.add k v m)
12641319
m2 m1
1265-
1266-
let merge_types t1 t2 =
1267-
C.Map.merge (fun _ l1 l2 ->
1268-
match l1, l2 with
1269-
| None, None -> None
1270-
| Some _ as l, None -> l
1271-
| None, (Some _ as l) -> l
1272-
| Some l1, Some l2 ->
1273-
Some (l1 @ (List.filter (fun x -> not @@ List.mem x l1) l2))) t1 t2
1320+
let merge_types _s t1 t2 =
1321+
C.Map.union (fun _ l1 l2 -> Some (Types.merge l1 l2)) t1 t2
12741322

12751323
let merge_type_abbrevs s m1 m2 =
1324+
if C.Map.is_empty m2 then m1 else
12761325
C.Map.fold (fun _ v m -> add_to_index_type_abbrev s m v) m1 m2
12771326

12781327
let rec toplevel_clausify loc ~depth state t =
@@ -1351,9 +1400,9 @@ let query_preterm_of_ast ~depth macros state (loc, t) =
13511400
let map_append k v m =
13521401
try
13531402
let l = C.Map.find k m in
1354-
C.Map.add k (v::l) m
1403+
C.Map.add k (Types.append v l) m
13551404
with Not_found ->
1356-
C.Map.add k [v] m
1405+
C.Map.add k (Types.make v) m
13571406

13581407
let run (state : State.t) ~toplevel_macros p =
13591408
(* FIXME: otypes omodes - NO, rewrite spilling on data.term *)
@@ -1365,7 +1414,7 @@ let query_preterm_of_ast ~depth macros state (loc, t) =
13651414
let type_abbrevs = List.fold_left (add_to_index_type_abbrev state) C.Map.empty type_abbrevs in
13661415
let state, types =
13671416
map_acc (compile_type lcs) state types in
1368-
let types = List.fold_left (fun m t -> map_append t.Structured.decl.tname t m) C.Map.empty types in
1417+
let types = List.fold_left (fun m t -> map_append t.Types.decl.tname t m) C.Map.empty types in
13691418
let state, modes = List.fold_left compile_mode (state,C.Map.empty) modes in
13701419
let defs_m = defs_of_modes modes in
13711420
let defs_t = defs_of_types types in
@@ -1391,7 +1440,7 @@ let query_preterm_of_ast ~depth macros state (loc, t) =
13911440
compile_program macros lcs state p in
13921441
let defs = C.Set.union defs symbols in
13931442
let modes = merge_modes state modes mp in
1394-
let types = merge_types types tp in
1443+
let types = merge_types state types tp in
13951444
let type_abbrevs = merge_type_abbrevs state type_abbrevs ta in
13961445
let state = set_varmap state orig_varmap in
13971446
let lcs, state, types, type_abbrevs, modes, defs, compiled_rest =
@@ -1514,12 +1563,12 @@ let subst_amap state f { nargs; c2i; i2n; n2t; n2i } =
15141563
t,c) n2t in
15151564
{ nargs; c2i; i2n; n2t; n2i }
15161565

1517-
let smart_map_type state f ({ Structured.tindex; decl = { tname; ttype; tloc }} as tdecl) =
1566+
let smart_map_type state f ({ Types.tindex; decl = { tname; ttype; tloc }} as tdecl) =
15181567
let tname1 = f tname in
15191568
let ttype1 = smart_map_term ~on_type:true state f ttype.term in
15201569
let tamap1 =subst_amap state f ttype.amap in
15211570
if tname1 == tname && ttype1 == ttype.term && ttype.amap = tamap1 then tdecl
1522-
else { Structured.tindex; decl = { tname = tname1; tloc; ttype = { term = ttype1; amap = tamap1; loc = ttype.loc; spilling = ttype.spilling } } }
1571+
else { Types.tindex; decl = { tname = tname1; tloc; ttype = { term = ttype1; amap = tamap1; loc = ttype.loc; spilling = ttype.spilling } } }
15231572

15241573

15251574
let map_sequent state f { peigen; pcontext; pconclusion } =
@@ -1577,7 +1626,7 @@ let subst_amap state f { nargs; c2i; i2n; n2t; n2i } =
15771626

15781627
let apply_subst_types ?live_symbols st s tm =
15791628
let ksub = apply_subst_constant ?live_symbols s in
1580-
C.Map.fold (fun k tl m -> C.Map.add (ksub k) (smart_map (smart_map_type st ksub) tl) m) tm C.Map.empty
1629+
C.Map.fold (fun k tl m -> C.Map.add (ksub k) (Types.smart_map (smart_map_type st ksub) tl) m) tm C.Map.empty
15811630

15821631
let apply_subst_type_abbrevs ?live_symbols st s = tabbrevs_map st (apply_subst_constant ?live_symbols s)
15831632

@@ -1611,15 +1660,15 @@ let subst_amap state f { nargs; c2i; i2n; n2t; n2i } =
16111660
| [] -> types, type_abbrevs, modes, clauses, chr
16121661
| Shorten(shorthands, { types = t; type_abbrevs = ta; modes = m; body; symbols = s }) :: rest ->
16131662
let insubst = push_subst_shorthands shorthands s subst in
1614-
let types = ToDBL.merge_types (apply_subst_types ~live_symbols state insubst t) types in
1663+
let types = ToDBL.merge_types state (apply_subst_types ~live_symbols state insubst t) types in
16151664
let type_abbrevs = ToDBL.merge_type_abbrevs state (apply_subst_type_abbrevs ~live_symbols state insubst ta) type_abbrevs in
16161665
let modes = ToDBL.merge_modes state (apply_subst_modes ~live_symbols insubst m) modes in
16171666
let types, type_abbrevs, modes, clauses, chr =
16181667
compile_body live_symbols state lcs types type_abbrevs modes clauses chr insubst body in
16191668
compile_body live_symbols state lcs types type_abbrevs modes clauses chr subst rest
16201669
| Namespace (extra, { types = t; type_abbrevs = ta; modes = m; body; symbols = s }) :: rest ->
16211670
let state, insubst = push_subst state extra s subst in
1622-
let types = ToDBL.merge_types (apply_subst_types ~live_symbols state insubst t) types in
1671+
let types = ToDBL.merge_types state (apply_subst_types ~live_symbols state insubst t) types in
16231672
let type_abbrevs = ToDBL.merge_type_abbrevs state (apply_subst_type_abbrevs ~live_symbols state insubst ta) type_abbrevs in
16241673
let modes = ToDBL.merge_modes state (apply_subst_modes ~live_symbols insubst m) modes in
16251674
let types, type_abbrevs, modes, clauses, chr =
@@ -1630,7 +1679,7 @@ let subst_amap state f { nargs; c2i; i2n; n2t; n2i } =
16301679
let clauses = clauses @ cl in
16311680
compile_body live_symbols state lcs types type_abbrevs modes clauses chr subst rest
16321681
| Constraints (clique, rules, { types = t; type_abbrevs = ta; modes = m; body }) :: rest ->
1633-
let types = ToDBL.merge_types (apply_subst_types ~live_symbols state subst t) types in
1682+
let types = ToDBL.merge_types state (apply_subst_types ~live_symbols state subst t) types in
16341683
let type_abbrevs = ToDBL.merge_type_abbrevs state (apply_subst_type_abbrevs ~live_symbols state subst ta) type_abbrevs in
16351684
let modes = ToDBL.merge_modes state (apply_subst_modes ~live_symbols subst m) modes in
16361685
let chr = apply_subst_chr ~live_symbols state subst (clique,rules) :: chr in
@@ -1697,16 +1746,16 @@ module Spill : sig
16971746

16981747

16991748
val spill_clause :
1700-
State.t -> types:Structured.typ list C.Map.t -> modes:(constant -> mode) ->
1749+
State.t -> types:Types.types C.Map.t -> modes:(constant -> mode) ->
17011750
(preterm, 'a) Ast.Clause.t -> (preterm, 'a) Ast.Clause.t
17021751

17031752
val spill_chr :
1704-
State.t -> types:Structured.typ list C.Map.t -> modes:(constant -> mode) ->
1753+
State.t -> types:Types.types C.Map.t -> modes:(constant -> mode) ->
17051754
(constant list * prechr_rule list) -> (constant list * prechr_rule list)
17061755

17071756
(* Exported to compile the query *)
17081757
val spill_preterm :
1709-
State.t -> Structured.typ list C.Map.t -> (C.t -> mode) -> preterm -> preterm
1758+
State.t -> Types.types C.Map.t -> (C.t -> mode) -> preterm -> preterm
17101759

17111760
end = struct (* {{{ *)
17121761

@@ -1722,7 +1771,7 @@ end = struct (* {{{ *)
17221771

17231772
let type_of_const types c =
17241773
try
1725-
let { Structured.decl = { ttype } } = List.hd @@ List.rev @@ C.Map.find c types in
1774+
let { Types.decl = { ttype } } = (C.Map.find c types).Types.def in
17261775
read_ty ttype.term
17271776
with
17281777
Not_found -> `Unknown
@@ -2037,7 +2086,7 @@ let assemble flags state code (ul : compilation_unit list) =
20372086
state, code in
20382087
let modes = ToDBL.merge_modes state m1 m2 in
20392088
let type_abbrevs = ToDBL.merge_type_abbrevs state ta1 ta2 in
2040-
let types = ToDBL.merge_types t1 t2 in
2089+
let types = ToDBL.merge_types state t1 t2 in
20412090
let cl2 = filter_if flags clause_name cl2 in
20422091
let cl2 = List.map (Spill.spill_clause state ~types ~modes:(fun c -> fst @@ C.Map.find c modes)) cl2 in
20432092
let c2 = List.map (Spill.spill_chr state ~types ~modes:(fun c -> fst @@ C.Map.find c modes)) c2 in
@@ -2206,19 +2255,19 @@ let is_builtin state tname =
22062255
let check_all_builtin_are_typed state types =
22072256
Constants.Set.iter (fun c ->
22082257
if not (match C.Map.find c types with
2209-
| l -> l |> List.for_all (fun { Structured.tindex;_} -> tindex = Ast.Structured.External)
2258+
| l -> l |> Types.for_all (fun { Types.tindex;_} -> tindex = Ast.Structured.External)
22102259
| exception Not_found -> false) then
22112260
error ("Built-in without external type declaration: " ^ Symbols.show state c))
22122261
(Builtins.all state);
2213-
C.Map.iter (fun tname tl -> tl |> List.iter (fun { Structured.tindex; decl = { tname; tloc }} ->
2262+
C.Map.iter (fun tname tl -> tl |> Types.iter (fun { Types.tindex; decl = { tname; tloc }} ->
22142263
if tindex = Ast.Structured.External && not (is_builtin state tname) then
22152264
error ~loc:tloc ("external type declaration without Built-in: " ^
22162265
Symbols.show state tname)))
22172266
types
22182267
;;
22192268

22202269
let check_no_regular_types_for_builtins state types =
2221-
C.Map.iter (fun tname l -> l |> List.iter (fun {Structured.tindex; decl = { tloc } } ->
2270+
C.Map.iter (fun tname l -> l |> Types.iter (fun {Types.tindex; decl = { tloc } } ->
22222271
if tindex <> Ast.Structured.External && is_builtin state tname then
22232272
anomaly ~loc:tloc ("type declaration for Built-in " ^
22242273
Symbols.show state tname ^ " must be flagged as external");
@@ -2467,7 +2516,7 @@ let run
24672516
map
24682517
with Not_found ->
24692518
C.Map.add name (mode,index) map in
2470-
let map = C.Map.fold (fun tname l acc -> l |> List.fold_left (fun acc { Structured.tindex } -> add_indexing_for tname (Some tindex) acc) acc) types C.Map.empty in
2519+
let map = C.Map.fold (fun tname l acc -> Types.fold (fun acc { Types.tindex } -> add_indexing_for tname (Some tindex) acc) acc l) types C.Map.empty in
24712520
let map = C.Map.fold (fun k _ m -> add_indexing_for k None m) modes map in
24722521
map in
24732522
let state, clauses_rev =
@@ -2715,8 +2764,9 @@ let static_check ~exec ~checker:(state,program)
27152764
let time = `Compiletime in
27162765
let state, p,q = quote_syntax time state q in
27172766
let state, tlist = C.Map.fold (fun tname l (state,tl) ->
2767+
let l = l.Types.lst in
27182768
let state, l =
2719-
List.rev l |> map_acc (fun state { Structured.decl = { ttype } } ->
2769+
List.rev l |> map_acc (fun state { Types.decl = { ttype } } ->
27202770
let state, c = mkQCon time ~compiler_state state ~on_type:false tname in
27212771
let ttypet = unfold_type_abbrevs ~compiler_state initial_depth type_abbrevs ttype in
27222772
let state, ttypet = quote_preterm time ~compiler_state state ~on_type:true ttypet in

0 commit comments

Comments
 (0)