From e75c87dc482eb18fcbc4e038e88d610c588ed63d Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Fri, 25 Dec 2015 01:04:43 +0100 Subject: [PATCH] Initial import of linear-scan-register-allocator The code in this commit was written by Marcell Fischbach & Benedikt Meurer. See [Mantis#5324](http://caml.inria.fr/mantis/view.php?id=5324) for some context. The code (which was originally written against 3.12) was ported to trunk by doing ```bash git clone https://github.com/bmeurer/ocaml-experimental/ cd ocaml-experimental git diff master...linear-scan-register-allocator > t.diff ``` and then applying the diff by hand. --- .depend | 169 ++++++++++++++---------- Changes | 8 ++ Makefile | 2 + asmcomp/asmgen.ml | 16 ++- asmcomp/interval.ml | 188 ++++++++++++++++++++++++++ asmcomp/interval.mli | 37 ++++++ asmcomp/linscan.ml | 190 +++++++++++++++++++++++++++ asmcomp/linscan.mli | 18 +++ asmcomp/printmach.ml | 13 ++ asmcomp/printmach.mli | 1 + asmcomp/spill.ml | 5 +- driver/main_args.ml | 12 ++ driver/main_args.mli | 2 + driver/optmain.ml | 2 + otherlibs/raw_spacetime_lib/Makefile | 2 +- tools/ocamloptp.ml | 2 + toplevel/opttopmain.ml | 2 + utils/clflags.ml | 2 + utils/clflags.mli | 2 + 19 files changed, 595 insertions(+), 78 deletions(-) create mode 100644 asmcomp/interval.ml create mode 100644 asmcomp/interval.mli create mode 100644 asmcomp/linscan.ml create mode 100644 asmcomp/linscan.mli diff --git a/.depend b/.depend index c93fc97ce..dd75f52a3 100644 --- a/.depend +++ b/.depend @@ -233,13 +233,13 @@ typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \ typing/mtype.cmi utils/misc.cmi parsing/location.cmi \ typing/includecore.cmi typing/includeclass.cmi typing/ident.cmi \ typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \ - typing/includemod.cmi + typing/btype.cmi typing/includemod.cmi typing/includemod.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \ typing/subst.cmx typing/printtyp.cmx typing/primitive.cmx typing/path.cmx \ typing/mtype.cmx utils/misc.cmx parsing/location.cmx \ typing/includecore.cmx typing/includeclass.cmx typing/ident.cmx \ typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \ - typing/includemod.cmi + typing/btype.cmx typing/includemod.cmi typing/includemod.cmi : typing/types.cmi typing/typedtree.cmi \ typing/path.cmi parsing/location.cmi typing/includecore.cmi \ typing/ident.cmi typing/env.cmi typing/ctype.cmi @@ -600,6 +600,11 @@ bytecomp/printlambda.cmi : bytecomp/lambda.cmi bytecomp/runtimedef.cmo : bytecomp/runtimedef.cmi bytecomp/runtimedef.cmx : bytecomp/runtimedef.cmi bytecomp/runtimedef.cmi : +bytecomp/semantics_of_primitives.cmo : bytecomp/lambda.cmi \ + bytecomp/semantics_of_primitives.cmi +bytecomp/semantics_of_primitives.cmx : bytecomp/lambda.cmx \ + bytecomp/semantics_of_primitives.cmi +bytecomp/semantics_of_primitives.cmi : bytecomp/lambda.cmi bytecomp/simplif.cmo : utils/warnings.cmi utils/tbl.cmi typing/stypes.cmi \ utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ utils/clflags.cmi parsing/asttypes.cmi typing/annot.cmi \ @@ -706,21 +711,22 @@ asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ asmcomp/CSEgen.cmi : asmcomp/mach.cmi asmcomp/afl_instrument.cmo : bytecomp/lambda.cmi typing/ident.cmi \ middle_end/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/afl_instrument.cmi + parsing/asttypes.cmi asmcomp/afl_instrument.cmi asmcomp/afl_instrument.cmx : bytecomp/lambda.cmx typing/ident.cmx \ middle_end/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/afl_instrument.cmi + parsing/asttypes.cmi asmcomp/afl_instrument.cmi asmcomp/afl_instrument.cmi : asmcomp/cmm.cmi -asmcomp/arch.cmo : utils/clflags.cmi -asmcomp/arch.cmx : utils/clflags.cmx +asmcomp/arch.cmo : utils/config.cmi utils/clflags.cmi +asmcomp/arch.cmx : utils/config.cmx utils/clflags.cmx asmcomp/asmgen.cmo : asmcomp/un_anf.cmi bytecomp/translmod.cmi \ utils/timings.cmi middle_end/base_types/symbol.cmi asmcomp/split.cmi \ asmcomp/spill.cmi asmcomp/selection.cmi asmcomp/scheduling.cmi \ asmcomp/reload.cmi asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/printmach.cmi \ asmcomp/printlinear.cmi asmcomp/printcmm.cmi asmcomp/printclambda.cmi \ typing/primitive.cmi utils/misc.cmi asmcomp/mach.cmi parsing/location.cmi \ - asmcomp/liveness.cmi middle_end/base_types/linkage_name.cmi \ - asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/interf.cmi \ + asmcomp/liveness.cmi asmcomp/linscan.cmi \ + middle_end/base_types/linkage_name.cmi asmcomp/linearize.cmi \ + bytecomp/lambda.cmi asmcomp/interval.cmi asmcomp/interf.cmi \ typing/ident.cmi asmcomp/flambda_to_clambda.cmi middle_end/flambda.cmi \ asmcomp/emitaux.cmi asmcomp/emit.cmi asmcomp/deadcode.cmi \ utils/config.cmi asmcomp/compilenv.cmi asmcomp/comballoc.cmi \ @@ -733,8 +739,9 @@ asmcomp/asmgen.cmx : asmcomp/un_anf.cmx bytecomp/translmod.cmx \ asmcomp/reload.cmx asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/printmach.cmx \ asmcomp/printlinear.cmx asmcomp/printcmm.cmx asmcomp/printclambda.cmx \ typing/primitive.cmx utils/misc.cmx asmcomp/mach.cmx parsing/location.cmx \ - asmcomp/liveness.cmx middle_end/base_types/linkage_name.cmx \ - asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/interf.cmx \ + asmcomp/liveness.cmx asmcomp/linscan.cmx \ + middle_end/base_types/linkage_name.cmx asmcomp/linearize.cmx \ + bytecomp/lambda.cmx asmcomp/interval.cmx asmcomp/interf.cmx \ typing/ident.cmx asmcomp/flambda_to_clambda.cmx middle_end/flambda.cmx \ asmcomp/emitaux.cmx asmcomp/emit.cmx asmcomp/deadcode.cmx \ utils/config.cmx asmcomp/compilenv.cmx asmcomp/comballoc.cmx \ @@ -821,14 +828,16 @@ asmcomp/clambda.cmx : bytecomp/lambda.cmx typing/ident.cmx \ asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \ middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/closure.cmo : utils/warnings.cmi utils/tbl.cmi bytecomp/switch.cmi \ - bytecomp/simplif.cmi typing/primitive.cmi utils/misc.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ + bytecomp/simplif.cmi bytecomp/semantics_of_primitives.cmi \ + typing/primitive.cmi utils/misc.cmi parsing/location.cmi \ + bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ middle_end/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ utils/clflags.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \ asmcomp/arch.cmo asmcomp/closure.cmi asmcomp/closure.cmx : utils/warnings.cmx utils/tbl.cmx bytecomp/switch.cmx \ - bytecomp/simplif.cmx typing/primitive.cmx utils/misc.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ + bytecomp/simplif.cmx bytecomp/semantics_of_primitives.cmx \ + typing/primitive.cmx utils/misc.cmx parsing/location.cmx \ + bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ middle_end/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ utils/clflags.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \ asmcomp/arch.cmx asmcomp/closure.cmi @@ -846,11 +855,13 @@ asmcomp/closure_offsets.cmx : middle_end/base_types/variable.cmx \ asmcomp/closure_offsets.cmi : middle_end/base_types/var_within_closure.cmi \ middle_end/flambda.cmi middle_end/base_types/closure_id.cmi asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/arch.cmo asmcomp/cmm.cmi + middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ + asmcomp/cmm.cmi asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/arch.cmx asmcomp/cmm.cmi + middle_end/debuginfo.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ + asmcomp/cmm.cmi asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi + middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/cmmgen.cmo : asmcomp/un_anf.cmi typing/types.cmi bytecomp/switch.cmi \ asmcomp/strmatch.cmi asmcomp/proc.cmi bytecomp/printlambda.cmi \ typing/primitive.cmi utils/misc.cmi bytecomp/lambda.cmi typing/ident.cmi \ @@ -882,16 +893,16 @@ asmcomp/compilenv.cmo : utils/warnings.cmi middle_end/base_types/symbol.cmi \ typing/ident.cmi middle_end/flambda.cmi asmcomp/export_info.cmi \ typing/env.cmi utils/config.cmi \ middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/clambda.cmi \ - asmcomp/compilenv.cmi + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + asmcomp/clambda.cmi asmcomp/compilenv.cmi asmcomp/compilenv.cmx : utils/warnings.cmx middle_end/base_types/symbol.cmx \ middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ parsing/location.cmx middle_end/base_types/linkage_name.cmx \ typing/ident.cmx middle_end/flambda.cmx asmcomp/export_info.cmx \ typing/env.cmx utils/config.cmx \ middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmx asmcomp/clambda.cmx \ - asmcomp/compilenv.cmi + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + asmcomp/clambda.cmx asmcomp/compilenv.cmi asmcomp/compilenv.cmi : utils/timings.cmi middle_end/base_types/symbol.cmi \ middle_end/base_types/set_of_closures_id.cmi \ middle_end/base_types/linkage_name.cmi typing/ident.cmi \ @@ -948,6 +959,7 @@ asmcomp/export_info.cmi : middle_end/base_types/variable.cmi \ asmcomp/export_info_for_pack.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/symbol.cmi \ + middle_end/base_types/set_of_closures_origin.cmi \ middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ middle_end/flambda.cmi asmcomp/export_info.cmi \ @@ -957,6 +969,7 @@ asmcomp/export_info_for_pack.cmo : middle_end/base_types/variable.cmi \ asmcomp/export_info_for_pack.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/symbol.cmx \ + middle_end/base_types/set_of_closures_origin.cmx \ middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ middle_end/flambda.cmx asmcomp/export_info.cmx \ @@ -1014,6 +1027,11 @@ asmcomp/interf.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ asmcomp/cmm.cmx asmcomp/interf.cmi asmcomp/interf.cmi : asmcomp/mach.cmi +asmcomp/interval.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ + asmcomp/interval.cmi +asmcomp/interval.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ + asmcomp/interval.cmi +asmcomp/interval.cmi : asmcomp/reg.cmi asmcomp/mach.cmi asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ asmcomp/mach.cmi middle_end/debuginfo.cmi utils/config.cmi \ asmcomp/cmm.cmi asmcomp/linearize.cmi @@ -1022,6 +1040,11 @@ asmcomp/linearize.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ asmcomp/cmm.cmx asmcomp/linearize.cmi asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi \ middle_end/debuginfo.cmi asmcomp/cmm.cmi +asmcomp/linscan.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/interval.cmi \ + asmcomp/linscan.cmi +asmcomp/linscan.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/interval.cmx \ + asmcomp/linscan.cmi +asmcomp/linscan.cmi : asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi utils/config.cmi \ asmcomp/cmm.cmi asmcomp/liveness.cmi @@ -1043,9 +1066,11 @@ asmcomp/printclambda.cmx : bytecomp/printlambda.cmx bytecomp/lambda.cmx \ asmcomp/printclambda.cmi asmcomp/printclambda.cmi : asmcomp/clambda.cmi asmcomp/printcmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi + middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \ + asmcomp/printcmm.cmi asmcomp/printcmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi + middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \ + asmcomp/printcmm.cmi asmcomp/printcmm.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printlinear.cmo : asmcomp/printmach.cmi asmcomp/printcmm.cmi \ asmcomp/mach.cmi asmcomp/linearize.cmi middle_end/debuginfo.cmi \ @@ -1055,11 +1080,13 @@ asmcomp/printlinear.cmx : asmcomp/printmach.cmx asmcomp/printcmm.cmx \ asmcomp/printlinear.cmi asmcomp/printlinear.cmi : asmcomp/linearize.cmi asmcomp/printmach.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ - asmcomp/printcmm.cmi asmcomp/mach.cmi middle_end/debuginfo.cmi \ - utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/printmach.cmi + asmcomp/printcmm.cmi asmcomp/mach.cmi asmcomp/interval.cmi \ + middle_end/debuginfo.cmi utils/config.cmi asmcomp/cmm.cmi \ + asmcomp/arch.cmo asmcomp/printmach.cmi asmcomp/printmach.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \ - asmcomp/printcmm.cmx asmcomp/mach.cmx middle_end/debuginfo.cmx \ - utils/config.cmx asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/printmach.cmi + asmcomp/printcmm.cmx asmcomp/mach.cmx asmcomp/interval.cmx \ + middle_end/debuginfo.cmx utils/config.cmx asmcomp/cmm.cmx \ + asmcomp/arch.cmx asmcomp/printmach.cmi asmcomp/printmach.cmi : asmcomp/reg.cmi asmcomp/mach.cmi asmcomp/proc.cmo : asmcomp/x86_proc.cmi asmcomp/reg.cmi utils/misc.cmi \ asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ @@ -1072,9 +1099,9 @@ asmcomp/reg.cmo : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reg.cmi asmcomp/reg.cmx : typing/ident.cmx asmcomp/cmm.cmx asmcomp/reg.cmi asmcomp/reg.cmi : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/reload.cmi + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/reload.cmi asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/reload.cmi + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/reload.cmi asmcomp/reload.cmi : asmcomp/mach.cmi asmcomp/reloadgen.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ asmcomp/reloadgen.cmi @@ -1094,33 +1121,35 @@ asmcomp/scheduling.cmi : asmcomp/linearize.cmi asmcomp/selectgen.cmo : utils/tbl.cmi bytecomp/simplif.cmi asmcomp/reg.cmi \ asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ typing/ident.cmi middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/selectgen.cmi + asmcomp/cmm.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ + asmcomp/selectgen.cmi asmcomp/selectgen.cmx : utils/tbl.cmx bytecomp/simplif.cmx asmcomp/reg.cmx \ asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \ typing/ident.cmx middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/selectgen.cmi + asmcomp/cmm.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ + asmcomp/selectgen.cmi asmcomp/selectgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi typing/ident.cmi \ middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo -asmcomp/selection.cmo : asmcomp/spacetime_profiling.cmi asmcomp/proc.cmi \ - asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/arch.cmo asmcomp/selection.cmi -asmcomp/selection.cmx : asmcomp/spacetime_profiling.cmx asmcomp/proc.cmx \ - asmcomp/mach.cmx utils/config.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/arch.cmx asmcomp/selection.cmi +asmcomp/selection.cmo : asmcomp/spacetime_profiling.cmi \ + asmcomp/selectgen.cmi asmcomp/proc.cmi asmcomp/mach.cmi utils/config.cmi \ + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/selection.cmi +asmcomp/selection.cmx : asmcomp/spacetime_profiling.cmx \ + asmcomp/selectgen.cmx asmcomp/proc.cmx asmcomp/mach.cmx utils/config.cmx \ + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/selection.cmi asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi asmcomp/spacetime_profiling.cmo : asmcomp/selectgen.cmi asmcomp/proc.cmi \ utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi typing/ident.cmi \ middle_end/debuginfo.cmi utils/config.cmi asmcomp/cmm.cmi \ - asmcomp/arch.cmo asmcomp/spacetime_profiling.cmi + parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/spacetime_profiling.cmi asmcomp/spacetime_profiling.cmx : asmcomp/selectgen.cmx asmcomp/proc.cmx \ utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx typing/ident.cmx \ middle_end/debuginfo.cmx utils/config.cmx asmcomp/cmm.cmx \ - asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi + parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi asmcomp/spacetime_profiling.cmi : asmcomp/selectgen.cmi asmcomp/spill.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi asmcomp/cmm.cmi asmcomp/spill.cmi + asmcomp/mach.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/spill.cmi asmcomp/spill.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx asmcomp/cmm.cmx asmcomp/spill.cmi + asmcomp/mach.cmx asmcomp/cmm.cmx utils/clflags.cmx asmcomp/spill.cmi asmcomp/spill.cmi : asmcomp/mach.cmi asmcomp/split.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ asmcomp/split.cmi @@ -1128,11 +1157,11 @@ asmcomp/split.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ asmcomp/split.cmi asmcomp/split.cmi : asmcomp/mach.cmi asmcomp/strmatch.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ - asmcomp/strmatch.cmi + middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \ + asmcomp/arch.cmo asmcomp/strmatch.cmi asmcomp/strmatch.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ - asmcomp/strmatch.cmi + middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \ + asmcomp/arch.cmx asmcomp/strmatch.cmi asmcomp/strmatch.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/un_anf.cmo : bytecomp/semantics_of_primitives.cmi \ asmcomp/printclambda.cmi utils/misc.cmi bytecomp/lambda.cmi \ @@ -1206,12 +1235,12 @@ middle_end/backend_intf.cmi : middle_end/base_types/symbol.cmi \ middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi bytecomp/simplif.cmi \ - bytecomp/printlambda.cmi typing/primitive.cmi typing/predef.cmi \ - utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi parsing/location.cmi \ - middle_end/base_types/linkage_name.cmi middle_end/lift_code.cmi \ - bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi utils/config.cmi \ + bytecomp/printlambda.cmi typing/predef.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + parsing/location.cmi middle_end/base_types/linkage_name.cmi \ + middle_end/lift_code.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + middle_end/debuginfo.cmi utils/config.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_id.cmi \ middle_end/closure_conversion_aux.cmi utils/clflags.cmi \ @@ -1219,12 +1248,12 @@ middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \ middle_end/closure_conversion.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx bytecomp/simplif.cmx \ - bytecomp/printlambda.cmx typing/primitive.cmx typing/predef.cmx \ - utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx parsing/location.cmx \ - middle_end/base_types/linkage_name.cmx middle_end/lift_code.cmx \ - bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/debuginfo.cmx utils/config.cmx \ + bytecomp/printlambda.cmx typing/predef.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + parsing/location.cmx middle_end/base_types/linkage_name.cmx \ + middle_end/lift_code.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + middle_end/debuginfo.cmx utils/config.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_id.cmx \ middle_end/closure_conversion_aux.cmx utils/clflags.cmx \ @@ -1233,15 +1262,15 @@ middle_end/closure_conversion.cmi : bytecomp/lambda.cmi typing/ident.cmi \ middle_end/flambda.cmi middle_end/backend_intf.cmi middle_end/closure_conversion_aux.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ - middle_end/base_types/static_exception.cmi typing/primitive.cmi \ - utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/base_types/static_exception.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ middle_end/closure_conversion_aux.cmi middle_end/closure_conversion_aux.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/symbol.cmx \ - middle_end/base_types/static_exception.cmx typing/primitive.cmx \ - utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/base_types/static_exception.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ middle_end/closure_conversion_aux.cmi middle_end/closure_conversion_aux.cmi : middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ @@ -1733,11 +1762,6 @@ middle_end/remove_unused_program_constructs.cmx : \ middle_end/effect_analysis.cmx \ middle_end/remove_unused_program_constructs.cmi middle_end/remove_unused_program_constructs.cmi : middle_end/flambda.cmi -bytecomp/semantics_of_primitives.cmo : bytecomp/printlambda.cmi \ - utils/misc.cmi bytecomp/lambda.cmi bytecomp/semantics_of_primitives.cmi -bytecomp/semantics_of_primitives.cmx : bytecomp/printlambda.cmx \ - utils/misc.cmx bytecomp/lambda.cmx bytecomp/semantics_of_primitives.cmi -bytecomp/semantics_of_primitives.cmi : bytecomp/lambda.cmi middle_end/share_constants.cmo : middle_end/base_types/symbol.cmi \ middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ middle_end/share_constants.cmi @@ -1748,7 +1772,8 @@ middle_end/share_constants.cmi : middle_end/flambda.cmi middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ + middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ + bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ middle_end/freshening.cmi middle_end/flambda_utils.cmi \ middle_end/flambda.cmi middle_end/base_types/export_id.cmi \ middle_end/effect_analysis.cmi middle_end/base_types/closure_id.cmi \ @@ -1756,7 +1781,8 @@ middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \ middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ + middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ + bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ middle_end/freshening.cmx middle_end/flambda_utils.cmx \ middle_end/flambda.cmx middle_end/base_types/export_id.cmx \ middle_end/effect_analysis.cmx middle_end/base_types/closure_id.cmx \ @@ -1764,7 +1790,8 @@ middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \ middle_end/simple_value_approx.cmi : middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - bytecomp/lambda.cmi middle_end/freshening.cmi middle_end/flambda.cmi \ + middle_end/base_types/set_of_closures_id.cmi bytecomp/lambda.cmi \ + middle_end/freshening.cmi middle_end/flambda.cmi \ middle_end/base_types/export_id.cmi middle_end/base_types/closure_id.cmi middle_end/simplify_boxed_integer_ops.cmo : middle_end/simplify_common.cmi \ middle_end/simplify_boxed_integer_ops_intf.cmi \ diff --git a/Changes b/Changes index 2718117f0..7d2c58eee 100644 --- a/Changes +++ b/Changes @@ -33,6 +33,14 @@ Next version (4.05.0): and "0 mod " in the case when was a non-constant evaluating to zero (Mark Shinwell) +- GPR#375: An alternative Linear Scan register allocator for ocamlopt, + activated with the -linscan command-line flag. This allocator represents + a trade-off between worse generated code performance for higher + compilation speed (especially interesting in some cases graph coloring + is necessarily quadratic). + (Marcell Fischbach and Benedikt Meurer, adapted by Nicolas Ojeda Bar, + review by Nicolas Ojeda Bar and Alain Frisch) + ### Runtime system: - PR#7423, GPR#946: expose new exception-raising functions diff --git a/Makefile b/Makefile index 0b2a398fd..4a7995c27 100644 --- a/Makefile +++ b/Makefile @@ -168,6 +168,7 @@ ASMCOMP=\ asmcomp/un_anf.cmo \ asmcomp/afl_instrument.cmo \ asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \ + asmcomp/interval.cmo \ asmcomp/printmach.cmo asmcomp/selectgen.cmo \ asmcomp/spacetime_profiling.cmo asmcomp/selection.cmo \ asmcomp/comballoc.cmo \ @@ -175,6 +176,7 @@ ASMCOMP=\ asmcomp/liveness.cmo \ asmcomp/spill.cmo asmcomp/split.cmo \ asmcomp/interf.cmo asmcomp/coloring.cmo \ + asmcomp/linscan.cmo \ asmcomp/reloadgen.cmo asmcomp/reload.cmo \ asmcomp/deadcode.cmo \ asmcomp/printlinear.cmo asmcomp/linearize.cmo \ diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml index 020732dd6..1ffa08b16 100644 --- a/asmcomp/asmgen.ml +++ b/asmcomp/asmgen.ml @@ -80,10 +80,18 @@ let rec regalloc ppf round fd = fatal_error(fd.Mach.fun_name ^ ": function too complex, cannot complete register allocation"); dump_if ppf dump_live "Liveness analysis" fd; - Interf.build_graph fd; - if !dump_interf then Printmach.interferences ppf (); - if !dump_prefer then Printmach.preferences ppf (); - Coloring.allocate_registers(); + if !use_linscan then begin + (* Linear Scan *) + Interval.build_intervals fd; + if !dump_interval then Printmach.intervals ppf (); + Linscan.allocate_registers() + end else begin + (* Graph Coloring *) + Interf.build_graph fd; + if !dump_interf then Printmach.interferences ppf (); + if !dump_prefer then Printmach.preferences ppf (); + Coloring.allocate_registers() + end; dump_if ppf dump_regalloc "After register allocation" fd; let (newfd, redo_regalloc) = Reload.fundecl fd in dump_if ppf dump_reload "After insertion of reloading code" newfd; diff --git a/asmcomp/interval.ml b/asmcomp/interval.ml new file mode 100644 index 000000000..db81d7a64 --- /dev/null +++ b/asmcomp/interval.ml @@ -0,0 +1,188 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Marcell Fischbach, University of Siegen *) +(* Benedikt Meurer, University of Siegen *) +(* *) +(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *) +(* Universität Siegen. All rights reserved. This file is distri- *) +(* buted under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* Live intervals for the linear scan register allocator. *) + +open Mach +open Reg + +type range = + { + mutable rbegin: int; + mutable rend: int; + } + +type t = + { + mutable reg: Reg.t; + mutable ibegin: int; + mutable iend: int; + mutable ranges: range list; + } + +type kind = + Result + | Argument + | Live + +let interval_list = ref ([] : t list) +let fixed_interval_list = ref ([] : t list) +let all_intervals() = !interval_list +let all_fixed_intervals() = !fixed_interval_list + +(* Check if two intervals overlap *) + +let overlap i0 i1 = + let rec overlap_ranges rl0 rl1 = + match rl0, rl1 with + r0 :: rl0', r1 :: rl1' -> + if r0.rend >= r1.rbegin && r1.rend >= r0.rbegin then true + else if r0.rend < r1.rend then overlap_ranges rl0' rl1 + else if r0.rend > r1.rend then overlap_ranges rl0 rl1' + else overlap_ranges rl0' rl1' + | _ -> false in + overlap_ranges i0.ranges i1.ranges + +let is_live i pos = + let rec is_live_in_ranges = function + [] -> false + | r :: rl -> if pos < r.rbegin then false + else if pos <= r.rend then true + else is_live_in_ranges rl in + is_live_in_ranges i.ranges + +let remove_expired_ranges i pos = + let rec filter = function + [] -> [] + | r :: rl' as rl -> if pos < r.rend then rl + else filter rl' in + i.ranges <- filter i.ranges + +let update_interval_position intervals pos kind reg = + let i = intervals.(reg.stamp) in + let on = pos lsl 1 in + let off = on + 1 in + let rbegin = (match kind with Result -> off | _ -> on) in + let rend = (match kind with Argument -> on | _ -> off) in + if i.iend = 0 then begin + i.ibegin <- rbegin; + i.reg <- reg; + i.ranges <- [{rbegin = rbegin; rend = rend}] + end else begin + let r = List.hd i.ranges in + let ridx = r.rend asr 1 in + if pos - ridx <= 1 then + r.rend <- rend + else + i.ranges <- {rbegin = rbegin; rend = rend} :: i.ranges + end; + i.iend <- rend + +let update_interval_position_by_array intervals regs pos kind = + Array.iter (update_interval_position intervals pos kind) regs + +let update_interval_position_by_set intervals regs pos kind = + Set.iter (update_interval_position intervals pos kind) regs + +let update_interval_position_by_instr intervals instr pos = + update_interval_position_by_array intervals instr.arg pos Argument; + update_interval_position_by_array intervals instr.res pos Result; + update_interval_position_by_set intervals instr.live pos Live + +let insert_destroyed_at_oper intervals instr pos = + let destroyed = Proc.destroyed_at_oper instr.desc in + if Array.length destroyed > 0 then + update_interval_position_by_array intervals destroyed pos Result + +let insert_destroyed_at_raise intervals pos = + let destroyed = Proc.destroyed_at_raise in + if Array.length destroyed > 0 then + update_interval_position_by_array intervals destroyed pos Result + +(* Build all intervals. + The intervals will be expanded by one step at the start and end + of a basic block. *) + +let build_intervals fd = + let intervals = Array.init + (Reg.num_registers()) + (fun _ -> { + reg = Reg.dummy; + ibegin = 0; + iend = 0; + ranges = []; }) in + let pos = ref 0 in + let rec walk_instruction i = + incr pos; + update_interval_position_by_instr intervals i !pos; + begin match i.desc with + Iend -> () + | Iop(Icall_ind _ | Icall_imm _ | Iextcall{alloc = true; _} + | Itailcall_ind _ | Itailcall_imm _) -> + walk_instruction i.next + | Iop _ -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction i.next + | Ireturn -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction i.next + | Iifthenelse(_, ifso, ifnot) -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction ifso; + walk_instruction ifnot; + walk_instruction i.next + | Iswitch(_, cases) -> + insert_destroyed_at_oper intervals i !pos; + Array.iter walk_instruction cases; + walk_instruction i.next + | Iloop body -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction body; + walk_instruction i.next + | Icatch(_, body, handler) -> + insert_destroyed_at_oper intervals i !pos; + List.iter (fun (_, i) -> walk_instruction i) body; + walk_instruction handler; + walk_instruction i.next + | Iexit _ -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction i.next + | Itrywith(body, handler) -> + insert_destroyed_at_oper intervals i !pos; + walk_instruction body; + insert_destroyed_at_raise intervals !pos; + walk_instruction handler; + walk_instruction i.next + | Iraise _ -> + walk_instruction i.next + end in + walk_instruction fd.fun_body; + (* Generate the interval and fixed interval lists *) + interval_list := []; + fixed_interval_list := []; + Array.iter + (fun i -> + if i.iend != 0 then begin + i.ranges <- List.rev i.ranges; + begin match i.reg.loc with + Reg _ -> + fixed_interval_list := i :: !fixed_interval_list + | _ -> + interval_list := i :: !interval_list + end + end) + intervals; + (* Sort the intervals according to their start position *) + interval_list := List.sort (fun i0 i1 -> i0.ibegin - i1.ibegin) !interval_list diff --git a/asmcomp/interval.mli b/asmcomp/interval.mli new file mode 100644 index 000000000..af4538d0d --- /dev/null +++ b/asmcomp/interval.mli @@ -0,0 +1,37 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Marcell Fischbach, University of Siegen *) +(* Benedikt Meurer, University of Siegen *) +(* *) +(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *) +(* Universität Siegen. All rights reserved. This file is distri- *) +(* buted under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* Live intervals for the linear scan register allocator. *) + +type range = + { + mutable rbegin: int; + mutable rend: int; + } + +type t = + { + mutable reg: Reg.t; + mutable ibegin: int; + mutable iend: int; + mutable ranges: range list; + } + +val all_intervals: unit -> t list +val all_fixed_intervals: unit -> t list +val overlap: t -> t -> bool +val is_live: t -> int -> bool +val remove_expired_ranges: t -> int -> unit +val build_intervals: Mach.fundecl -> unit diff --git a/asmcomp/linscan.ml b/asmcomp/linscan.ml new file mode 100644 index 000000000..6de3be4aa --- /dev/null +++ b/asmcomp/linscan.ml @@ -0,0 +1,190 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Marcell Fischbach, University of Siegen *) +(* Benedikt Meurer, University of Siegen *) +(* *) +(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *) +(* Universität Siegen. All rights reserved. This file is distri- *) +(* buted under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* Linear scan register allocation. *) + +open Interval +open Reg + +(* Live intervals per register class *) + +type class_intervals = + { + mutable ci_fixed: Interval.t list; + mutable ci_active: Interval.t list; + mutable ci_inactive: Interval.t list; + } + +let active = Array.init Proc.num_register_classes (fun _ -> { + ci_fixed = []; + ci_active = []; + ci_inactive = [] +}) + +(* Insert interval into list sorted by end position *) + +let rec insert_interval_sorted i = function + [] -> [i] + | j :: _ as il when j.iend <= i.iend -> i :: il + | j :: il -> j :: insert_interval_sorted i il + +let rec release_expired_fixed pos = function + i :: il when i.iend >= pos -> + Interval.remove_expired_ranges i pos; + i :: release_expired_fixed pos il + | _ -> [] + +let rec release_expired_active ci pos = function + i :: il when i.iend >= pos -> + Interval.remove_expired_ranges i pos; + if Interval.is_live i pos then + i :: release_expired_active ci pos il + else begin + ci.ci_inactive <- insert_interval_sorted i ci.ci_inactive; + release_expired_active ci pos il + end + | _ -> [] + +let rec release_expired_inactive ci pos = function + i :: il when i.iend >= pos -> + Interval.remove_expired_ranges i pos; + if not (Interval.is_live i pos) then + i :: release_expired_inactive ci pos il + else begin + ci.ci_active <- insert_interval_sorted i ci.ci_active; + release_expired_inactive ci pos il + end + | _ -> [] + +(* Allocate a new stack slot to the interval. *) + +let allocate_stack_slot i = + let cl = Proc.register_class i.reg in + let ss = Proc.num_stack_slots.(cl) in + Proc.num_stack_slots.(cl) <- succ ss; + i.reg.loc <- Stack(Local ss); + i.reg.spill <- true + +(* Find a register for the given interval and assigns this register. + The interval is added to active. Raises Not_found if no free registers + left. *) + +let allocate_free_register i = + begin match i.reg.loc, i.reg.spill with + Unknown, true -> + (* Allocate a stack slot for the already spilled interval *) + allocate_stack_slot i + | Unknown, _ -> + (* We need to allocate a register to this interval somehow *) + let cl = Proc.register_class i.reg in + begin match Proc.num_available_registers.(cl) with + 0 -> + (* There are no registers available for this class *) + raise Not_found + | rn -> + let ci = active.(cl) in + let r0 = Proc.first_available_register.(cl) in + (* Create register mask for this class *) + let regmask = Array.make rn true in + (* Remove all assigned registers from the register mask *) + List.iter + (function + {reg = {loc = Reg r}} -> regmask.(r - r0) <- false + | _ -> ()) + ci.ci_active; + (* Remove all overlapping registers from the register mask *) + let remove_bound_overlapping = function + {reg = {loc = Reg r}} as j -> + if regmask.(r - r0) && Interval.overlap j i then + regmask.(r - r0) <- false + | _ -> () in + List.iter remove_bound_overlapping ci.ci_inactive; + List.iter remove_bound_overlapping ci.ci_fixed; + (* Assign the first free register (if any) *) + let rec assign r = + if r = rn then + raise Not_found + else if regmask.(r) then begin + (* Assign the free register and insert the + current interval into the active list *) + i.reg.loc <- Reg (r0 + r); + i.reg.spill <- false; + ci.ci_active <- insert_interval_sorted i ci.ci_active + end else + assign (succ r) in + assign 0 + end + | _ -> () + end + +let allocate_blocked_register i = + let cl = Proc.register_class i.reg in + let ci = active.(cl) in + begin match ci.ci_active with + ilast :: il when ilast.iend > i.iend -> + (* Last interval in active is the last interval, so spill it. *) + begin match ilast.reg.loc with + Reg _ as loc -> + (* Use register from last interval for current interval *) + i.reg.loc <- loc + | _ -> () + end; + (* Remove the last interval from active and insert the current *) + ci.ci_active <- insert_interval_sorted i il; + (* Now get a new stack slot for the spilled register *) + allocate_stack_slot ilast + | _ -> + (* Either the current interval is last and we have to spill it, + or there are no registers at all in the register class (i.e. + floating point class on i386). *) + allocate_stack_slot i + end + +let walk_interval i = + let pos = i.ibegin land (lnot 0x01) in + (* Release all intervals that have been expired at the current position *) + Array.iter + (fun ci -> + ci.ci_fixed <- release_expired_fixed pos ci.ci_fixed; + ci.ci_active <- release_expired_active ci pos ci.ci_active; + ci.ci_inactive <- release_expired_inactive ci pos ci.ci_inactive) + active; + try + (* Allocate free register (if any) *) + allocate_free_register i + with + Not_found -> + (* No free register, need to decide which interval to spill *) + allocate_blocked_register i + +let allocate_registers() = + (* Initialize the stack slots and interval lists *) + for cl = 0 to Proc.num_register_classes - 1 do + (* Start with empty interval lists *) + active.(cl) <- { + ci_fixed = []; + ci_active = []; + ci_inactive = [] + }; + Proc.num_stack_slots.(cl) <- 0 + done; + (* Add all fixed intervals (sorted by end position) *) + List.iter + (fun i -> + let ci = active.(Proc.register_class i.reg) in + ci.ci_fixed <- insert_interval_sorted i ci.ci_fixed) + (Interval.all_fixed_intervals()); + (* Walk all the intervals within the list *) + List.iter walk_interval (Interval.all_intervals()) diff --git a/asmcomp/linscan.mli b/asmcomp/linscan.mli new file mode 100644 index 000000000..4cee154c0 --- /dev/null +++ b/asmcomp/linscan.mli @@ -0,0 +1,18 @@ +(***********************************************************************) +(* *) +(* Objective Caml *) +(* *) +(* Marcell Fischbach, University of Siegen *) +(* Benedikt Meurer, University of Siegen *) +(* *) +(* Copyright 2011 Lehrstuhl für Compilerbau und Softwareanalyse, *) +(* Universität Siegen. All rights reserved. This file is distri- *) +(* buted under the terms of the Q Public License version 1.0. *) +(* *) +(***********************************************************************) + +(* $Id$ *) + +(* Linear scan register allocation. *) + +val allocate_registers: unit -> unit diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml index f45dbb8fc..343ab54f2 100644 --- a/asmcomp/printmach.ml +++ b/asmcomp/printmach.ml @@ -19,6 +19,7 @@ open Format open Cmm open Reg open Mach +open Interval let reg ppf r = if not (Reg.anonymous r) then @@ -242,6 +243,18 @@ let interferences ppf () = fprintf ppf "*** Interferences@."; List.iter (interference ppf) (Reg.all_registers()) +let interval ppf i = + let interv ppf = + List.iter + (fun r -> fprintf ppf "@ [%d;%d]" r.rbegin r.rend) + i.ranges in + fprintf ppf "@[<2>%a:%t@]@." reg i.reg interv + +let intervals ppf () = + fprintf ppf "*** Intervals@."; + List.iter (interval ppf) (Interval.all_fixed_intervals()); + List.iter (interval ppf) (Interval.all_intervals()) + let preference ppf r = let prefs ppf = List.iter diff --git a/asmcomp/printmach.mli b/asmcomp/printmach.mli index fb7411a6a..13a794647 100644 --- a/asmcomp/printmach.mli +++ b/asmcomp/printmach.mli @@ -27,6 +27,7 @@ val instr: formatter -> Mach.instruction -> unit val fundecl: formatter -> Mach.fundecl -> unit val phase: string -> formatter -> Mach.fundecl -> unit val interferences: formatter -> unit -> unit +val intervals: formatter -> unit -> unit val preferences: formatter -> unit -> unit val print_live: bool ref diff --git a/asmcomp/spill.ml b/asmcomp/spill.ml index cefef95e4..1df2ef35a 100644 --- a/asmcomp/spill.ml +++ b/asmcomp/spill.ml @@ -151,8 +151,9 @@ let rec reload i before = | Iop op -> let new_before = (* Quick check to see if the register pressure is below the maximum *) - if Reg.Set.cardinal i.live + Array.length i.res <= - Proc.safe_register_pressure op + if !Clflags.use_linscan || + (Reg.Set.cardinal i.live + Array.length i.res <= + Proc.safe_register_pressure op) then before else add_superpressure_regs op i.live i.res before in let after = diff --git a/driver/main_args.ml b/driver/main_args.ml index bf1fb8ef1..38ce1836c 100644 --- a/driver/main_args.ml +++ b/driver/main_args.ml @@ -248,6 +248,10 @@ let mk_linkall f = "-linkall", Arg.Unit f, " Link all modules, even unused ones" ;; +let mk_linscan f = + "-linscan", Arg.Unit f, " Use the linear scan register allocator" +;; + let mk_make_runtime f = "-make-runtime", Arg.Unit f, " Build a runtime system with given C objects and libraries" @@ -697,6 +701,10 @@ let mk_dlinear f = "-dlinear", Arg.Unit f, " (undocumented)" ;; +let mk_dinterval f = + "-dinterval", Arg.Unit f, " (undocumented)" +;; + let mk_dstartup f = "-dstartup", Arg.Unit f, " (undocumented)" ;; @@ -931,6 +939,7 @@ module type Optcomp_options = sig include Common_options include Compiler_options include Optcommon_options + val _linscan : unit -> unit val _no_float_const_prop : unit -> unit val _nodynlink : unit -> unit val _p : unit -> unit @@ -939,6 +948,7 @@ module type Optcomp_options = sig val _shared : unit -> unit val _afl_instrument : unit -> unit val _afl_inst_ratio : int -> unit + val _dinterval : unit -> unit end;; module type Opttop_options = sig @@ -1167,6 +1177,7 @@ struct mk_inline_max_depth F._inline_max_depth; mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_linscan F._linscan; mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_no_float_const_prop F._no_float_const_prop; @@ -1249,6 +1260,7 @@ struct mk_dreload F._dreload; mk_dscheduling F._dscheduling; mk_dlinear F._dlinear; + mk_dinterval F._dinterval; mk_dstartup F._dstartup; mk_dtimings F._dtimings; mk_dump_pass F._dump_pass; diff --git a/driver/main_args.mli b/driver/main_args.mli index dfe90c000..046275dfa 100644 --- a/driver/main_args.mli +++ b/driver/main_args.mli @@ -196,6 +196,7 @@ module type Optcomp_options = sig include Common_options include Compiler_options include Optcommon_options + val _linscan : unit -> unit val _no_float_const_prop : unit -> unit val _nodynlink : unit -> unit val _p : unit -> unit @@ -204,6 +205,7 @@ module type Optcomp_options = sig val _shared : unit -> unit val _afl_instrument : unit -> unit val _afl_inst_ratio : int -> unit + val _dinterval : unit -> unit end;; module type Opttop_options = sig diff --git a/driver/optmain.ml b/driver/optmain.ml index be262f802..22092eb73 100644 --- a/driver/optmain.ml +++ b/driver/optmain.ml @@ -120,6 +120,7 @@ module Options = Main_args.Make_optcomp_options (struct inline_max_depth let _alias_deps = clear transparent_modules let _no_alias_deps = set transparent_modules + let _linscan = set use_linscan let _app_funct = set applicative_functors let _no_app_funct = clear applicative_functors let _no_float_const_prop = clear float_const_prop @@ -221,6 +222,7 @@ module Options = Main_args.Make_optcomp_options (struct let _dreload = set dump_reload let _dscheduling = set dump_scheduling let _dlinear = set dump_linear + let _dinterval = set dump_interval let _dstartup = set keep_startup_file let _dtimings = set print_timings let _opaque = set opaque diff --git a/otherlibs/raw_spacetime_lib/Makefile b/otherlibs/raw_spacetime_lib/Makefile index 7e4bf2c7c..7228b765e 100644 --- a/otherlibs/raw_spacetime_lib/Makefile +++ b/otherlibs/raw_spacetime_lib/Makefile @@ -78,6 +78,6 @@ clean:: partialclean $(CAMLOPT) -c $(COMPFLAGS) $< depend: - $(CAMLRUN) $(ROOTDIR)/tools/ocamldep *.mli *.ml >> .depend + $(CAMLRUN) $(ROOTDIR)/tools/ocamldep *.mli *.ml > .depend include .depend diff --git a/tools/ocamloptp.ml b/tools/ocamloptp.ml index 33147ea74..895031931 100644 --- a/tools/ocamloptp.ml +++ b/tools/ocamloptp.ml @@ -144,6 +144,7 @@ module Options = Main_args.Make_optcomp_options (struct let _color s = option_with_arg "-color" s let _where = option "-where" + let _linscan = option "-linscan" let _nopervasives = option "-nopervasives" let _dsource = option "-dsource" let _dparsetree = option "-dparsetree" @@ -171,6 +172,7 @@ module Options = Main_args.Make_optcomp_options (struct let _dscheduling = option "-dscheduling" let _dlinear = option "-dlinear" let _dstartup = option "-dstartup" + let _dinterval = option "-dinterval" let _dtimings = option "-dtimings" let _opaque = option "-opaque" diff --git a/toplevel/opttopmain.ml b/toplevel/opttopmain.ml index 96d22185d..f3fd291c8 100644 --- a/toplevel/opttopmain.ml +++ b/toplevel/opttopmain.ml @@ -178,6 +178,7 @@ module Options = Main_args.Make_opttop_options (struct let _labels = clear classic let _alias_deps = clear transparent_modules let _no_alias_deps = set transparent_modules + let _dlinscan = set use_linscan let _app_funct = set applicative_functors let _no_app_funct = clear applicative_functors let _noassert = set noassert @@ -229,6 +230,7 @@ module Options = Main_args.Make_opttop_options (struct let _dreload = set dump_reload let _dscheduling = set dump_scheduling let _dlinear = set dump_linear + let _dinterval = set dump_interval let _dstartup = set keep_startup_file let _safe_string = clear unsafe_string let _unsafe_string = set unsafe_string diff --git a/utils/clflags.ml b/utils/clflags.ml index 0d185b07b..c12268e4d 100644 --- a/utils/clflags.ml +++ b/utils/clflags.ml @@ -50,6 +50,7 @@ and print_types = ref false (* -i *) and make_archive = ref false (* -a *) and debug = ref false (* -g *) and fast = ref false (* -unsafe *) +and use_linscan = ref false (* -linscan *) and link_everything = ref false (* -linkall *) and custom_runtime = ref false (* -custom *) and no_check_prims = ref false (* -no-check-prims *) @@ -120,6 +121,7 @@ let dump_regalloc = ref false (* -dalloc *) let dump_reload = ref false (* -dreload *) let dump_scheduling = ref false (* -dscheduling *) let dump_linear = ref false (* -dlinear *) +let dump_interval = ref false (* -dinterval *) let keep_startup_file = ref false (* -dstartup *) let dump_combine = ref false (* -dcombine *) let print_timings = ref false (* -dtimings *) diff --git a/utils/clflags.mli b/utils/clflags.mli index 65353609e..cc230724b 100644 --- a/utils/clflags.mli +++ b/utils/clflags.mli @@ -75,6 +75,7 @@ val print_types : bool ref val make_archive : bool ref val debug : bool ref val fast : bool ref +val use_linscan : bool ref val link_everything : bool ref val custom_runtime : bool ref val no_check_prims : bool ref @@ -141,6 +142,7 @@ val dump_regalloc : bool ref val dump_reload : bool ref val dump_scheduling : bool ref val dump_linear : bool ref +val dump_interval : bool ref val keep_startup_file : bool ref val dump_combine : bool ref val native_code : bool ref