summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <tstellar@gmail.com>2010-11-08 18:49:44 -0800
committerTom Stellard <tstellar@gmail.com>2010-11-21 18:48:31 -0800
commitbbe49bc585c4fed46f55d184b463d13bddd97f1b (patch)
tree55597798857bcf9d1ed8f8d0c53fbb160d5fabd8
parentddceededf850c942c1bb8185ec7dc0c203d3bad6 (diff)
r300/compiler: Use presubtract operations as much as possible
Previously, presubtract operations where only being used by instructions with less than three source source registers.
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c122
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h15
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c16
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_optimize.c36
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c17
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h5
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c52
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h8
8 files changed, 204 insertions, 67 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
index 97f4c75849..2b8d284ce9 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
@@ -31,6 +31,8 @@
#include "radeon_compiler_util.h"
+#include "radeon_compiler.h"
+#include "radeon_dataflow.h"
/**
*/
unsigned int rc_swizzle_to_writemask(unsigned int swz)
@@ -59,3 +61,123 @@ unsigned int rc_src_reads_dst_mask(
}
return dst_mask & rc_swizzle_to_writemask(src_swz);
}
+
+unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels)
+{
+ unsigned int chan;
+ unsigned int swz = RC_SWIZZLE_UNUSED;
+ unsigned int ret = RC_SOURCE_NONE;
+
+ for(chan = 0; chan < channels; chan++) {
+ swz = GET_SWZ(swizzle, chan);
+ if (swz == RC_SWIZZLE_W) {
+ ret |= RC_SOURCE_ALPHA;
+ } else if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y
+ || swz == RC_SWIZZLE_Z) {
+ ret |= RC_SOURCE_RGB;
+ }
+ }
+ return ret;
+}
+
+unsigned int rc_source_type_mask(unsigned int mask)
+{
+ unsigned int ret = RC_SOURCE_NONE;
+
+ if (mask & RC_MASK_XYZ)
+ ret |= RC_SOURCE_RGB;
+
+ if (mask & RC_MASK_W)
+ ret |= RC_SOURCE_ALPHA;
+
+ return ret;
+}
+
+struct can_use_presub_data {
+ struct rc_src_register RemoveSrcs[3];
+ unsigned int RGBCount;
+ unsigned int AlphaCount;
+};
+
+static void can_use_presub_read_cb(
+ void * userdata,
+ struct rc_instruction * inst,
+ rc_register_file file,
+ unsigned int index,
+ unsigned int mask)
+{
+ struct can_use_presub_data * d = userdata;
+ unsigned int src_type = rc_source_type_mask(mask);
+ unsigned int i;
+
+ if (file == RC_FILE_NONE)
+ return;
+
+ for(i = 0; i < 3; i++) {
+ if (d->RemoveSrcs[i].File == file
+ && d->RemoveSrcs[i].Index == index) {
+ src_type &=
+ ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle, 4);
+ }
+ }
+
+ if (src_type & RC_SOURCE_RGB)
+ d->RGBCount++;
+
+ if (src_type & RC_SOURCE_ALPHA)
+ d->AlphaCount++;
+}
+
+unsigned int rc_inst_can_use_presub(
+ struct rc_instruction * inst,
+ rc_presubtract_op presub_op,
+ unsigned int presub_writemask,
+ struct rc_src_register replace_reg,
+ struct rc_src_register presub_src0,
+ struct rc_src_register presub_src1)
+{
+ struct can_use_presub_data d;
+ unsigned int num_presub_srcs;
+ unsigned int presub_src_type = rc_source_type_mask(presub_writemask);
+ const struct rc_opcode_info * info =
+ rc_get_opcode_info(inst->U.I.Opcode);
+
+ if (presub_op == RC_PRESUB_NONE) {
+ return 1;
+ }
+
+ if (info->HasTexture) {
+ return 0;
+ }
+
+ /* We can't use more than one presubtract value in an
+ * instruction, unless the two prsubtract operations
+ * are the same and read from the same registers.
+ * XXX For now we will limit instructions to only one presubtract
+ * value.*/
+ if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE) {
+ return 0;
+ }
+
+ memset(&d, 0, sizeof(d));
+ d.RemoveSrcs[0] = replace_reg;
+ d.RemoveSrcs[1] = presub_src0;
+ d.RemoveSrcs[2] = presub_src1;
+
+ rc_for_all_reads_mask(inst, can_use_presub_read_cb, &d);
+
+ num_presub_srcs = rc_presubtract_src_reg_count(presub_op);
+
+ if ((presub_src_type & RC_SOURCE_RGB)
+ && d.RGBCount + num_presub_srcs > 3) {
+ return 0;
+ }
+
+ if ((presub_src_type & RC_SOURCE_ALPHA)
+ && d.AlphaCount + num_presub_srcs > 3) {
+ return 0;
+ }
+
+ return 1;
+}
+
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
index 1a14e7cb0e..e50dfbd4fb 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
@@ -3,6 +3,9 @@
#ifndef RADEON_PROGRAM_UTIL_H
#define RADEON_PROGRAM_UTIL_H
+struct rc_instruction;
+struct rc_src_register;
+
unsigned int rc_swizzle_to_writemask(unsigned int swz);
unsigned int rc_src_reads_dst_mask(
@@ -13,4 +16,16 @@ unsigned int rc_src_reads_dst_mask(
unsigned int dst_idx,
unsigned int dst_mask);
+unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels);
+
+unsigned int rc_source_type_mask(unsigned int mask);
+
+unsigned int rc_inst_can_use_presub(
+ struct rc_instruction * inst,
+ rc_presubtract_op presub_op,
+ unsigned int presub_writemask,
+ struct rc_src_register replace_reg,
+ struct rc_src_register presub_src0,
+ struct rc_src_register presub_src1);
+
#endif /* RADEON_PROGRAM_UTIL_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
index 600be8b886..9df07edf2b 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
@@ -139,9 +139,17 @@ static void pair_sub_for_all_args(
const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);
for(i = 0; i < info->NumSrcRegs; i++) {
- unsigned int src_type = rc_source_type_that_arg_reads(
- sub->Arg[i].Source, sub->Arg[i].Swizzle);
- if (src_type == RC_PAIR_SOURCE_NONE)
+ unsigned int src_type;
+ unsigned int channels = 0;
+ if (&fullinst->U.P.RGB == sub)
+ channels = 3;
+ else if (&fullinst->U.P.Alpha == sub)
+ channels = 1;
+
+ assert(channels > 0);
+ src_type = rc_source_type_swz(sub->Arg[i].Swizzle, channels);
+
+ if (src_type == RC_SOURCE_NONE)
continue;
if (sub->Arg[i].Source == RC_PAIR_PRESUB_SRC) {
@@ -149,7 +157,7 @@ static void pair_sub_for_all_args(
unsigned int presub_src_count;
struct rc_pair_instruction_source * src_array;
unsigned int j;
- if (src_type & RC_PAIR_SOURCE_RGB) {
+ if (src_type & RC_SOURCE_RGB) {
presub_type = fullinst->
U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Index;
src_array = fullinst->U.P.RGB.Src;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
index 2eb548474f..27b10ffbd6 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
@@ -71,12 +71,13 @@ static void copy_propagate_scan_read(void * data, struct rc_instruction * inst,
{
rc_register_file file = src->File;
struct rc_reader_data * reader_data = data;
- const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode);
- /* It is possible to do copy propigation in this situation,
- * just not right now, see peephole_add_presub_inv() */
- if (reader_data->Writer->U.I.PreSub.Opcode != RC_PRESUB_NONE &&
- (info->NumSrcRegs > 2 || info->HasTexture)) {
+ if(!rc_inst_can_use_presub(inst,
+ reader_data->Writer->U.I.PreSub.Opcode,
+ rc_swizzle_to_writemask(src->Swizzle),
+ *src,
+ reader_data->Writer->U.I.PreSub.SrcReg[0],
+ reader_data->Writer->U.I.PreSub.SrcReg[1])) {
reader_data->Abort = 1;
return;
}
@@ -424,24 +425,13 @@ static void presub_scan_read(
struct rc_src_register * src)
{
struct rc_reader_data * reader_data = data;
- const struct rc_opcode_info * info =
- rc_get_opcode_info(inst->U.I.Opcode);
- /* XXX: There are some situations where instructions
- * with more than 2 src registers can use the
- * presubtract select, but to keep things simple we
- * will disable presubtract on these instructions for
- * now. */
- if (info->NumSrcRegs > 2 || info->HasTexture) {
- reader_data->Abort = 1;
- return;
- }
+ rc_presubtract_op * presub_opcode = reader_data->CbData;
- /* We can't use more than one presubtract value in an
- * instruction, unless the two prsubtract operations
- * are the same and read from the same registers.
- * XXX For now we will limit instructions to only one presubtract
- * value.*/
- if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE) {
+ if (!rc_inst_can_use_presub(inst, *presub_opcode,
+ reader_data->Writer->U.I.DstReg.WriteMask,
+ *src,
+ reader_data->Writer->U.I.SrcReg[0],
+ reader_data->Writer->U.I.SrcReg[1])) {
reader_data->Abort = 1;
return;
}
@@ -455,7 +445,9 @@ static int presub_helper(
{
struct rc_reader_data reader_data;
unsigned int i;
+ rc_presubtract_op cb_op = presub_opcode;
+ reader_data.CbData = &cb_op;
rc_get_readers(c, inst_add, &reader_data, presub_scan_read, NULL,
is_src_clobbered_scan_write);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
index cce253f11e..cbb5ef6237 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
@@ -30,6 +30,7 @@
#include <stdio.h>
#include "radeon_compiler.h"
+#include "radeon_compiler_util.h"
#include "radeon_dataflow.h"
@@ -301,12 +302,12 @@ static int merge_presub_sources(
assert(dst_full->Alpha.Opcode == RC_OPCODE_NOP);
switch(type) {
- case RC_PAIR_SOURCE_RGB:
+ case RC_SOURCE_RGB:
is_rgb = 1;
is_alpha = 0;
dst_sub = &dst_full->RGB;
break;
- case RC_PAIR_SOURCE_ALPHA:
+ case RC_SOURCE_ALPHA:
is_rgb = 0;
is_alpha = 1;
dst_sub = &dst_full->Alpha;
@@ -347,6 +348,8 @@ static int merge_presub_sources(
continue;
free_source = rc_pair_alloc_source(dst_full, is_rgb,
is_alpha, temp.File, temp.Index);
+ if (free_source < 0)
+ return 0;
one_way = 1;
} else {
dst_sub->Src[free_source] = temp;
@@ -362,11 +365,11 @@ static int merge_presub_sources(
for(arg = 0; arg < info->NumSrcRegs; arg++) {
/*If this arg does not read from an rgb source,
* do nothing. */
- if (!(rc_source_type_that_arg_reads(
- dst_full->RGB.Arg[arg].Source,
- dst_full->RGB.Arg[arg].Swizzle) & type)) {
+ if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle,
+ 3) & type)) {
continue;
}
+
if (dst_full->RGB.Arg[arg].Source == srcp_src)
dst_full->RGB.Arg[arg].Source = free_source;
/* We need to do this just in case register
@@ -398,13 +401,13 @@ static int destructive_merge_instructions(
/* Merge the rgb presubtract registers. */
if (alpha->RGB.Src[RC_PAIR_PRESUB_SRC].Used) {
- if (!merge_presub_sources(rgb, alpha->RGB, RC_PAIR_SOURCE_RGB)) {
+ if (!merge_presub_sources(rgb, alpha->RGB, RC_SOURCE_RGB)) {
return 0;
}
}
/* Merge the alpha presubtract registers */
if (alpha->Alpha.Src[RC_PAIR_PRESUB_SRC].Used) {
- if(!merge_presub_sources(rgb, alpha->Alpha, RC_PAIR_SOURCE_ALPHA)){
+ if(!merge_presub_sources(rgb, alpha->Alpha, RC_SOURCE_ALPHA)){
return 0;
}
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h
index 9dcd44c522..45f79ece5b 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_constants.h
@@ -181,4 +181,9 @@ static inline int rc_presubtract_src_reg_count(rc_presubtract_op op){
return 0;
}
}
+
+#define RC_SOURCE_NONE 0x0
+#define RC_SOURCE_RGB 0x1
+#define RC_SOURCE_ALPHA 0x2
+
#endif /* RADEON_PROGRAM_CONSTANTS_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
index 582d73b61f..5905d26e52 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
@@ -27,6 +27,8 @@
#include "radeon_program_pair.h"
+#include "radeon_compiler_util.h"
+
#include <stdlib.h>
/**
@@ -205,37 +207,35 @@ void rc_pair_foreach_source_that_rgb_reads(
}
}
-/*return 0 for rgb, 1 for alpha -1 for error. */
-
-unsigned int rc_source_type_that_arg_reads(
- unsigned int source,
- unsigned int swizzle)
-{
- unsigned int chan;
- unsigned int swz = RC_SWIZZLE_UNUSED;
- unsigned int ret = RC_PAIR_SOURCE_NONE;
-
- for(chan = 0; chan < 3; chan++) {
- swz = GET_SWZ(swizzle, chan);
- if (swz == RC_SWIZZLE_W) {
- ret |= RC_PAIR_SOURCE_ALPHA;
- } else if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y
- || swz == RC_SWIZZLE_Z) {
- ret |= RC_PAIR_SOURCE_RGB;
- }
- }
- return ret;
-}
-
struct rc_pair_instruction_source * rc_pair_get_src(
struct rc_pair_instruction * pair_inst,
struct rc_pair_instruction_arg * arg)
{
- unsigned int type = rc_source_type_that_arg_reads(arg->Source,
- arg->Swizzle);
- if (type & RC_PAIR_SOURCE_RGB) {
+ unsigned int i, type;
+ unsigned int channels = 0;
+
+ for(i = 0; i < 3; i++) {
+ if (arg == pair_inst->RGB.Arg + i) {
+ channels = 3;
+ break;
+ }
+ }
+
+ if (channels == 0) {
+ for (i = 0; i < 3; i++) {
+ if (arg == pair_inst->Alpha.Arg + i) {
+ channels = 1;
+ break;
+ }
+ }
+ }
+
+ assert(channels > 0);
+ type = rc_source_type_swz(arg->Swizzle, channels);
+
+ if (type & RC_SOURCE_RGB) {
return &pair_inst->RGB.Src[arg->Source];
- } else if (type & RC_PAIR_SOURCE_ALPHA) {
+ } else if (type & RC_SOURCE_ALPHA) {
return &pair_inst->Alpha.Src[arg->Source];
} else {
return NULL;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
index 54ca56762b..ccf7a0070c 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
@@ -55,10 +55,6 @@ struct radeon_compiler;
*/
#define RC_PAIR_PRESUB_SRC 3
-#define RC_PAIR_SOURCE_NONE 0x0
-#define RC_PAIR_SOURCE_RGB 0x1
-#define RC_PAIR_SOURCE_ALPHA 0x2
-
struct rc_pair_instruction_source {
unsigned int Used:1;
unsigned int File:3;
@@ -115,10 +111,6 @@ void rc_pair_foreach_source_that_rgb_reads(
void * data,
rc_pair_foreach_src_fn cb);
-unsigned int rc_source_type_that_arg_reads(
- unsigned int source,
- unsigned int swizzle);
-
struct rc_pair_instruction_source * rc_pair_get_src(
struct rc_pair_instruction * pair_inst,
struct rc_pair_instruction_arg * arg);