freedreno/a3xx/compiler: relative addressing fixes.
authorRob Clark <robclark@freedesktop.org>
Sun, 27 Oct 2013 14:19:58 +0000 (10:19 -0400)
committerRob Clark <robclark@freedesktop.org>
Sat, 2 Nov 2013 00:18:44 +0000 (20:18 -0400)
Handle some relative addressing constraints: cannot handle const or
relative in cat5 and src2 of cat3.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/a3xx/fd3_compiler.c

index 352afcf..5e94a6f 100644 (file)
@@ -433,6 +433,18 @@ is_const(struct tgsi_src_register *src)
                        (src->File == TGSI_FILE_IMMEDIATE);
 }
 
+static inline bool
+is_relative(struct tgsi_src_register *src)
+{
+       return src->Indirect;
+}
+
+static inline bool
+is_rel_or_const(struct tgsi_src_register *src)
+{
+       return is_relative(src) || is_const(src);
+}
+
 static type_t
 get_ftype(struct fd3_compile_context *ctx)
 {
@@ -467,7 +479,7 @@ get_unconst(struct fd3_compile_context *ctx, struct tgsi_src_register *src)
        struct tgsi_dst_register tmp_dst;
        struct tgsi_src_register *tmp_src;
 
-       compile_assert(ctx, is_const(src));
+       compile_assert(ctx, is_rel_or_const(src));
 
        tmp_src = get_internal_temp(ctx, &tmp_dst);
 
@@ -845,8 +857,8 @@ trans_dotp(const struct instr_translater *t,
 
        /* in particular, can't handle const for src1 for cat3/mad:
         */
-       if (is_const(src1)) {
-               if (!is_const(src0)) {
+       if (is_rel_or_const(src1)) {
+               if (!is_rel_or_const(src0)) {
                        struct tgsi_src_register *tmp;
                        tmp = src0;
                        src0 = src1;
@@ -1065,7 +1077,8 @@ trans_samp(const struct instr_translater *t,
        struct tgsi_src_register *samp  = &inst->Src[1].Register;
        unsigned tex = inst->Texture.Texture;
        int8_t *order;
-       unsigned i, j, flags = 0;
+       unsigned i, flags = 0;
+       bool needs_mov = false;
 
        switch (t->arg) {
        case TGSI_OPCODE_TEX:
@@ -1089,38 +1102,44 @@ trans_samp(const struct instr_translater *t,
                flags |= IR3_INSTR_3D;
        }
 
+       /* cat5 instruction cannot seem to handle const or relative: */
+       if (is_rel_or_const(coord))
+               needs_mov = true;
+
        /* The texture sample instructions need to coord in successive
         * registers/components (ie. src.xy but not src.yx).  And TXP
         * needs the .w component in .z for 2D..  so in some cases we
         * might need to emit some mov instructions to shuffle things
         * around:
         */
-       for (i = 1; (i < 4) && (order[i] >= 0); i++) {
-               if (src_swiz(coord, i) != (src_swiz(coord, 0) + order[i])) {
-                       struct tgsi_dst_register tmp_dst;
-                       struct tgsi_src_register *tmp_src;
-
-                       type_t type_mov = get_ftype(ctx);
-
-                       /* need to move things around: */
-                       tmp_src = get_internal_temp(ctx, &tmp_dst);
-
-                       for (j = 0; (j < 4) && (order[j] >= 0); j++) {
-                               instr = ir3_instr_create(ctx->ir, 1, 0);
-                               instr->cat1.src_type = type_mov;
-                               instr->cat1.dst_type = type_mov;
-                               add_dst_reg(ctx, instr, &tmp_dst, j);
-                               add_src_reg(ctx, instr, coord,
-                                               src_swiz(coord, order[j]));
-                       }
+       for (i = 1; (i < 4) && (order[i] >= 0) && !needs_mov; i++)
+               if (src_swiz(coord, i) != (src_swiz(coord, 0) + order[i]))
+                       needs_mov = true;
 
-                       coord = tmp_src;
+       if (needs_mov) {
+               struct tgsi_dst_register tmp_dst;
+               struct tgsi_src_register *tmp_src;
+               unsigned j;
 
-                       if (j < 4)
-                               ir3_instr_create(ctx->ir, 0, OPC_NOP)->repeat = 4 - j - 1;
+               type_t type_mov = get_ftype(ctx);
 
-                       break;
+               /* need to move things around: */
+               tmp_src = get_internal_temp(ctx, &tmp_dst);
+
+               for (j = 0; (j < 4) && (order[j] >= 0); j++) {
+                       instr = ir3_instr_create(ctx->ir, 1, 0);
+                       instr->cat1.src_type = type_mov;
+                       instr->cat1.dst_type = type_mov;
+                       add_dst_reg(ctx, instr, &tmp_dst, j);
+                       add_src_reg(ctx, instr, coord,
+                                       src_swiz(coord, order[j]));
                }
+
+               coord = tmp_src;
+
+               if (j < 4)
+                       ir3_instr_create(ctx->ir, 0, OPC_NOP)->repeat = 4 - j - 1;
+
        }
 
        instr = ir3_instr_create(ctx->ir, 5, t->opc);
@@ -1483,8 +1502,8 @@ instr_cat3(const struct instr_translater *t,
        /* in particular, can't handle const for src1 for cat3..
         * for mad, we can swap first two src's if needed:
         */
-       if (is_const(src1)) {
-               if (is_mad(t->opc) && !is_const(src0)) {
+       if (is_rel_or_const(src1)) {
+               if (is_mad(t->opc) && !is_rel_or_const(src0)) {
                        struct tgsi_src_register *tmp;
                        tmp = src0;
                        src0 = src1;
@@ -1568,6 +1587,7 @@ static const struct instr_translater translaters[TGSI_OPCODE_LAST] = {
        INSTR(ELSE,         trans_else),
        INSTR(ENDIF,        trans_endif),
        INSTR(END,          instr_cat0, .opc = OPC_END),
+       INSTR(KILL,         instr_cat0, .opc = OPC_KILL),
 };
 
 static int