Skip to content

Commit fa5fb60

Browse files
authored
Remove more fields from Reg.t (#3838)
1 parent afcaa97 commit fa5fb60

12 files changed

+155
-136
lines changed

backend/reg.ml

+6-23
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ type t =
4040
{ mutable raw_name: Raw_name.t;
4141
stamp: int;
4242
typ: Cmm.machtype_component;
43-
mutable loc: location;
44-
mutable spill: bool;
45-
mutable spill_cost: int; }
43+
mutable loc: location; }
4644

4745
and location =
4846
Unknown
@@ -58,19 +56,14 @@ and stack_location =
5856
type reg = t
5957

6058
let dummy =
61-
{ raw_name = Raw_name.Anon; stamp = 0; typ = Int; loc = Unknown;
62-
spill = false; spill_cost = 0;
63-
}
59+
{ raw_name = Raw_name.Anon; stamp = 0; typ = Int; loc = Unknown; }
6460

6561
let currstamp = ref 0
6662
let reg_list = ref([] : t list)
6763
let hw_reg_list = ref ([] : t list)
6864

6965
let create ty =
70-
let r = { raw_name = Raw_name.Anon; stamp = !currstamp; typ = ty;
71-
loc = Unknown;
72-
spill = false;
73-
spill_cost = 0; } in
66+
let r = { raw_name = Raw_name.Anon; stamp = !currstamp; typ = ty; loc = Unknown; } in
7467
reg_list := r :: !reg_list;
7568
incr currstamp;
7669
r
@@ -93,9 +86,7 @@ let clone r =
9386
nr
9487

9588
let at_location ty loc =
96-
let r = { raw_name = Raw_name.R; stamp = !currstamp; typ = ty; loc;
97-
spill = false;
98-
spill_cost = 0; } in
89+
let r = { raw_name = Raw_name.R; stamp = !currstamp; typ = ty; loc; } in
9990
hw_reg_list := r :: !hw_reg_list;
10091
incr currstamp;
10192
r
@@ -121,11 +112,7 @@ let is_unknown t =
121112
let name t =
122113
match Raw_name.to_string t.raw_name with
123114
| None -> ""
124-
| Some raw_name ->
125-
if t.spill then
126-
"spilled-" ^ raw_name
127-
else
128-
raw_name
115+
| Some raw_name -> raw_name
129116

130117
let first_virtual_reg_stamp = ref (-1)
131118

@@ -155,11 +142,7 @@ let all_registers() = !reg_list
155142
let num_registers() = !currstamp
156143

157144
let reinit_reg r =
158-
r.loc <- Unknown;
159-
(* Preserve the very high spill costs introduced by the reloading pass *)
160-
if r.spill_cost >= 100000
161-
then r.spill_cost <- 100000
162-
else r.spill_cost <- 0
145+
r.loc <- Unknown
163146

164147
let reinit() =
165148
List.iter reinit_reg !reg_list

backend/reg.mli

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ type t =
2525
{ mutable raw_name: Raw_name.t; (* Name *)
2626
stamp: int; (* Unique stamp *)
2727
typ: Cmm.machtype_component; (* Type of contents *)
28-
mutable loc: location; (* Actual location *)
29-
mutable spill: bool; (* "true" to force stack allocation *)
30-
mutable spill_cost: int; } (* Estimate of spilling cost *)
28+
mutable loc: location; } (* Actual location *)
3129

3230
and location =
3331
Unknown

backend/regalloc/regalloc_gi.ml

