Skip to content

Commit 1746aa8

Browse files
committed
updated cmm_helpers interface to be more amenable to adding other integer sizes
1 parent 9e7c322 commit 1746aa8

File tree

5 files changed

+232
-203
lines changed

5 files changed

+232
-203
lines changed

backend/cmm_builtins.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ let transl_builtin name args dbg typ_res =
512512
| "caml_unsigned_int64_mulh_unboxed" ->
513513
mulhi ~signed:false Unboxed_int64 args dbg
514514
| "caml_int32_unsigned_to_int_trunc_unboxed_to_untagged" ->
515-
Some (zero_extend_32 dbg (one_arg name args))
515+
Some (zero_extend ~bits:32 ~dbg (one_arg name args))
516516
| "caml_csel_value" | "caml_csel_int_untagged" | "caml_csel_int64_unboxed"
517517
| "caml_csel_int32_unboxed" | "caml_csel_nativeint_unboxed" ->
518518
(* Unboxed float variant of csel intrinsic is not currently supported. It

backend/cmm_helpers.ml

+103-34
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module VP = Backend_var.With_provenance
2020
open Cmm
2121
open Arch
2222

23+
let arch_bits = Arch.size_int * 8
24+
2325
type arity =
2426
{ function_kind : Lambda.function_kind;
2527
params_layout : Lambda.layout list;
@@ -749,35 +751,46 @@ let mod_int c1 c2 is_safe dbg =
749751
(* Division or modulo on boxed integers. The overflow case min_int / -1 can
750752
occur, in which case we force x / -1 = -x and x mod -1 = 0. (PR#5513). *)
751753

752-
let is_different_from x = function
753-
| Cconst_int (n, _) -> n <> x
754-
| Cconst_natint (n, _) -> n <> Nativeint.of_int x
755-
| _ -> false
754+
(* Division or modulo on boxed integers. The overflow case min_int / -1 can
755+
occur, in which case we force x / -1 = -x and x mod -1 = 0. (PR#5513). *)
756756

757-
let safe_divmod_bi mkop kind is_safe mkm1 c1 c2 bi dbg =
758-
bind "divisor" c2 (fun c2 ->
759-
bind "dividend" c1 (fun c1 ->
760-
let c = mkop c1 c2 is_safe dbg in
761-
if Arch.division_crashes_on_overflow
762-
&& bi <> Primitive.Unboxed_int32
763-
&& not (is_different_from (-1) c2)
764-
then
765-
Cifthenelse
766-
( Cop (Ccmpi Cne, [c2; Cconst_int (-1, dbg)], dbg),
767-
dbg,
768-
c,
769-
dbg,
770-
mkm1 c1 dbg,
771-
dbg,
772-
kind )
773-
else c))
757+
let safe_divmod_bi mkop mkm1 ?(dividend_cannot_be_min_int = false) is_safe
758+
dividend divisor dbg =
759+
let is_different_from x = function
760+
| Cconst_int (n, _) -> Nativeint.of_int n <> x
761+
| Cconst_natint (n, _) -> n <> x
762+
| _ -> false
763+
in
764+
bind "divisor" divisor (fun divisor ->
765+
bind "dividend" dividend (fun dividend ->
766+
let c = mkop dividend divisor is_safe dbg in
767+
if not Arch.division_crashes_on_overflow
768+
then c
769+
else
770+
let dividend_cannot_be_min_int =
771+
dividend_cannot_be_min_int
772+
|| is_different_from Nativeint.min_int dividend
773+
in
774+
let divisor_cannot_be_negative_one =
775+
is_different_from (-1n) divisor
776+
in
777+
if dividend_cannot_be_min_int || divisor_cannot_be_negative_one
778+
then c
779+
else
780+
Cifthenelse
781+
( Cop (Ccmpi Cne, [divisor; Cconst_int (-1, dbg)], dbg),
782+
dbg,
783+
c,
784+
dbg,
785+
mkm1 dividend dbg,
786+
dbg,
787+
Any )))
774788

775-
let safe_div_bi is_safe =
776-
safe_divmod_bi div_int Any is_safe (fun c1 dbg ->
789+
let safe_div_bi =
790+
safe_divmod_bi div_int (fun c1 dbg ->
777791
Cop (Csubi, [Cconst_int (0, dbg); c1], dbg))
778792

779-
let safe_mod_bi is_safe =
780-
safe_divmod_bi mod_int Any is_safe (fun _ dbg -> Cconst_int (0, dbg))
793+
let safe_mod_bi = safe_divmod_bi mod_int (fun _ dbg -> Cconst_int (0, dbg))
781794

782795
(* Bool *)
783796

@@ -1500,6 +1513,37 @@ let setfield_unboxed_vec128 arr ~index_in_words newval dbg =
15001513
[field_address; newval],
15011514
dbg ))
15021515

1516+
let get_field_unboxed ~dbg memory_chunk mutability block ~index_in_words =
1517+
match (memory_chunk : memory_chunk) with
1518+
| Single { reg = Float32 } ->
1519+
get_field_unboxed_float32 mutability ~block ~index:index_in_words dbg
1520+
| Double ->
1521+
unboxed_float_array_ref mutability ~block ~index:index_in_words dbg
1522+
| Onetwentyeight_unaligned | Onetwentyeight_aligned ->
1523+
get_field_unboxed_vec128 mutability ~block ~index_in_words dbg
1524+
| Thirtytwo_signed ->
1525+
get_field_unboxed_int32 mutability ~block ~index:index_in_words dbg
1526+
| Word_int ->
1527+
get_field_unboxed_int64_or_nativeint mutability ~block ~index:index_in_words
1528+
dbg
1529+
| Word_val ->
1530+
Misc.fatal_error "cannot use get_field_unboxed with a heap block"
1531+
| _ -> Misc.fatal_error "get_field_unboxed: unexpected memory chunk"
1532+
1533+
let set_field_unboxed ~dbg memory_chunk block ~index_in_words newval =
1534+
match (memory_chunk : memory_chunk) with
1535+
| Single { reg = Float32 } ->
1536+
setfield_unboxed_float32 block index_in_words newval dbg
1537+
| Double -> float_array_set block index_in_words newval dbg
1538+
| Onetwentyeight_unaligned | Onetwentyeight_aligned ->
1539+
setfield_unboxed_vec128 block ~index_in_words newval dbg
1540+
| Thirtytwo_signed -> setfield_unboxed_int32 block index_in_words newval dbg
1541+
| Word_int ->
1542+
setfield_unboxed_int64_or_nativeint block index_in_words newval dbg
1543+
| Word_val ->
1544+
Misc.fatal_error "cannot use set_field_unboxed with a heap block"
1545+
| _ -> Misc.fatal_error "set_field_unboxed : unexpected memory chunk"
1546+
15031547
(* String length *)
15041548

15051549
(* Length of string block *)
@@ -2010,6 +2054,40 @@ let zero_extend_63 dbg e =
20102054
let e = low_63 dbg e in
20112055
Cop (Cand, [e; natint_const_untagged dbg 0x7FFF_FFFF_FFFF_FFFFn], dbg)
20122056

2057+
let zero_extend ~bits ~dbg e =
2058+
assert (0 < bits && bits <= arch_bits);
2059+
if bits = arch_bits
2060+
then e
2061+
else
2062+
match bits with
2063+
| 63 -> zero_extend_63 dbg e
2064+
| 32 -> zero_extend_32 dbg e
2065+
| bits -> Misc.fatal_errorf "zero_extend not implemented for %d bits" bits
2066+
2067+
let sign_extend ~bits ~dbg e =
2068+
assert (0 < bits && bits <= arch_bits);
2069+
if bits = arch_bits
2070+
then e
2071+
else
2072+
match bits with
2073+
| 63 -> sign_extend_63 dbg e
2074+
| 32 -> sign_extend_32 dbg e
2075+
| bits -> Misc.fatal_errorf "sign_extend not implemented for %d bits" bits
2076+
2077+
let low_bits ~bits ~(dbg : Debuginfo.t) e =
2078+
assert (0 < bits && bits <= arch_bits);
2079+
if bits = arch_bits
2080+
then e
2081+
else
2082+
match bits with
2083+
| 63 -> low_63 dbg e
2084+
| 32 -> low_32 dbg e
2085+
| bits -> Misc.fatal_errorf "low_bits not implemented for %d bits" bits
2086+
2087+
let ignore_low_bits ~bits ~dbg:(_ : Debuginfo.t) e =
2088+
assert (0 <= bits && bits <= arch_bits);
2089+
if bits = 0 then e else ignore_low_bit_int e
2090+
20132091
let and_int e1 e2 dbg =
20142092
let is_mask32 = function
20152093
| Cconst_natint (0xFFFF_FFFFn, _) -> true
@@ -3504,15 +3582,6 @@ let xor_int_caml arg1 arg2 dbg =
35043582
Cconst_int (1, dbg) ],
35053583
dbg )
35063584

3507-
let lsl_int_caml arg1 arg2 dbg =
3508-
incr_int (lsl_int (decr_int arg1 dbg) (untag_int arg2 dbg) dbg) dbg
3509-
3510-
let lsr_int_caml arg1 arg2 dbg =
3511-
Cop (Cor, [lsr_int arg1 (untag_int arg2 dbg) dbg; Cconst_int (1, dbg)], dbg)
3512-
3513-
let asr_int_caml arg1 arg2 dbg =
3514-
Cop (Cor, [asr_int arg1 (untag_int arg2 dbg) dbg; Cconst_int (1, dbg)], dbg)
3515-
35163585
type ternary_primitive =
35173586
expression -> expression -> expression -> Debuginfo.t -> expression
35183587

backend/cmm_helpers.mli

+26-73
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
open Cmm
1717

18+
val arch_bits : int
19+
1820
type arity =
1921
{ function_kind : Lambda.function_kind;
2022
params_layout : Lambda.layout list;
@@ -65,9 +67,6 @@ val alloc_infix_header : int -> Debuginfo.t -> expression
6567
(** Make an integer constant from the given integer (tags the integer) *)
6668
val int_const : Debuginfo.t -> int -> expression
6769

68-
(** Simplify the given expression knowing its last bit will be irrelevant *)
69-
val ignore_low_bit_int : expression -> expression
70-
7170
(** Arithmetical operations on integers *)
7271
val add_int : expression -> expression -> Debuginfo.t -> expression
7372

@@ -103,18 +102,18 @@ val untag_int : expression -> Debuginfo.t -> expression
103102

104103
(** Specific division operations for boxed integers *)
105104
val safe_div_bi :
105+
?dividend_cannot_be_min_int:bool ->
106106
Lambda.is_safe ->
107107
expression ->
108108
expression ->
109-
Primitive.unboxed_integer ->
110109
Debuginfo.t ->
111110
expression
112111

113112
val safe_mod_bi :
113+
?dividend_cannot_be_min_int:bool ->
114114
Lambda.is_safe ->
115115
expression ->
116116
expression ->
117-
Primitive.unboxed_integer ->
118117
Debuginfo.t ->
119118
expression
120119

@@ -381,28 +380,18 @@ val bigarray_elt_size_in_bytes : Lambda.bigarray_kind -> int
381380
bigarray. *)
382381
val bigarray_word_kind : Lambda.bigarray_kind -> memory_chunk
383382

384-
(** Operations on 32-bit integers *)
385-
386-
(** [low_32 _ x] is a value which agrees with x on at least the low 32 bits *)
387-
val low_32 : Debuginfo.t -> expression -> expression
383+
(** Operations on n-bit integers *)
388384

389-
(** Sign extend from 32 bits to the word size *)
390-
val sign_extend_32 : Debuginfo.t -> expression -> expression
385+
(** Simplify the given expression knowing low [bits] bits will be irrelevant *)
386+
val ignore_low_bits : bits:int -> dbg:Debuginfo.t -> expression -> expression
391387

392-
(** Zero extend from 32 bits to the word size *)
393-
val zero_extend_32 : Debuginfo.t -> expression -> expression
388+
(** Simplify the given expression knowing that bits other than the low [bits] bits will be
389+
irrelevant *)
390+
val low_bits : bits:int -> dbg:Debuginfo.t -> expression -> expression
394391

395-
(** Operations on 63-bit integers. These may only be used for compilation to
396-
64-bit targets. *)
392+
val sign_extend : bits:int -> dbg:Debuginfo.t -> expression -> expression
397393

398-
(** [low_63 _ x] is a value which agrees with x on at least the low 63 bits *)
399-
val low_63 : Debuginfo.t -> expression -> expression
400-
401-
(** Sign extend from 63 bits to the word size *)
402-
val sign_extend_63 : Debuginfo.t -> expression -> expression
403-
404-
(** Zero extend from 63 bits to the word size *)
405-
val zero_extend_63 : Debuginfo.t -> expression -> expression
394+
val zero_extend : bits:int -> dbg:Debuginfo.t -> expression -> expression
406395

407396
(** Box a given integer, without sharing of constants *)
408397
val box_int_gen :
@@ -498,12 +487,6 @@ val or_int_caml : binary_primitive
498487

499488
val xor_int_caml : binary_primitive
500489

501-
val lsl_int_caml : binary_primitive
502-
503-
val lsr_int_caml : binary_primitive
504-
505-
val asr_int_caml : binary_primitive
506-
507490
type ternary_primitive =
508491
expression -> expression -> expression -> Debuginfo.t -> expression
509492

@@ -719,13 +702,14 @@ val create_ccatch :
719702
body:Cmm.expression ->
720703
Cmm.expression
721704

705+
(** Shift operations. take as first argument a tagged caml integer, and as
706+
second argument an untagged machine intger which is the amount to shift the
707+
first argument by. *)
708+
722709
val lsl_int_caml_raw : dbg:Debuginfo.t -> expression -> expression -> expression
723710

724711
val lsr_int_caml_raw : dbg:Debuginfo.t -> expression -> expression -> expression
725712

726-
(** Shift operations. take as first argument a tagged caml integer, and as
727-
second argument an untagged machine intger which is the amount to shift the
728-
first argument by. *)
729713
val asr_int_caml_raw : dbg:Debuginfo.t -> expression -> expression -> expression
730714

731715
(** Reinterpret cast functions *)
@@ -1198,57 +1182,26 @@ val unboxed_int64_or_nativeint_array_set :
11981182
expression
11991183

12001184
(** {2 Getters and setters for unboxed int and float32 fields of mixed
1201-
blocks} *)
1202-
1203-
(** The argument structure for getters is parallel to [get_field_computed]. *)
1204-
1205-
val get_field_unboxed_int32 :
1206-
Asttypes.mutable_flag ->
1207-
block:expression ->
1208-
index:expression ->
1209-
Debuginfo.t ->
1210-
expression
1211-
1212-
val get_field_unboxed_float32 :
1213-
Asttypes.mutable_flag ->
1214-
block:expression ->
1215-
index:expression ->
1216-
Debuginfo.t ->
1217-
expression
1185+
blocks} [immediate_or_pointer] is not needed as the layout is implied from the name,
1186+
and [initialization_or_assignment] is not needed as unboxed ints can always be
1187+
assigned without caml_modify (etc.). *)
12181188

1219-
val get_field_unboxed_vec128 :
1189+
val get_field_unboxed :
1190+
dbg:Debuginfo.t ->
1191+
memory_chunk ->
12201192
Asttypes.mutable_flag ->
1221-
block:expression ->
1193+
expression ->
12221194
index_in_words:expression ->
1223-
Debuginfo.t ->
12241195
expression
12251196

1226-
val get_field_unboxed_int64_or_nativeint :
1227-
Asttypes.mutable_flag ->
1228-
block:expression ->
1229-
index:expression ->
1230-
Debuginfo.t ->
1231-
expression
1232-
1233-
(** The argument structure for setters is parallel to [setfield_computed].
1234-
[immediate_or_pointer] is not needed as the layout is implied from the name,
1235-
and [initialization_or_assignment] is not needed as unboxed ints can always be
1236-
assigned without caml_modify (etc.).
1237-
*)
1238-
1239-
val setfield_unboxed_int32 : ternary_primitive
1240-
1241-
val setfield_unboxed_float32 : ternary_primitive
1242-
1243-
val setfield_unboxed_vec128 :
1197+
val set_field_unboxed :
1198+
dbg:Debuginfo.t ->
1199+
memory_chunk ->
12441200
expression ->
12451201
index_in_words:expression ->
12461202
expression ->
1247-
Debuginfo.t ->
12481203
expression
12491204

1250-
val setfield_unboxed_int64_or_nativeint : ternary_primitive
1251-
12521205
val dls_get : dbg:Debuginfo.t -> expression
12531206

12541207
val poll : dbg:Debuginfo.t -> expression

middle_end/flambda2/to_cmm/to_cmm_expr.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ let translate_external_call env res ~free_vars apply ~callee_simple ~args
115115
not. There is no need to wrap other return arities. *)
116116
let maybe_sign_extend kind dbg cmm =
117117
match Flambda_kind.With_subkind.kind kind with
118-
| Naked_number Naked_int32 -> C.sign_extend_32 dbg cmm
118+
| Naked_number Naked_int32 -> C.sign_extend ~bits:32 ~dbg cmm
119119
| Naked_number
120120
( Naked_float | Naked_immediate | Naked_int64 | Naked_nativeint
121121
| Naked_vec128 | Naked_float32 )

0 commit comments

Comments
 (0)