diff options
author | Tom Stellard <[email protected]> | 2012-09-06 00:20:27 -0400 |
---|---|---|
committer | Tom Stellard <[email protected]> | 2012-09-19 19:25:53 -0400 |
commit | 886a4d4a6ad8a67e02e67d5dd79ae37a592930c6 (patch) | |
tree | 043ecf5faa15433997c83ef958343033b927802f /src/gallium/drivers/r300/compiler | |
parent | 9282adcae9b05399ae0e44881db1f8b0e8368d0a (diff) |
r300g: Init regalloc state during context creation
Initializing the regalloc state is expensive, and since it is always
the same for every compile we only need to initialize it once per
context. This should help improve shader compile times for the driver.
Diffstat (limited to 'src/gallium/drivers/r300/compiler')
4 files changed, 191 insertions, 153 deletions
diff --git a/src/gallium/drivers/r300/compiler/radeon_compiler.c b/src/gallium/drivers/r300/compiler/radeon_compiler.c index 4d4eb645841..081cd2d0d55 100644 --- a/src/gallium/drivers/r300/compiler/radeon_compiler.c +++ b/src/gallium/drivers/r300/compiler/radeon_compiler.c @@ -29,10 +29,11 @@ #include "radeon_dataflow.h" #include "radeon_program.h" #include "radeon_program_pair.h" +#include "radeon_regalloc.h" #include "radeon_compiler_util.h" -void rc_init(struct radeon_compiler * c) +void rc_init(struct radeon_compiler * c, const struct rc_regalloc_state *rs) { memset(c, 0, sizeof(*c)); @@ -40,6 +41,7 @@ void rc_init(struct radeon_compiler * c) c->Program.Instructions.Prev = &c->Program.Instructions; c->Program.Instructions.Next = &c->Program.Instructions; c->Program.Instructions.U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE; + c->regalloc_state = rs; } void rc_destroy(struct radeon_compiler * c) diff --git a/src/gallium/drivers/r300/compiler/radeon_compiler.h b/src/gallium/drivers/r300/compiler/radeon_compiler.h index f78a51c19c3..e2710d848c5 100644 --- a/src/gallium/drivers/r300/compiler/radeon_compiler.h +++ b/src/gallium/drivers/r300/compiler/radeon_compiler.h @@ -44,6 +44,7 @@ enum rc_program_type { struct radeon_compiler { struct memory_pool Pool; struct rc_program Program; + const struct rc_regalloc_state *regalloc_state; enum rc_program_type type; unsigned Debug:2; unsigned Error:1; @@ -77,7 +78,7 @@ struct radeon_compiler { unsigned initial_num_insts; /* Number of instructions at start. */ }; -void rc_init(struct radeon_compiler * c); +void rc_init(struct radeon_compiler * c, const struct rc_regalloc_state *rs); void rc_destroy(struct radeon_compiler * c); void rc_debug(struct radeon_compiler * c, const char * fmt, ...); diff --git a/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c b/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c index 12594c81966..0a0ca116deb 100644 --- a/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c +++ b/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c @@ -39,6 +39,7 @@ #include "radeon_compiler_util.h" #include "radeon_dataflow.h" #include "radeon_list.h" +#include "radeon_regalloc.h" #include "radeon_variable.h" #define VERBOSE 0 @@ -70,47 +71,96 @@ struct regalloc_state { int LoopEnd; }; -enum rc_reg_class { - RC_REG_CLASS_SINGLE, - RC_REG_CLASS_DOUBLE, - RC_REG_CLASS_TRIPLE, - RC_REG_CLASS_ALPHA, - RC_REG_CLASS_SINGLE_PLUS_ALPHA, - RC_REG_CLASS_DOUBLE_PLUS_ALPHA, - RC_REG_CLASS_TRIPLE_PLUS_ALPHA, - RC_REG_CLASS_X, - RC_REG_CLASS_Y, - RC_REG_CLASS_Z, - RC_REG_CLASS_XY, - RC_REG_CLASS_YZ, - RC_REG_CLASS_XZ, - RC_REG_CLASS_XW, - RC_REG_CLASS_YW, - RC_REG_CLASS_ZW, - RC_REG_CLASS_XYW, - RC_REG_CLASS_YZW, - RC_REG_CLASS_XZW, - RC_REG_CLASS_COUNT -}; - struct rc_class { - enum rc_reg_class Class; + enum rc_reg_class ID; unsigned int WritemaskCount; - /** This is 1 if this class is being used by the register allocator - * and 0 otherwise */ - unsigned int Used; - - /** This is the ID number assigned to this class by ra. */ - unsigned int Id; - /** List of writemasks that belong to this class */ unsigned int Writemasks[3]; }; +static const struct rc_class rc_class_list [] = { + {RC_REG_CLASS_SINGLE, 3, + {RC_MASK_X, + RC_MASK_Y, + RC_MASK_Z}}, + {RC_REG_CLASS_DOUBLE, 3, + {RC_MASK_X | RC_MASK_Y, + RC_MASK_X | RC_MASK_Z, + RC_MASK_Y | RC_MASK_Z}}, + {RC_REG_CLASS_TRIPLE, 1, + {RC_MASK_X | RC_MASK_Y | RC_MASK_Z, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_ALPHA, 1, + {RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_SINGLE_PLUS_ALPHA, 3, + {RC_MASK_X | RC_MASK_W, + RC_MASK_Y | RC_MASK_W, + RC_MASK_Z | RC_MASK_W}}, + {RC_REG_CLASS_DOUBLE_PLUS_ALPHA, 3, + {RC_MASK_X | RC_MASK_Y | RC_MASK_W, + RC_MASK_X | RC_MASK_Z | RC_MASK_W, + RC_MASK_Y | RC_MASK_Z | RC_MASK_W}}, + {RC_REG_CLASS_TRIPLE_PLUS_ALPHA, 1, + {RC_MASK_X | RC_MASK_Y | RC_MASK_Z | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_X, 1, + {RC_MASK_X, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_Y, 1, + {RC_MASK_Y, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_Z, 1, + {RC_MASK_Z, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_XY, 1, + {RC_MASK_X | RC_MASK_Y, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_YZ, 1, + {RC_MASK_Y | RC_MASK_Z, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_XZ, 1, + {RC_MASK_X | RC_MASK_Z, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_XW, 1, + {RC_MASK_X | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_YW, 1, + {RC_MASK_Y | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_ZW, 1, + {RC_MASK_Z | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_XYW, 1, + {RC_MASK_X | RC_MASK_Y | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_YZW, 1, + {RC_MASK_Y | RC_MASK_Z | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}}, + {RC_REG_CLASS_XZW, 1, + {RC_MASK_X | RC_MASK_Z | RC_MASK_W, + RC_MASK_NONE, + RC_MASK_NONE}} +}; + static void print_live_intervals(struct live_intervals * src) { if (!src || !src->Used) { @@ -234,7 +284,7 @@ static unsigned int is_derivative(rc_opcode op) } static int find_class( - struct rc_class * classes, + const struct rc_class * classes, unsigned int writemask, unsigned int max_writemask_count) { @@ -274,7 +324,7 @@ static void variable_get_class_read_cb( static enum rc_reg_class variable_get_class( struct rc_variable * variable, - struct rc_class * classes) + const struct rc_class * classes) { unsigned int i; unsigned int can_change_writemask= 1; @@ -380,7 +430,7 @@ static enum rc_reg_class variable_get_class( can_change_writemask ? 3 : 1); done: if (class_index > -1) { - return classes[class_index].Class; + return classes[class_index].ID; } else { error: rc_error(variable->C, @@ -458,95 +508,14 @@ static void add_register_conflicts( static void do_advanced_regalloc(struct regalloc_state * s) { - struct rc_class rc_class_list [] = { - {RC_REG_CLASS_SINGLE, 3, 0, 0, - {RC_MASK_X, - RC_MASK_Y, - RC_MASK_Z}}, - {RC_REG_CLASS_DOUBLE, 3, 0, 0, - {RC_MASK_X | RC_MASK_Y, - RC_MASK_X | RC_MASK_Z, - RC_MASK_Y | RC_MASK_Z}}, - {RC_REG_CLASS_TRIPLE, 1, 0, 0, - {RC_MASK_X | RC_MASK_Y | RC_MASK_Z, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_ALPHA, 1, 0, 0, - {RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_SINGLE_PLUS_ALPHA, 3, 0, 0, - {RC_MASK_X | RC_MASK_W, - RC_MASK_Y | RC_MASK_W, - RC_MASK_Z | RC_MASK_W}}, - {RC_REG_CLASS_DOUBLE_PLUS_ALPHA, 3, 0, 0, - {RC_MASK_X | RC_MASK_Y | RC_MASK_W, - RC_MASK_X | RC_MASK_Z | RC_MASK_W, - RC_MASK_Y | RC_MASK_Z | RC_MASK_W}}, - {RC_REG_CLASS_TRIPLE_PLUS_ALPHA, 1, 0, 0, - {RC_MASK_X | RC_MASK_Y | RC_MASK_Z | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_X, 1, 0, 0, - {RC_MASK_X, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_Y, 1, 0, 0, - {RC_MASK_Y, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_Z, 1, 0, 0, - {RC_MASK_Z, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_XY, 1, 0, 0, - {RC_MASK_X | RC_MASK_Y, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_YZ, 1, 0, 0, - {RC_MASK_Y | RC_MASK_Z, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_XZ, 1, 0, 0, - {RC_MASK_X | RC_MASK_Z, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_XW, 1, 0, 0, - {RC_MASK_X | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_YW, 1, 0, 0, - {RC_MASK_Y | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_ZW, 1, 0, 0, - {RC_MASK_Z | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_XYW, 1, 0, 0, - {RC_MASK_X | RC_MASK_Y | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_YZW, 1, 0, 0, - {RC_MASK_Y | RC_MASK_Z | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}}, - {RC_REG_CLASS_XZW, 1, 0, 0, - {RC_MASK_X | RC_MASK_Z | RC_MASK_W, - RC_MASK_NONE, - RC_MASK_NONE}} - }; - - unsigned int i, j, index, input_node, node_count, node_index; + + unsigned int i, input_node, node_count, node_index; unsigned int * node_classes; struct rc_instruction * inst; struct rc_list * var_ptr; struct rc_list * variables; - struct ra_regs * regs; struct ra_graph * graph; - - /* Allocate the main ra data structure */ - regs = ra_alloc_reg_set(NULL, s->C->max_temp_regs * RC_MASK_XYZW); + const struct rc_regalloc_state *ra_state = s->C->regalloc_state; /* Get list of program variables */ variables = rc_get_variables(s->C); @@ -561,37 +530,10 @@ static void do_advanced_regalloc(struct regalloc_state * s) rc_variable_compute_live_intervals(var_ptr->Item); class_index = variable_get_class(var_ptr->Item, rc_class_list); - - /* If we haven't used this register class yet, mark it - * as used and allocate space for it. */ - if (!rc_class_list[class_index].Used) { - rc_class_list[class_index].Used = 1; - rc_class_list[class_index].Id = ra_alloc_reg_class(regs); - } - - node_classes[node_index] = rc_class_list[class_index].Id; + node_classes[node_index] = ra_state->class_ids[class_index]; } - /* Assign registers to the classes */ - for (i = 0; i < RC_REG_CLASS_COUNT; i++) { - struct rc_class class = rc_class_list[i]; - if (!class.Used) { - continue; - } - - for (index = 0; index < s->C->max_temp_regs; index++) { - for (j = 0; j < class.WritemaskCount; j++) { - int reg_id = get_reg_id(index, - class.Writemasks[j]); - ra_class_add_reg(regs, class.Id, reg_id); - } - } - } - - /* Add register conflicts */ - add_register_conflicts(regs, s->C->max_temp_regs); - /* Calculate live intervals for input registers */ for (inst = s->C->Program.Instructions.Next; inst != &s->C->Program.Instructions; @@ -609,7 +551,7 @@ static void do_advanced_regalloc(struct regalloc_state * s) /* Compute the writemask for inputs. */ for (i = 0; i < s->NumInputs; i++) { - unsigned int chan, class_id, writemask = 0; + unsigned int chan, writemask = 0; for (chan = 0; chan < 4; chan++) { if (s->Input[i].Live[chan].Used) { writemask |= (1 << chan); @@ -618,9 +560,8 @@ static void do_advanced_regalloc(struct regalloc_state * s) s->Input[i].Writemask = writemask; } - ra_set_finalize(regs, NULL); - - graph = ra_alloc_interference_graph(regs, node_count + s->NumInputs); + graph = ra_alloc_interference_graph(ra_state->regs, + node_count + s->NumInputs); /* Build the interference graph */ for (var_ptr = variables, node_index = 0; var_ptr; @@ -691,7 +632,39 @@ static void do_advanced_regalloc(struct regalloc_state * s) } ralloc_free(graph); - ralloc_free(regs); +} + +void rc_init_regalloc_state(struct rc_regalloc_state *s) +{ + unsigned i, j, index; + /* Allocate the main ra data structure */ + s->regs = ra_alloc_reg_set(NULL, R500_PFS_NUM_TEMP_REGS * RC_MASK_XYZW); + + /* Create the register classes */ + for (i = 0; i < RC_REG_CLASS_COUNT; i++) { + const struct rc_class *class = &rc_class_list[i]; + s->class_ids[class->ID] = ra_alloc_reg_class(s->regs); + + /* Assign registers to the classes */ + for (index = 0; index < R500_PFS_NUM_TEMP_REGS; index++) { + for (j = 0; j < class->WritemaskCount; j++) { + int reg_id = get_reg_id(index, + class->Writemasks[j]); + ra_class_add_reg(s->regs, + s->class_ids[class->ID], reg_id); + } + } + } + + /* Add register conflicts */ + add_register_conflicts(s->regs, R500_PFS_NUM_TEMP_REGS); + + ra_set_finalize(s->regs, NULL); +} + +void rc_destroy_regalloc_state(struct rc_regalloc_state *s) +{ + ralloc_free(s->regs); } /** diff --git a/src/gallium/drivers/r300/compiler/radeon_regalloc.h b/src/gallium/drivers/r300/compiler/radeon_regalloc.h new file mode 100644 index 00000000000..260a3caf91d --- /dev/null +++ b/src/gallium/drivers/r300/compiler/radeon_regalloc.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Author: Tom Stellard <[email protected]> + */ + +#ifndef RADEON_REGALLOC_H +#define RADEON_REGALLOC_H + +struct ra_regs; + +enum rc_reg_class { + RC_REG_CLASS_SINGLE, + RC_REG_CLASS_DOUBLE, + RC_REG_CLASS_TRIPLE, + RC_REG_CLASS_ALPHA, + RC_REG_CLASS_SINGLE_PLUS_ALPHA, + RC_REG_CLASS_DOUBLE_PLUS_ALPHA, + RC_REG_CLASS_TRIPLE_PLUS_ALPHA, + RC_REG_CLASS_X, + RC_REG_CLASS_Y, + RC_REG_CLASS_Z, + RC_REG_CLASS_XY, + RC_REG_CLASS_YZ, + RC_REG_CLASS_XZ, + RC_REG_CLASS_XW, + RC_REG_CLASS_YW, + RC_REG_CLASS_ZW, + RC_REG_CLASS_XYW, + RC_REG_CLASS_YZW, + RC_REG_CLASS_XZW, + RC_REG_CLASS_COUNT +}; + +struct rc_regalloc_state { + struct ra_regs *regs; + unsigned class_ids[RC_REG_CLASS_COUNT]; +}; + +void rc_init_regalloc_state(struct rc_regalloc_state *s); +void rc_destroy_regalloc_state(struct rc_regalloc_state *s); + +#endif /* RADEON_REGALLOC_H */ |