Skip to content

Commit b04e920

Browse files
authored
Store instruction id sequence in CFG (#3933)
1 parent 7f1f234 commit b04e920

29 files changed

+181
-274
lines changed

backend/cfg/cfg.ml

+5-36
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ type t =
8787
fun_contains_calls : bool;
8888
(* CR-someday gyorsh: compute locally. *)
8989
fun_num_stack_slots : int Stack_class.Tbl.t;
90-
fun_poll : Lambda.poll_attribute
90+
fun_poll : Lambda.poll_attribute;
91+
next_instruction_id : InstructionId.sequence
9192
}
9293

9394
let create ~fun_name ~fun_args ~fun_codegen_options ~fun_dbg ~fun_contains_calls
94-
~fun_num_stack_slots ~fun_poll =
95+
~fun_num_stack_slots ~fun_poll ~next_instruction_id =
9596
{ fun_name;
9697
fun_args;
9798
fun_codegen_options;
@@ -102,7 +103,8 @@ let create ~fun_name ~fun_args ~fun_codegen_options ~fun_dbg ~fun_contains_calls
102103
blocks = Label.Tbl.create 31;
103104
fun_contains_calls;
104105
fun_num_stack_slots;
105-
fun_poll
106+
fun_poll;
107+
next_instruction_id
106108
}
107109

108110
let mem_block t label = Label.Tbl.mem t.blocks label
@@ -539,31 +541,8 @@ let make_instruction ~desc ?(arg = [||]) ?(res = [||]) ?(dbg = Debuginfo.none)
539541
available_across
540542
}
541543

542-
let instr_id = InstructionId.make_sequence ()
543-
544-
let reset_instr_id () = InstructionId.reset instr_id
545-
546-
let next_instr_id () = InstructionId.get_and_incr instr_id
547-
548544
let invalid_stack_offset = -1
549545

550-
let make_instr desc arg res dbg =
551-
{ desc;
552-
arg;
553-
res;
554-
dbg;
555-
fdo = Fdo_info.none;
556-
live = Reg.Set.empty;
557-
stack_offset = invalid_stack_offset;
558-
id = next_instr_id ();
559-
irc_work_list = Unknown_list;
560-
ls_order = 0;
561-
(* CR mshinwell/xclerc: should this be [None]? *)
562-
available_before =
563-
Some (Reg_availability_set.Ok Reg_with_debug_info.Set.empty);
564-
available_across = None
565-
}
566-
567546
let make_empty_block ?label terminator : basic_block =
568547
let start =
569548
match label with None -> Cmm.new_label () | Some label -> label
@@ -654,16 +633,6 @@ let basic_block_contains_calls block =
654633
| Prim { op = Probe _; _ } -> true)
655634
|| DLL.exists block.body ~f:is_alloc_or_poll
656635

657-
let max_instr_id t =
658-
(* CR-someday xclerc for xclerc: factor out with similar function in
659-
regalloc/. *)
660-
fold_blocks t ~init:InstructionId.none ~f:(fun _label block max_id ->
661-
let max_id =
662-
DLL.fold_left block.body ~init:max_id ~f:(fun max_id instr ->
663-
InstructionId.max max_id instr.id)
664-
in
665-
InstructionId.max max_id block.terminator.id)
666-
667636
let equal_irc_work_list left right =
668637
match left, right with
669638
| Unknown_list, Unknown_list

backend/cfg/cfg.mli

+6-13
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ type codegen_option =
8383

8484
val of_cmm_codegen_option : Cmm.codegen_option list -> codegen_option list
8585

