summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorTom Stellard <[email protected]>2013-03-10 20:55:26 -0400
committerTom Stellard <[email protected]>2013-06-30 21:38:57 -0700
commite2c3640540dbe423d2c75d89615854aeb9f560f3 (patch)
treea2866c2cf8be3363db308171d3f5abd492433064 /src/gallium
parentab40d8d56f1cd6868a90fedd1dfaa87a3087bfa3 (diff)
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 <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/r300/compiler/tests/omod_two_writers.test5
-rw-r--r--src/gallium/drivers/r300/compiler/tests/r300_compiler_tests.h1
-rw-r--r--src/gallium/drivers/r300/compiler/tests/radeon_compiler_optimize_tests.c33
-rw-r--r--src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c161
-rw-r--r--src/gallium/drivers/r300/compiler/tests/rc_test_helpers.h16
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 00000000000..fb16bb08f92
--- /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 266addf66d9..d40834a942b 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 600228e83b0..819fb6c88d5 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 551fe05ece2..af7b3cee48f 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 49a46a94abd..6cc8d9cdcb4 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);