r300g: Init regalloc state during context creation
authorTom Stellard <thomas.stellard@amd.com>
Thu, 6 Sep 2012 04:20:27 +0000 (00:20 -0400)
committerTom Stellard <thomas.stellard@amd.com>
Wed, 19 Sep 2012 23:25:53 +0000 (19:25 -0400)
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.

src/gallium/drivers/r300/compiler/radeon_compiler.c
src/gallium/drivers/r300/compiler/radeon_compiler.h
src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c
src/gallium/drivers/r300/compiler/radeon_regalloc.h [new file with mode: 0644]
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_fs.c
src/gallium/drivers/r300/r300_vs.c

index 4d4eb6458412bc5b8591a28fa39c1ea8c4a99967..081cd2d0d5557e3344e185465bb04b176e09e67c 100644 (file)
 #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)
index f78a51c19c3f544c9f926d0f995666eb8782815c..e2710d848c5ac6cf938a1dabb4ae8b48b476fb01 100644 (file)
@@ -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, ...);
index 12594c8196607f3e28e2093e62a5c0354813203c..0a0ca116deb3b86f480deb04cc1698fedf69e23f 100644 (file)
@@ -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 (file)
index 0000000..260a3ca
--- /dev/null
@@ -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 <thomas.stellard@amd.com>
+ */
+
+#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 */
index 8cbe246f7872e387e248ab70b2f4764135da6875..76c2e232009940e58f4be0b35d963d96133463c4 100644 (file)
@@ -35,6 +35,7 @@
 #include "r300_emit.h"
 #include "r300_screen.h"
 #include "r300_screen_buffer.h"
+#include "compiler/radeon_regalloc.h"
 
 static void r300_release_referenced_objects(struct r300_context *r300)
 {
@@ -89,6 +90,8 @@ static void r300_destroy_context(struct pipe_context* context)
     if (r300->cs)
         r300->rws->cs_destroy(r300->cs);
 
+    rc_destroy_regalloc_state(&r300->fs_regalloc_state);
+
     /* XXX: No way to tell if this was initialized or not? */
     util_slab_destroy(&r300->pool_transfers);
 
@@ -466,6 +469,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300->hyperz_time_of_last_flush = os_time_get();
 
+    /* Register allocator state */
+    rc_init_regalloc_state(&r300->fs_regalloc_state);
+
     /* Print driver info. */
 #ifdef DEBUG
     {
index 2c7b477685a7b67573485d08ad3dd730ab7809ab..fe2530890948a23a28f45f020d759c335e41b1ce 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "r300_defines.h"
 #include "r300_screen.h"
+#include "compiler/radeon_regalloc.h"
 #include "../../winsys/radeon/drm/radeon_winsys.h"
 
 struct u_upload_mgr;
@@ -622,6 +623,10 @@ struct r300_context {
     boolean hiz_in_use;         /* Whether HIZ is enabled. */
     enum r300_hiz_func hiz_func; /* HiZ function. Can be either MIN or MAX. */
     uint32_t hiz_clear_value;   /* HiZ clear value. */
+
+    /* Compiler state. */
+    struct rc_regalloc_state fs_regalloc_state; /* Register allocator info for
+                                                 * fragment shaders. */
 };
 
 #define foreach_atom(r300, atom) \
index 8a492d2b40d1be6e26b4c8b9c1b05500b792ab7e..0842f9ad5dc741662d175f88df21a41354bd8a92 100644 (file)
@@ -442,7 +442,7 @@ static void r300_translate_fragment_shader(
 
     /* Setup the compiler. */
     memset(&compiler, 0, sizeof(compiler));
-    rc_init(&compiler.Base);
+    rc_init(&compiler.Base, &r300->fs_regalloc_state);
     DBG_ON(r300, DBG_FP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
     DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0;
 
index 4faf2b58b0f8e84c3698117f7b1ccced55280ef5..ea0621e2d3e485285b56e400bf88e0725b3478a3 100644 (file)
@@ -210,7 +210,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
 
     /* Setup the compiler */
     memset(&compiler, 0, sizeof(compiler));
-    rc_init(&compiler.Base);
+    rc_init(&compiler.Base, NULL);
 
     DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
     DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0;