From e99f1d41bc8a7e035e35fd5aef6f3ea023d7f12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Thu, 16 Mar 2017 16:38:22 +0100 Subject: hipe: Add range splitter restore_reuse hipe_restore_reuse is a simplistic range splitter that splits temps that are forced onto the stack by being live over call instructions. In particular, it attempts to avoid cases where there are several accesses to such stack allocated temps in straight-line code, uninterrupted by any calls. In order to achieve this it splits temps between just before the first access(es) and just after the last access(es) in such straight-line code groups. The hipe_restore_reuse pass is controlled by a new option ra_restore_reuse. ra_restore_reuse is added to o1. --- lib/hipe/regalloc/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/hipe/regalloc/Makefile') diff --git a/lib/hipe/regalloc/Makefile b/lib/hipe/regalloc/Makefile index 209f230a9b..73ac232f51 100644 --- a/lib/hipe/regalloc/Makefile +++ b/lib/hipe/regalloc/Makefile @@ -52,6 +52,7 @@ MODULES = hipe_ig hipe_ig_moves hipe_moves \ hipe_graph_coloring_regalloc \ hipe_regalloc_loop \ hipe_regalloc_prepass \ + hipe_restore_reuse \ hipe_ls_regalloc \ hipe_ppc_specific hipe_ppc_specific_fp \ hipe_sparc_specific hipe_sparc_specific_fp \ -- cgit v1.2.3 From d1d26f4bf9da3cc5eab4e918df771d67fe9e6bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Thu, 16 Mar 2017 16:39:26 +0100 Subject: hipe: Add range splitter range_split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hipe_range_split is a complex live range splitter, more sophisticated thatn hipe_restore_reuse, but still targeted specifically at temporaries forced onto stack by being live over call instructions. hipe_range_split partitions the control flow graph at call instructions, like hipe_regalloc_prepass. Splitting decisions are made on a per partition and per temporary basis. There are three different ways in which hipe_range_split may choose to split a temporary in a program partition: * Mode1: Spill the temp before calls, and restore it after them * Mode2: Spill the temp after definitions, restore it after calls * Mode3: Spill the temp after definitions, restore it before uses To pick which of these should be used for each tempĂ—partiton pair, hipe_range_split uses a cost function. The cost is simply the sum of the cost of all expected stack accesses, and the cost for an individual stack access is based on the probability weight of the basic block that it resides in. This biases the range splitter so that it attempts moving stack accesses from a functions hot path to the cold path. hipe_bb_weights is used to compute the probability weights. mode3 is effectively the same as what hipe_restore_reuse does. Because of this, hipe_restore_reuse reuses the analysis pass of hipe_restore_reuse in order to compute the minimal needed set of spills and restores. The reason mode3 was introduced to hipe_range_split rather than simply composing it with hipe_restore_reuse (by running both) is that such a composition resulted in poor register allocation results due to insufficiently strong move coalescing in the register allocator. The cost function heuristic has a couple of tuning knobs: * {range_split_min_gain, Gain} (default: 1.1, range: [0.0, inf)) The minimum proportional improvement that the cost of all stack accesses to a temp must display in order for that temp to be split. * {range_split_mode1_fudge, Factor} (default: 1.1, range: [0.0, inf)) Costs for mode1 are multiplied by this factor in order to discourage it when it provides marginal benefits. The justification is that mode1 causes temps to be live for longest, thus leading to higher register pressure. * {range_split_weight_power, Factor} (default: 2, range: (0.0, inf)) Adjusts how much effect the basic block weights have on the cost of a stack access. A stack access in a block with weight 1.0 has cost 1.0, a stack access in a block with weight 0.01 has cost 1/Factor. Additionally, the option range_split_weights chooses whether the basic block weights are used at all. In the case that the input is very big, hipe_range_split automatically falls back to hipe_restore_reuse only in order to keep compile times under control. Note that this is not only because of hipe_range_split being slow, but also due to the resulting program being slow to register allocate, and is not as partitionable by hipe_regalloc_prepass. hipe_restore_reuse, on the other hand, does not affect the programs partitionability. The hipe_range_split pass is controlled by a new option ra_range_split. ra_range_split is added to o2, and ra_restore_reuse is disabled in o2. --- lib/hipe/regalloc/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/hipe/regalloc/Makefile') diff --git a/lib/hipe/regalloc/Makefile b/lib/hipe/regalloc/Makefile index 73ac232f51..81a92e5d35 100644 --- a/lib/hipe/regalloc/Makefile +++ b/lib/hipe/regalloc/Makefile @@ -50,6 +50,7 @@ MODULES = hipe_ig hipe_ig_moves hipe_moves \ hipe_optimistic_regalloc \ hipe_coalescing_regalloc \ hipe_graph_coloring_regalloc \ + hipe_range_split \ hipe_regalloc_loop \ hipe_regalloc_prepass \ hipe_restore_reuse \ -- cgit v1.2.3