Skip to content

Commit bb50f33

Browse files
stedolanmshinwell
authored andcommitted
Backend support for local allocations (#478)
Adds local allocations (Ialloc Alloc_local) to the backend, as well as new primitives for region boundaries (Ibeginregion/Iendregion). In Cmm, instead of explicit Ibeginregion/Iendregion, there is a new block-structured Cregion. Since tail calls are supposed to end a region before transferring control, Cmm also has two new constructs that end a region early: Capply with Apply_tail, and Ctail (for general code blocks, resulting from tail calls that have been inlined).
1 parent 4fe43c4 commit bb50f33

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+865
-378
lines changed

backend/CSEgen.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ method class_of_operation op =
249249
| Ispecific _ -> Op_other
250250
| Iname_for_debugger _ -> Op_pure
251251
| Iprobe_is_enabled _ -> Op_other
252+
| Ibeginregion | Iendregion -> Op_other
252253

253254
(* Operations that are so cheap that it isn't worth factoring them. *)
254255

backend/afl_instrument.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ and instrument = function
8888
in
8989
Ccatch (isrec, cases, instrument body)
9090
| Cexit (ex, args, traps) -> Cexit (ex, List.map instrument args, traps)
91+
| Cregion e -> Cregion (instrument e)
92+
| Ctail e -> Ctail (instrument e)
9193

9294
(* these are base cases and have no logging *)
9395
| Cconst_int _ | Cconst_natint _ | Cconst_float _

backend/amd64/CSE.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ method! class_of_operation op =
4747
| Istackoffset _ | Iload _ | Istore _ | Ialloc _
4848
| Iintop _ | Iintop_imm _
4949
| Iname_for_debugger _ | Iprobe _ | Iprobe_is_enabled _ | Iopaque
50+
| Ibeginregion | Iendregion
5051
-> super#class_of_operation op
5152

5253
end

backend/amd64/emit.mlp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,19 @@ let emit_call_gc gc =
305305
def_label gc.gc_frame;
306306
I.jmp (label gc.gc_return_lbl)
307307

308+
(* Record calls to local stack reallocation *)
309+
310+
type local_realloc_call =
311+
{ lr_lbl: label;
312+
lr_return_lbl: label; }
313+
314+
let local_realloc_sites = ref ([] : local_realloc_call list)
315+
316+
let emit_local_realloc lr =
317+
def_label lr.lr_lbl;
318+
emit_call "caml_call_local_realloc";
319+
I.jmp (label lr.lr_return_lbl)
320+
308321
(* Record calls to caml_ml_array_bound_error.
309322
In -g mode we maintain one call to
310323
caml_ml_array_bound_error per bound check site. Without -g, we can share
@@ -760,7 +773,7 @@ let emit_instr fallthrough i =
760773
| Double ->
761774
I.movsd (arg i 0) (addressing addr REAL8 i 1)
762775
end
763-
| Lop(Ialloc { bytes = n; dbginfo }) ->
776+
| Lop(Ialloc { bytes = n; dbginfo; mode = Alloc_heap }) ->
764777
assert (n <= (Config.max_young_wosize + 1) * Arch.size_addr);
765778
if !fastcode_flag then begin
766779
I.sub (int n) r15;
@@ -790,6 +803,21 @@ let emit_instr fallthrough i =
790803
def_label label;
791804
I.lea (mem64 NONE 8 R15) (res i 0)
792805
end
806+
| Lop(Ialloc { bytes = n; dbginfo=_; mode = Alloc_local }) ->
807+
let r = res i 0 in
808+
I.mov (domain_field Domainstate.Domain_local_sp) r;
809+
I.sub (int n) r;
810+
I.mov r (domain_field Domainstate.Domain_local_sp);
811+
I.cmp (domain_field Domainstate.Domain_local_limit) r;
812+
let lbl_call = new_label () in
813+
I.j L (label lbl_call);
814+
let lbl_after_alloc = new_label () in
815+
def_label lbl_after_alloc;
816+
I.add (domain_field Domainstate.Domain_local_top) r;
817+
I.add (int 8) r;
818+
local_realloc_sites :=
819+
{ lr_lbl = lbl_call;
820+
lr_return_lbl = lbl_after_alloc } :: !local_realloc_sites
793821
| Lop(Iintop(Icomp cmp)) ->
794822
I.cmp (arg i 1) (arg i 0);
795823
I.set (cond cmp) al;
@@ -962,6 +990,10 @@ let emit_instr fallthrough i =
962990
| High -> T0
963991
in
964992
I.prefetch is_write locality (addressing addr QWORD i 0)
993+
| Lop(Ibeginregion) ->
994+
I.mov (domain_field Domainstate.Domain_local_sp) (res i 0)
995+
| Lop(Iendregion) ->
996+
I.mov (arg i 0) (domain_field Domainstate.Domain_local_sp)
965997
| Lop (Iname_for_debugger _) -> ()
966998
| Lop (Iprobe _) ->
967999
let probe_label = new_label () in
@@ -1148,6 +1180,7 @@ let fundecl fundecl =
11481180
tailrec_entry_point := fundecl.fun_tailrec_entry_point_label;
11491181
stack_offset := 0;
11501182
call_gc_sites := [];
1183+
local_realloc_sites := [];
11511184
bound_error_sites := [];
11521185
bound_error_call := 0;
11531186
for i = 0 to Proc.num_register_classes - 1 do
@@ -1171,6 +1204,7 @@ let fundecl fundecl =
11711204
cfi_startproc ();
11721205
emit_all true fundecl.fun_body;
11731206
List.iter emit_call_gc !call_gc_sites;
1207+
List.iter emit_local_realloc !local_realloc_sites;
11741208
emit_call_bound_errors ();
11751209
if !frame_required then begin
11761210
let n = frame_size() - 8 - (if fp then 8 else 0) in

backend/amd64/proc.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ let destroyed_at_oper = function
337337
| Iname_for_debugger _ | Iprobe _| Iprobe_is_enabled _ | Iopaque)
338338
| Iend | Ireturn _ | Iifthenelse (_, _, _) | Icatch (_, _, _, _)
339339
| Iexit _ | Iraise _
340+
| Iop(Ibeginregion | Iendregion)
340341
->
341342
if fp then
342343
(* prevent any use of the frame pointer ! *)
@@ -362,6 +363,7 @@ let safe_register_pressure = function
362363
| Istackoffset _ | Iload (_, _) | Istore (_, _, _)
363364
| Iintop _ | Iintop_imm (_, _) | Ispecific _ | Iname_for_debugger _
364365
| Iprobe _ | Iprobe_is_enabled _ | Iopaque
366+
| Ibeginregion | Iendregion
365367
-> if fp then 10 else 11
366368

367369
let max_register_pressure =
@@ -401,6 +403,7 @@ let max_register_pressure =
401403
| Ioffset_loc (_, _) | Ifloatarithmem (_, _)
402404
| Ibswap _ | Ifloatsqrtf _ | Isqrtf)
403405
| Iname_for_debugger _ | Iprobe _ | Iprobe_is_enabled _ | Iopaque
406+
| Ibeginregion | Iendregion
404407
-> consumes ~int:0 ~float:0
405408

406409
(* Pure operations (without any side effect besides updating their result
@@ -410,6 +413,7 @@ let op_is_pure = function
410413
| Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
411414
| Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
412415
| Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) | Iopaque -> false
416+
| Ibeginregion | Iendregion -> false
413417
| Ispecific(Ipause)
414418
| Ispecific(Iprefetch _) -> false
415419
| Ispecific(Ilea _ | Isextend32 | Izextend32 | Ifloat_iround | Ifloat_round _
@@ -451,7 +455,7 @@ let init () =
451455
let operation_supported = function
452456
| Cpopcnt -> !popcnt_support
453457
| Cprefetch _
454-
| Capply _ | Cextcall _ | Cload _ | Calloc | Cstore _
458+
| Capply _ | Cextcall _ | Cload _ | Calloc _ | Cstore _
455459
| Caddi | Csubi | Cmuli | Cmulhi _ | Cdivi | Cmodi
456460
| Cand | Cor | Cxor | Clsl | Clsr | Casr
457461
| Cclz _ | Cctz _

backend/amd64/reload.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ method! reload_operation op arg res =
158158
| Itailcall_ind|Itailcall_imm _|Iextcall _|Istackoffset _|Iload (_, _)
159159
| Istore (_, _, _)|Ialloc _|Iname_for_debugger _|Iprobe _|Iprobe_is_enabled _
160160
| Iopaque
161+
| Ibeginregion | Iendregion
161162
-> (* Other operations: all args and results in registers *)
162163
super#reload_operation op arg res
163164

backend/amd64/selection.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ let pseudoregs_for_operation op arg res =
155155
| Iconst_symbol _|Icall_ind|Icall_imm _|Itailcall_ind|Itailcall_imm _
156156
| Iextcall _|Istackoffset _|Iload (_, _)|Istore (_, _, _)|Ialloc _
157157
| Iname_for_debugger _|Iprobe _|Iprobe_is_enabled _ | Iopaque
158+
| Ibeginregion | Iendregion
158159
-> raise Use_default
159160

160161
let select_locality (l : Cmm.prefetch_temporal_locality_hint)
@@ -242,6 +243,7 @@ method! select_store is_assign addr exp =
242243
| Cassign (_, _) | Ctuple _ | Cop (_, _, _) | Csequence (_, _)
243244
| Cifthenelse (_, _, _, _, _, _) | Cswitch (_, _, _, _) | Ccatch (_, _, _)
244245
| Cexit (_, _, _) | Ctrywith (_, _, _, _, _)
246+
| Cregion _ | Ctail _
245247
->
246248
super#select_store is_assign addr exp
247249

backend/arm64/emit.mlp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ module BR = Branch_relaxation.Make (struct
511511
| 16 | 24 | 32 -> 1
512512
| _ -> 1 + num_instructions_for_intconst (Nativeint.of_int num_bytes)
513513
end
514+
| Lop (Ibeginregion | Iendregion) ->
515+
Misc.fatal_error "Local allocations not supported on this architecture"
514516
| Lop (Iintop (Icomp _)) -> 2
515517
| Lop (Icompf _) -> 2
516518
| Lop (Iintop_imm (Icomp _, _)) -> 2
@@ -787,10 +789,12 @@ let emit_instr i =
787789
| Word_int | Word_val | Double ->
788790
` str {emit_reg src}, {emit_addressing addr base}\n`
789791
end
790-
| Lop(Ialloc { bytes = n; dbginfo }) ->
792+
| Lop(Ialloc { bytes = n; dbginfo; mode = Alloc_heap }) ->
791793
assembly_code_for_allocation i ~n ~far:false ~dbginfo
792794
| Lop(Ispecific (Ifar_alloc { bytes = n; dbginfo })) ->
793795
assembly_code_for_allocation i ~n ~far:true ~dbginfo
796+
| Lop(Ialloc { mode = Alloc_local } | Ibeginregion | Iendregion) ->
797+
Misc.fatal_error "Local allocations not supported on this architecture"
794798
| Lop(Iintop_imm(Iadd, n)) ->
795799
emit_addimm i.res.(0) i.arg.(0) n
796800
| Lop(Iintop_imm(Isub, n)) ->

backend/arm64/proc.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ let op_is_pure = function
288288
| Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
289289
| Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
290290
| Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) | Iopaque
291+
| Ibeginregion | Iendregion
291292
| Ispecific(Ishiftcheckbound _) -> false
292293
| _ -> true
293294

@@ -314,7 +315,7 @@ let operation_supported = function
314315
| Cclz _ | Cctz _ | Cpopcnt
315316
| Cprefetch _
316317
-> false (* Not implemented *)
317-
| Capply _ | Cextcall _ | Cload _ | Calloc | Cstore _
318+
| Capply _ | Cextcall _ | Cload _ | Calloc _ | Cstore _
318319
| Caddi | Csubi | Cmuli | Cmulhi _ | Cdivi | Cmodi
319320
| Cand | Cor | Cxor | Clsl | Clsr | Casr
320321
| Ccmpi _ | Caddv | Cadda | Ccmpa _

backend/cfg/cfg.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ let dump_op ppf = function
221221
Format.fprintf ppf "probe %s %s" name handler_code_sym
222222
| Probe_is_enabled { name } -> Format.fprintf ppf "probe_is_enabled %s" name
223223
| Opaque -> Format.fprintf ppf "opaque"
224+
| Begin_region -> Format.fprintf ppf "beginregion"
225+
| End_region -> Format.fprintf ppf "endregion"
224226
| Name_for_debugger _ -> Format.fprintf ppf "name_for_debugger"
225227

226228
let dump_call ppf = function
@@ -319,6 +321,8 @@ let can_raise_operation : operation -> bool = function
319321
| Specific _ -> false (* CR xclerc for xclerc: double check *)
320322
| Opaque -> false
321323
| Name_for_debugger _ -> false
324+
| Begin_region -> false
325+
| End_region -> false
322326

323327
let can_raise_basic : basic -> bool = function
324328
| Op op -> can_raise_operation op

backend/cfg/cfg_equivalence.ml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ let check_operation : location -> Cfg.operation -> Cfg.operation -> unit =
250250
when Arch.equal_specific_operation expected_spec result_spec ->
251251
()
252252
| Opaque, Opaque -> ()
253+
| Begin_region, Begin_region -> ()
254+
| End_region, End_region -> ()
253255
| ( Name_for_debugger
254256
{ ident = left_ident;
255257
which_parameter = left_which_parameter;
@@ -276,9 +278,16 @@ let check_prim_call_operation :
276278
match expected, result with
277279
| External expected, External result ->
278280
check_external_call_operation location expected result
279-
| ( Alloc { bytes = expected_bytes; dbginfo = _expected_dbginfo },
280-
Alloc { bytes = result_bytes; dbginfo = _result_dbginfo } )
281-
when Int.equal expected_bytes result_bytes ->
281+
| ( Alloc
282+
{ bytes = expected_bytes;
283+
dbginfo = _expected_dbginfo;
284+
mode = expected_mode
285+
},
286+
Alloc
287+
{ bytes = result_bytes; dbginfo = _result_dbginfo; mode = result_mode }
288+
)
289+
when Int.equal expected_bytes result_bytes
290+
&& Lambda.eq_mode expected_mode result_mode ->
282291
(* CR xclerc for xclerc: also check debug info *)
283292
()
284293
| ( Checkbound { immediate = expected_immediate },

backend/cfg/cfg_intf.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ module S = struct
4949
| External of external_call_operation
5050
| Alloc of
5151
{ bytes : int;
52-
dbginfo : Debuginfo.alloc_dbginfo
52+
dbginfo : Debuginfo.alloc_dbginfo;
53+
mode : Lambda.alloc_mode
5354
}
5455
| Checkbound of { immediate : int option }
5556

@@ -80,6 +81,8 @@ module S = struct
8081
}
8182
| Probe_is_enabled of { name : string }
8283
| Opaque
84+
| Begin_region
85+
| End_region
8386
| Specific of Arch.specific_operation
8487
| Name_for_debugger of
8588
{ ident : Ident.t;

backend/cfg/cfg_to_linear.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ let from_basic (basic : Cfg.basic) : L.instruction_desc =
5151
| Call (P (Checkbound { immediate = None })) -> Lop (Iintop Icheckbound)
5252
| Call (P (Checkbound { immediate = Some i })) ->
5353
Lop (Iintop_imm (Icheckbound, i))
54-
| Call (P (Alloc { bytes; dbginfo })) -> Lop (Ialloc { bytes; dbginfo })
54+
| Call (P (Alloc { bytes; dbginfo; mode })) ->
55+
Lop (Ialloc { bytes; dbginfo; mode })
5556
| Op op ->
5657
let op : Mach.operation =
5758
match op with
@@ -79,6 +80,8 @@ let from_basic (basic : Cfg.basic) : L.instruction_desc =
7980
| Probe_is_enabled { name } -> Iprobe_is_enabled { name }
8081
| Opaque -> Iopaque
8182
| Specific op -> Ispecific op
83+
| Begin_region -> Ibeginregion
84+
| End_region -> Iendregion
8285
| Name_for_debugger { ident; which_parameter; provenance; is_assignment }
8386
->
8487
Iname_for_debugger { ident; which_parameter; provenance; is_assignment }

backend/cfg/cfgize.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ let basic_or_terminator_of_operation :
158158
| Istackoffset ofs -> Basic (Op (Stackoffset ofs))
159159
| Iload (mem, mode) -> Basic (Op (Load (mem, mode)))
160160
| Istore (mem, mode, assignment) -> Basic (Op (Store (mem, mode, assignment)))
161-
| Ialloc { bytes; dbginfo } -> Basic (Call (P (Alloc { bytes; dbginfo })))
161+
| Ialloc { bytes; dbginfo; mode } ->
162+
Basic (Call (P (Alloc { bytes; dbginfo; mode })))
162163
| Iintop Icheckbound -> Basic (Call (P (Checkbound { immediate = None })))
163164
| Iintop_imm (Icheckbound, i) ->
164165
Basic (Call (P (Checkbound { immediate = Some i })))
@@ -189,6 +190,8 @@ let basic_or_terminator_of_operation :
189190
| Iprobe { name; handler_code_sym } ->
190191
Basic (Op (Probe { name; handler_code_sym }))
191192
| Iprobe_is_enabled { name } -> Basic (Op (Probe_is_enabled { name }))
193+
| Ibeginregion -> Basic (Op Begin_region)
194+
| Iendregion -> Basic (Op End_region)
192195

193196
let float_test_of_float_comparison :
194197
Cmm.float_comparison ->
@@ -316,7 +319,8 @@ let is_noop_move (instr : Cfg.basic Cfg.instruction) : bool =
316319
( Const_int _ | Const_float _ | Const_symbol _ | Stackoffset _ | Load _
317320
| Store _ | Intop _ | Intop_imm _ | Negf | Absf | Addf | Subf | Mulf
318321
| Divf | Compf _ | Floatofint | Intoffloat | Probe _ | Opaque
319-
| Probe_is_enabled _ | Specific _ | Name_for_debugger _ )
322+
| Probe_is_enabled _ | Specific _ | Name_for_debugger _ | Begin_region
323+
| End_region )
320324
| Call _ | Reloadretaddr | Pushtrap _ | Poptrap | Prologue ->
321325
false
322326

backend/cfg/linear_to_cfg.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ let to_basic (mop : Mach.operation) : C.basic =
393393
| Ipopcnt | Iclz _ | Ictz _ | Ilsl | Ilsr | Iasr | Icomp _ ) as op),
394394
i ) ->
395395
Op (Intop_imm (op, i))
396-
| Ialloc { bytes; dbginfo } -> Call (P (Alloc { bytes; dbginfo }))
396+
| Ialloc { bytes; dbginfo; mode } -> Call (P (Alloc { bytes; dbginfo; mode }))
397397
| Iprobe { name; handler_code_sym } -> Op (Probe { name; handler_code_sym })
398398
| Iprobe_is_enabled { name } -> Op (Probe_is_enabled { name })
399399
| Istackoffset i -> Op (Stackoffset i)
@@ -415,6 +415,8 @@ let to_basic (mop : Mach.operation) : C.basic =
415415
| Ifloatofint -> Op Floatofint
416416
| Iintoffloat -> Op Intoffloat
417417
| Iopaque -> Op Opaque
418+
| Ibeginregion -> Op Begin_region
419+
| Iendregion -> Op End_region
418420
| Ispecific op -> Op (Specific op)
419421
| Iname_for_debugger { ident; which_parameter; provenance; is_assignment } ->
420422
Op (Name_for_debugger { ident; which_parameter; provenance; is_assignment })
@@ -611,8 +613,8 @@ let rec create_blocks (t : t) (i : L.instruction) (block : C.basic_block)
611613
| Istore (_, _, _)
612614
| Ialloc _ | Iintop _
613615
| Iintop_imm (_, _)
614-
| Iopaque | Iprobe _ | Iprobe_is_enabled _ | Ispecific _
615-
| Iname_for_debugger _ ->
616+
| Iopaque | Iprobe _ | Iprobe_is_enabled _ | Ispecific _ | Ibeginregion
617+
| Iendregion | Iname_for_debugger _ ->
616618
let desc = to_basic mop in
617619
block.body <- create_instruction t desc i ~trap_depth :: block.body;
618620
if Mach.operation_can_raise mop

0 commit comments

Comments
 (0)