86+
(* CR-someday xclerc: we should probably make `t` abstract and make each and
87+
every modifiction through accessors; that would help enforce invariants. *)
88+
8689
(** Control Flow Graph of a function. *)
8790
type t =
8891
{ blocks : basic_block Label.Tbl.t; (** Map from labels to blocks *)
@@ -100,7 +103,8 @@ type t =
100103
(** Precomputed during selection and poll insertion. *)
101104
fun_num_stack_slots : int Stack_class.Tbl.t;
102105
(** Precomputed at register allocation time *)
103-
fun_poll : Lambda.poll_attribute (* Whether to insert polling points. *)
106+
fun_poll : Lambda.poll_attribute; (* Whether to insert polling points. *)
107+
next_instruction_id : InstructionId.sequence (* Next instruction id. *)
104108
}
105109

106110
val create :
@@ -111,6 +115,7 @@ val create :
111115
fun_contains_calls:bool ->
112116
fun_num_stack_slots:int Stack_class.Tbl.t ->
113117
fun_poll:Lambda.poll_attribute ->
118+
next_instruction_id:InstructionId.sequence ->
114119
t
115120

116121
val fun_name : t -> string
@@ -229,23 +234,11 @@ val make_instruction :
229234
unit ->
230235
'a instruction
231236

232-
(* CR mshinwell: consolidate with [make_instruction] and tidy up ID interface *)
233-
val make_instr :
234-
'a -> Reg.t array -> Reg.t array -> Debuginfo.t -> 'a instruction
235-
236-
(** These IDs are also used by [make_instr] *)
237-
val next_instr_id : unit -> InstructionId.t
238-
239-
val reset_instr_id : unit -> unit
240-
241237
val make_empty_block : ?label:Label.t -> terminator instruction -> basic_block
242238

243239
(** "Contains calls" in the traditional sense as used in upstream [Selectgen]. *)
244240
val basic_block_contains_calls : basic_block -> bool
245241

246-
(* [max_instr_id cfg] returns the maximum instruction identifier in [cfg]. *)
247-
val max_instr_id : t -> InstructionId.t
248-
249242
val equal_irc_work_list : irc_work_list -> irc_work_list -> bool
250243

251244
val invalid_stack_offset : int

backend/cfg/cfg_comballoc.ml

+1-3
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,7 @@ let rec combine : instr_id:InstructionId.sequence -> cell option -> unit =
177177
let run : Cfg_with_layout.t -> Cfg_with_layout.t =
178178
fun cfg_with_layout ->
179179
let cfg = Cfg_with_layout.cfg cfg_with_layout in
180-
let instr_id =
181-
InstructionId.make_sequence ~last_used:(Cfg.max_instr_id cfg) ()
182-
in
180+
let instr_id = cfg.next_instruction_id in
183181
Cfg.iter_blocks cfg ~f:(fun _label block ->
184182
combine ~instr_id (DLL.hd_cell block.body));
185183
cfg_with_layout

backend/cfg/cfg_cse.ml

+3-6
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,14 @@ let debug = false
258258
module State : sig
259259
type t
260260

261-
val make : last_used:InstructionId.t -> t
261+
val make : InstructionId.sequence -> t
262262

263263
val get_and_incr_instruction_id : t -> InstructionId.t
264264
end = struct
265265
(* CR-soon xclerc for xclerc: factor out with the state of GI, IRC, LS. *)
266266
type t = { instruction_id : InstructionId.sequence }
267267

268-
let make ~last_used =
269-
let instruction_id = InstructionId.make_sequence ~last_used () in
270-
{ instruction_id }
268+
let make instruction_id = { instruction_id }
271269

272270
let get_and_incr_instruction_id state =
273271
InstructionId.get_and_incr state.instruction_id
@@ -521,8 +519,7 @@ module Cse_generic (Target : Cfg_cse_target_intf.S) = struct
521519
let cfg = Cfg_with_layout.cfg cfg_with_layout in
522520
(if not (List.mem ~set:cfg.fun_codegen_options Cfg.No_CSE)
523521
then
524-
let cfg_infos = Regalloc_utils.collect_cfg_infos cfg_with_layout in
525-
let state = State.make ~last_used:cfg_infos.max_instruction_id in
522+
let state = State.make cfg.next_instruction_id in
526523
cse_blocks state cfg);
527524
cfg_with_layout
528525
end

