From: Marek Olšák Date: Mon, 23 Aug 2010 03:48:39 +0000 (+0200) Subject: r300/compiler: implement elimination of unused constants X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=574ba4b5f50bfe661427327cd792a8a200559376;p=mesa.git r300/compiler: implement elimination of unused constants Wine likes to create a *lot* of constants, exceeding the size of the constant file in hw. --- diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile index 3167d49bcae..d0eb1707845 100644 --- a/src/mesa/drivers/dri/r300/compiler/Makefile +++ b/src/mesa/drivers/dri/r300/compiler/Makefile @@ -23,6 +23,7 @@ C_SOURCES = \ radeon_dataflow_deadcode.c \ radeon_dataflow_swizzles.c \ radeon_optimize.c \ + radeon_remove_constants.c \ radeon_rename_regs.c \ r3xx_fragprog.c \ r300_fragprog.c \ diff --git a/src/mesa/drivers/dri/r300/compiler/SConscript b/src/mesa/drivers/dri/r300/compiler/SConscript index c6f47a6f8a4..9729441f3a6 100755 --- a/src/mesa/drivers/dri/r300/compiler/SConscript +++ b/src/mesa/drivers/dri/r300/compiler/SConscript @@ -22,6 +22,7 @@ r300compiler = env.ConvenienceLibrary( 'radeon_pair_schedule.c', 'radeon_pair_regalloc.c', 'radeon_optimize.c', + 'radeon_remove_constants.c' 'radeon_rename_regs.c', 'radeon_emulate_branches.c', 'radeon_emulate_loops.c', diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c index 59f4efc8883..8613ec51091 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c @@ -30,6 +30,7 @@ #include "radeon_program_alu.h" #include "radeon_program_tex.h" #include "radeon_rename_regs.h" +#include "radeon_remove_constants.h" #include "r300_fragprog.h" #include "r300_fragprog_swizzle.h" #include "r500_fragprog.h" @@ -180,6 +181,13 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) debug_program_log(c, "after dataflow passes"); + if (c->Base.remove_unused_constants) { + rc_remove_unused_constants(&c->Base, + &c->code->constants_remap_table); + + debug_program_log(c, "after constants cleanup"); + } + if(!c->Base.is_r500) { /* This pass makes it easier for the scheduler to group TEX * instructions and reduces the chances of creating too diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c index 5009ab9eed2..997c0912d7d 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c @@ -31,6 +31,7 @@ #include "radeon_swizzle.h" #include "radeon_emulate_branches.h" #include "radeon_emulate_loops.h" +#include "radeon_remove_constants.h" struct loop { int BgnLoop; @@ -993,6 +994,14 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler *c) debug_program_log(c, "after register allocation"); + if (c->Base.remove_unused_constants) { + rc_remove_unused_constants(&c->Base, + &c->code->constants_remap_table); + if (c->Base.Error) + return; + + debug_program_log(c, "after constants cleanup"); + } translate_vertex_program(c); if (c->Base.Error) diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index 896246d2035..f76676fae8e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -235,6 +235,7 @@ struct rX00_fragment_program_code { unsigned writes_depth:1; struct rc_constant_list constants; + unsigned *constants_remap_table; }; @@ -266,6 +267,7 @@ struct r300_vertex_program_code { int outputs[VSF_MAX_OUTPUTS]; struct rc_constant_list constants; + unsigned *constants_remap_table; uint32_t InputsRead; uint32_t OutputsWritten; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h index 7c42eb3ae57..5155b912e17 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h @@ -39,9 +39,12 @@ struct radeon_compiler { char * ErrorMsg; /* Hardware specification. */ - unsigned is_r500; + unsigned is_r500:1; unsigned max_temp_regs; + /* Whether to remove unused constants and empty holes in constant space. */ + unsigned remove_unused_constants:1; + /** * Variables used internally, not be touched by callers * of the compiler diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c new file mode 100644 index 00000000000..be89e9fa5b4 --- /dev/null +++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010 Marek Olšák + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "radeon_remove_constants.h" + +void rc_remove_unused_constants(struct radeon_compiler *c, + unsigned **out_remap_table) +{ + unsigned char *const_used; + unsigned *remap_table; + unsigned *inv_remap_table; + unsigned has_rel_addr = 0; + unsigned is_identity = 1; + unsigned are_externals_remapped = 0; + struct rc_constant *constants = c->Program.Constants.Constants; + + if (!c->Program.Constants.Count) { + *out_remap_table = NULL; + return; + } + + const_used = malloc(c->Program.Constants.Count); + memset(const_used, 0, c->Program.Constants.Count); + + /* Pass 1: Mark used constants. */ + for (struct rc_instruction *inst = c->Program.Instructions.Next; + inst != &c->Program.Instructions; inst = inst->Next) { + const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); + + for (unsigned i = 0; i < opcode->NumSrcRegs; i++) { + if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) { + if (inst->U.I.SrcReg[i].RelAddr) { + has_rel_addr = 1; + } else { + const_used[inst->U.I.SrcReg[i].Index] = 1; + } + } + } + } + + /* Pass 2: If there is relative addressing, mark all externals as used. */ + if (has_rel_addr) { + for (unsigned i = 0; i < c->Program.Constants.Count; i++) + if (constants[i].Type == RC_CONSTANT_EXTERNAL) + const_used[i] = 1; + } + + /* Pass 3: Make the remapping table and remap constants. + * This pass removes unused constants simply by overwriting them by other constants. */ + remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned)); + inv_remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned)); + unsigned new_count = 0; + + for (unsigned i = 0; i < c->Program.Constants.Count; i++) { + if (const_used[i]) { + remap_table[new_count] = i; + inv_remap_table[i] = new_count; + + if (i != new_count) { + if (constants[i].Type == RC_CONSTANT_EXTERNAL) + are_externals_remapped = 1; + + constants[new_count] = constants[i]; + is_identity = 0; + } + new_count++; + } + } + + /* is_identity ==> new_count == old_count + * !is_identity ==> new_count < old_count */ + assert( is_identity || new_count < c->Program.Constants.Count); + assert(!(has_rel_addr && are_externals_remapped)); + + /* Pass 4: Redirect reads of all constants to their new locations. */ + if (!is_identity) { + for (struct rc_instruction *inst = c->Program.Instructions.Next; + inst != &c->Program.Instructions; inst = inst->Next) { + const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode); + + for (unsigned i = 0; i < opcode->NumSrcRegs; i++) { + if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) { + inst->U.I.SrcReg[i].Index = inv_remap_table[inst->U.I.SrcReg[i].Index]; + } + } + } + + } + + /* Set the new constant count. Note that new_count may be less than + * Count even though the remapping function is identity. In that case, + * the constants have been removed at the end of the array. */ + c->Program.Constants.Count = new_count; + + if (are_externals_remapped) { + *out_remap_table = remap_table; + } else { + *out_remap_table = NULL; + free(remap_table); + } + + free(const_used); + free(inv_remap_table); +} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h new file mode 100644 index 00000000000..0d3a26ca1ca --- /dev/null +++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Marek Olšák + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef RADEON_REMOVE_CONSTANTS_H +#define RADEON_REMOVE_CONSTANTS_H + +#include "radeon_compiler.h" + +void rc_remove_unused_constants(struct radeon_compiler *c, + unsigned **out_remap_table); + +#endif