Mesa (master): r300g/compiler/tests: Add an assembly parser

Tom Stellard tstellar at kemper.freedesktop.org
Mon Jul 1 04:37:08 UTC 2013


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

Author: Tom Stellard <thomas.stellard at amd.com>
Date:   Sun Mar 10 20:55:26 2013 -0400

r300g/compiler/tests: Add an assembly parser

The assembly parser can be used to load r300 assembly dumps
and run them through any of the r300 compiler passes.

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

---

 .../r300/compiler/tests/omod_two_writers.test      |    5 +
 .../r300/compiler/tests/r300_compiler_tests.h      |    1 +
 .../tests/radeon_compiler_optimize_tests.c         |   33 +++--
 .../drivers/r300/compiler/tests/rc_test_helpers.c  |  161 +++++++++++++++++++-
 .../drivers/r300/compiler/tests/rc_test_helpers.h  |   16 ++
 5 files changed, 200 insertions(+), 16 deletions(-)

diff --git a/src/gallium/drivers/r300/compiler/tests/omod_two_writers.test b/src/gallium/drivers/r300/compiler/tests/omod_two_writers.test
new file mode 100644
index 0000000..fb16bb0
--- /dev/null
+++ b/src/gallium/drivers/r300/compiler/tests/omod_two_writers.test
@@ -0,0 +1,5 @@
+RCP temp[0].x, const[1].x___;
+RCP temp[0].y, const[1]._y__;
+MUL temp[1].xy, const[0].xx__, temp[0].xy__;
+MOV output[0].xy, temp[1].xy;
+=
diff --git a/src/gallium/drivers/r300/compiler/tests/r300_compiler_tests.h b/src/gallium/drivers/r300/compiler/tests/r300_compiler_tests.h
index 266addf..d40834a 100644
--- a/src/gallium/drivers/r300/compiler/tests/r300_compiler_tests.h
+++ b/src/gallium/drivers/r300/compiler/tests/r300_compiler_tests.h
@@ -26,4 +26,5 @@
  */
 
 unsigned radeon_compiler_optimize_run_tests(void);
+unsigned radeon_compiler_regalloc_run_tests(void);
 unsigned radeon_compiler_util_run_tests(void);
diff --git a/src/gallium/drivers/r300/compiler/tests/radeon_compiler_optimize_tests.c b/src/gallium/drivers/r300/compiler/tests/radeon_compiler_optimize_tests.c
index 600228e..819fb6c 100644
--- a/src/gallium/drivers/r300/compiler/tests/radeon_compiler_optimize_tests.c
+++ b/src/gallium/drivers/r300/compiler/tests/radeon_compiler_optimize_tests.c
@@ -30,30 +30,42 @@
 #include "rc_test_helpers.h"
 #include "unit_test.h"
 
+static unsigned test_rc_optimize(
+	struct test_result * result,
+	struct radeon_compiler * c,
+	const char * filename)
+{
+	struct rc_test_file test_file;
+
+	test_begin(result);
+
+	if (!load_program(c, &test_file, filename)) {
+		fprintf(stderr, "Failed to load program\n");
+		return 0;
+	}
+
+	rc_optimize(c, NULL);
+	return 1;
+}
+
 static void test_runner_rc_optimize(struct test_result * result)
 {
+	unsigned pass = 1;
 	struct radeon_compiler c;
 	struct rc_instruction *inst;
 	struct rc_instruction *inst_list[3];
 	unsigned inst_count = 0;
 	float const0[4] = {2.0f, 0.0f, 0.0f, 0.0f};
-	unsigned pass = 1;
 
-	test_begin(result);
 	init_compiler(&c, RC_FRAGMENT_PROGRAM, 1, 0);
 
 	rc_constants_add_immediate_vec4(&c.Program.Constants, const0);
 
-	add_instruction(&c, "RCP temp[0].x, const[1].x___;");
-	add_instruction(&c, "RCP temp[0].y, const[1]._y__;");
-	add_instruction(&c, "MUL temp[1].xy, const[0].xx__, temp[0].xy__;");
-	add_instruction(&c, "MOV output[0].xy, temp[1].xy;" );
-
-	rc_optimize(&c, NULL);
+	test_rc_optimize(result, &c, "omod_two_writers.test");
 
 	for(inst = c.Program.Instructions.Next;
-					inst != &c.Program.Instructions;
-					inst = inst->Next, inst_count++) {
+				inst != &c.Program.Instructions;
+				inst = inst->Next, inst_count++) {
 		inst_list[inst_count] = inst;
 	}
 
@@ -62,6 +74,7 @@ static void test_runner_rc_optimize(struct test_result * result)
 			inst_list[2]->U.I.Opcode != RC_OPCODE_MOV) {
 		pass = 0;
 	}
