From 736570b74d25b67acc5e681aa080c4f61320d36d Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Wed, 1 Mar 2023 18:15:04 +0100 Subject: [PATCH] ir3: Add support for ldc.u This will be important for using shared registers as much as possible. Part-of: --- src/freedreno/ir3/ir3.h | 6 +++++- src/freedreno/ir3/ir3_lexer.l | 1 + src/freedreno/ir3/ir3_parser.y | 1 + src/freedreno/ir3/ir3_print.c | 2 ++ src/freedreno/ir3/ir3_validate.c | 6 ++++++ src/freedreno/ir3/tests/disasm.c | 3 +++ src/freedreno/isa/ir3-cat6.xml | 6 ++++-- 7 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 642daf016a2fa..0e2ec78560d06 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -334,10 +334,14 @@ typedef enum ir3_instruction_flags { IR3_INSTR_NONUNIF = BIT(13), /* (cat5-only) Get some parts of the encoding from a1.x */ IR3_INSTR_A1EN = BIT(14), + /* uniform destination for ldc, which must be set if and only if it has a + * shared reg destination + */ + IR3_INSTR_U = BIT(15), /* meta-flags, for intermediate stages of IR, ie. * before register assignment is done: */ - IR3_INSTR_MARK = BIT(15), + IR3_INSTR_MARK = BIT(16), /* Used by shared register allocation when creating spill/reload instructions * to inform validation that this is created by RA. This also may be set on diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index e6e580ff3428a..9a2e0efdc3553 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -435,6 +435,7 @@ static int parse_reg(const char *str) "s2en" return TOKEN(T_S2EN); "s" return 's'; "k" return 'k'; +"u" return 'u'; "base"[0-9]+ ir3_yylval.num = strtol(yytext+4, NULL, 10); return T_BASE; "offset"[0-9]+ ir3_yylval.num = strtol(yytext+6, NULL, 10); return T_OFFSET; "uniform" return T_UNIFORM; diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index 7b69bf530d46d..acbdff49d4f52 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -1308,6 +1308,7 @@ cat6_bindless_ldc_opc: T_OP_LDC { new_instr(OPC_LDC); } /* This is separated from the opcode to avoid lookahead/shift-reduce conflicts */ cat6_bindless_ldc_middle: T_OFFSET '.' cat6_immed '.' cat6_bindless_mode dst_reg { instr->cat6.d = $1; } +| 'u' '.' T_OFFSET '.' cat6_immed '.' cat6_bindless_mode dst_reg { instr->flags |= IR3_INSTR_U; instr->cat6.d = $3; } | cat6_immed '.' 'k' '.' cat6_bindless_mode 'c' '[' T_A1 ']' { instr->opc = OPC_LDC_K; } cat6_bindless_ldc: cat6_bindless_ldc_opc '.' cat6_bindless_ldc_middle ',' cat6_reg_or_immed ',' cat6_reg_or_immed { diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c index 2fe1ddd22257a..60df5910f43a4 100644 --- a/src/freedreno/ir3/ir3_print.c +++ b/src/freedreno/ir3/ir3_print.c @@ -202,6 +202,8 @@ print_instr_name(struct log_stream *stream, struct ir3_instruction *instr, mesa_log_stream_printf(stream, ".s"); if (instr->flags & IR3_INSTR_A1EN) mesa_log_stream_printf(stream, ".a1en"); + if (instr->flags & IR3_INSTR_U) + mesa_log_stream_printf(stream, ".u"); if (instr->opc == OPC_LDC) mesa_log_stream_printf(stream, ".offset%d", instr->cat6.d); if (instr->opc == OPC_LDC_K) diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c index 9ed7c10201610..96bb7ae84cda9 100644 --- a/src/freedreno/ir3/ir3_validate.c +++ b/src/freedreno/ir3/ir3_validate.c @@ -400,6 +400,12 @@ validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr) break; case OPC_PUSH_CONSTS_LOAD_MACRO: break; + case OPC_LDC: + validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF)); + validate_assert(ctx, !!(instr->dsts[0]->flags & IR3_REG_SHARED) == + !!(instr->flags & IR3_INSTR_U)); + break; case OPC_LDC_K: validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF)); validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF)); diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c index 0a8ed52d401f9..cea67be42a57c 100644 --- a/src/freedreno/ir3/tests/disasm.c +++ b/src/freedreno/ir3/tests/disasm.c @@ -380,6 +380,9 @@ static const struct test { INSTR_6XX(c0260000_00478400, "ldc.offset2.1.imm r0.x, r0.x, 0"), /* ldc.1.mode0.base0 r0.x, r0.x, 0 */ INSTR_6XX(c0260000_00478600, "ldc.offset3.1.imm r0.x, r0.x, 0"), /* ldc.1.mode0.base0 r0.x, r0.x, 0 */ + /* dEQP-VK.glsl.arrays.length.float_fragment */ + INSTR_6XX(c02600c1_00c7a900, "ldc.u.offset0.3.imm.base0 r48.y, 0, 0"), /* ldc.u.3.mode4.base0 sr48.y, 0, 0 */ + /* dEQP-VK.glsl.conditionals.if.if_else_vertex */ INSTR_6XX(c0360000_00c78100, "ldc.1.k.imm.base0 c[a1.x], 0, 0"), /* ldc.1.k.mode4.base0 c[a1.x], 0, 0 */ /* custom */ diff --git a/src/freedreno/isa/ir3-cat6.xml b/src/freedreno/isa/ir3-cat6.xml index b928f3ddd9fab..06b451ffdbbb8 100644 --- a/src/freedreno/isa/ir3-cat6.xml +++ b/src/freedreno/isa/ir3-cat6.xml @@ -1020,7 +1020,6 @@ SOFTWARE. x - x 011110 1xx @@ -1057,6 +1056,7 @@ SOFTWARE. {SY}{JP}ldc.{LOAD_SIZE}.k.{MODE}{BASE} c[a1.x], {SRC1}, {SRC2} + x @@ -1077,13 +1077,15 @@ SOFTWARE. meaning? Maybe I don't have enough ldc examples from deqp-glesN --> - {SY}{JP}{NAME}.offset{OFFSET}.{TYPE_SIZE}.{MODE}{BASE} {DST}, {SRC1}, {SRC2} + {SY}{JP}{NAME}{U}.offset{OFFSET}.{TYPE_SIZE}.{MODE}{BASE} {DST}, {SRC1}, {SRC2} + 10 src->cat6.d + !!(src->flags & IR3_INSTR_U)