r600g: split instruction into scalar
authorJerome Glisse <jglisse@redhat.com>
Sat, 5 Jun 2010 11:16:50 +0000 (13:16 +0200)
committerJerome Glisse <jglisse@redhat.com>
Sat, 5 Jun 2010 15:13:25 +0000 (17:13 +0200)
Split instruction into scalar in core compiler this simplify
the way we translate the instruction in latter stage.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
src/gallium/drivers/r600/r600_compiler.h
src/gallium/drivers/r600/r600_compiler_dump.c
src/gallium/drivers/r600/r600_compiler_r600.c
src/gallium/drivers/r600/r600_compiler_tgsi.c

index 64dab5000be97a56d9ffb363868f9f1e22b5b22c..3de19970c31b1f82f0e919851dca669c9c5ad7a6 100644 (file)
@@ -71,7 +71,7 @@ struct c_vector {
 #define C_SWIZZLE_W            3
 #define C_SWIZZLE_0            4
 #define C_SWIZZLE_1            5
-#define C_SWIZZLE_D            6       /**< discard */
+#define C_SWIZZLE_D            6
 
 #define C_FILE_NULL            0
 #define C_FILE_CONSTANT                1
@@ -247,18 +247,21 @@ struct c_vector {
 
 struct c_operand {
        struct c_vector         *vector;
-       unsigned                swizzle[4];
-       unsigned                flag[4];
+       unsigned                swizzle;
+       unsigned                flag;
 };
 
-struct c_instruction {
-       struct c_instruction    *next, *prev;
-       unsigned                opcode;
+struct c_op {
        unsigned                ninput;
        struct c_operand        input[3];
        struct c_operand        output;
-       unsigned                write_mask;
-       void                    *backend;
+       unsigned                opcode;
+};
+
+struct c_instruction {
+       struct c_instruction    *next, *prev;
+       unsigned                nop;
+       struct c_op             op[5];
 };
 
 struct c_node;
index 9df6a38598eca019506b0f287ecfc81ccd644711..485032088c8e2f96a4fdd925e6852c9dbb9f75d7 100644 (file)
@@ -229,28 +229,25 @@ static void pindent(unsigned indent)
 static void c_node_dump(struct c_node *node, unsigned indent)
 {
        struct c_instruction *i;
-       unsigned j;
+       unsigned j, k;
 
        pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode));
        c_list_for_each(i, &node->insts) {
-               pindent(indent); fprintf(stderr, "%s", c_get_name(c_opcode_str, i->opcode));
-               fprintf(stderr, " %s[%d][%s%s%s%s]",
-                               c_get_name(c_file_str, i->output.vector->file),
-                               i->output.vector->id,
-                               c_get_name(c_file_swz, i->output.swizzle[0]),
-                               c_get_name(c_file_swz, i->output.swizzle[1]),
-                               c_get_name(c_file_swz, i->output.swizzle[2]),
-                               c_get_name(c_file_swz, i->output.swizzle[3]));
-               for (j = 0; j < i->ninput; j++) {
-                       fprintf(stderr, " %s[%d][%s%s%s%s]",
-                                       c_get_name(c_file_str, i->input[j].vector->file),
-                                       i->input[j].vector->id,
-                                       c_get_name(c_file_swz, i->input[j].swizzle[0]),
-                                       c_get_name(c_file_swz, i->input[j].swizzle[1]),
-                                       c_get_name(c_file_swz, i->input[j].swizzle[2]),
-                                       c_get_name(c_file_swz, i->input[j].swizzle[3]));
+               for (k = 0; k < i->nop; k++) {
+                       pindent(indent);
+                       fprintf(stderr, "%s", c_get_name(c_opcode_str, i->op[k].opcode));
+                       fprintf(stderr, " %s[%d][%s]",
+                               c_get_name(c_file_str, i->op[k].output.vector->file),
+                               i->op[k].output.vector->id,
+                               c_get_name(c_file_swz, i->op[k].output.swizzle));
+                       for (j = 0; j < i->op[k].ninput; j++) {
+                               fprintf(stderr, " %s[%d][%s]",
+                                               c_get_name(c_file_str, i->op[k].input[j].vector->file),
+                                               i->op[k].input[j].vector->id,
+                                               c_get_name(c_file_swz, i->op[k].input[j].swizzle));
+                       }
+                       fprintf(stderr, ";\n");
                }
-               fprintf(stderr, ";\n");
        }
 }
 
index 1be5bf2b4a0b10178fb184f64c7ae154b3642480..623ac043777b96c92aefe7272fd526cd75455d50 100644 (file)
@@ -60,16 +60,31 @@ int r600_shader_insert_fetch(struct c_shader *shader)
                if (vr == NULL)
                        return -ENOMEM;
                memset(&instruction, 0, sizeof(struct c_instruction));
-               instruction.opcode = C_OPCODE_VFETCH;
-               instruction.write_mask = 0xF;
-               instruction.ninput = 2;
-               instruction.output.vector = v;
-               instruction.input[0].vector = vi;
-               instruction.input[1].vector = vr;
-               instruction.output.swizzle[0] = C_SWIZZLE_X;
-               instruction.output.swizzle[1] = C_SWIZZLE_Y;
-               instruction.output.swizzle[2] = C_SWIZZLE_Z;
-               instruction.output.swizzle[3] = C_SWIZZLE_W;
+               instruction.nop = 4;
+               instruction.op[0].opcode = C_OPCODE_VFETCH;
+               instruction.op[1].opcode = C_OPCODE_VFETCH;
+               instruction.op[2].opcode = C_OPCODE_VFETCH;
+               instruction.op[3].opcode = C_OPCODE_VFETCH;
+               instruction.op[0].ninput = 2;
+               instruction.op[1].ninput = 2;
+               instruction.op[2].ninput = 2;
+               instruction.op[3].ninput = 2;
+               instruction.op[0].output.vector = v;
+               instruction.op[1].output.vector = v;
+               instruction.op[2].output.vector = v;
+               instruction.op[3].output.vector = v;
+               instruction.op[0].input[0].vector = vi;
+               instruction.op[0].input[1].vector = vr;
+               instruction.op[1].input[0].vector = vi;
+               instruction.op[1].input[1].vector = vr;
+               instruction.op[2].input[0].vector = vi;
+               instruction.op[2].input[1].vector = vr;
+               instruction.op[3].input[0].vector = vi;
+               instruction.op[3].input[1].vector = vr;
+               instruction.op[0].output.swizzle = C_SWIZZLE_X;
+               instruction.op[1].output.swizzle = C_SWIZZLE_Y;
+               instruction.op[2].output.swizzle = C_SWIZZLE_Z;
+               instruction.op[3].output.swizzle = C_SWIZZLE_W;
                r = c_node_add_new_instruction_head(&shader->entry, &instruction);
                if (r)
                        return r;
@@ -316,7 +331,7 @@ static int r600_shader_add_vfetch(struct r600_shader *rshader,
 
        if (instruction == NULL)
                return 0;
-       if (instruction->opcode != C_OPCODE_VFETCH)
+       if (instruction->op[0].opcode != C_OPCODE_VFETCH)
                return 0;
        if (!c_list_empty(&node->alu)) {
                rnode = r600_shader_new_node(rshader, node->node);
@@ -327,13 +342,13 @@ static int r600_shader_add_vfetch(struct r600_shader *rshader,
        vfetch = calloc(1, sizeof(struct r600_shader_vfetch));
        if (vfetch == NULL)
                return -ENOMEM;
-       r = r600_shader_find_gpr(rshader, instruction->output.vector, 0, &vfetch->dst[0]);
+       r = r600_shader_find_gpr(rshader, instruction->op[0].output.vector, 0, &vfetch->dst[0]);
        if (r)
                return r;
-       r = r600_shader_find_gpr(rshader, instruction->input[0].vector, 0, &vfetch->src[0]);
+       r = r600_shader_find_gpr(rshader, instruction->op[0].input[0].vector, 0, &vfetch->src[0]);
        if (r)
                return r;
-       r = r600_shader_find_gpr(rshader, instruction->input[1].vector, 0, &vfetch->src[1]);
+       r = r600_shader_find_gpr(rshader, instruction->op[0].input[1].vector, 0, &vfetch->src[1]);
        if (r)
                return r;
        vfetch->dst[0].chan = C_SWIZZLE_X;
@@ -355,7 +370,7 @@ static int r600_node_translate(struct r600_shader *rshader, struct c_node *node)
        if (rnode == NULL)
                return -ENOMEM;
        c_list_for_each(instruction, &node->insts) {
-               switch (instruction->opcode) {
+               switch (instruction->op[0].opcode) {
                case C_OPCODE_VFETCH:
                        r = r600_shader_add_vfetch(rshader, rnode, instruction);
                        if (r) {
@@ -414,79 +429,13 @@ static struct r600_shader_alu *r600_shader_insert_alu(struct r600_shader *rshade
        return alu;
 }
 
-static int r600_shader_node_add_alu(struct r600_shader *rshader,
-                                       struct r600_shader_node *node,
-                                       struct r600_shader_alu *alu,
-                                       unsigned instruction,
-                                       unsigned ninput,
-                                       struct r600_shader_operand *dst,
-                                       struct r600_shader_operand src[3])
-{
-       struct r600_shader_alu *nalu;
-       unsigned nconstant = 0, nliteral = 0, slot, i;
-
-       /* count number of constant & literal */
-       for (i = 0; i < ninput; i++) {
-               if (src[i].vector->file == C_FILE_IMMEDIATE) {
-                       nliteral++;
-                       nconstant++;
-               }
-       }
-
-       slot = dst->chan;
-       if (r600_instruction_info[instruction].is_trans) {
-               slot = 4;
-       }
-
-       /* allocate new alu group if necessary */
-       nalu = alu;
-       if (alu == NULL) {
-               nalu = r600_shader_insert_alu(rshader, node);
-               if (nalu == NULL)
-                       return -ENOMEM;
-               alu = nalu;
-       }
-       if ((alu->alu[slot].inst != INST_NOP &&
-               alu->alu[4].inst != INST_NOP) ||
-               (alu->nconstant + nconstant) > 4 ||
-               (alu->nliteral + nliteral) > 4) {
-               /* neither trans neither dst slot are free need new alu */
-               nalu = r600_shader_insert_alu(rshader, node);
-               if (nalu == NULL)
-                       return -ENOMEM;
-               alu = nalu;
-       }
-       if (alu->alu[slot].inst != INST_NOP) {
-               slot = 4;
-       }
-
-       alu->alu[slot].dst = *dst;
-       alu->alu[slot].inst = instruction;
-       alu->alu[slot].opcode = r600_instruction_info[instruction].opcode;
-       alu->alu[slot].is_op3 = r600_instruction_info[instruction].is_op3;
-       for (i = 0; i < ninput; i++) {
-               alu->alu[slot].src[i] = src[i];
-               if (src[i].vector->file == C_FILE_IMMEDIATE) {
-                       alu->literal[alu->nliteral++] = src[i].vector->channel[0]->value;
-                       alu->literal[alu->nliteral++] = src[i].vector->channel[1]->value;
-                       alu->literal[alu->nliteral++] = src[i].vector->channel[2]->value;
-                       alu->literal[alu->nliteral++] = src[i].vector->channel[3]->value;
-               }
-       }
-       return 0;
-}
-
 static int r600_shader_alu_translate(struct r600_shader *rshader,
                                        struct r600_shader_node *node,
                                        struct c_instruction *instruction)
 {
-       struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->opcode];
-       struct r600_instruction_info *info;
-       struct r600_shader_alu *alu;
        struct r600_shader_node *rnode;
-       int r, i, j;
-       struct r600_shader_operand dst;
-       struct r600_shader_operand src[3];
+       struct r600_shader_alu *alu;
+       int i, j, r, comp;
 
        if (!c_list_empty(&node->vfetch)) {
                rnode = r600_shader_new_node(rshader, node->node);
@@ -496,40 +445,57 @@ static int r600_shader_alu_translate(struct r600_shader *rshader,
                }
                node = rnode;
        }
+
+       /* initialize alu */
        alu = r600_shader_insert_alu(rshader, node);
-       if (alu == NULL) {
-               fprintf(stderr, "%s %d instert alu node failed\n", __func__, __LINE__);
-               return -ENOMEM;
-       }
-       for (i = 0; i < 4; i++) {
-               if (!(instruction->write_mask) || instruction->output.swizzle[i] == C_SWIZZLE_D)
-                       continue;
-               if (ainfo->instruction == INST_NOP) {
-                       fprintf(stderr, "%s:%d unsupported instruction %d\n", __FILE__, __LINE__, instruction->opcode);
-                       continue;
-               }
-               info = &r600_instruction_info[ainfo->instruction];
-               r = r600_shader_find_gpr(rshader, instruction->output.vector,
-                                       instruction->output.swizzle[i], &dst);
-               if (r) {
-                       fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
-                       return r;
+
+       /* check special operation like lit */
+
+       /* go through operation */
+       for (i = 0; i < instruction->nop; i++) {
+               struct r600_alu_instruction *ainfo = &r600_alu_instruction[instruction->op[i].opcode];
+               struct r600_instruction_info *iinfo = &r600_instruction_info[ainfo->instruction];
+               unsigned comp;
+
+               /* check that output is a valid component */
+               comp = instruction->op[i].output.swizzle;
+               switch (comp) {
+               case C_SWIZZLE_X:
+               case C_SWIZZLE_Y:
+               case C_SWIZZLE_Z:
+               case C_SWIZZLE_W:
+                       break;
+               case C_SWIZZLE_0:
+               case C_SWIZZLE_1:
+               default:
+                       fprintf(stderr, "%s %d invalid output\n", __func__, __LINE__);
+                       return -EINVAL;
                }
-               for (j = 0; j < instruction->ninput; j++) {
-                       r = r600_shader_find_gpr(rshader, instruction->input[j].vector,
-                                       instruction->input[j].swizzle[i], &src[j]);
+               alu->alu[comp].inst = ainfo->instruction;
+               alu->alu[comp].opcode = iinfo->opcode;
+               alu->alu[comp].is_op3 = iinfo->is_op3;
+               for (j = 0; j < instruction->op[i].ninput; j++) {
+                       r = r600_shader_find_gpr(rshader, instruction->op[i].input[j].vector,
+                                       instruction->op[i].input[j].swizzle, &alu->alu[comp].src[j]);
                        if (r) {
                                fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
                                return r;
                        }
                }
-               r = r600_shader_node_add_alu(rshader, node, alu, ainfo->instruction,
-                                       instruction->ninput, &dst, src);
+               r = r600_shader_find_gpr(rshader, instruction->op[i].output.vector,
+                               instruction->op[i].output.swizzle, &alu->alu[comp].dst);
                if (r) {
-                       fprintf(stderr, "%s %d failed\n", __FILE__, __LINE__);
+                       fprintf(stderr, "%s %d register failed\n", __FILE__, __LINE__);
                        return r;
                }
        }
+       for (i = instruction->nop; i >= 0; i--) {
+               if (alu->alu[i].inst != INST_NOP) {
+                       alu->alu[i].last = 1;
+                       alu->nalu = i + 1;
+                       break;
+               }
+       }
        return 0;
 }
 
@@ -576,12 +542,14 @@ int r600_shader_legalize(struct r600_shader *rshader)
        struct r600_shader_node *node, *nnode;
        struct r600_shader_alu *alu, *nalu;
 
+#if 0
        c_list_for_each_safe(node, nnode, &rshader->nodes) {
                c_list_for_each_safe(alu, nalu, &node->alu) {
                        alu->nalu = 5;
                        alu->alu[4].last = 1;
                }
        }
+#endif
        return 0;
 }
 
index 563ca063afe004106cbc4e8d6c11832cabf2890e..172cf154a34118793cf87d8e4d71c32f54197d72 100644 (file)
@@ -146,7 +146,7 @@ static int ntransform_instruction(struct tgsi_shader *ts)
        struct c_shader *shader = ts->shader;
        struct c_instruction instruction;
        unsigned opcode;
-       int i, r;
+       int i, j, r;
 
        if (fi->Instruction.NumDstRegs > 1) {
                fprintf(stderr, "%s %d unsupported\n", __func__, __LINE__);
@@ -192,21 +192,48 @@ static int ntransform_instruction(struct tgsi_shader *ts)
        }
        /* FIXME add flow instruction handling */
        memset(&instruction, 0, sizeof(struct c_instruction));
-       instruction.opcode = opcode;
-       instruction.ninput = fi->Instruction.NumSrcRegs;
-       instruction.write_mask = fi->Dst[0].Register.WriteMask;
-       for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
-               instruction.input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index];
-               instruction.input[i].swizzle[0] = fi->Src[i].Register.SwizzleX;
-               instruction.input[i].swizzle[1] = fi->Src[i].Register.SwizzleY;
-               instruction.input[i].swizzle[2] = fi->Src[i].Register.SwizzleZ;
-               instruction.input[i].swizzle[3] = fi->Src[i].Register.SwizzleW;
+       instruction.nop = 0;
+       for (j = 0; j < 4; j++) {
+               instruction.op[instruction.nop].opcode = opcode;
+               instruction.op[instruction.nop].ninput = fi->Instruction.NumSrcRegs;
+               for (i = 0; i < fi->Instruction.NumSrcRegs; i++) {
+                       instruction.op[instruction.nop].input[i].vector = ts->v[fi->Src[i].Register.File][fi->Src[i].Register.Index];
+                       switch (j) {
+                       case 0:
+                               instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleX;
+                               break;
+                       case 1:
+                               instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleY;
+                               break;
+                       case 2:
+                               instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleZ;
+                               break;
+                       case 3:
+                               instruction.op[instruction.nop].input[i].swizzle = fi->Src[i].Register.SwizzleW;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+               instruction.op[instruction.nop].output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index];
+               switch (j) {
+               case 0:
+                       instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D;
+                       break;
+               case 1:
+                       instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Y : C_SWIZZLE_D;
+                       break;
+               case 2:
+                       instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_Z : C_SWIZZLE_D;
+                       break;
+               case 3:
+                       instruction.op[instruction.nop].output.swizzle = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_W : C_SWIZZLE_D;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               instruction.nop++;
        }
-       instruction.output.vector = ts->v[fi->Dst[0].Register.File][fi->Dst[0].Register.Index];
-       instruction.output.swizzle[0] = (fi->Dst[0].Register.WriteMask & 0x1) ? C_SWIZZLE_X : C_SWIZZLE_D;
-       instruction.output.swizzle[1] = (fi->Dst[0].Register.WriteMask & 0x2) ? C_SWIZZLE_Y : C_SWIZZLE_D;
-       instruction.output.swizzle[2] = (fi->Dst[0].Register.WriteMask & 0x4) ? C_SWIZZLE_Z : C_SWIZZLE_D;
-       instruction.output.swizzle[3] = (fi->Dst[0].Register.WriteMask & 0x8) ? C_SWIZZLE_W : C_SWIZZLE_D;
        return c_node_add_new_instruction(ts->node, &instruction);
 }