backend/cfg/cfg_polling.ml

+1-6
Original file line numberDiff line numberDiff line change
@@ -303,13 +303,8 @@ let instr_cfg_with_layout :
303303
bool =
304304
fun cfg_with_layout ~safe_map ~back_edges ->
305305
let cfg = Cfg_with_layout.cfg cfg_with_layout in
306-
let instruction_id =
307-
lazy
308-
(let cfg = Cfg_with_layout.cfg cfg_with_layout in
309-
InstructionId.make_sequence ~last_used:(Cfg.max_instr_id cfg) ())
310-
in
311306
let next_instruction_id () =
312-
InstructionId.get_and_incr (Lazy.force instruction_id)
307+
InstructionId.get_and_incr cfg.next_instruction_id
313308
in
314309
Cfg_edge.Set.fold
315310
(fun { Cfg_edge.src; dst } added_poll ->

backend/cfg/cfg_stack_checks.ml

+17-34
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ let is_nontail_call : Cfg.terminator -> bool =
4444

4545
(* Returns the stack check info, and the max of seen instruction ids. *)
4646
let block_preproc_stack_check_result :
47-
Cfg.basic_block ->
48-
frame_size:int ->
49-
Emitaux.preproc_stack_check_result * InstructionId.t =
47+
Cfg.basic_block -> frame_size:int -> Emitaux.preproc_stack_check_result =
5048
fun block ~frame_size ->
5149
let contains_nontail_calls =
5250
(* XCR mshinwell: move to a method in Cfg somewhere?
@@ -55,20 +53,17 @@ let block_preproc_stack_check_result :
5553
think the predicate is generic enough to be moved to `Cfg`. *)
5654
is_nontail_call block.terminator.desc
5755
in
58-
let max_frame_size, max_instr_id =
59-
DLL.fold_left block.body
60-
~init:(block.terminator.stack_offset, block.terminator.id)
61-
~f:(fun (max_stack_frame, max_instr_id) (instr : _ Cfg.instruction) ->
62-
( Int.max max_stack_frame instr.stack_offset,
63-
InstructionId.max max_instr_id instr.id ))
56+
let max_frame_size =
57+
DLL.fold_left block.body ~init:block.terminator.stack_offset
58+
~f:(fun max_stack_frame (instr : _ Cfg.instruction) ->
59+
Int.max max_stack_frame instr.stack_offset)
6460
in
6561
let max_frame_size = max_frame_size + frame_size in
66-
{ max_frame_size; contains_nontail_calls }, max_instr_id
62+
{ max_frame_size; contains_nontail_calls }
6763

6864
type cfg_info =
6965
{ max_frame_size : int;
70-
blocks_needing_stack_checks : Label.Set.t;
71-
max_instr_id : InstructionId.t
66+
blocks_needing_stack_checks : Label.Set.t
7267
}
7368

7469
let build_cfg_info : Cfg.t -> cfg_info =
@@ -78,18 +73,11 @@ let build_cfg_info : Cfg.t -> cfg_info =
7873
~contains_calls:cfg.fun_contains_calls
7974
in
8075
let init =
81-
{ max_frame_size = 0;
82-
blocks_needing_stack_checks = Label.Set.empty;
83-
max_instr_id = InstructionId.none
84-
}
76+
{ max_frame_size = 0; blocks_needing_stack_checks = Label.Set.empty }
8577
in
8678
Cfg.fold_blocks cfg ~init
87-
~f:(fun
88-
label
89-
block
90-
{ max_frame_size; blocks_needing_stack_checks; max_instr_id }
91-
->
92-
let preproc_stack_check_result, max_instr_id_block =
79+
~f:(fun label block { max_frame_size; blocks_needing_stack_checks } ->
80+
let preproc_stack_check_result =
9381
block_preproc_stack_check_result block ~frame_size
9482
in
9583
let block_needs_stack_checks =
@@ -105,8 +93,7 @@ let build_cfg_info : Cfg.t -> cfg_info =
10593
then Label.Set.add label blocks_needing_stack_checks
10694
else blocks_needing_stack_checks
10795
in
108-
let max_instr_id = InstructionId.max max_instr_id max_instr_id_block in
109-
{ max_frame_size; blocks_needing_stack_checks; max_instr_id })
96+
{ max_frame_size; blocks_needing_stack_checks })
11097

11198
(* Populates `num_checks` with the number of blocks needing a stack check in the
11299
subtree whose root is the associated label, and returns that value. *)
@@ -170,8 +157,7 @@ let rec find_stack_check_block :
170157
num_checks_tree"
171158
to_cover
172159

173-
let insert_instruction (cfg : Cfg.t) (label : Label.t) ~max_frame_size
174-
~max_instr_id =
160+
let insert_instruction (cfg : Cfg.t) (label : Label.t) ~max_frame_size =
175161
let block = Cfg.get_block_exn cfg label in
176162
let stack_offset = Cfg.first_instruction_stack_offset block in
177163
let check : Cfg.basic Cfg.instruction =
@@ -183,16 +169,15 @@ let insert_instruction (cfg : Cfg.t) (label : Label.t) ~max_frame_size
183169
184170
xclerc: (keeping the comment, and the explicit values below until all of
185171
that is implemented.) *)
186-
let seq = InstructionId.make_sequence ~last_used:max_instr_id () in
187-
let id = InstructionId.get_and_incr seq in
172+
let id = InstructionId.get_and_incr cfg.next_instruction_id in
188173
Cfg.make_instruction ()
189174
~desc:(Cfg.Stack_check { max_frame_size_bytes = max_frame_size })
190175
~stack_offset ~id ~available_before:None ~available_across:None
191176
in
192177
DLL.add_begin block.body check
193178