+
 	test_check(result, pass);
 }
 
diff --git a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c
index 551fe05..af7b3ce 100644
--- a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c
+++ b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c
@@ -42,6 +42,7 @@
 #include "radeon_program.h"
 #include "radeon_regalloc.h"
 #include "radeon_swizzle.h"
+#include "util/u_math.h"
 
 #include "rc_test_helpers.h"
 
@@ -61,6 +62,16 @@ struct match_info {
 	int Length;
 };
 
+static int is_whitespace(const char *str)
+{
+	regex_t regex;
+	if (regcomp(&regex, "^[ \n]+$", REG_EXTENDED)) {
+		fprintf(stderr, "Failed to compile whitespace regex\n");
+		return 0;
+	}
+	return regexec(&regex, str, 0, NULL, 0) != REG_NOMATCH;
+}
+
 static int match_length(regmatch_t * matches, int index)
 {
 	return matches[index].rm_eo - matches[index].rm_so;
@@ -124,7 +135,7 @@ int init_rc_normal_src(
 	unsigned int src_index,
 	const char * src_str)
 {
-	const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[([[:digit:]])\\](\\.*[[:lower:]-]*)";
+	const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]_]*)";
 	regmatch_t matches[REGEX_SRC_MATCHES];
 	struct src_tokens tokens;
 	struct rc_src_register * src_reg = &inst->U.I.SrcReg[src_index];
@@ -187,7 +198,8 @@ int init_rc_normal_src(
 			fprintf(stderr, "First char of swizzle is not valid.\n");
 			return 0;
 		}
