Mesa (master): r300/compiler: Use presubtract operations as much as possible

Tom Stellard tstellar at kemper.freedesktop.org
Mon Nov 22 05:41:38 UTC 2010


Module: Mesa
Branch: master
Commit: bbe49bc585c4fed46f55d184b463d13bddd97f1b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bbe49bc585c4fed46f55d184b463d13bddd97f1b

Author: Tom Stellard <tstellar at gmail.com>
Date:   Mon Nov  8 18:49:44 2010 -0800

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.

---

 .../dri/r300/compiler/radeon_compiler_util.c       |  122 ++++++++++++++++++++
 .../dri/r300/compiler/radeon_compiler_util.h       |   15 +++
 .../drivers/dri/r300/compiler/radeon_dataflow.c    |   16 ++-
 .../drivers/dri/r300/compiler/radeon_optimize.c    |   36 +++----
 .../dri/r300/compiler/radeon_pair_schedule.c       |   17 ++-
 .../dri/r300/compiler/radeon_program_constants.h   |    5 +
 .../dri/r300/compiler/radeon_program_pair.c        |   52 ++++----
 .../dri/r300/compiler/radeon_program_pair.h        |    8 --
 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 97f4c75..2b8d284 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 1a14e7c..e50dfbd 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 600be8b..9df07ed 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 2eb5484..27b10ff 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 cce253f..cbb5ef6 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 9dcd44c..45f79ec 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 582d73b..5905d26 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 54ca567..ccf7a00 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);




More information about the mesa-commit mailing list