From: Marek Olšák Date: Sat, 29 Apr 2017 21:56:03 +0000 (+0200) Subject: ac: eliminate duplicated VS exports X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b08715499e61161b8dc070f125c5c2dc68e9afe7;p=mesa.git ac: eliminate duplicated VS exports Only very few shaders have them (from 48486 shaders): shaders/private/left_4_dead_2/765.shader_test - ac: 1 matches 2 shaders/private/left_4_dead_2/877.shader_test - ac: 1 matches 6 shaders/private/left_4_dead_2/2141.shader_test - ac: 1 matches 6 shaders/private/ue4_effects_cave/11.shader_test - ac: 4 matches 5 shaders/private/ue4_effects_cave/14.shader_test - ac: 5 matches 6 shaders/private/ue4_effects_cave/46.shader_test - ac: 5 matches 6 shaders/private/ue4_effects_cave/42.shader_test - ac: 4 matches 5 shaders/private/ue4_effects_cave/104.shader_test - ac: 4 matches 5 shaders/private/f1-2015/336.shader_test - ac: 3 matches 4 shaders/private/f1-2015/948.shader_test - ac: 6 matches 7 shaders/private/f1-2015/602.shader_test - ac: 0 matches 3 shaders/private/f1-2015/600.shader_test - ac: 0 matches 3 shaders/private/f1-2015/1214.shader_test - ac: 0 matches 1 shaders/private/f1-2015/988.shader_test - ac: 4 matches 5 shaders/private/ue4_elemental/149.shader_test - ac: 3 matches 4 shaders/private/ue4_elemental/346.shader_test - ac: 4 matches 5 shaders/private/ue4_elemental/178.shader_test - ac: 3 matches 4 shaders/private/ue4_elemental/136.shader_test - ac: 4 matches 5 shaders/private/ue4_elemental/168.shader_test - ac: 4 matches 5 shaders/private/ue4_elemental/690.shader_test - ac: 3 matches 4 shaders/private/ue4_elemental/19.shader_test - ac: 5 matches 6 shaders/private/dota2/1901.shader_test - ac: 0 matches 5 shaders/private/dota2/1357.shader_test - ac: 0 matches 5 shaders/private/dota2/1375.shader_test - ac: 0 matches 5 shaders/private/dota2/1369.shader_test - ac: 0 matches 5 shaders/private/dota2/1583.shader_test - ac: 0 matches 5 shaders/private/dota2/1811.shader_test - ac: 0 matches 5 shaders/private/dota2/1893.shader_test - ac: 0 matches 5 shaders/private/dota2/1533.shader_test - ac: 0 matches 5 shaders/private/dota2/1951.shader_test - ac: 0 matches 5 shaders/private/dota2/1361.shader_test - ac: 0 matches 5 shaders/private/mad_max/2792.shader_test - ac: 0 matches 1 shaders/private/mad_max/2794.shader_test - ac: 0 matches 1 shaders/private/mad_max/2780.shader_test - ac: 0 matches 1 shaders/private/mad_max/2902.shader_test - ac: 0 matches 1 shaders/private/bioshock-infinite/3050.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/2544.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/3062.shader_test - ac: 3 matches 8 shaders/private/bioshock-infinite/2012.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/3058.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/3270.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/732.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/3026.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/3258.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/3198.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/3046.shader_test - ac: 3 matches 7 shaders/private/bioshock-infinite/3168.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/2550.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/3210.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/3032.shader_test - ac: 3 matches 6 shaders/private/bioshock-infinite/668.shader_test - ac: 3 matches 7 Reviewed-by: Dave Airlie Reviewed-by: Nicolai Hähnle --- diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 26ade111177..c89633f923c 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -1320,6 +1320,80 @@ static bool ac_eliminate_const_output(uint8_t *vs_output_param_offset, return true; } +static bool ac_eliminate_duplicated_output(uint8_t *vs_output_param_offset, + uint32_t num_outputs, + struct ac_vs_exports *processed, + struct ac_vs_exp_inst *exp) +{ + unsigned p, copy_back_channels = 0; + + /* See if the output is already in the list of processed outputs. + * The LLVMValueRef comparison relies on SSA. + */ + for (p = 0; p < processed->num; p++) { + bool different = false; + + for (unsigned j = 0; j < 4; j++) { + struct ac_vs_exp_chan *c1 = &processed->exp[p].chan[j]; + struct ac_vs_exp_chan *c2 = &exp->chan[j]; + + /* Treat undef as a match. */ + if (c2->type == AC_IR_UNDEF) + continue; + + /* If c1 is undef but c2 isn't, we can copy c2 to c1 + * and consider the instruction duplicated. + */ + if (c1->type == AC_IR_UNDEF) { + copy_back_channels |= 1 << j; + continue; + } + + /* Test whether the channels are not equal. */ + if (c1->type != c2->type || + (c1->type == AC_IR_CONST && + c1->const_float != c2->const_float) || + (c1->type == AC_IR_VALUE && + c1->value != c2->value)) { + different = true; + break; + } + } + if (!different) + break; + + copy_back_channels = 0; + } + if (p == processed->num) + return false; + + /* If a match was found, but the matching export has undef where the new + * one has a normal value, copy the normal value to the undef channel. + */ + struct ac_vs_exp_inst *match = &processed->exp[p]; + + while (copy_back_channels) { + unsigned chan = u_bit_scan(©_back_channels); + + assert(match->chan[chan].type == AC_IR_UNDEF); + LLVMSetOperand(match->inst, AC_EXP_OUT0 + chan, + exp->chan[chan].value); + match->chan[chan] = exp->chan[chan]; + } + + /* The PARAM export is duplicated. Kill it. */ + LLVMInstructionEraseFromParent(exp->inst); + + /* Change OFFSET to the matching export. */ + for (unsigned i = 0; i < num_outputs; i++) { + if (vs_output_param_offset[i] == exp->offset) { + vs_output_param_offset[i] = match->offset; + break; + } + } + return true; +} + void ac_optimize_vs_outputs(struct ac_llvm_context *ctx, LLVMValueRef main_fn, uint8_t *vs_output_param_offset, @@ -1389,9 +1463,12 @@ void ac_optimize_vs_outputs(struct ac_llvm_context *ctx, } } - /* Eliminate constant value PARAM exports. */ + /* Eliminate constant and duplicated PARAM exports. */ if (ac_eliminate_const_output(vs_output_param_offset, - num_outputs, &exp)) { + num_outputs, &exp) || + ac_eliminate_duplicated_output(vs_output_param_offset, + num_outputs, &exports, + &exp)) { removed_any = true; } else { exports.exp[exports.num++] = exp;