summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConnor Abbott <cwabbott0@gmail.com>2023-03-01 18:15:04 +0100
committerMarge Bot <emma+marge@anholt.net>2024-04-26 12:55:13 +0000
commit736570b74d25b67acc5e681aa080c4f61320d36d (patch)
tree26373daf6e4c6cec1a145cde9d68c79da7a88f78
parent94c1ff415bdd109bfc52b8990c5aac9dd2b421b0 (diff)
ir3: Add support for ldc.u
This will be important for using shared registers as much as possible. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22075>
-rw-r--r--src/freedreno/ir3/ir3.h6
-rw-r--r--src/freedreno/ir3/ir3_lexer.l1
-rw-r--r--src/freedreno/ir3/ir3_parser.y1
-rw-r--r--src/freedreno/ir3/ir3_print.c2
-rw-r--r--src/freedreno/ir3/ir3_validate.c6
-rw-r--r--src/freedreno/ir3/tests/disasm.c3
-rw-r--r--src/freedreno/isa/ir3-cat6.xml6
7 files changed, 22 insertions, 3 deletions
diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index 642daf016a2..0e2ec78560d 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 e6e580ff342..9a2e0efdc35 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 7b69bf530d4..acbdff49d4f 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 2fe1ddd2225..60df5910f43 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 9ed7c102016..96bb7ae84cd 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 0a8ed52d401..cea67be42a5 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 b928f3ddd9f..06b451ffdbb 100644
--- a/src/freedreno/isa/ir3-cat6.xml
+++ b/src/freedreno/isa/ir3-cat6.xml
@@ -1020,7 +1020,6 @@ SOFTWARE.
<bitset name="#cat6-ldc-common" extends="#instruction-cat6-a6xx">
<pattern pos="0" >x</pattern>
- <pattern pos="11" >x</pattern> <!-- TYPED -->
<pattern low="14" high="19">011110</pattern> <!-- OPC -->
<pattern low="20" high="22">1xx</pattern>
<field pos="23" name="SRC1_IM" type="bool"/>
@@ -1057,6 +1056,7 @@ SOFTWARE.
{SY}{JP}ldc.{LOAD_SIZE}.k.{MODE}{BASE} c[a1.x], {SRC1}, {SRC2}
</display>
+ <pattern pos="11">x</pattern>
<derived name="LOAD_SIZE" expr="#cat6-load-size" type="uint"/>
<field low="32" high="39" name="LOAD_SIZE_MINUS_ONE" type="uint"/>
@@ -1077,13 +1077,15 @@ SOFTWARE.
meaning? Maybe I don't have enough ldc examples from deqp-glesN
-->
<display>
- {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}
</display>
+ <field pos="11" name="U" type="bool" display=".u"/>
<field low="9" high="10" name="OFFSET" type="uint"/> <!-- D_MINUS_ONE -->
<field low="32" high="39" name="DST" type="#reg-gpr"/>
<pattern low="52" high="53">10</pattern>
<encode>
<map name="OFFSET">src->cat6.d</map>
+ <map name="U">!!(src->flags &amp; IR3_INSTR_U)</map>
</encode>
</bitset>