+5-8
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,15 @@ let rec main : round:int -> flat:bool -> State.t -> Cfg_with_infos.t -> unit =
134134
log "main, round #%d" round;
135135
log_cfg_with_infos cfg_with_infos);
136136
if debug then log "updating spilling costs";
137-
update_spill_cost cfg_with_infos ~flat ();
137+
let costs = SpillCosts.compute cfg_with_infos ~flat () in
138138
State.iter_introduced_temporaries state ~f:(fun (reg : Reg.t) ->
139-
reg.Reg.spill_cost <- reg.Reg.spill_cost + 10_000);
139+
SpillCosts.add_to_reg costs reg 10_000);
140140
if debug
141141
then (
142142
log "spilling costs";
143143
indent ();
144-
List.iter (Reg.all_registers ()) ~f:(fun (reg : Reg.t) ->
145-
reg.Reg.spill <- false;
146-
log "%a: %d" Printreg.reg reg reg.spill_cost);
144+
SpillCosts.iter costs ~f:(fun (reg : Reg.t) (cost : int) ->
145+
log "%a: %d" Printreg.reg reg cost);
147146
dedent ());
148147
let hardware_registers, prio_queue =
149148
make_hardware_registers_and_prio_queue cfg_with_infos
@@ -162,7 +161,7 @@ let rec main : round:int -> flat:bool -> State.t -> Cfg_with_infos.t -> unit =
162161
indent ();
163162
log "got register %a (prio=%d)" Printreg.reg reg priority);
164163
(match
165-
Hardware_registers.find_available hardware_registers reg interval
164+
Hardware_registers.find_available hardware_registers costs reg interval
166165
with
167166
| For_assignment { hardware_reg } ->
168167
if debug
@@ -211,7 +210,6 @@ let rec main : round:int -> flat:bool -> State.t -> Cfg_with_infos.t -> unit =
211210
| Split_or_spill ->
212211
(* CR xclerc for xclerc: we should actually try to split. *)
213212
if debug then log "spilling %a" Printreg.reg reg;
214-
reg.Reg.spill <- true;
215213
spilling := (reg, interval) :: !spilling);
216214
if debug then dedent ()
217215
done;
@@ -280,7 +278,6 @@ let run : Cfg_with_infos.t -> Cfg_with_infos.t =
280278
(match Reg.Set.elements spilling_because_unused with
281279
| [] -> ()
282280
| _ :: _ as spilled_nodes ->
283-
List.iter spilled_nodes ~f:(fun reg -> reg.Reg.spill <- true);
284281
(* note: rewrite will remove the `spilling` registers from the "spilled"
285282
work list and set the field to unknown. *)
286283
let (_ : bool) = rewrite state cfg_with_infos ~spilled_nodes in

backend/regalloc/regalloc_gi_utils.ml

+10-8
Original file line numberDiff line numberDiff line change
@@ -620,11 +620,11 @@ module Hardware_registers = struct
620620
fun t ~of_reg ~f ~init ->
621621
Array.fold_left t.(Proc.register_class of_reg) ~f ~init
622622

623-
let actual_cost (reg : Reg.t) : int =
623+
let actual_cost (costs : SpillCosts.t) (reg : Reg.t) : int =
624624
(* CR xclerc for xclerc: it could make sense to give a lower cost to reg
625625
already spilled (e.g. by the split preprocessing) since they already have
626626
a stack slot *)
627-
reg.Reg.spill_cost
627+
SpillCosts.for_reg costs reg
628628

629629
let overlap (hardware_reg : Hardware_register.t) (interval : Interval.t) :
630630
bool =
@@ -668,7 +668,8 @@ module Hardware_registers = struct
668668
else acc)
669669
|> Option.map fst
670670

