Skip to content

Commit 1fa0eca

Browse files
vouillonhhugo
andauthored
Make optimized compilation terminate sooner (#1939)
* Fix code comparison function Properly handle NaN. * Inlining: do not try to handle recursive functions This was not really working and resulted in spurious code changes. * Switch to a bit representation of floats --------- Co-authored-by: Hugo Heuzard <[email protected]>
1 parent b9d902c commit 1fa0eca

File tree

10 files changed

+71
-62
lines changed

10 files changed

+71
-62
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Ppx: allow "function" in object literals (#1897)
2525
* Lib: make the Wasm version of Json.output work with native ints and JavaScript objects (#1872)
2626
* Compiler: static evaluation of more primitives (#1912)
27+
* Compiler: faster compilation by stopping sooner when optimizations become unproductive (#1939)
2728

2829
## Bug fixes
2930
* Compiler: fix stack overflow issues with double translation (#1869)

compiler/lib-wasm/gc_target.ml

+5-2
Original file line numberDiff line numberDiff line change
@@ -1025,12 +1025,15 @@ module Constant = struct
10251025
return (Const_named ("str_" ^ s), W.ArrayNewFixed (ty, l))
10261026
| Float f ->
10271027
let* ty = Type.float_type in
1028-
return (Const, W.StructNew (ty, [ Const (F64 f) ]))
1028+
return (Const, W.StructNew (ty, [ Const (F64 (Int64.float_of_bits f)) ]))
10291029
| Float_array l ->
10301030
let l = Array.to_list l in
10311031
let* ty = Type.float_array_type in
10321032
(*ZZZ Boxed array? *)
1033-
return (Const, W.ArrayNewFixed (ty, List.map ~f:(fun f -> W.Const (F64 f)) l))
1033+
return
1034+
( Const
1035+
, W.ArrayNewFixed
1036+
(ty, List.map ~f:(fun f -> W.Const (F64 (Int64.float_of_bits f))) l) )
10341037
| Int64 i ->
10351038
let* e = Memory.make_int64 (return (W.Const (I64 i))) in
10361039
return (Const, e)

compiler/lib/code.ml

+18-18
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,8 @@ end
268268
type constant =
269269
| String of string
270270
| NativeString of Native_string.t
271-
| Float of float
272-
| Float_array of float array
271+
| Float of Int64.t
272+
| Float_array of Int64.t array
273273
| Int of Targetint.t
274274
| Int32 of Int32.t
275275
| Int64 of Int64.t
@@ -299,8 +299,14 @@ module Constant = struct
299299
| Int32 a, Int32 b -> Some (Int32.equal a b)
300300
| Int64 a, Int64 b -> Some (Int64.equal a b)
301301
| NativeInt a, NativeInt b -> Some (Int32.equal a b)
302-
| Float_array a, Float_array b -> Some (Array.equal Float.ieee_equal a b)
303-
| Float a, Float b -> Some (Float.ieee_equal a b)
302+
| Float_array a, Float_array b ->
303+
Some
304+
(Array.equal
305+
(fun f g -> Float.ieee_equal (Int64.float_of_bits f) (Int64.float_of_bits g))
306+
a
307+
b)
308+
| Float a, Float b ->
309+
Some (Float.ieee_equal (Int64.float_of_bits a) (Int64.float_of_bits b))
304310
| String _, NativeString _ | NativeString _, String _ -> None
305311
| Int _, Float _ | Float _, Int _ -> None
306312
| Tuple ((0 | 254), _, _), Float_array _ -> None
@@ -434,12 +440,12 @@ module Print = struct
434440
| String s -> Format.fprintf f "%S" s
435441
| NativeString (Byte s) -> Format.fprintf f "%Sj" s
436442
| NativeString (Utf (Utf8 s)) -> Format.fprintf f "%Sj" s
437-
| Float fl -> Format.fprintf f "%.12g" fl
443+
| Float fl -> Format.fprintf f "%.12g" (Int64.float_of_bits fl)
438444
| Float_array a ->
439445
Format.fprintf f "[|";
440446
for i = 0 to Array.length a - 1 do
441447
if i > 0 then Format.fprintf f ", ";
442-
Format.fprintf f "%.12g" a.(i)
448+
Format.fprintf f "%.12g" (Int64.float_of_bits a.(i))
443449
done;
444450
Format.fprintf f "|]"
445451
| Int i -> Format.fprintf f "%s" (Targetint.to_string i)
@@ -782,19 +788,13 @@ let fold_closures_outermost_first { start; blocks; _ } f accu =
782788

783789
let eq p1 p2 =
784790
p1.start = p2.start
785-
&& Addr.Map.cardinal p1.blocks = Addr.Map.cardinal p2.blocks
786-
&& Addr.Map.fold
787-
(fun pc block1 b ->
788-
b
789-
&&
790-
try
791-
let block2 = Addr.Map.find pc p2.blocks in
792-
Poly.equal block1.params block2.params
793-
&& Poly.equal block1.branch block2.branch
794-
&& Poly.equal block1.body block2.body
795-
with Not_found -> false)
791+
&& Addr.Map.equal
792+
(fun { params; body; branch } b ->
793+
List.equal ~eq:Var.equal params b.params
794+
&& Poly.equal branch b.branch
795+
&& List.equal ~eq:Poly.equal body b.body)
796796
p1.blocks
797-
true
797+
p2.blocks
798798

799799
let with_invariant = Debug.find "invariant"
800800

compiler/lib/code.mli

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ end
157157
type constant =
158158
| String of string
159159
| NativeString of Native_string.t
160-
| Float of float
161-
| Float_array of float array
160+
| Float of Int64.t
161+
| Float_array of Int64.t array
162162
| Int of Targetint.t
163163
| Int32 of Int32.t (** Only produced when compiling to WebAssembly. *)
164164
| Int64 of Int64.t

compiler/lib/eval.ml

+33-27
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ let shift_op l f =
4545
| [ Int i; Int j ] -> Some (Int (f i (Targetint.to_int_exn j)))
4646
| _ -> None
4747

48+
let float f : constant = Float (Int64.bits_of_float f)
49+
4850
let float_binop_aux (l : constant list) (f : float -> float -> 'a) : 'a option =
4951
let args =
5052
match l with
51-
| [ Float i; Float j ] -> Some (i, j)
53+
| [ Float i; Float j ] -> Some (Int64.float_of_bits i, Int64.float_of_bits j)
5254
| _ -> None
5355
in
5456
match args with
@@ -57,12 +59,12 @@ let float_binop_aux (l : constant list) (f : float -> float -> 'a) : 'a option =
5759

5860
let float_binop (l : constant list) (f : float -> float -> float) : constant option =
5961
match float_binop_aux l f with
60-
| Some x -> Some (Float x)
62+
| Some x -> Some (float x)
6163
| None -> None
6264

6365
let float_unop (l : constant list) (f : float -> float) : constant option =
6466
match l with
65-
| [ Float i ] -> Some (Float (f i))
67+
| [ Float i ] -> Some (float (f (Int64.float_of_bits i)))
6668
| _ -> None
6769

6870
let bool' b = Int Targetint.(if b then one else zero)
@@ -71,7 +73,7 @@ let bool b = Some (bool' b)
7173

7274
let float_unop_bool (l : constant list) (f : float -> bool) =
7375
match l with
74-
| [ Float i ] -> bool (f i)
76+
| [ Float i ] -> bool (f (Int64.float_of_bits i))
7577
| _ -> None
7678

7779
let float_binop_bool l f =
@@ -168,10 +170,10 @@ let eval_prim x =
168170
| "caml_div_float", _ -> float_binop l ( /. )
169171
| "caml_fmod_float", _ -> float_binop l mod_float
170172
| "caml_int_of_float", [ Float f ] -> (
171-
match Targetint.of_float_opt f with
173+
match Targetint.of_float_opt (Int64.float_of_bits f) with
172174
| None -> None
173175
| Some f -> Some (Int f))
174-
| "caml_float_of_int", [ Int i ] -> Some (Float (Targetint.to_float i))
176+
| "caml_float_of_int", [ Int i ] -> Some (float (Targetint.to_float i))
175177
(* Math *)
176178
| "caml_neg_float", _ -> float_unop l ( ~-. )
177179
| "caml_abs_float", _ -> float_unop l abs_float
@@ -209,16 +211,19 @@ let eval_prim x =
209211
| "caml_erfc_float", _ -> float_unop l Float.erfc
210212
| "caml_nextafter_float", _ -> float_binop l Float.next_after
211213
| "caml_float_compare", [ Float i; Float j ] ->
212-
Some (Int (Targetint.of_int_exn (Float.compare i j)))
214+
Some
215+
(Int
216+
(Targetint.of_int_exn
217+
(Float.compare (Int64.float_of_bits i) (Int64.float_of_bits j))))
213218
| "caml_ldexp_float", [ Float f; Int i ] ->
214-
Some (Float (ldexp f (Targetint.to_int_exn i)))
219+
Some (float (ldexp (Int64.float_of_bits f) (Targetint.to_int_exn i)))
215220
(* int32 *)
216-
| "caml_int32_bits_of_float", [ Float f ] -> int32 (Int32.bits_of_float f)
217-
| "caml_int32_float_of_bits", [ Int i ] ->
218-
Some (Float (Int32.float_of_bits (Targetint.to_int32 i)))
219-
| "caml_int32_float_of_bits", [ Int32 i ] -> Some (Float (Int32.float_of_bits i))
220-
| "caml_int32_of_float", [ Float f ] -> int32 (Int32.of_float f)
221-
| "caml_int32_to_float", [ Int32 i ] -> Some (Float (Int32.to_float i))
221+
| "caml_int32_bits_of_float", [ Float f ] ->
222+
int32 (Int32.bits_of_float (Int64.float_of_bits f))
223+
| "caml_int32_float_of_bits", [ Int32 i ] -> Some (float (Int32.float_of_bits i))
224+
| "caml_int32_of_float", [ Float f ] ->
225+
int32 (Int32.of_float (Int64.float_of_bits f))
226+
| "caml_int32_to_float", [ Int32 i ] -> Some (float (Int32.to_float i))
222227
| "caml_int32_neg", _ -> int32_unop l Int32.neg
223228
| "caml_int32_add", _ -> int32_binop l Int32.add
224229
| "caml_int32_sub", _ -> int32_binop l Int32.sub
@@ -240,13 +245,13 @@ let eval_prim x =
240245
| "caml_nativeint_of_int32", [ Int32 i ] -> Some (NativeInt i)
241246
| "caml_nativeint_to_int32", [ NativeInt i ] -> Some (Int32 i)
242247
(* nativeint *)
243-
| "caml_nativeint_bits_of_float", [ Float f ] -> nativeint (Int32.bits_of_float f)
244-
| "caml_nativeint_float_of_bits", [ Int i ] ->
245-
Some (Float (Int32.float_of_bits (Targetint.to_int32 i)))
248+
| "caml_nativeint_bits_of_float", [ Float f ] ->
249+
nativeint (Int32.bits_of_float (Int64.float_of_bits f))
246250
| "caml_nativeint_float_of_bits", [ NativeInt i ] ->
247-
Some (Float (Int32.float_of_bits i))
248-
| "caml_nativeint_of_float", [ Float f ] -> nativeint (Int32.of_float f)
249-
| "caml_nativeint_to_float", [ NativeInt i ] -> Some (Float (Int32.to_float i))
251+
Some (float (Int32.float_of_bits i))
252+
| "caml_nativeint_of_float", [ Float f ] ->
253+
nativeint (Int32.of_float (Int64.float_of_bits f))
254+
| "caml_nativeint_to_float", [ NativeInt i ] -> Some (float (Int32.to_float i))
250255
| "caml_nativeint_neg", _ -> nativeint_unop l Int32.neg
251256
| "caml_nativeint_add", _ -> nativeint_binop l Int32.add
252257
| "caml_nativeint_sub", _ -> nativeint_binop l Int32.sub
@@ -267,10 +272,11 @@ let eval_prim x =
267272
| "caml_nativeint_to_int", [ Int32 i ] -> Some (Int (Targetint.of_int32_truncate i))
268273
| "caml_nativeint_of_int", [ Int i ] -> nativeint (Targetint.to_int32 i)
269274
(* int64 *)
270-
| "caml_int64_bits_of_float", [ Float f ] -> int64 (Int64.bits_of_float f)
271-
| "caml_int64_float_of_bits", [ Int64 i ] -> Some (Float (Int64.float_of_bits i))
272-
| "caml_int64_of_float", [ Float f ] -> int64 (Int64.of_float f)
273-
| "caml_int64_to_float", [ Int64 i ] -> Some (Float (Int64.to_float i))
275+
| "caml_int64_bits_of_float", [ Float f ] -> int64 f
276+
| "caml_int64_float_of_bits", [ Int64 i ] -> Some (Float i)
277+
| "caml_int64_of_float", [ Float f ] ->
278+
int64 (Int64.of_float (Int64.float_of_bits f))
279+
| "caml_int64_to_float", [ Int64 i ] -> Some (float (Int64.to_float i))
274280
| "caml_int64_neg", _ -> int64_unop l Int64.neg
275281
| "caml_int64_add", _ -> int64_binop l Int64.add
276282
| "caml_int64_sub", _ -> int64_binop l Int64.sub
@@ -289,8 +295,7 @@ let eval_prim x =
289295
Some (Int (Targetint.of_int_exn (Int64.compare i j)))
290296
| "caml_int64_to_int", [ Int64 i ] ->
291297
Some (Int (Targetint.of_int32_truncate (Int64.to_int32 i)))
292-
| ( ("caml_int64_of_int" | "caml_int64_of_int32" | "caml_int64_of_nativeint")
293-
, [ Int i ] ) -> int64 (Int64.of_int32 (Targetint.to_int32 i))
298+
| "caml_int64_of_int", [ Int i ] -> int64 (Int64.of_int32 (Targetint.to_int32 i))
294299
| "caml_int64_to_int32", [ Int64 i ] -> int32 (Int64.to_int32 i)
295300
| "caml_int64_of_int32", [ Int32 i ] -> int64 (Int64.of_int32 i)
296301
| "caml_int64_to_nativeint", [ Int64 i ] -> nativeint (Int64.to_int32 i)
@@ -435,7 +440,8 @@ let rec int_predicate deep info pred x (i : Targetint.t) =
435440
let constant_js_equal a b =
436441
match a, b with
437442
| Int i, Int j -> Some (Targetint.equal i j)
438-
| Float a, Float b -> Some (Float.ieee_equal a b)
443+
| Float a, Float b ->
444+
Some (Float.ieee_equal (Int64.float_of_bits a) (Int64.float_of_bits b))
439445
| NativeString a, NativeString b -> Some (Native_string.equal a b)
440446
| String a, String b when Config.Flag.use_js_string () -> Some (String.equal a b)
441447
| Int _, Float _ | Float _, Int _ -> None

compiler/lib/flow.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ let the_def_of info x =
362362
let constant_identical ~(target : [ `JavaScript | `Wasm ]) a b =
363363
match a, b, target with
364364
| Int i, Int j, _ -> Targetint.equal i j
365-
| Float a, Float b, `JavaScript -> Float.bitwise_equal a b
365+
| Float a, Float b, `JavaScript -> Int64.equal a b
366366
| Float _, Float _, `Wasm -> false
367367
| NativeString a, NativeString b, `JavaScript -> Native_string.equal a b
368368
| NativeString _, NativeString _, `Wasm ->

compiler/lib/generate.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ let source_location ctx position pc =
386386

387387
(****)
388388

389-
let float_const f = J.ENum (J.Num.of_float f)
389+
let float_const f = J.ENum (J.Num.of_float (Int64.float_of_bits f))
390390

391391
let s_var name = J.EVar (J.ident (Utf8_string.of_string_exn name))
392392

compiler/lib/inline.ml

+3-7
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ let rec args_equal xs ys =
171171
| x :: xs, Pv y :: ys -> Code.Var.compare x y = 0 && args_equal xs ys
172172
| _ -> false
173173

174-
let inline ~first_class_primitives live_vars closures name pc (outer, p) =
174+
let inline ~first_class_primitives live_vars closures pc (outer, p) =
175175
let block = Addr.Map.find pc p.blocks in
176176
let body, (outer, branch, p) =
177177
List.fold_right
@@ -245,11 +245,7 @@ let inline ~first_class_primitives live_vars closures name pc (outer, p) =
245245
Var.Map.mem farg_tc closures && live_vars.(Var.idx farg_tc) = 1)
246246
tc_params
247247
|| f_size <= 1)
248-
&& ((not recursive)
249-
||
250-
match name with
251-
| None -> true
252-
| Some f' -> not (Var.equal f f')) ->
248+
&& not recursive ->
253249
let () =
254250
(* Update live_vars *)
255251
Var.Map.iter
@@ -345,7 +341,7 @@ let f p live_vars =
345341
let traverse outer =
346342
Code.traverse
347343
{ fold = Code.fold_children }
348-
(inline ~first_class_primitives live_vars closures name)
344+
(inline ~first_class_primitives live_vars closures)
349345
pc
350346
p.blocks
351347
(outer, p)

compiler/lib/ocaml_compiler.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ let rec constant_of_const c : Code.constant =
2525
| Const_base (Const_int i) -> Int (Targetint.of_int_warning_on_overflow i)
2626
| Const_base (Const_char c) -> Int (Targetint.of_int_exn (Char.code c))
2727
| Const_base (Const_string (s, _, _)) -> String s
28-
| Const_base (Const_float s) -> Float (float_of_string s)
28+
| Const_base (Const_float s) -> Float (Int64.bits_of_float (float_of_string s))
2929
| Const_base (Const_int32 i) -> Int32 i
3030
| Const_base (Const_int64 i) -> Int64 i
3131
| Const_base (Const_nativeint i) -> NativeInt (Int32.of_nativeint_warning_on_overflow i)
3232
| Const_immstring s -> String s
3333
| Const_float_array sl ->
34-
let l = List.map ~f:(fun f -> float_of_string f) sl in
34+
let l = List.map ~f:(fun f -> Int64.bits_of_float (float_of_string f)) sl in
3535
Float_array (Array.of_list l)
3636
| Const_block (tag, l) ->
3737
let l = Array.of_list (List.map l ~f:constant_of_const) in

compiler/lib/parse_bytecode.ml

+5-2
Original file line numberDiff line numberDiff line change
@@ -442,9 +442,12 @@ end = struct
442442
if tag = Obj.string_tag
443443
then String (Obj.magic x : string)
444444
else if tag = Obj.double_tag
445-
then Float (Obj.magic x : float)
445+
then Float (Int64.bits_of_float (Obj.magic x : float))
446446
else if tag = Obj.double_array_tag
447-
then Float_array (Array.init (Obj.size x) ~f:(fun i -> Obj.double_field x i))
447+
then
448+
Float_array
449+
(Array.init (Obj.size x) ~f:(fun i ->
450+
Int64.bits_of_float (Obj.double_field x i)))
448451
else if tag = Obj.custom_tag
449452
then
450453
match ident_of_custom x with

0 commit comments

Comments
 (0)