194179
let insert_stack_checks (cfg : Cfg.t) ~max_frame_size
195-
~blocks_needing_stack_checks ~max_instr_id =
180+
~blocks_needing_stack_checks =
196181
(* CR-soon xclerc for xclerc: use the dominators and loop infos from
197182
Cfg_with_infos (at least on some paths). *)
198183
let doms = Cfg_dominators.build cfg in
@@ -207,7 +192,7 @@ let insert_stack_checks (cfg : Cfg.t) ~max_frame_size
207192
| 0 -> ()
208193
| to_cover ->
209194
let label = find_stack_check_block tree ~to_cover ~num_checks ~loop_infos in
210-
insert_instruction cfg label ~max_frame_size ~max_instr_id
195+
insert_instruction cfg label ~max_frame_size
211196

212197
(* CR-someday xclerc for xclerc: we may want to duplicate the check in some
213198
cases, rather than simply pushing it down. *)
@@ -218,7 +203,7 @@ let cfg (cfg_with_layout : Cfg_with_layout.t) =
218203
let cfg = Cfg_with_layout.cfg cfg_with_layout in
219204
(if not Config.no_stack_checks
220205
then
221-
let { max_frame_size; blocks_needing_stack_checks; max_instr_id } =
206+
let { max_frame_size; blocks_needing_stack_checks } =
222207
build_cfg_info cfg
223208
in
224209
if not (Label.Set.is_empty blocks_needing_stack_checks)
@@ -227,7 +212,5 @@ let cfg (cfg_with_layout : Cfg_with_layout.t) =
227212
< !Flambda_backend_flags.cfg_stack_checks_threshold
228213
then
229214
insert_stack_checks cfg ~max_frame_size ~blocks_needing_stack_checks
230-
~max_instr_id
231-
else
232-
insert_instruction cfg cfg.entry_label ~max_frame_size ~max_instr_id);
215+
else insert_instruction cfg cfg.entry_label ~max_frame_size);
233216
cfg_with_layout

0 commit comments

Comments
 (0)