freedreno/ir3: Sync some new changes from envytools.
authorEric Anholt <eric@anholt.net>
Fri, 1 May 2020 21:37:27 +0000 (14:37 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 4 May 2020 18:14:46 +0000 (11:14 -0700)
With this I also brought in a few new control flow instruction disasm
tests that I'd made back when I wrote the disasm test, but which were too
far from correct to include until now.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4857>

src/freedreno/ir3/disasm-a3xx.c
src/freedreno/ir3/instr-a3xx.h
src/freedreno/ir3/ir3.c
src/freedreno/ir3/ir3.h
src/freedreno/ir3/ir3_compiler_nir.c
src/freedreno/ir3/ir3_delay.c
src/freedreno/ir3/ir3_legalize.c
src/freedreno/ir3/ir3_parser.y
src/freedreno/ir3/ir3_postsched.c
src/freedreno/ir3/ir3_print.c
src/freedreno/ir3/tests/disasm.c

index 54ed027f55c36f2b0e6822a4c53243d8565ac0dc..697219ce4054cdf4cd13a8ec17ff770be3a84b5a 100644 (file)
@@ -203,26 +203,54 @@ static void print_src(struct disasm_ctx *ctx, struct reginfo *info)
 
 static void print_instr_cat0(struct disasm_ctx *ctx, instr_t *instr)
 {
+       static const struct {
+               const char *suffix;
+               int nsrc;
+               bool idx;
+       } brinfo[7] = {
+               [BRANCH_PLAIN] = { "r",   1, false },
+               [BRANCH_OR]    = { "rao", 2, false },
+               [BRANCH_AND]   = { "raa", 2, false },
+               [BRANCH_CONST] = { "rac", 0, true  },
+               [BRANCH_ANY]   = { "any", 1, false },
+               [BRANCH_ALL]   = { "all", 1, false },
+               [BRANCH_X]     = { "rax", 0, false },
+       };
        instr_cat0_t *cat0 = &instr->cat0;
 
-       switch (cat0->opc) {
+       switch (instr_opc(instr, ctx->gpu_id)) {
        case OPC_KILL:
-       case OPC_IF:
-               fprintf(ctx->out, " %sp0.%c", cat0->inv ? "!" : "",
-                               component[cat0->comp]);
+       case OPC_PREDT:
+       case OPC_PREDF:
+               fprintf(ctx->out, " %sp0.%c", cat0->inv0 ? "!" : "",
+                               component[cat0->comp0]);
                break;
-       case OPC_BR:
-               fprintf(ctx->out, " %sp0.%c, #%d", cat0->inv ? "!" : "",
-                               component[cat0->comp], cat0->a3xx.immed);
+       case OPC_B:
+               fprintf(ctx->out, "%s", brinfo[cat0->brtype].suffix);
+               if (brinfo[cat0->brtype].idx) {
+                       fprintf(ctx->out, ".%u", cat0->idx);
+               }
+               if (brinfo[cat0->brtype].nsrc >= 1) {
+                       fprintf(ctx->out, " %sp0.%c,", cat0->inv0 ? "!" : "",
+                                       component[cat0->comp0]);
+               }
+               if (brinfo[cat0->brtype].nsrc >= 2) {
+                       fprintf(ctx->out, " %sp0.%c,", cat0->inv1 ? "!" : "",
+                                       component[cat0->comp1]);
+               }
+               fprintf(ctx->out, " #%d", cat0->a3xx.immed);
                break;
        case OPC_JUMP:
        case OPC_CALL:
+       case OPC_BKT:
+       case OPC_GETONE:
+       case OPC_SHPS:
                fprintf(ctx->out, " #%d", cat0->a3xx.immed);
                break;
        }
 
-       if ((debug & PRINT_VERBOSE) && (cat0->dummy2|cat0->dummy3|cat0->dummy4))
-               fprintf(ctx->out, "\t{0: %x,%x,%x}", cat0->dummy2, cat0->dummy3, cat0->dummy4);
+       if ((debug & PRINT_VERBOSE) && (cat0->dummy3|cat0->dummy4))
+               fprintf(ctx->out, "\t{0: %x,%x}", cat0->dummy3, cat0->dummy4);
 }
 
 static void print_instr_cat1(struct disasm_ctx *ctx, instr_t *instr)
@@ -1065,7 +1093,7 @@ static const struct opc_info {
 #define OPC(cat, opc, name) [(opc)] = { (cat), (opc), #name, print_instr_cat##cat }
        /* category 0: */
        OPC(0, OPC_NOP,          nop),
-       OPC(0, OPC_BR,           br),
+       OPC(0, OPC_B,            b),
        OPC(0, OPC_JUMP,         jump),
        OPC(0, OPC_CALL,         call),
        OPC(0, OPC_RET,          ret),
@@ -1076,9 +1104,18 @@ static const struct opc_info {
        OPC(0, OPC_CHMASK,       chmask),
        OPC(0, OPC_CHSH,         chsh),
        OPC(0, OPC_FLOW_REV,     flow_rev),
-       OPC(0, OPC_IF,           if),
-       OPC(0, OPC_ELSE,         else),
-       OPC(0, OPC_ENDIF,        endif),
+       OPC(0, OPC_PREDT,        predt),
+       OPC(0, OPC_PREDF,        predf),
+       OPC(0, OPC_PREDE,        prede),
+       OPC(0, OPC_BKT,          bkt),
+       OPC(0, OPC_STKS,         stks),
+       OPC(0, OPC_STKR,         stkr),
+       OPC(0, OPC_XSET,         xset),
+       OPC(0, OPC_XCLR,         xclr),
+       OPC(0, OPC_GETONE,       getone),
+       OPC(0, OPC_DBG,          dbg),
+       OPC(0, OPC_SHPS,         shps),
+       OPC(0, OPC_SHPE,         shpe),
 
        /* category 1: */
        OPC(1, OPC_MOV, ),
@@ -1292,6 +1329,8 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
        }
        if (instr->jmp_tgt)
                fprintf(ctx->out, "(jp)");
+       if ((instr->opc_cat == 0) && instr->cat0.eq)
+               fprintf(ctx->out, "(eq)");
        if (instr_sat(instr))
                fprintf(ctx->out, "(sat)");
        if (ctx->repeat)
index 565b296739f8adb2300dd5ea1aaf3cb8c6211c13..23b21eb653d1471bdd93373bb33091146593ad30 100644 (file)
@@ -39,7 +39,7 @@
 typedef enum {
        /* category 0: */
        OPC_NOP             = _OPC(0, 0),
-       OPC_BR              = _OPC(0, 1),
+       OPC_B               = _OPC(0, 1),
        OPC_JUMP            = _OPC(0, 2),
        OPC_CALL            = _OPC(0, 3),
        OPC_RET             = _OPC(0, 4),
@@ -51,9 +51,19 @@ typedef enum {
        OPC_CHSH            = _OPC(0, 10),
        OPC_FLOW_REV        = _OPC(0, 11),
 
-       OPC_IF              = _OPC(0, 13),
-       OPC_ELSE            = _OPC(0, 14),
-       OPC_ENDIF           = _OPC(0, 15),
+       OPC_BKT             = _OPC(0, 16),
+       OPC_STKS            = _OPC(0, 17),
+       OPC_STKR            = _OPC(0, 18),
+       OPC_XSET            = _OPC(0, 19),
+       OPC_XCLR            = _OPC(0, 20),
+       OPC_GETONE          = _OPC(0, 21),
+       OPC_DBG             = _OPC(0, 22),
+       OPC_SHPS            = _OPC(0, 23),   /* shader prologue start */
+       OPC_SHPE            = _OPC(0, 24),   /* shader prologue end */
+
+       OPC_PREDT           = _OPC(0, 29),   /* predicated true */
+       OPC_PREDF           = _OPC(0, 30),   /* predicated false */
+       OPC_PREDE           = _OPC(0, 31),   /* predicated end */
 
        /* category 1: */
        OPC_MOV             = _OPC(1, 0),
@@ -311,6 +321,16 @@ static inline int reg_special(reg_t reg)
        return (reg.num == REG_A0) || (reg.num == REG_P0);
 }
 
+typedef enum {
+       BRANCH_PLAIN = 0,   /* br */
+       BRANCH_OR    = 1,   /* brao */
+       BRANCH_AND   = 2,   /* braa */
+       BRANCH_CONST = 3,   /* brac */
+       BRANCH_ANY   = 4,   /* bany */
+       BRANCH_ALL   = 5,   /* ball */
+       BRANCH_X     = 6,   /* brax ??? */
+} brtype_t;
+
 typedef struct PACKED {
        /* dword0: */
        union PACKED {
@@ -328,13 +348,18 @@ typedef struct PACKED {
        };
 
        /* dword1: */
-       uint32_t dummy2   : 8;
+       uint32_t idx      : 5;  /* brac.N index */
+       uint32_t brtype   : 3;  /* branch type, see brtype_t */
        uint32_t repeat   : 3;
        uint32_t dummy3   : 1;
        uint32_t ss       : 1;
-       uint32_t dummy4   : 7;
-       uint32_t inv      : 1;
-       uint32_t comp     : 2;
+       uint32_t inv1     : 1;
+       uint32_t comp1    : 2;
+       uint32_t eq       : 1;
+       uint32_t opc_hi   : 1;  /* at least one bit */
+       uint32_t dummy4   : 2;
+       uint32_t inv0     : 1;
+       uint32_t comp0    : 2;  /* component for first src */
        uint32_t opc      : 4;
        uint32_t jmp_tgt  : 1;
        uint32_t sync     : 1;
@@ -963,7 +988,7 @@ static inline bool is_cat6_legacy(instr_t *instr, unsigned gpu_id)
 static inline uint32_t instr_opc(instr_t *instr, unsigned gpu_id)
 {
        switch (instr->opc_cat) {
-       case 0:  return instr->cat0.opc;
+       case 0:  return instr->cat0.opc | instr->cat0.opc_hi << 4;
        case 1:  return 0;
        case 2:  return instr->cat2.opc;
        case 3:  return instr->cat3.opc;
index cb7418bf2e0dcfdcf655eaaa3cca6eb7850627e0..8c30bf9829832b287dabe45683be57709d4ac724 100644 (file)
@@ -141,23 +141,14 @@ static int emit_cat0(struct ir3_instruction *instr, void *ptr,
        }
        cat0->repeat   = instr->repeat;
        cat0->ss       = !!(instr->flags & IR3_INSTR_SS);
-       cat0->inv      = instr->cat0.inv;
-       cat0->comp     = instr->cat0.comp;
+       cat0->inv0     = instr->cat0.inv;
+       cat0->comp0    = instr->cat0.comp;
        cat0->opc      = instr->opc;
+       cat0->opc_hi   = instr->opc >= 16;
        cat0->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
        cat0->sync     = !!(instr->flags & IR3_INSTR_SY);
        cat0->opc_cat  = 0;
 
-       switch (instr->opc) {
-       case OPC_IF:
-       case OPC_ELSE:
-       case OPC_ENDIF:
-               cat0->dummy4 = 16;
-               break;
-       default:
-               break;
-       }
-
        return 0;
 }
 
index 0f3bb54f31652fa9fef8ea5ba885a56f9a01eb54..4e7550f5e8dab7a466ddd120e49098ba95599ca1 100644 (file)
@@ -1423,15 +1423,15 @@ ir3_##name(struct ir3_block *block,                                      \
 #define INSTR4(name)        __INSTR4(0, name, OPC_##name)
 
 /* cat0 instructions: */
-INSTR1(BR)
+INSTR1(B)
 INSTR0(JUMP)
 INSTR1(KILL)
 INSTR0(END)
 INSTR0(CHSH)
 INSTR0(CHMASK)
-INSTR1(IF)
-INSTR0(ELSE)
-INSTR0(ENDIF)
+INSTR1(PREDT)
+INSTR0(PREDF)
+INSTR0(PREDE)
 
 /* cat2 instructions, most 2 src but some 1 src: */
 INSTR2(ADD_F)
index bd65f91e780e35a2c882281aa4a11f9790f8c01e..b3d0556a03ed97ece46231cae2774c835a2ec469 100644 (file)
@@ -1536,7 +1536,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
 
        case nir_intrinsic_end_patch_ir3:
                assert(ctx->so->type == MESA_SHADER_TESS_CTRL);
-               struct ir3_instruction *end = ir3_ENDIF(b);
+               struct ir3_instruction *end = ir3_PREDE(b);
                array_insert(b, b->keeps, end);
 
                end->barrier_class = IR3_BARRIER_EVERYTHING;
@@ -1933,7 +1933,7 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
                /* condition always goes in predicate register: */
                cond->regs[0]->num = regid(REG_P0, 0);
 
-               kill = ir3_IF(b, cond, 0);
+               kill = ir3_PREDT(b, cond, 0);
 
                kill->barrier_class = IR3_BARRIER_EVERYTHING;
                kill->barrier_conflict = IR3_BARRIER_EVERYTHING;
index 3fc4d911f1454009e61bde8fccbfdb49677bb832..15434fdedd10bfabd05d3bb86b1d026ac918be50 100644 (file)
@@ -123,7 +123,7 @@ count_instruction(struct ir3_instruction *n)
         * be eliminated later in resolve_jumps().. really should do that
         * earlier so we don't have this constraint.
         */
-       return is_alu(n) || (is_flow(n) && (n->opc != OPC_JUMP) && (n->opc != OPC_BR));
+       return is_alu(n) || (is_flow(n) && (n->opc != OPC_JUMP) && (n->opc != OPC_B));
 }
 
 /**
index d0b0dd83b46e3abdc3f59f0f4f3ff3dff4d93f97..2b1f3b94d8bb4bf2d5666e181da3c8fdc5b86381 100644 (file)
@@ -138,7 +138,7 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
                        regmask_init(&state->needs_sy);
                }
 
-               if (last_n && (last_n->opc == OPC_IF)) {
+               if (last_n && (last_n->opc == OPC_PREDT)) {
                        n->flags |= IR3_INSTR_SS;
                        regmask_init(&state->needs_ss_war);
                        regmask_init(&state->needs_ss);
@@ -574,12 +574,12 @@ block_sched(struct ir3 *ir)
                        /* create "else" branch first (since "then" block should
                         * frequently/always end up being a fall-thru):
                         */
-                       br = ir3_BR(block, block->condition, 0);
+                       br = ir3_B(block, block->condition, 0);
                        br->cat0.inv = true;
                        br->cat0.target = block->successors[1];
 
                        /* "then" branch: */
-                       br = ir3_BR(block, block->condition, 0);
+                       br = ir3_B(block, block->condition, 0);
                        br->cat0.target = block->successors[0];
 
                } else if (block->successors[0]) {
@@ -633,7 +633,7 @@ kill_sched(struct ir3 *ir, struct ir3_shader_variant *so)
                        if (instr->opc != OPC_KILL)
                                continue;
 
-                       struct ir3_instruction *br = ir3_instr_create(block, OPC_BR);
+                       struct ir3_instruction *br = ir3_instr_create(block, OPC_B);
                        br->regs[1] = instr->regs[1];
                        br->cat0.target =
                                list_last_entry(&ir->block_list, struct ir3_block, node);
index c9cede4b725121e8baf238ab53e3a39cc7ffe6fa..08779380b12c4133fe45424b60e0c1f52563ac9a 100644 (file)
@@ -596,7 +596,7 @@ cat0_src:          '!' T_P0        { instr->cat0.inv = true; instr->cat0.comp =
 cat0_immed:        '#' integer     { instr->cat0.immed = $2; }
 
 cat0_instr:        T_OP_NOP        { new_instr(OPC_NOP); }
-|                  T_OP_BR         { new_instr(OPC_BR); }    cat0_src ',' cat0_immed
+|                  T_OP_BR         { new_instr(OPC_B); }    cat0_src ',' cat0_immed
 |                  T_OP_JUMP       { new_instr(OPC_JUMP); }  cat0_immed
 |                  T_OP_CALL       { new_instr(OPC_CALL); }  cat0_immed
 |                  T_OP_RET        { new_instr(OPC_RET); }
index 521078a04c9a6d322140da2a10c8b2a379fee387..496c1d211b8ed4e5ac3aefc68337f50124d50043 100644 (file)
@@ -582,7 +582,7 @@ sched_block(struct ir3_postsched_ctx *ctx, struct ir3_block *block)
        foreach_instr_safe (instr, &ctx->unscheduled_list) {
                switch (instr->opc) {
                case OPC_NOP:
-               case OPC_BR:
+               case OPC_B:
                case OPC_JUMP:
                        list_delinit(&instr->node);
                        break;
index 1b6908edefbb65012c8140388adc7992ce0e52c8..034bcd8248e8e94776fdcc63149274397ad83ec1 100644 (file)
@@ -264,8 +264,8 @@ print_instr(struct ir3_instruction *instr, int lvl)
 
        if (is_flow(instr) && instr->cat0.target) {
                /* the predicate register src is implied: */
-               if (instr->opc == OPC_BR) {
-                       printf(" %sp0.x", instr->cat0.inv ? "!" : "");
+               if (instr->opc == OPC_B) {
+                       printf("r %sp0.x", instr->cat0.inv ? "!" : "");
                }
                printf(", target=block%u", block_id(instr->cat0.target));
        }
index 81916c69e5a007ab7a59b93390049d1641e2a85c..ba6af20583498314c6c3c70eb9426a0ce7b7b8c6 100644 (file)
@@ -41,6 +41,9 @@ static const struct test {
        INSTR_6XX(03000000_00000000, "end"),
        INSTR_6XX(00800000_00000004, "br p0.x, #4"),
        INSTR_6XX(00900000_00000003, "br !p0.x, #3"),
+       INSTR_6XX(03820000_00000015, "shps #21"), /* emit */
+       INSTR_6XX(04021000_00000000, "(ss)shpe"), /* cut */
+       INSTR_6XX(02820000_00000014, "getone #20"), /* kill p0.x */
 
        /* cat1 */
        INSTR_6XX(20244000_00000020, "mov.f32f32 r0.x, c8.x"),