-		for (i = 0; i < 4; i++, str_index++) {
+		for (i = 0; i < 4 && str_index < tokens.Swizzle.Length;
+							i++, str_index++) {
 			if (tokens.Swizzle.String[str_index] == '-') {
 				src_reg->Negate |= (1 << i);
 				str_index++;
@@ -218,7 +230,8 @@ int init_rc_normal_src(
 				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_UNUSED);
 				break;
 			default:
-				fprintf(stderr, "Unknown src register swizzle.\n");
+				fprintf(stderr, "Unknown src register swizzle: %c\n",
+						tokens.Swizzle.String[str_index]);
 				return 0;
 			}
 		}
@@ -251,7 +264,7 @@ int init_rc_normal_dst(
 	struct rc_instruction * inst,
 	const char * dst_str)
 {
-	const char * regex_str = "([[:lower:]]*)\\[([[:digit:]]*)\\](\\.*[[:lower:]]*)";
+	const char * regex_str = "([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]]*)";
 	regmatch_t matches[REGEX_DST_MATCHES];
 	struct dst_tokens tokens;
 	unsigned int i;
@@ -275,6 +288,9 @@ int init_rc_normal_dst(
 		inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
 	} else if (!strncmp(tokens.File.String, "output", tokens.File.Length)) {
 		inst->U.I.DstReg.File = RC_FILE_OUTPUT;
+	} else if (!strncmp(tokens.File.String, "none", tokens.File.Length)) {
+		inst->U.I.DstReg.File = RC_FILE_NONE;
+		return 1;
 	} else {
 		fprintf(stderr, "Unknown dst register file type.\n");
 		return 0;
@@ -314,7 +330,8 @@ int init_rc_normal_dst(
 				inst->U.I.DstReg.WriteMask |= RC_MASK_W;
 				break;
 			default:
-				fprintf(stderr, "Unknown swizzle in writemask.\n");
+				fprintf(stderr, "Unknown swizzle in writemask: %c\n",
+							tokens.WriteMask.String[i]);
 				return 0;
 			}
 		}
@@ -327,6 +344,7 @@ int init_rc_normal_dst(
 }
 
 #define REGEX_INST_MATCHES 7
+#define REGEX_CONST_MATCHES 5
 
 struct inst_tokens {
 	struct match_info Opcode;
@@ -351,7 +369,7 @@ int parse_rc_normal_instruction(
 	struct rc_instruction * inst,
 	const char * inst_str)
 {
-	const char * regex_str = "([[:upper:]]+)(_SAT)* ([^,]*)[, ]*([^,]*)[, ]*([^,]*)[, ]*([^;]*)";
+	const char * regex_str = "[[:digit:]: ]*([[:upper:][:digit:]]+)(_SAT)*[ ]*([^,;]*)[, ]*([^,;]*)[, ]*([^,;]*)[, ]*([^;]*)";
 	int i;
 	regmatch_t matches[REGEX_INST_MATCHES];
 	struct inst_tokens tokens;
@@ -408,11 +426,24 @@ int parse_rc_normal_instruction(
 			src_str[tokens.Srcs[j].Length] = '\0';
 			init_rc_normal_src(inst, j, src_str);
 		}
+		if (info->HasTexture) {
+			/* XXX: Will this always be XYZW ? */
+			inst->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
+		}
 		break;
 	}
 	return 1;
 }
 
+#define INDEX_TOKEN_LEN 4
+#define FLOAT_TOKEN_LEN 50
+int parse_constant(unsigned *index, float *data, const char *const_str)
+{
+	int matched = sscanf(const_str, "const[%d] {%f, %f, %f, %f}", index,
+				&data[0], &data[1], &data[2], &data[3]);
+	return matched == 5;
+}
+
 int init_rc_normal_instruction(
 	struct rc_instruction * inst,
 	const char * inst_str)
@@ -432,6 +463,44 @@ void add_instruction(struct radeon_compiler *c, const char * inst_string)
 
 }
 
+int add_constant(struct radeon_compiler *c, const char *const_str)
+{
+	float data[4];
+	unsigned index;
+	struct rc_constant_list *constants;
+	struct rc_constant constant;
+
+	if (!parse_constant(&index, data, const_str)) {
+		return 0;
+	}
+
+	constants = &c->Program.Constants;
+	if (constants->_Reserved < index) {
+		struct rc_constant * newlist;
+
+		constants->_Reserved = index + 100;
+
+		newlist = malloc(sizeof(struct rc_constant) * constants->_Reserved);
+		if (constants->Constants) {
+			memcpy(newlist, constants->Constants,
+				sizeof(struct rc_constant) *
+					constants->_Reserved);
+			free(constants->Constants);
+		}
+
+		constants->Constants = newlist;
+	}
+
+	memset(&constant, 0, sizeof(constant));
+	constant.Type = RC_CONSTANT_IMMEDIATE;
+	constant.Size = 4;
+	memcpy(constant.u.Immediate, data, sizeof(float) * 4);
+	constants->Constants[index] = constant;
+	constants->Count = MAX2(constants->Count, index + 1);
+
+	return 1;
+}
+
 void init_compiler(
 	struct radeon_compiler *c,
 	enum rc_program_type program_type,
@@ -439,6 +508,7 @@ void init_compiler(
 	unsigned is_r400)
 {
 	struct rc_regalloc_state *rs = malloc(sizeof(struct rc_regalloc_state));
+	rc_init_regalloc_state(rs);
 	rc_init(c, rs);
 
 	c->is_r500 = is_r500;
@@ -456,3 +526,82 @@ void init_compiler(
 		c->SwizzleCaps = &r300_vertprog_swizzle_caps;
 	}
 }
+
+#define MAX_LINE_LENGTH 100
+#define MAX_PATH_LENGTH 100
+
+unsigned load_program(
+	struct radeon_compiler *c,
+	struct rc_test_file *test,
+	const char *filename)
+{
+	char line[MAX_LINE_LENGTH];
+	char path[MAX_PATH_LENGTH];
+	FILE *file;
+	unsigned *count;
+	char **string_store;
+	unsigned i = 0;
+
+	snprintf(path, MAX_PATH_LENGTH, "compiler/tests/%s", filename);
+	file = fopen(path, "r");
+	if (!file) {
+		return 0;
+	}
+	memset(test, 0, sizeof(struct rc_test_file));
+
+	count = &test->num_input_lines;
+
+	while (fgets(line, MAX_LINE_LENGTH, file)){
+		if (line[MAX_LINE_LENGTH - 2] == '\n') {
+			fprintf(stderr, "Error line cannot be longer than 100 "
+				"characters:\n%s\n", line);
+			return 0;
+		}
+
+		// Comment
+		if (line[0] == '#' || is_whitespace(line)) {
+			continue;
+		}
+
+		if (line[0] == '=') {
+			count = &test->num_expected_lines;
+			continue;
+		}
+
+		(*count)++;
+	}
+
+	test->input = malloc(sizeof(char *) * test->num_input_lines);
+	test->expected = malloc(sizeof(char *) * test->num_expected_lines);
+
+	rewind(file);
+	string_store = test->input;
+
+	while(fgets(line, MAX_LINE_LENGTH, file)) {
+		// Comment
+		char * dst;
+		if (line[0] == '#' || is_whitespace(line)) {
+			continue;
+		}
+
+		if (line[0] == '=') {
+			i = 0;
+			string_store = test->expected;
+			continue;
+		}
+
+		dst = string_store[i++] = malloc((strlen(line) + 1) *
+							sizeof (char));
+		strcpy(dst, line);
+	}
+
+	for (i = 0; i < test->num_input_lines; i++) {
+		if (test->input[i][0] == 'c') {
+			add_constant(c, test->input[i]);
+			continue;
+		}
+		// XXX: Parse immediates from the file.
+		add_instruction(c, test->input[i]);
+	}
+	return 1;
+}
diff --git a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.h b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.h
index 49a46a9..6cc8d9c 100644
--- a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.h
+++ b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.h
@@ -29,6 +29,13 @@
 
 #include "radeon_compiler.h"
 
+struct rc_test_file {
+	unsigned num_input_lines;
+	char **input;
+	unsigned num_expected_lines;
+	char **expected;
+};
+
 int init_rc_normal_src(
 	struct rc_instruction * inst,
 	unsigned int src_index,
@@ -42,14 +49,23 @@ int parse_rc_normal_instruction(
 	struct rc_instruction * inst,
 	const char * inst_str);
 
+int parse_constant(unsigned *index, float *data, const char *const_str);
+
 int init_rc_normal_instruction(
 	struct rc_instruction * inst,
 	const char * inst_str);
 
 void add_instruction(struct radeon_compiler *c, const char * inst_string);
 
+int add_constant(struct radeon_compiler *c, const char *const_str);
+
 void init_compiler(
 	struct radeon_compiler *c,
 	enum rc_program_type program_type,
 	unsigned is_r500,
 	unsigned is_r400);
+
+unsigned load_program(
+	struct radeon_compiler *c,
+	struct rc_test_file *test,
+	const char *filename);




More information about the mesa-commit mailing list