summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2020-05-01 14:37:27 -0700
committerEric Anholt <eric@anholt.net>2020-05-04 11:14:46 -0700
commit97b21110b8b845bb02596036bdbf9e9562cfa7a5 (patch)
tree9d6b5610070b1e44aa382f7bdb1e20e2a6197a79
parent1e5b0c92c549b392065f4856a2e5370b2157d961 (diff)
freedreno/ir3: Sync some new changes from envytools.
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>
-rw-r--r--src/freedreno/ir3/disasm-a3xx.c65
-rw-r--r--src/freedreno/ir3/instr-a3xx.h43
-rw-r--r--src/freedreno/ir3/ir3.c15
-rw-r--r--src/freedreno/ir3/ir3.h8
-rw-r--r--src/freedreno/ir3/ir3_compiler_nir.c4
-rw-r--r--src/freedreno/ir3/ir3_delay.c2
-rw-r--r--src/freedreno/ir3/ir3_legalize.c8
-rw-r--r--src/freedreno/ir3/ir3_parser.y2
-rw-r--r--src/freedreno/ir3/ir3_postsched.c2
-rw-r--r--src/freedreno/ir3/ir3_print.c4
-rw-r--r--src/freedreno/ir3/tests/disasm.c3
11 files changed, 107 insertions, 49 deletions
diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c
index 54ed027f55c..697219ce405 100644
--- a/src/freedreno/ir3/disasm-a3xx.c
+++ b/src/freedreno/ir3/disasm-a3xx.c
@@ -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)
diff --git a/src/freedreno/ir3/instr-a3xx.h b/src/freedreno/ir3/instr-a3xx.h
index 565b296739f..23b21eb653d 100644
--- a/src/freedreno/ir3/instr-a3xx.h
+++ b/src/freedreno/ir3/instr-a3xx.h
@@ -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;
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index cb7418bf2e0..8c30bf98298 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -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;
}
diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index 0f3bb54f316..4e7550f5e8d 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -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)
diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c
index bd65f91e780..b3d0556a03e 100644
--- a/src/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/freedreno/ir3/ir3_compiler_nir.c
@@ -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;
diff --git a/src/freedreno/ir3/ir3_delay.c b/src/freedreno/ir3/ir3_delay.c
index 3fc4d911f14..15434fdedd1 100644
--- a/src/freedreno/ir3/ir3_delay.c
+++ b/src/freedreno/ir3/ir3_delay.c
@@ -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));
}
/**
diff --git a/src/freedreno/ir3/ir3_legalize.c b/src/freedreno/ir3/ir3_legalize.c
index d0b0dd83b46..2b1f3b94d8b 100644
--- a/src/freedreno/ir3/ir3_legalize.c
+++ b/src/freedreno/ir3/ir3_legalize.c
@@ -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);
diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y
index c9cede4b725..08779380b12 100644
--- a/src/freedreno/ir3/ir3_parser.y
+++ b/src/freedreno/ir3/ir3_parser.y
@@ -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); }
diff --git a/src/freedreno/ir3/ir3_postsched.c b/src/freedreno/ir3/ir3_postsched.c
index 521078a04c9..496c1d211b8 100644
--- a/src/freedreno/ir3/ir3_postsched.c
+++ b/src/freedreno/ir3/ir3_postsched.c
@@ -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;
diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c
index 1b6908edefb..034bcd8248e 100644
--- a/src/freedreno/ir3/ir3_print.c
+++ b/src/freedreno/ir3/ir3_print.c
@@ -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));
}
diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c
index 81916c69e5a..ba6af205834 100644
--- a/src/freedreno/ir3/tests/disasm.c
+++ b/src/freedreno/ir3/tests/disasm.c
@@ -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"),