ir3/isa: add isaspec definition for movs

movs works like subgroupBroadcast/OpGroupNonUniformBroadcast. The fiber
id can either be an immediate or a value in a0.x. In the latter case,
the value has to be dynamically uniform or else the behavior is
undefined. The dst register has to be shared or else the behavior seems
to be equivalent to a normal mov (i.e., the fiber id is not taken into
account anymore).

movs can do a cov on the broadcasted value. It works exactly like a
normal cov except that using u8 as the src type does not seem to work at
all.

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32624>
This commit is contained in:
Job Noorman 2025-06-26 11:35:54 +02:00 committed by Marge Bot
parent d328b1e8c0
commit 4b3f58701c
7 changed files with 66 additions and 2 deletions

View file

@ -185,6 +185,7 @@ static const struct opc_info {
OPC(1, OPC_SWZ, swz),
OPC(1, OPC_SCT, sct),
OPC(1, OPC_GAT, gat),
OPC(1, OPC_MOVS, movs),
OPC(1, OPC_BALLOT_MACRO, ballot.macro),
OPC(1, OPC_ANY_MACRO, any.macro),
OPC(1, OPC_ALL_MACRO, all.macro),

View file

@ -82,6 +82,7 @@ typedef enum {
/* category 1: */
OPC_MOV = _OPC(1, 0),
OPC_MOVP = _OPC(1, 1),
OPC_MOVS = _OPC(1, 2),
/* swz, gat, sct */
OPC_MOVMSK = _OPC(1, 3),
@ -98,6 +99,8 @@ typedef enum {
OPC_MOV_GPR = _OPC(1, 42),
OPC_MOV_RELGPR = _OPC(1, 43),
OPC_MOV_RELCONST = _OPC(1, 44),
OPC_MOVS_IMMED = _OPC(1, 45),
OPC_MOVS_A0 = _OPC(1, 46),
/* Macros that expand to an if statement + move */
OPC_BALLOT_MACRO = _OPC(1, 50),

View file

@ -223,6 +223,7 @@ static int parse_reg(const char *str)
"swz" return TOKEN(T_OP_SWZ);
"gat" return TOKEN(T_OP_GAT);
"sct" return TOKEN(T_OP_SCT);
"movs" return TOKEN(T_OP_MOVS);
("f16"|"f32"|"u16"|"u32"|"s16"|"s32"|"u8"|"u8_32"|"u64"){2} ir3_yylval.str = yytext; return T_CAT1_TYPE_TYPE;
/* category 2: */

View file

@ -502,6 +502,7 @@ static void print_token(FILE *file, int type, YYSTYPE value)
%token <tok> T_OP_SWZ
%token <tok> T_OP_GAT
%token <tok> T_OP_SCT
%token <tok> T_OP_MOVS
/* category 2: */
%token <tok> T_OP_ADD_F
@ -1040,6 +1041,11 @@ cat1_gat: T_OP_GAT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC
cat1_sct: T_OP_SCT '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_SCT), $3); } dst_reg ',' dst_reg ',' dst_reg ',' dst_reg ',' src_reg
movs_invocation: uinteger { new_src(0, IR3_REG_IMMED)->uim_val = $1; }
| src_a0
cat1_movs: T_OP_MOVS '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_MOVS), $3); } dst_reg ',' src_reg ',' movs_invocation
/* NOTE: cat1 can also *write* to relative gpr */
cat1_instr: cat1_movmsk
| cat1_mova1
@ -1049,6 +1055,7 @@ cat1_instr: cat1_movmsk
| cat1_sct
| cat1_opc dst_reg ',' cat1_src
| cat1_opc relative_gpr_dst ',' cat1_src
| cat1_movs
cat2_opc_1src: T_OP_ABSNEG_F { new_instr(OPC_ABSNEG_F); }
| T_OP_ABSNEG_S { new_instr(OPC_ABSNEG_S); }

View file

@ -93,6 +93,9 @@ static const struct test {
INSTR_7XX(2004c005_00000405, "cov.f32u32 r1.y, (last)r1.y"),
INSTR_7XX(200440c0_ae800004, "movs.f32f32 r48.x, r1.x, 93"),
INSTR_7XX(201100c0_c000040b, "movs.s16s16 hr48.x, (last)hr2.w, a0.x"),
/* cat2 */
INSTR_6XX(40104002_0c210001, "add.f hr0.z, r0.y, c<a0.x + 33>"),
INSTR_6XX(40b80804_10408004, "(nop3) cmps.f.lt r1.x, (abs)r1.x, c16.x"),

View file

@ -79,6 +79,12 @@ __instruction_case(struct encode_state *s, const struct ir3_instruction *instr)
} else {
return OPC_MOV_GPR;
}
} else if (instr->opc == OPC_MOVS) {
if (instr->srcs[1]->flags & IR3_REG_IMMED) {
return OPC_MOVS_IMMED;
} else {
return OPC_MOVS_A0;
}
} else if (instr->opc == OPC_DEMOTE) {
return OPC_KILL;
} else if (s->compiler->gen >= 6) {

View file

@ -277,7 +277,7 @@ SOFTWARE.
<pattern low="53" high="54">01</pattern>
</bitset>
<bitset name="mov-gpr" extends="#instruction-cat1-mov">
<bitset name="#instruction-cat1-mov-gpr" extends="#instruction-cat1-mov">
<field name="SRC" low="0" high="7" type="#cat1-gpr-src">
<param name="LAST"/>
<param name="SRC_R"/>
@ -285,7 +285,6 @@ SOFTWARE.
</field>
<pattern low="8" high="9">00</pattern>
<field name="LAST" pos="10" type="bool" display="(last)"/>
<pattern low="11" high="31">000000000000000000000</pattern>
<field name="SRC_R" pos="43" type="bool" display="(r)"/>
<pattern low="53" high="54">00</pattern>
<encode>
@ -293,6 +292,50 @@ SOFTWARE.
</encode>
</bitset>
<bitset name="mov-gpr" extends="#instruction-cat1-mov-gpr">
<pattern low="11" high="31">000000000000000000000</pattern>
</bitset>
<bitset name="#instruction-cat1-movs" extends="#instruction-cat1-mov-gpr">
<doc>
movs works like subgroupBroadcast/OpGroupNonUniformBroadcast.
The fiber id can either be an immediate or a value in a0.x. In
the latter case, the value has to be dynamically uniform or else
the behavior is undefined. The dst register has to be shared or
else the behavior seems to be equivalent to a normal mov (i.e.,
the fiber id is not taken into account anymore).
movs can do a cov on the broadcasted value. It works exactly
like a normal cov except that using u8 as the src type does not
seem to work at all.
</doc>
<pattern low="11" high="22">000000000000</pattern>
<pattern pos="31">1</pattern> <!-- movs -->
</bitset>
<bitset name="movs-immed" extends="#instruction-cat1-movs">
<display>
{SY}{SS}{JP}{REPEAT}{UL}movs.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC}, {INVOCATION}
</display>
<field name="INVOCATION" low="23" high="29" type="uint"/>
<pattern pos="30">0</pattern> <!-- invocation in immed -->
<encode>
<map name="INVOCATION">extract_reg_uim(src->srcs[1])</map>
</encode>
</bitset>
<bitset name="movs-a0" extends="#instruction-cat1-movs">
<display>
{SY}{SS}{JP}{REPEAT}{UL}movs.{SRC_TYPE}{DST_TYPE} {ROUND}{DST_HALF}{DST}, {SRC}, a0.x
</display>
<pattern low="23" high="29">0000000</pattern>
<pattern pos="30">1</pattern> <!-- invocation in a0.x -->
</bitset>
<bitset name="#instruction-cat1-relative" extends="#instruction-cat1-mov">
<pattern pos="11">1</pattern>
<pattern low="12" high="31">00000000000000000000</pattern>