From: Jason Ekstrand Date: Sat, 13 Apr 2019 21:01:50 +0000 (-0500) Subject: intel/fs: Account for live range lengths in spill costs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cd4ffb376f2aeefdd6a1b80d69a1580c4e569778;p=mesa.git intel/fs: Account for live range lengths in spill costs The current register allocator has a concept of "spill benefit" which is based on the number of nodes with which a given node interferes. The idea is that you want to spill stuff with high interference because those are the most likely registers to help when spilling. However, this fails to take into account the length of the live range so the allocator frequently picks "cheap" (not many uses) registers which are actually very short lived and so spilling them doesn't help with the pressure situation. This commit takes into account the length of the live range to make long-lived registers more likely to get spilled than short-lived ones. This encourages the spill chooser to choose slightly larger registers which will affect a larger area of the program and hopefully we have to spill fewer of them to get the same reduction in over-all register pressure. Shader-db results on Kaby Lake: total spills in shared programs: 23664 -> 12050 (-49.08%) spills in affected programs: 19243 -> 7629 (-60.35%) helped: 296 HURT: 8 total fills in shared programs: 32028 -> 25139 (-21.51%) fills in affected programs: 20378 -> 13489 (-33.81%) helped: 295 HURT: 16 Of course, most of that is in Deus Ex... Shader-db results on Kaby Lake (without Deus Ex): total spills in shared programs: 6479 -> 5834 (-9.96%) spills in affected programs: 3231 -> 2586 (-19.96%) helped: 40 HURT: 4 total fills in shared programs: 17165 -> 17099 (-0.38%) fills in affected programs: 6951 -> 6885 (-0.95%) helped: 40 HURT: 7 Even without Deus Ex, the spill help is pretty respectable. The worst hurt shaders were one compute shader in Aztec Ruins and one fragment shader in KSP that were each hurt by around 13% fill 9% spill. VkPipeline-db results on Kaby Lake: total spills in shared programs: 9149 -> 8069 (-11.80%) spills in affected programs: 5197 -> 4117 (-20.78%) helped: 27 HURT: 16 total fills in shared programs: 26390 -> 25477 (-3.46%) fills in affected programs: 12662 -> 11749 (-7.21%) helped: 24 HURT: 22 The Vulkan results were decidedly more mixed but we don't have nearly as many apps in that database yet. Reviewed-by: Kenneth Graunke Reviewed-by: Matt Turner --- diff --git a/src/intel/compiler/brw_fs_reg_allocate.cpp b/src/intel/compiler/brw_fs_reg_allocate.cpp index 94b18153492..d5c4f032182 100644 --- a/src/intel/compiler/brw_fs_reg_allocate.cpp +++ b/src/intel/compiler/brw_fs_reg_allocate.cpp @@ -932,8 +932,20 @@ fs_visitor::choose_spill_reg(struct ra_graph *g) } for (unsigned i = 0; i < this->alloc.count; i++) { + int live_length = virtual_grf_end[i] - virtual_grf_start[i]; + if (live_length <= 0) + continue; + + /* Divide the cost (in number of spills/fills) by the log of the length + * of the live range of the register. This will encourage spill logic + * to spill long-living things before spilling short-lived things where + * spilling is less likely to actually do us any good. We use the log + * of the length because it will fall off very quickly and not cause us + * to spill medium length registers with more uses. + */ + float adjusted_cost = spill_costs[i] / logf(live_length); if (!no_spill[i]) - ra_set_node_spill_cost(g, i, spill_costs[i]); + ra_set_node_spill_cost(g, i, adjusted_cost); } return ra_get_best_spill_node(g);