From 904caa71a3754e3ee7f681cc7d4106d4a9979f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Wed, 31 Aug 2016 14:48:45 +0200 Subject: hipe: Make sure prepass temps are below SpillLimit If temps introduced by hipe_regalloc_prepass end up above SpillLimit, the register allocators will not spill them. This constraint is unnecessarily limiting the allocators and might theoretically lead to unallocatable programs (more temps above SpillLimit alive at a time than there are physical registers). --- lib/hipe/regalloc/hipe_regalloc_loop.erl | 59 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'lib/hipe/regalloc/hipe_regalloc_loop.erl') diff --git a/lib/hipe/regalloc/hipe_regalloc_loop.erl b/lib/hipe/regalloc/hipe_regalloc_loop.erl index 8d564c35ae..3b21a377df 100644 --- a/lib/hipe/regalloc/hipe_regalloc_loop.erl +++ b/lib/hipe/regalloc/hipe_regalloc_loop.erl @@ -34,31 +34,29 @@ ra(CFG, SpillIndex, Options, RegAllocMod, TargetMod) -> ra_fp(CFG, Options, RegAllocMod, TargetMod) -> ra_common(CFG, 0, Options, RegAllocMod, TargetMod). -ra_common(CFG, SpillIndex, Options, RegAllocMod, TargetMod) -> +ra_common(CFG0, SpillIndex, Options, RegAllocMod, TargetMod) -> ?inc_counter(ra_calls_counter, 1), + SpillLimit0 = TargetMod:number_of_temporaries(CFG0), + {Coloring, _, CFG, MaybeLiveness} = + call_allocator_initial(CFG0, SpillLimit0, SpillIndex, Options, RegAllocMod, + TargetMod), + %% The first iteration, the hipe_regalloc_prepass may create new temps, these + %% should not end up above SpillLimit. SpillLimit = TargetMod:number_of_temporaries(CFG), - alloc(CFG, SpillLimit, SpillIndex, Options, RegAllocMod, TargetMod). + alloc(Coloring, CFG, MaybeLiveness, SpillLimit, SpillIndex, Options, + RegAllocMod, TargetMod). -alloc(CFG0, SpillLimit, SpillIndex, Options, RegAllocMod, TargetMod) -> +alloc(Coloring, CFG0, MaybeLiveness0, SpillLimit, SpillIndex, Options, + RegAllocMod, TargetMod) -> ?inc_counter(ra_iteration_counter, 1), - {Coloring, _NewSpillIndex, CFG, MaybeLiveness} = - case proplists:get_bool(ra_prespill, Options) of - true -> - hipe_regalloc_prepass:regalloc( - RegAllocMod, CFG0, SpillIndex, SpillLimit, TargetMod, Options); - false -> - {C, SI, L} = RegAllocMod:regalloc(CFG0, SpillIndex, SpillLimit, - TargetMod, Options), - {C, SI, CFG0, L} - end, - {NewCFG, DidSpill} = TargetMod:check_and_rewrite(CFG, Coloring), + {CFG, DidSpill} = TargetMod:check_and_rewrite(CFG0, Coloring), case DidSpill of false -> %% No new temps, we are done. ?add_spills(Options, _NewSpillIndex), TempMap = hipe_temp_map:cols2tuple(Coloring, TargetMod), - Liveness = liveness_force(TargetMod, CFG, MaybeLiveness), + Liveness = liveness_force(TargetMod, CFG0, MaybeLiveness0), {TempMap2, NewSpillIndex2} = - hipe_spillmin:stackalloc(CFG, Liveness, [], SpillIndex, Options, + hipe_spillmin:stackalloc(CFG0, Liveness, [], SpillIndex, Options, TargetMod, TempMap), Coloring2 = hipe_spillmin:mapmerge(hipe_temp_map:to_substlist(TempMap), TempMap2), @@ -68,11 +66,36 @@ alloc(CFG0, SpillLimit, SpillIndex, Options, RegAllocMod, TargetMod) -> %% false -> %% ok %% end, - {NewCFG, Coloring2, NewSpillIndex2}; + {CFG, Coloring2, NewSpillIndex2}; _ -> %% Since SpillLimit is used as a low-water-mark %% the list of temps not to spill is uninteresting. - alloc(NewCFG, SpillLimit, SpillIndex, Options, RegAllocMod, TargetMod) + {NewColoring, _NewSpillIndex, Liveness} = + call_allocator(CFG, SpillLimit, SpillIndex, Options, RegAllocMod, + TargetMod), + alloc(NewColoring, CFG, Liveness, SpillLimit, SpillIndex, Options, + RegAllocMod, TargetMod) + end. + +call_allocator_initial(CFG, SpillLimit, SpillIndex, Options, RegAllocMod, + TargetMod) -> + case proplists:get_bool(ra_prespill, Options) of + true -> + hipe_regalloc_prepass:regalloc_initial( + RegAllocMod, CFG, SpillIndex, SpillLimit, TargetMod, Options); + false -> + {C, SI, L} = RegAllocMod:regalloc(CFG, SpillIndex, SpillLimit, + TargetMod, Options), + {C, SI, CFG, L} + end. + +call_allocator(CFG, SpillLimit, SpillIndex, Options, RegAllocMod, TargetMod) -> + case proplists:get_bool(ra_prespill, Options) of + true -> + hipe_regalloc_prepass:regalloc( + RegAllocMod, CFG, SpillIndex, SpillLimit, TargetMod, Options); + false -> + RegAllocMod:regalloc(CFG, SpillIndex, SpillLimit, TargetMod, Options) end. liveness_force(TargetMod, CFG, undefined) -> TargetMod:analyze(CFG); -- cgit v1.2.3