186 lines
4.7 KiB
OCaml
186 lines
4.7 KiB
OCaml
(* TEST
|
|
include config
|
|
flags = "-w -55"
|
|
ocamlc_flags = "config.cmo"
|
|
ocamlopt_flags = "-inline 20 config.cmx"
|
|
*)
|
|
|
|
let eliminate_intermediate_float_record () =
|
|
let r = ref 0. in
|
|
for n = 1 to 1000 do
|
|
let open Complex in
|
|
let c = { re = float n; im = 0. } in
|
|
(* The following line triggers warning 55 twice when compiled without
|
|
flambda. It would be better to disable this warning just here but since
|
|
this is a backend-warning, this is not currently possible. Hence the use
|
|
of the -w-55 command-line flag for this test *)
|
|
r := !r +. (norm [@inlined]) ((add [@inlined]) c i);
|
|
done;
|
|
ignore (Sys.opaque_identity !r)
|
|
|
|
module PR_6686 = struct
|
|
type t =
|
|
| A of float
|
|
| B of (int * int)
|
|
|
|
let rec foo = function
|
|
| A x -> x
|
|
| B (x, y) -> float x +. float y
|
|
|
|
let (_ : float) = foo (A 4.)
|
|
end
|
|
|
|
module PR_6770 = struct
|
|
type t =
|
|
| Constant of float
|
|
| Exponent of (float * float)
|
|
|
|
let to_string = function
|
|
| Exponent (_b, _e) ->
|
|
ignore _b;
|
|
ignore _e;
|
|
""
|
|
| Constant _ -> ""
|
|
|
|
let _ = to_string (Constant 4.)
|
|
end
|
|
|
|
|
|
let check_noalloc name f =
|
|
let a0 = Gc.allocated_bytes () in
|
|
let a1 = Gc.allocated_bytes () in
|
|
let _x = f () in
|
|
let a2 = Gc.allocated_bytes () in
|
|
let alloc = (a2 -. 2. *. a1 +. a0) in
|
|
|
|
match Sys.backend_type with
|
|
| Sys.Bytecode -> ()
|
|
| Sys.Native ->
|
|
if alloc > 100. then
|
|
failwith (Printf.sprintf "%s; alloc = %.0f" name alloc)
|
|
| _ -> assert false
|
|
|
|
module GPR_109 = struct
|
|
|
|
let f () =
|
|
let r = ref 0. in
|
|
for i = 1 to 1000 do
|
|
let x = float i in
|
|
let y = if i mod 2 = 0 then x else x +. 1. in
|
|
r := !r +. y
|
|
done;
|
|
!r
|
|
|
|
let () = check_noalloc "gpr 1O9" f
|
|
end
|
|
|
|
|
|
let unbox_classify_float () =
|
|
let x = ref 100. in
|
|
for i = 1 to 1000 do
|
|
assert (classify_float !x = FP_normal);
|
|
x := !x +. 1.
|
|
done;
|
|
ignore (Sys.opaque_identity !x)
|
|
|
|
let unbox_compare_float () =
|
|
let module M = struct type sf = { mutable x: float; y: float; } end in
|
|
let x = { M.x=100. ; y=1. } in
|
|
for i = 1 to 1000 do
|
|
assert (compare x.M.x x.M.y >= 0);
|
|
x.M.x <- x.M.x +. 1.
|
|
done;
|
|
ignore (Sys.opaque_identity x.M.x)
|
|
|
|
let unbox_float_refs () =
|
|
let r = ref nan in
|
|
for i = 1 to 1000 do r := !r +. float i done;
|
|
ignore (Sys.opaque_identity !r)
|
|
|
|
let unbox_let_float () =
|
|
let r = ref 0. in
|
|
for i = 1 to 1000 do
|
|
let y =
|
|
if i mod 2 = 0 then nan else float i
|
|
in
|
|
r := !r +. (y *. 2.)
|
|
done;
|
|
ignore (Sys.opaque_identity !r)
|
|
|
|
type block =
|
|
{ mutable float : float;
|
|
mutable int32 : int32 }
|
|
|
|
let make_some_block record =
|
|
{ record with int32 = record.int32 }
|
|
|
|
let unbox_record_1 record =
|
|
(* There is some let lifting problem to handle that case with one
|
|
round, this currently requires 2 rounds to be correctly
|
|
recognized as a mutable variable pattern *)
|
|
(* let block = (make_some_block [@inlined]) record in *)
|
|
let block = { record with int32 = record.int32 } in
|
|
for i = 1 to 1000 do
|
|
let y_float =
|
|
if i mod 2 = 0 then nan else Stdlib.float i
|
|
in
|
|
block.float <- block.float +. (y_float *. 2.);
|
|
let y_int32 =
|
|
if i mod 2 = 0 then Int32.max_int else Int32.of_int i
|
|
in
|
|
block.int32 <- Int32.(add block.int32 (mul y_int32 2l))
|
|
done;
|
|
ignore (Sys.opaque_identity block.float);
|
|
ignore (Sys.opaque_identity block.int32)
|
|
[@@inline never]
|
|
(* Prevent inlining to test that the type is effectively used *)
|
|
|
|
let float_int32_record = { float = 3.14; int32 = 12l }
|
|
|
|
let unbox_record () =
|
|
unbox_record_1 float_int32_record
|
|
|
|
let r = ref 0.
|
|
|
|
let unbox_only_if_useful () =
|
|
for i = 1 to 1000 do
|
|
let x =
|
|
if i mod 2 = 0 then 1.
|
|
else 0.
|
|
in
|
|
r := x; (* would force boxing if the let binding above were unboxed *)
|
|
r := x (* use [x] twice to avoid elimination of the let-binding *)
|
|
done;
|
|
ignore (Sys.opaque_identity !r)
|
|
|
|
let unbox_minor_words () =
|
|
for i = 1 to 1000 do
|
|
ignore (Gc.minor_words () = 0.)
|
|
done
|
|
|
|
let ignore_useless_args () =
|
|
let f x _y = int_of_float (cos x) in
|
|
let rec g a n x =
|
|
if n = 0
|
|
then a
|
|
else g (a + (f [@inlined always]) x (x +. 1.)) (n - 1) x
|
|
in
|
|
ignore (g 0 10 5.)
|
|
|
|
let () =
|
|
check_noalloc "classify float" unbox_classify_float;
|
|
check_noalloc "compare float" unbox_compare_float;
|
|
check_noalloc "float refs" unbox_float_refs;
|
|
check_noalloc "unbox let float" unbox_let_float;
|
|
check_noalloc "unbox only if useful" unbox_only_if_useful;
|
|
check_noalloc "ignore useless args" ignore_useless_args;
|
|
|
|
if Config.flambda then begin
|
|
check_noalloc "float and int32 record" unbox_record;
|
|
check_noalloc "eliminate intermediate immutable float record"
|
|
eliminate_intermediate_float_record;
|
|
end;
|
|
|
|
check_noalloc "Gc.minor_words" unbox_minor_words;
|
|
()
|