671-
let find_evictable (t : t) (reg : Reg.t) (interval : Interval.t) : available =
671+
let find_evictable (t : t) (costs : SpillCosts.t) (reg : Reg.t)
672+
(interval : Interval.t) : available =
672673
let eviction =
673674
fold_class t ~of_reg:reg ~init:None ~f:(fun acc hardware_reg ->
674675
if debug
@@ -705,7 +706,8 @@ module Hardware_registers = struct
705706
(acc_cost, acc_evictable)
706707
{ Hardware_register.pseudo_reg; interval = _; evictable }
707708
->
708-
acc_cost + actual_cost pseudo_reg, acc_evictable && evictable)
709+
( acc_cost + actual_cost costs pseudo_reg,
710+
acc_evictable && evictable ))
709711
in
710712
if debug then dedent ();
711713
if not evictable
@@ -714,7 +716,7 @@ module Hardware_registers = struct
714716
let evict_cost =
715717
match acc with None -> max_int | Some (_, _, c) -> c
716718
in
717-
if cost < evict_cost && cost < actual_cost reg
719+
if cost < evict_cost && cost < actual_cost costs reg
718720
then (
719721
if debug
720722
then
@@ -729,8 +731,8 @@ module Hardware_registers = struct
729731
For_eviction { hardware_reg; evicted_regs }
730732
| None -> Split_or_spill
731733

732-
let find_available : t -> Reg.t -> Interval.t -> available =
733-
fun t reg interval ->
734+
let find_available : t -> SpillCosts.t -> Reg.t -> Interval.t -> available =
735+
fun t costs reg interval ->
734736
let with_no_overlap =
735737
let heuristic =
736738
match Lazy.force Selection_heuristics.value with
@@ -756,5 +758,5 @@ module Hardware_registers = struct
756758
| Some hardware_reg -> For_assignment { hardware_reg }
757759
| None ->
758760
if debug then log "trying to find an evictable register";
759-
find_evictable t reg interval
761+
find_evictable t costs reg interval
760762
end

backend/regalloc/regalloc_gi_utils.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,5 @@ module Hardware_registers : sig
190190

191191
val of_reg : t -> Reg.t -> Hardware_register.t option
192192

193-
val find_available : t -> Reg.t -> Interval.t -> available
193+
val find_available : t -> SpillCosts.t -> Reg.t -> Interval.t -> available
194194
end

backend/regalloc/regalloc_irc.ml

+28-18
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,9 @@ let freeze : State.t -> unit =
256256
State.add_simplify_work_list state reg;
257257
freeze_moves state reg
258258

259-
let select_spilling_register_using_heuristics : State.t -> Reg.t =
260-
fun state ->
259+
let select_spilling_register_using_heuristics : State.t -> SpillCosts.t -> Reg.t
260+
=
261+
fun state costs ->
261262
match Lazy.force Spilling_heuristics.value with
262263
| Set_choose -> (
263264
(* This is the "heuristics" from the IRC paper: pick any candidate, just try
@@ -280,8 +281,9 @@ let select_spilling_register_using_heuristics : State.t -> Reg.t =
280281
let weighted_cost (reg : Reg.t) =
281282
if debug
282283
then
283-
log "register %a has spill cost %d" Printreg.reg reg reg.Reg.spill_cost;
284-
(float reg.Reg.spill_cost /. float (State.degree state reg))
284+
log "register %a has spill cost %d" Printreg.reg reg
285+
(SpillCosts.for_reg costs reg);
286+
(float (SpillCosts.for_reg costs reg) /. float (State.degree state reg))
285287
(* note: while this magic constant is questionable, it is key to not favor
286288
the introduced temporaries which, by construct, have very few
287289
occurrences. *)
@@ -300,13 +302,13 @@ let select_spilling_register_using_heuristics : State.t -> Reg.t =
300302
else acc)
301303
|> fst)
302304

303-
let select_spill : State.t -> unit =
304-
fun state ->
305+
let select_spill : State.t -> SpillCosts.t -> unit =
306+
fun state costs ->
305307
if debug
306308
then (
307309
log "select_spill";
308310
indent ());
309-
let reg = select_spilling_register_using_heuristics state in
311+
let reg = select_spilling_register_using_heuristics state costs in
310312
if debug
311313
then
312314
log "chose %a using heuristics %S" Printreg.reg reg
@@ -461,7 +463,7 @@ let rec main : round:int -> State.t -> Cfg_with_infos.t -> unit =
461463
make_work_list state;
462464
State.invariant state;
463465
if debug then log_work_list_desc "before loop";
464-
let spill_cost_is_up_to_date = ref false in
466+
let spill_costs = ref (None : SpillCosts.t option) in
465467
let continue = ref true in
466468
while !continue do
467469
if not (State.is_empty_simplify_work_list state)
@@ -471,16 +473,24 @@ let rec main : round:int -> State.t -> Cfg_with_infos.t -> unit =
471473
else if not (State.is_empty_freeze_work_list state)
472474
then freeze state
473475
else if not (State.is_empty_spill_work_list state)
474-
then (
475-
if not !spill_cost_is_up_to_date
476-
then (
477-
(match Lazy.force Spilling_heuristics.value with
478-
| Set_choose ->
479-
(* note: `spill_cost` will not be used by the heuristics *) ()
480-
| Flat_uses -> update_spill_cost cfg_with_infos ~flat:true ()
481-
| Hierarchical_uses -> update_spill_cost cfg_with_infos ~flat:false ());
482-
spill_cost_is_up_to_date := true);
483-
select_spill state)
476+
then
477+
let costs =
478+
match !spill_costs with
479+
| Some costs -> costs
480+
| None ->
481+
let costs =
482+
match Lazy.force Spilling_heuristics.value with
483+
| Set_choose ->
484+
(* note: `spill_cost` will not be used by the heuristics *)
485+
SpillCosts.empty ()
486+
| Flat_uses -> SpillCosts.compute cfg_with_infos ~flat:true ()
487+
| Hierarchical_uses ->
488+
SpillCosts.compute cfg_with_infos ~flat:false ()
489+
in
490+
spill_costs := Some costs;
491+
costs
492+
in
493+
select_spill state costs
484494
else continue := false;
485495
if debug then log_work_list_desc "end of loop";
486496
State.invariant state

backend/regalloc/regalloc_ls.ml

+3-7
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ let allocate_stack_slot : Reg.t -> spilling_reg =
110110
fun reg ->
111111
indent ();
112112
log "spilling register %a" Printreg.reg reg;
113-
reg.spill <- true;
114113
dedent ();
115114
Spilling reg
116115

@@ -119,9 +118,8 @@ exception No_free_register
119118
let allocate_free_register : State.t -> Interval.t -> spilling_reg =
120119
fun state interval ->
121120
let reg = interval.reg in
122-
match reg.loc, reg.spill with
123-
| Unknown, true -> allocate_stack_slot reg
124-
| Unknown, _ -> (
121+
match reg.loc with
122+
| Unknown -> (
125123
let reg_class = Proc.register_class reg in
126124
let intervals = State.active state ~reg_class in
127125
let first_available = Proc.first_available_register.(reg_class) in
@@ -161,7 +159,6 @@ let allocate_free_register : State.t -> Interval.t -> spilling_reg =
161159
else if available.(idx)
162160
then (
163161
reg.loc <- Reg (first_available + idx);
164-
reg.spill <- false;
165162
Interval.DLL.insert_sorted intervals.active_dll interval;
166163
if debug
167164
then (
@@ -172,7 +169,7 @@ let allocate_free_register : State.t -> Interval.t -> spilling_reg =
172169
else assign (succ idx)
173170
in
174171
assign 0)
175-
| (Reg _ | Stack _), _ -> Not_spilling
172+
| Reg _ | Stack _ -> Not_spilling
176173

177174
let allocate_blocked_register : State.t -> Interval.t -> spilling_reg =
178175
fun state interval ->
@@ -282,7 +279,6 @@ let run : Cfg_with_infos.t -> Cfg_with_infos.t =
282279
(match Reg.Set.elements spilling_because_unused with
283280
| [] -> ()
284281
| _ :: _ as spilled_nodes ->
285-
List.iter spilled_nodes ~f:(fun reg -> reg.Reg.spill <- true);
286282
rewrite state cfg_with_infos ~spilled_nodes ~block_temporaries:false;
287283
Cfg_with_infos.invalidate_liveness cfg_with_infos);
288284
main ~round:1 state cfg_with_infos;

0 commit comments

Comments
 (0)