freedreno/ir3/cp: handle indirect properly
authorRob Clark <robclark@freedesktop.org>
Wed, 8 Apr 2015 18:10:00 +0000 (14:10 -0400)
committerRob Clark <robclark@freedesktop.org>
Sat, 11 Apr 2015 15:40:21 +0000 (11:40 -0400)
I noticed some cases where we where trying to copy-propagate indirect
src's into places they cannot go, like 2nd src for cat3 (mad, etc).
Expand out valid_flags() to be aware of relativ flag, and fix up a few
related spots.

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

index 77bfbc53e2ae1a4a5fe7a46a41f9552407af55c3..313a423b7cb7ca88715820097335bd8eebe0de32 100644 (file)
@@ -89,7 +89,7 @@ static unsigned cp_flags(unsigned flags)
        flags &= (IR3_REG_CONST | IR3_REG_IMMED |
                        IR3_REG_FNEG | IR3_REG_FABS |
                        IR3_REG_SNEG | IR3_REG_SABS |
-                       IR3_REG_BNOT);
+                       IR3_REG_BNOT | IR3_REG_RELATIV);
        return flags;
 }
 
@@ -102,6 +102,10 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
        /* clear flags that are 'ok' */
        switch (instr->category) {
        case 1:
+               valid_flags = IR3_REG_IMMED | IR3_REG_RELATIV;
+               if (flags & ~valid_flags)
+                       return false;
+               break;
        case 5:
                /* no flags allowed */
                if (flags)
@@ -113,7 +117,8 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
                        return false;
                break;
        case 2:
-               valid_flags = ir3_cat2_absneg(instr->opc) | IR3_REG_CONST;
+               valid_flags = ir3_cat2_absneg(instr->opc) |
+                               IR3_REG_CONST | IR3_REG_RELATIV;
 
                if (ir3_cat2_int(instr->opc))
                        valid_flags |= IR3_REG_IMMED;
@@ -140,19 +145,19 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
                }
                break;
        case 3:
-               valid_flags = ir3_cat3_absneg(instr->opc) | IR3_REG_CONST;
+               valid_flags = ir3_cat3_absneg(instr->opc) |
+                               IR3_REG_CONST | IR3_REG_RELATIV;
 
                if (flags & ~valid_flags)
                        return false;
 
-               if (flags & IR3_REG_CONST) {
-                       /* cannot deal w/ const in 2nd src: */
-                       /* TODO in some common cases, like mad, we can swap
-                        * first two args.. possibly we should allow that here
-                        * and fixup in legalize?
-                        */
+               if (flags & (IR3_REG_CONST | IR3_REG_RELATIV)) {
+                       /* cannot deal w/ const/relativ in 2nd src: */
                        if (n == 1)
                                return false;
+               }
+
+               if (flags & IR3_REG_CONST) {
                        /* cannot be const + ABS|NEG: */
                        if (flags & (IR3_REG_FABS | IR3_REG_FNEG |
                                        IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT))
@@ -240,16 +245,17 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
 
        if (!valid_flags(instr, n, reg->flags)) {
                /* insert an absneg.f */
-               if (reg->flags & (IR3_REG_SNEG | IR3_REG_SABS)) {
+               if (reg->flags & (IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT)) {
                        debug_assert(!(reg->flags & (IR3_REG_FNEG | IR3_REG_FABS)));
                        reg->instr = ir3_ABSNEG_S(instr->block,
                                        reg->instr, cp_flags(src_flags));
                } else {
-                       debug_assert(!(reg->flags & (IR3_REG_SNEG | IR3_REG_SABS)));
+                       debug_assert(!(reg->flags & (IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT)));
                        reg->instr = ir3_ABSNEG_F(instr->block,
                                        reg->instr, cp_flags(src_flags));
                }
                reg->flags &= ~cp_flags(src_flags);
+               debug_assert(valid_flags(instr, n, reg->flags));
                /* send it through instr_cp() again since
                 * the absneg src might be a mov from const
                 * that could be cleaned up:
@@ -269,7 +275,7 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
                         * try swapping the first two args if that fits better.
                         */
                        if ((n == 1) && is_valid_mad(instr) &&
-                                       !(instr->regs[0 + 1]->flags & IR3_REG_CONST) &&
+                                       !(instr->regs[0 + 1]->flags & (IR3_REG_CONST | IR3_REG_RELATIV)) &&
                                        valid_flags(instr, 0, new_flags)) {
                                /* swap src[0] and src[1]: */
                                struct ir3_register *tmp;
@@ -327,7 +333,8 @@ reg_cp(struct ir3_instruction *instr, struct ir3_register *reg, unsigned n)
                if (src_reg->flags & IR3_REG_IMMED) {
                        int32_t iim_val = src_reg->iim_val;
 
-                       debug_assert((instr->category == 6) ||
+                       debug_assert((instr->category == 1) ||
+                                       (instr->category == 6) ||
                                        ((instr->category == 2) &&
                                                ir3_cat2_int(instr->opc)));