Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: driver/main_args.mli
- ===================================================================
- --- driver/main_args.mli (Revision 2)
- +++ driver/main_args.mli (Revision 27)
- @@ -142,6 +142,8 @@
- val _warn_help : unit -> unit
- val _where : unit -> unit
- + val _linscan : unit -> unit
- +
- val _nopervasives : unit -> unit
- val _dparsetree : unit -> unit
- val _drawlambda : unit -> unit
- @@ -158,6 +160,7 @@
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- + val _dinterval : unit -> unit
- val _dstartup : unit -> unit
- val anonymous : string -> unit
- @@ -185,6 +188,8 @@
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
- + val _linscan : unit -> unit
- +
- val _dparsetree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- @@ -200,6 +205,7 @@
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- + val _dinterval : unit -> unit
- val _dstartup : unit -> unit
- val anonymous : string -> unit
- Index: driver/main_args.ml
- ===================================================================
- --- driver/main_args.ml (Revision 2)
- +++ driver/main_args.ml (Revision 27)
- @@ -298,6 +298,11 @@
- "-use-prims", Arg.String f, "<file> (undocumented)"
- ;;
- +let mk_linscan f =
- + "-linscan", Arg.Unit f, " (undocumented)"
- +;;
- +
- +
- let mk_dparsetree f =
- "-dparsetree", Arg.Unit f, " (undocumented)"
- ;;
- @@ -362,6 +367,11 @@
- "-dlinear", Arg.Unit f, " (undocumented)"
- ;;
- +let mk_dinterval f =
- + "-dinterval", Arg.Unit f, " (undocumented)"
- +;;
- +
- +
- let mk_dstartup f =
- "-dstartup", Arg.Unit f, " (undocumented)"
- ;;
- @@ -499,6 +509,8 @@
- val _warn_help : unit -> unit
- val _where : unit -> unit
- + val _linscan : unit -> unit
- +
- val _nopervasives : unit -> unit
- val _dparsetree : unit -> unit
- val _drawlambda : unit -> unit
- @@ -515,6 +527,7 @@
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- + val _dinterval : unit -> unit
- val _dstartup : unit -> unit
- val anonymous : string -> unit
- @@ -542,6 +555,8 @@
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
- + val _linscan : unit -> unit
- +
- val _dparsetree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- @@ -557,6 +572,7 @@
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- + val _dinterval : unit -> unit
- val _dstartup : unit -> unit
- val anonymous : string -> unit
- @@ -709,6 +725,8 @@
- mk_warn_help F._warn_help;
- mk_where F._where;
- + mk_linscan F._linscan;
- +
- mk_nopervasives F._nopervasives;
- mk_dparsetree F._dparsetree;
- mk_drawlambda F._drawlambda;
- @@ -718,12 +736,14 @@
- mk_dcombine F._dcombine;
- mk_dlive F._dlive;
- mk_dspill F._dspill;
- + mk_dsplit F._dspill;
- mk_dinterf F._dinterf;
- mk_dprefer F._dprefer;
- mk_dalloc F._dalloc;
- mk_dreload F._dreload;
- mk_dscheduling F._dscheduling;
- mk_dlinear F._dlinear;
- + mk_dinterval F._dinterval;
- mk_dstartup F._dstartup;
- mk__ F.anonymous;
- @@ -753,6 +773,8 @@
- mk_warn_error F._warn_error;
- mk_warn_help F._warn_help;
- + mk_linscan F._linscan;
- +
- mk_dparsetree F._dparsetree;
- mk_drawlambda F._drawlambda;
- mk_dcmm F._dcmm;
- @@ -760,12 +782,14 @@
- mk_dcombine F._dcombine;
- mk_dlive F._dlive;
- mk_dspill F._dspill;
- + mk_dsplit F._dspill;
- mk_dinterf F._dinterf;
- mk_dprefer F._dprefer;
- mk_dalloc F._dalloc;
- mk_dreload F._dreload;
- mk_dscheduling F._dscheduling;
- mk_dlinear F._dlinear;
- + mk_dinterval F._dinterval;
- mk_dstartup F._dstartup;
- mk__ F.anonymous;
- Index: driver/optmain.ml
- ===================================================================
- --- driver/optmain.ml (Revision 2)
- +++ driver/optmain.ml (Revision 27)
- @@ -142,6 +142,8 @@
- let _warn_help = Warnings.help_warnings
- let _where () = print_standard_library ()
- + let _linscan = set use_linscan
- +
- let _nopervasives = set nopervasives
- let _dparsetree = set dump_parsetree
- let _drawlambda = set dump_rawlambda
- @@ -158,6 +160,7 @@
- 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 anonymous = anonymous
- Index: asmcomp/interval.mli
- ===================================================================
- --- asmcomp/interval.mli (Revision 0)
- +++ asmcomp/interval.mli (Revision 27)
- @@ -0,0 +1,40 @@
- +(***********************************************************************)
- +(* *)
- +(* Objective Caml *)
- +(* *)
- +(* Marcell Fischbach *)
- +(* *)
- +(* Copyright 2011 University of Siegen. All rights reserved. *)
- +(* This file is distributed under the terms of the *)
- +(* Q Public License version 1.0. *)
- +(* *)
- +(***********************************************************************)
- +
- +
- +
- +open Format
- +
- +
- +type range =
- + {
- + mutable rbegin : int;
- + mutable rend : int;
- + }
- +
- +type interval =
- + {
- + mutable reg : Reg.t;
- + mutable ibegin : int;
- + mutable iend : int;
- + mutable ranges : range list;
- + }
- +
- +
- +val all_intervals : unit -> interval list
- +val all_fixed_intervals: unit -> interval list
- +val debug_intervals: formatter -> Mach.fundecl -> unit
- +val build_intervals: Mach.fundecl -> unit
- +val live_on: interval -> int -> bool
- +val overlapping_ranges: range -> range -> bool
- +val overlapping: interval -> interval -> bool
- +val strip_expired_ranges: range list -> int -> range list
- Index: asmcomp/asmgen.ml
- ===================================================================
- --- asmcomp/asmgen.ml (Revision 2)
- +++ asmcomp/asmgen.ml (Revision 27)
- @@ -20,6 +20,8 @@
- open Misc
- open Cmm
- +external sys_time : unit -> float = "caml_sys_time"
- +
- type error = Assembler_error of string
- exception Error of error
- @@ -38,21 +40,53 @@
- phrase
- let rec regalloc ppf round fd =
- - if round > 50 then
- - 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();
- - 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;
- - if redo_regalloc then begin
- - Reg.reinit(); Liveness.fundecl ppf newfd; regalloc ppf (round + 1) newfd
- - end else newfd
- + if not !use_linscan then begin
- + if round > 50 then
- + 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();
- + dump_if ppf dump_regalloc "After register allocation" fd;
- + let (newfd, redo_regalloc) = Reload.fundecl fd in
- + if redo_regalloc then begin
- + Reg.reinit();
- + Liveness.fundecl ppf newfd;
- + dump_if ppf dump_reload "After insertion of reloading code" newfd;
- + regalloc ppf (round + 1) newfd
- + end
- + else
- + begin
- + dump_if ppf dump_reload "After insertion of reloading code" newfd;
- + newfd
- + end
- + end
- + else
- + fd
- +let rec regalloc_linscan ppf round fd =
- + if !use_linscan then begin
- + if round > 50 then
- + fatal_error(fd.Mach.fun_name ^
- + ": function too complex, cannot complete register allocation");
- +
- + Interval.build_intervals fd;
- + if !dump_interval then Interval.debug_intervals ppf fd;
- + Linscan.walk_intervals (Interval.all_intervals ()) (Interval.all_fixed_intervals()) fd;
- + let (newfd, redo_regalloc) = Reload.fundecl fd in
- + dump_if ppf dump_reload "After insertion of reloading code" newfd;
- + if redo_regalloc then begin
- + Reg.reinit();
- + Liveness.fundecl ppf newfd;
- + regalloc_linscan ppf (round + 1) newfd
- + end else newfd
- + end
- + else
- + fd
- +
- +
- let (++) x f = f x
- let compile_fundecl (ppf : formatter) fd_cmm =
- @@ -70,7 +104,8 @@
- ++ Split.fundecl
- ++ pass_dump_if ppf dump_split "After live range splitting"
- ++ liveness ppf
- - ++ regalloc ppf 1
- + ++ regalloc ppf 1
- + ++ regalloc_linscan ppf 1
- ++ Linearize.fundecl
- ++ pass_dump_linear_if ppf dump_linear "Linearized code"
- ++ Scheduling.fundecl
- Index: asmcomp/interval.ml
- ===================================================================
- --- asmcomp/interval.ml (Revision 0)
- +++ asmcomp/interval.ml (Revision 27)
- @@ -0,0 +1,290 @@
- +(***********************************************************************)
- +(* *)
- +(* Objective Caml *)
- +(* *)
- +(* Marcell Fischbach *)
- +(* *)
- +(* Copyright 2011 University of Siegen. All rights reserved. *)
- +(* This file is distributed under the terms of the *)
- +(* Q Public License version 1.0. *)
- +(* *)
- +(***********************************************************************)
- +
- +
- +
- +open List
- +open Mach
- +open Reg
- +
- +type range =
- + {
- + mutable rbegin : int;
- + mutable rend : int;
- + }
- +
- +type interval =
- + {
- + mutable reg : Reg.t;
- + mutable ibegin : int;
- + mutable iend : int;
- + mutable ranges : range list;
- + }
- +
- +
- +let interval_list = ref ([] : interval list)
- +let fixed_interval_list = ref ([] : interval list)
- +let all_intervals() = !interval_list
- +let all_fixed_intervals() = !fixed_interval_list
- +
- +let overlapping_ranges r0 r1 =
- + r0.rend > r1.rbegin && r1.rend > r0.rbegin
- +
- +
- +let overlapping i0 i1 =
- +
- + let rec test_ranges r0s r1s =
- + begin match r0s, r1s with
- + | [], _ -> false
- + | _, [] -> false
- + | r0::r0tl, r1::r1tl ->
- + if overlapping_ranges r0 r1 then true
- + else if r0.rend < r1.rend then test_ranges r0tl r1s
- + else if r0.rend > r1.rend then test_ranges r0s r1tl
- + else test_ranges r0tl r1tl
- + end
- + in
- +
- + test_ranges i0.ranges i1.ranges
- +
- +let live_on i p =
- + let rec live_on_ranges r =
- + begin match r with
- + | [] -> false
- + | hd::tl ->
- + if p < hd.rbegin then false
- + else if p < hd.rend then true
- + else live_on_ranges tl
- + end in
- + live_on_ranges i.ranges
- +
- +
- +let rec strip_expired_ranges ranges pos =
- + begin match ranges with
- + | [] -> []
- + | hd::tl ->
- + if hd.rend > pos then ranges
- + else strip_expired_ranges tl pos
- + end
- +
- +
- +
- +
- +let debug_intervals ppf fd =
- + Format.fprintf ppf "*** Intervals\n";
- + Format.fprintf ppf "%s\n" fd.fun_name;
- +
- + let dump_interval i =
- + Format.fprintf ppf " ";
- + Printmach.reg ppf i.reg;
- + List.iter (fun r ->
- + Format.fprintf ppf " [%d;%d[ " r.rbegin r.rend
- + ) i.ranges;
- + Format.fprintf ppf "\n"
- + in
- + List.iter dump_interval !fixed_interval_list;
- + List.iter dump_interval !interval_list;
- + ()
- +
- +
- +let get_and_initialize_interval intervals reg pos_tst pos_set use_kind =
- + let interval = intervals.(reg.stamp) in
- + if interval.iend = 0 then begin
- + interval.ibegin <- pos_tst;
- + interval.iend <- pos_set;
- + interval.reg <- reg;
- + interval.ranges <- [{rbegin = pos_tst; rend = pos_set; }]
- + end;
- + interval
- +
- +
- +let update_interval_position intervals pos_tst pos_set use_kind reg =
- + let interval = get_and_initialize_interval intervals reg pos_tst pos_set use_kind in
- + let range = begin match interval.ranges with |[] -> Misc.fatal_error "Illegal empty range" | hd::_ -> hd end in
- +
- + interval.iend <- pos_set;
- +
- + if (range.rend = pos_tst || (range.rend + 1) = pos_tst) && use_kind != 1 then
- + range.rend <- pos_set
- + else if range.rbegin = pos_tst && range.rend = pos_tst && use_kind = 1 then
- + range.rend <- pos_set
- + else
- + interval.ranges <- {rbegin=pos_tst;rend=pos_set;} :: interval.ranges
- +
- +
- +
- +let update_interval_position_by_reg_array intervals regs pos_tst pos_set use_kind =
- + Array.iter (update_interval_position intervals pos_tst pos_set use_kind) regs
- +
- +let update_interval_position_by_reg_set intervals regs pos_tst pos_set use_kind =
- + Set.iter (update_interval_position intervals pos_tst pos_set use_kind) regs
- +
- +let update_interval_position_by_instr intervals instr pos_tst pos_set =
- + update_interval_position_by_reg_array intervals instr.arg pos_tst pos_set 0;
- + update_interval_position_by_reg_array intervals instr.res pos_set pos_set 1;
- + update_interval_position_by_reg_set intervals instr.live pos_tst pos_set 0
- +
- +
- +let insert_pos_for_live intervals instr pos =
- + if (not (Set.is_empty instr.live)) || Array.length instr.arg > 0 then
- + begin
- + pos := succ !pos;
- + update_interval_position_by_reg_set intervals instr.live !pos !pos 0;
- + update_interval_position_by_reg_array intervals instr.arg !pos !pos 0
- + end
- +
- +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_reg_array intervals destroyed pos pos 1
- +
- +let insert_destroyed_at_raise intervals pos =
- + let destroyed = Proc.destroyed_at_raise in
- + if Array.length destroyed > 0 then
- + update_interval_position_by_reg_array intervals destroyed pos pos 1
- +
- +
- +(* generate all intervals.
- + the intervals will be expanded by one step at the beginning and
- + the ending of a basic block
- +*)
- +let build_intervals fundecl =
- +
- + let intervals = Array.init (Reg.num_registers()) (fun i ->
- + { reg = Reg.dummy;
- + ibegin = 0;
- + iend = 0;
- + ranges = [];
- + }) in
- +
- +
- + let rec walk_instruction i pos shift =
- + pos := !pos + 1 + shift;
- + update_interval_position_by_instr intervals i (!pos - shift) !pos;
- +
- +
- + begin match i.desc with
- + | Iend ->
- + (* end ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + | Iop(Icall_ind | Icall_imm _ | Iextcall(_, true) | Itailcall_ind | Itailcall_imm _) ->
- + walk_instruction i.next pos 0
- +
- + | Iop _ ->
- + insert_destroyed_at_oper intervals i !pos;
- + walk_instruction i.next pos 0
- +
- + | Ireturn ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* returns ends a bb *)
- + insert_pos_for_live intervals i pos;
- + walk_instruction i.next pos 0
- +
- +
- + | Iifthenelse(test, ifso, ifnot) ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* if ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + (* ifso starts a new bb *)
- + walk_instruction ifso pos 1;
- +
- + (* ifnot starts a new bb *)
- + walk_instruction ifnot pos 1;
- +
- + (* next starts a new bb *)
- + walk_instruction i.next pos 1
- + | Iswitch(index, cases) ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* switch ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + for j = 0 to Array.length cases -1 do
- + (* each case starts a new bb *)
- + walk_instruction cases.(j) pos 1
- + done;
- + (* next starts a new bb *)
- + walk_instruction i.next pos 1
- + | Iloop body ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* loop ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + (* the body starts a new block *)
- + walk_instruction body pos 1;
- +
- + (* next starts a new bb *)
- + walk_instruction i.next pos 1
- + | Icatch(io, body, handler) ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* catch ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + (* the body starts a new bb *)
- + walk_instruction body pos 1;
- +
- + (* the handler starts a new bb *)
- + walk_instruction handler pos 1;
- +
- + (* next starts a new bb *)
- + walk_instruction i.next pos 1;
- + | Iexit nfail ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* exit ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + | Itrywith(body, handler) ->
- + insert_destroyed_at_oper intervals i !pos;
- + (* trywith ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + (* the body starts a new bb *)
- + walk_instruction body pos 1;
- +
- + (* the handler starts a new bb *)
- + insert_pos_for_live intervals handler pos;
- + insert_destroyed_at_raise intervals !pos;
- + walk_instruction handler pos 0;
- +
- + (* nex starts a new bb *)
- + walk_instruction i.next pos 1
- + | Iraise ->
- + (* raise ends a bb *)
- + insert_pos_for_live intervals i pos;
- +
- + walk_instruction i.next pos 1
- + end
- +
- +
- +
- + in
- +
- + let pos = ref 0 in
- + walk_instruction fundecl.fun_body pos 1;
- +
- +
- + 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 r -> fixed_interval_list := i :: !fixed_interval_list
- + | _ -> interval_list := i :: !interval_list
- + end
- + end) intervals;
- +
- +
- + interval_list := List.sort (fun i0 i1 -> i0.ibegin - i1.ibegin) !interval_list;
- +
- + ()
- Index: asmcomp/linscan.ml
- ===================================================================
- --- asmcomp/linscan.ml (Revision 0)
- +++ asmcomp/linscan.ml (Revision 27)
- @@ -0,0 +1,295 @@
- +(***********************************************************************)
- +(* *)
- +(* Objective Caml *)
- +(* *)
- +(* Marcell Fischbach *)
- +(* *)
- +(* Copyright 2011 University of Siegen. All rights reserved. *)
- +(* This file is distributed under the terms of the *)
- +(* Q Public License version 1.0. *)
- +(* *)
- +(***********************************************************************)
- +
- +
- +open Interval
- +open Clflags
- +open List
- +open Format
- +open Mach
- +
- +
- +type active_t =
- +{
- + mutable active : interval list;
- + mutable inactive : interval list;
- + mutable fixed : interval list;
- +}
- +
- +
- +let active = Array.init Proc.num_register_classes (fun i -> {active = []; inactive = []; fixed= [] })
- +
- +let rec insert_into active current =
- + begin match active with
- + | [] -> [current]
- + | interval::tl ->
- + (* check code for <= or < *)
- + if interval.iend <= current.iend then
- + current :: active
- + else
- + interval :: insert_into tl current
- + end
- +
- +
- +let rec release_expired_fixed pos intervals =
- + begin match intervals with
- + | [] -> []
- + | interval::tl ->
- + if interval.iend > pos then begin
- + interval.ranges <- Interval.strip_expired_ranges interval.ranges pos;
- + interval :: release_expired_fixed pos tl
- + end
- + else
- + []
- + end
- +
- +
- +let rec release_expired_active active_cl pos intervals =
- + begin match intervals with
- + | [] -> []
- + | interval::tl ->
- + if interval.iend > pos then begin
- + interval.ranges <- Interval.strip_expired_ranges interval.ranges pos;
- + if Interval.live_on interval pos then
- + interval :: release_expired_active active_cl pos tl
- + else begin
- + active_cl.inactive <- insert_into active_cl.inactive interval;
- + release_expired_active active_cl pos tl
- + end
- + end
- + else
- + []
- + end
- +
- +let rec release_expired_inactive active_cl pos intervals =
- + begin match intervals with
- + | [] -> []
- + | interval::tl ->
- + if interval.iend > pos then begin
- + interval.ranges <- Interval.strip_expired_ranges interval.ranges pos;
- + if not (Interval.live_on interval pos) then
- + interval :: release_expired_inactive active_cl pos tl
- + else begin
- + active_cl.active <- insert_into active_cl.active interval;
- + release_expired_inactive active_cl pos tl
- + end
- + end
- + else
- + []
- + end
- +
- +
- +
- +
- +let get_stack_slot cl =
- + let nslots = Proc.num_stack_slots.(cl) in
- + Proc.num_stack_slots.(cl) <- nslots + 1;
- + nslots
- +
- +
- +
- +let pop_active active =
- + begin match active with
- + | [] -> []
- + | _::tl -> tl
- + end
- +
- +
- +(* find a register for the given interval and assigns this
- + register. The interval is inserted into active.
- + If there is no space available for this interval then
- + nothings happens and false is returned. Otherwise
- + returns true.
- + *)
- +let try_alloc_free_register interval =
- + let cl = Proc.register_class interval.reg in
- + (* this intervals has already been spilled *)
- + if interval.reg.Reg.spill then begin
- + begin match interval.reg.Reg.loc with
- + | Reg.Unknown -> interval.reg.Reg.loc <- Reg.Stack(Reg.Local (get_stack_slot cl));
- + | _ -> ()
- + end
- + end;
- +
- + let num = Proc.num_available_registers.(cl) in
- + if interval.reg.Reg.loc != Reg.Unknown then true (* this register is already allocated or spilled *)
- + else if num = 0 then false (* there are not registers for this class *)
- + else begin
- + let first_reg = Proc.first_available_register.(cl) in
- + let active_cl = active.(cl) in
- +
- + (* create array containing all possible free regs *)
- + let regs = Array.make num true in
- +
- + (* remove all assigned registers from the free array *)
- + let rec remove_bound actives =
- + begin match actives with
- + | [] -> ()
- + | i::tl ->
- + begin
- + begin match i.reg.Reg.loc with
- + | Reg.Reg(r) -> regs.(r - first_reg) <- false
- + | _ -> ()
- + end;
- + remove_bound tl
- + end
- + end
- + in
- +
- + remove_bound active_cl.active;
- +
- + (* remove all overlapping registers from the free array *)
- + let rec remove_bound_overlapping fix =
- + begin match fix with
- + | [] -> ()
- + | i::tl ->
- + begin
- + begin match i.reg.Reg.loc with
- + | Reg.Reg(r) ->
- + if regs.(r-first_reg) && Interval.overlapping i interval then
- + regs.(r - first_reg) <- false
- + | _ -> ()
- + end;
- + remove_bound_overlapping tl
- + end
- + end
- + in
- + remove_bound_overlapping active_cl.inactive;
- + remove_bound_overlapping active_cl.fixed;
- +
- +
- + let rec find_first_free_reg c =
- + if c = num then -1
- + else if regs.(c) then c
- + else find_first_free_reg (c+1) in
- +
- + let first_free_reg = find_first_free_reg 0 in
- +
- + if first_free_reg = -1 then false
- + else begin
- + (* assign the free register *)
- + interval.reg.Reg.loc <- Reg.Reg (first_reg + first_free_reg);
- + interval.reg.Reg.spill <- false;
- + (* and insert the current interval into active *)
- + active_cl.active <- insert_into active_cl.active interval;
- + true
- + end;
- + end
- +
- +
- +let allocate_blocked_register interval =
- + let cl = Proc.register_class interval.reg in
- + let active_cl = active.(cl) in
- +
- +
- + if active_cl.active = [] then begin
- + (* this is the special case when there are no register at all
- + in the register class. This can happen e.g. for float Regs on i386 *)
- + interval.reg.Reg.loc <- Reg.Stack(Reg.Local (get_stack_slot cl));
- + interval.reg.Reg.spill <- true
- + end
- + else begin
- +
- + (* get the latest interval in active *)
- + let last_active = List.hd active_cl.active in
- +
- + if last_active.iend > interval.iend then begin
- + (* last interval in active ends latest -> spill it*)
- +
- + (* transfer the register from the active in the current interval *)
- + begin match last_active.reg.Reg.loc with
- + | Reg.Reg r -> interval.reg.Reg.loc <- Reg.Reg r
- + | _ -> ()
- + end;
- +
- + (* remove the latest interval from active ... *)
- + active_cl.active <- pop_active active_cl.active;
- + (* ... and insert the current *)
- + active_cl.active <- insert_into active_cl.active interval;
- +
- + (* now get a new stack slot for the spilled register *)
- + last_active.reg.Reg.loc <- Reg.Stack(Reg.Local (get_stack_slot cl));
- + last_active.reg.Reg.spill <- true
- + end
- + else begin
- + (* the current interval ends latest -> spill it *)
- + interval.reg.Reg.loc <- Reg.Stack(Reg.Local (get_stack_slot cl));
- + interval.reg.Reg.spill <- true
- + end;
- + end;
- + ()
- +
- +
- +let handle_interval interval =
- + let position = interval.ibegin in
- +
- + (* release all intervals that have been expired at the current step*)
- + for i = 0 to Proc.num_register_classes - 1 do
- + let active_cl = active.(i) in
- + active_cl.active <- release_expired_active active_cl position active_cl.active;
- + active_cl.inactive <- release_expired_inactive active_cl position active_cl.inactive;
- + active_cl.fixed <- release_expired_fixed position active_cl.fixed;
- + done;
- +
- +
- + (* find a register for allocation *)
- + if not (try_alloc_free_register interval) then
- + (* a valid free register could not be found, so we have to
- + decide which interval is to be spilled *)
- + allocate_blocked_register interval
- +
- +(* create active liste for every register class *)
- +let initialize_interval_lists intervals =
- +
- +
- + for i=0 to Proc.num_register_classes - 1 do
- + let active_cl = active.(i) in
- + (* start with empty actives *)
- + active_cl.active <- [];
- + active_cl.inactive <- [];
- + active_cl.fixed <- [];
- + done;
- +
- + (* add all fixed intervals to the list of active_fixed intervals *)
- + let rec add_fixed_intervals intervals =
- + begin match intervals with
- + | [] -> ()
- + | i :: tl ->
- + let active_cl = active.(Proc.register_class i.reg) in
- + active_cl.fixed <- i :: active_cl.fixed;
- + add_fixed_intervals tl
- + end in
- + add_fixed_intervals intervals;
- +
- + for i = 0 to Proc.num_register_classes - 1 do
- + let active_cl = active.(i) in
- + active_cl.fixed <- List.sort (fun i0 i1 -> i1.iend - i0.iend) active_cl.fixed
- + done
- +
- +
- +
- +
- +
- +let walk_intervals intervals fixed_intervals fd =
- + (* Initialize the stack slots *)
- + for i = 0 to Proc.num_register_classes - 1 do
- + Proc.num_stack_slots.(i) <- 0
- + done;
- +
- +
- + (* create the active lists *)
- + initialize_interval_lists fixed_intervals;
- +
- +
- + (* Walk all the intervals within the list *)
- + List.iter handle_interval intervals
- +
- Index: asmcomp/linscan.mli
- ===================================================================
- --- asmcomp/linscan.mli (Revision 0)
- +++ asmcomp/linscan.mli (Revision 27)
- @@ -0,0 +1,16 @@
- +(***********************************************************************)
- +(* *)
- +(* Objective Caml *)
- +(* *)
- +(* Marcell Fischbach *)
- +(* *)
- +(* Copyright 2011 University of Siegen. All rights reserved. *)
- +(* This file is distributed under the terms of the *)
- +(* Q Public License version 1.0. *)
- +(* *)
- +(***********************************************************************)
- +
- +
- +
- +val walk_intervals: Interval.interval list -> Interval.interval list -> Mach.fundecl -> unit
- +
- Index: Makefile
- ===================================================================
- --- Makefile (Revision 2)
- +++ Makefile (Revision 27)
- @@ -79,6 +79,7 @@
- asmcomp/interf.cmo asmcomp/coloring.cmo \
- asmcomp/reloadgen.cmo asmcomp/reload.cmo \
- asmcomp/printlinear.cmo asmcomp/linearize.cmo \
- + asmcomp/interval.cmo asmcomp/linscan.cmo \
- asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
- asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
- asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo
- Index: toplevel/opttopmain.ml
- ===================================================================
- --- toplevel/opttopmain.ml (Revision 2)
- +++ toplevel/opttopmain.ml (Revision 27)
- @@ -85,6 +85,8 @@
- let _warn_error s = Warnings.parse_options true s
- let _warn_help = Warnings.help_warnings
- + let _linscan = set use_linscan
- +
- let _dparsetree = set dump_parsetree
- let _drawlambda = set dump_rawlambda
- let _dlambda = set dump_lambda
- @@ -100,6 +102,7 @@
- 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 anonymous = file_argument
- Index: Makefile.nt
- ===================================================================
- --- Makefile.nt (Revision 2)
- +++ Makefile.nt (Revision 27)
- @@ -76,6 +76,7 @@
- asmcomp/interf.cmo asmcomp/coloring.cmo \
- asmcomp/reloadgen.cmo asmcomp/reload.cmo \
- asmcomp/printlinear.cmo asmcomp/linearize.cmo \
- + asmcomp/interval.cmo asmcomp/linscan.cmo \
- asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
- asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
- asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo
- Index: utils/clflags.ml
- ===================================================================
- --- utils/clflags.ml (Revision 2)
- +++ utils/clflags.ml (Revision 27)
- @@ -26,6 +26,7 @@
- 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 output_c_object = ref false (* -output-obj *)
- @@ -73,6 +74,7 @@
- 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 *)
- Index: utils/clflags.mli
- ===================================================================
- --- utils/clflags.mli (Revision 2)
- +++ utils/clflags.mli (Revision 27)
- @@ -23,6 +23,7 @@
- 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 output_c_object : bool ref
- @@ -67,6 +68,7 @@
- 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
Add Comment
Please, Sign In to add comment