From 891a232214640d3637e39beea59bb18fa4d8e7ca Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Wed, 5 Jun 2019 13:08:56 -0700 Subject: [PATCH] nir/large_constants: Use dominance information to find more constants MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Relax the restriction that all the writes need to be in the first block: now accept variables that have all the writes in the same block, and all the reads are dominated by that block. This let the pass identify large constants that are local to a helper function. The writes will be at the place that the function is inlined, possibly not in the first block (but still all in the same block). Results for vkpipeline-db in SKL: total instructions in shared programs: 3624891 -> 3623145 (-0.05%) instructions in affected programs: 79416 -> 77670 (-2.20%) helped: 16 HURT: 0 total cycles in shared programs: 1458149667 -> 1458147273 (<.01%) cycles in affected programs: 30154164 -> 30151770 (<.01%) helped: 14 HURT: 2 total loops in shared programs: 2437 -> 2437 (0.00%) loops in affected programs: 0 -> 0 helped: 0 HURT: 0 total spills in shared programs: 8813 -> 8745 (-0.77%) spills in affected programs: 2894 -> 2826 (-2.35%) helped: 8 HURT: 0 total fills in shared programs: 23470 -> 23392 (-0.33%) fills in affected programs: 12248 -> 12170 (-0.64%) helped: 6 HURT: 2 LOST: 0 GAINED: 0 Results for shader-db in SKL with Iris: total instructions in shared programs: 15379442 -> 15379392 (<.01%) instructions in affected programs: 837 -> 787 (-5.97%) helped: 2 HURT: 2 helped stats (abs) min: 27 max: 27 x̄: 27.00 x̃: 27 helped stats (rel) min: 10.47% max: 10.67% x̄: 10.57% x̃: 10.57% HURT stats (abs) min: 2 max: 2 x̄: 2.00 x̃: 2 HURT stats (rel) min: 1.23% max: 1.23% x̄: 1.23% x̃: 1.23% 95% mean confidence interval for instructions value: -39.14 14.14 95% mean confidence interval for instructions %-change: -15.51% 6.17% Inconclusive result (value mean confidence interval includes 0). total loops in shared programs: 4880 -> 4880 (0.00%) loops in affected programs: 0 -> 0 helped: 0 HURT: 0 total cycles in shared programs: 370677237 -> 370676567 (<.01%) cycles in affected programs: 17852 -> 17182 (-3.75%) helped: 2 HURT: 1 helped stats (abs) min: 338 max: 356 x̄: 347.00 x̃: 347 helped stats (rel) min: 13.98% max: 14.64% x̄: 14.31% x̃: 14.31% HURT stats (abs) min: 24 max: 24 x̄: 24.00 x̃: 24 HURT stats (rel) min: 0.18% max: 0.18% x̄: 0.18% x̃: 0.18% total spills in shared programs: 11772 -> 11772 (0.00%) spills in affected programs: 0 -> 0 helped: 0 HURT: 0 total fills in shared programs: 24948 -> 24948 (0.00%) fills in affected programs: 0 -> 0 helped: 0 HURT: 0 LOST: 0 GAINED: 0 Reviewed-by: Jason Ekstrand --- src/compiler/nir/nir_opt_large_constants.c | 36 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/compiler/nir/nir_opt_large_constants.c b/src/compiler/nir/nir_opt_large_constants.c index d234196e8fd..09361a0099d 100644 --- a/src/compiler/nir/nir_opt_large_constants.c +++ b/src/compiler/nir/nir_opt_large_constants.c @@ -28,6 +28,11 @@ struct var_info { bool is_constant; bool found_read; + + /* Block that has all the variable stores. All the blocks with reads + * should be dominated by this block. + */ + nir_block *block; }; static nir_ssa_def * @@ -151,6 +156,9 @@ nir_opt_large_constants(nir_shader *shader, nir_foreach_variable(var, &impl->locals) var->data.index = num_locals++; + if (num_locals == 0) + return false; + struct var_info *var_infos = malloc(num_locals * sizeof(struct var_info)); for (unsigned i = 0; i < num_locals; i++) { var_infos[i] = (struct var_info) { @@ -159,10 +167,11 @@ nir_opt_large_constants(nir_shader *shader, }; } + nir_metadata_require(impl, nir_metadata_dominance); + /* First, walk through the shader and figure out what variables we can * lower to the constant blob. */ - bool first_block = true; nir_foreach_block(block, impl) { nir_foreach_instr(instr, block) { if (instr->type != nir_instr_type_intrinsic) @@ -200,12 +209,18 @@ nir_opt_large_constants(nir_shader *shader, nir_variable *var = nir_deref_instr_get_variable(dst_deref); assert(var->data.mode == nir_var_function_temp); + struct var_info *info = &var_infos[var->data.index]; + if (!info->is_constant) + continue; + + if (!info->block) + info->block = block; + /* We only consider variables constant if they only have constant * stores, all the stores come before any reads, and all stores - * come in the first block. We also can't handle indirect stores. + * come from the same block. We also can't handle indirect stores. */ - struct var_info *info = &var_infos[var->data.index]; - if (!src_is_const || info->found_read || !first_block || + if (!src_is_const || info->found_read || block != info->block || nir_deref_instr_has_indirect(dst_deref)) info->is_constant = false; } @@ -214,10 +229,19 @@ nir_opt_large_constants(nir_shader *shader, nir_variable *var = nir_deref_instr_get_variable(src_deref); assert(var->data.mode == nir_var_function_temp); - var_infos[var->data.index].found_read = true; + /* We only consider variables constant if all the reads are + * dominated by the block that writes to it. + */ + struct var_info *info = &var_infos[var->data.index]; + if (!info->is_constant) + continue; + + if (!info->block || !nir_block_dominates(info->block, block)) + info->is_constant = false; + + info->found_read = true; } } - first_block = false; } shader->constant_data_size = 0; -- 2.30.2