intel/brw: Add validation for ARF scalar register

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32236>
This commit is contained in:
Caio Oliveira
2024-11-19 13:25:21 -08:00
committed by Marge Bot
parent f8c7348468
commit 5420c027e6
2 changed files with 250 additions and 1 deletions
+88 -1
View File
@@ -1605,11 +1605,16 @@ special_requirements_for_handling_double_precision_data_types(
"source and destination are not supported except for "
"broadcast of a scalar.");
/* NOTE: Expanded this to include Scalar. See documentation issue
* open in https://gfxspecs.intel.com/Predator/Home/Index/56640.
*/
ERROR_IF((address_mode == BRW_ADDRESS_DIRECT && file == ARF &&
reg != BRW_ARF_SCALAR &&
reg != BRW_ARF_NULL && !(reg >= BRW_ARF_ACCUMULATOR && reg < BRW_ARF_FLAG)) ||
(inst->dst.file == ARF &&
dst_reg != BRW_ARF_SCALAR &&
dst_reg != BRW_ARF_NULL && (dst_reg & 0xF0) != BRW_ARF_ACCUMULATOR),
"Explicit ARF registers except null and accumulator must not "
"Explicit ARF registers except null, accumulator, and scalar must not "
"be used.");
}
@@ -2164,6 +2169,87 @@ send_descriptor_restrictions(const struct brw_isa_info *isa,
return error_msg;
}
static struct string
scalar_register_restrictions(const struct brw_isa_info *isa,
const brw_hw_decoded_inst *inst)
{
const struct intel_device_info *devinfo = isa->devinfo;
struct string error_msg = { .str = NULL, .len = 0 };
/* Restrictions from BSpec 71168 (r55736). */
if (devinfo->ver >= 30) {
if (inst->dst.file == ARF && inst->dst.nr == BRW_ARF_SCALAR) {
switch (inst->opcode) {
case BRW_OPCODE_MOV: {
unsigned dst_size_bits = brw_type_size_bits(inst->dst.type);
ERROR_IF(inst->dst.type != inst->src[0].type,
"When destination is scalar register, "
"source and destination data-types must be the same.");
ERROR_IF(!brw_type_is_int(inst->dst.type) || (dst_size_bits != 16 &&
dst_size_bits != 32 &&
dst_size_bits != 64),
"When destination is scalar register, "
"it must be an integer with size 16, 32, or 64 bits.");
if (inst->src[0].file == IMM) {
ERROR_IF(inst->exec_size != 1,
"When destination is scalar register with immediate source, "
"execution size must be 1.");
ERROR_IF(inst->cond_modifier != BRW_CONDITIONAL_NONE,
"When destination is scalar register with immediate source, "
"conditional modifier must not be used.");
}
ERROR_IF((inst->dst.subnr / 32) != ((inst->dst.subnr + brw_type_size_bytes(inst->dst.type)) / 32),
"When destination is scalar register, it must not span across "
"the lower to upper 8 dword boundary of the register.");
break;
}
default:
ERROR("When destination is scalar register, opcode must be MOV.");
break;
}
}
if (inst->src[0].file == ARF && inst->src[0].nr == BRW_ARF_SCALAR) {
switch (inst->opcode) {
case BRW_OPCODE_MOV: {
ERROR_IF(inst->dst.file == ARF && inst->dst.nr == BRW_ARF_SCALAR,
"When source is a scalar register, destination must not be a scalar register.");
ERROR_IF(!src_has_scalar_region(inst, 0),
"When source is a scalar register and opcode is MOV, the scalar (broadcast) regioning must be used.");
break;
}
case BRW_OPCODE_SEND:
case BRW_OPCODE_SENDC: {
ERROR_IF(!src1_is_null(inst),
"When source is a scalar and opcode is a SEND or SENDC, Src1 must be NULL.");
break;
}
default:
ERROR("When source is a scalar register, opcode must be MOV, SEND, or SENDC.");
break;
}
}
if ((inst->src[1].file == ARF && inst->src[1].nr == BRW_ARF_SCALAR) ||
(inst->src[2].file == ARF && inst->src[2].nr == BRW_ARF_SCALAR)) {
ERROR("When source is a scalar register, it must be on Source 0.");
}
} else {
assert(devinfo->ver < 30);
if ((inst->dst.file == ARF && inst->dst.nr == BRW_ARF_SCALAR) ||
(inst->src[0].file == ARF && inst->src[0].nr == BRW_ARF_SCALAR) ||
(inst->src[1].file == ARF && inst->src[1].nr == BRW_ARF_SCALAR) ||
(inst->src[2].file == ARF && inst->src[2].nr == BRW_ARF_SCALAR))
ERROR("Scalar register not available before Gfx30.");
}
return error_msg;
}
static unsigned
VSTRIDE_3SRC(unsigned vstride)
{
@@ -2562,6 +2648,7 @@ brw_validate_instruction(const struct brw_isa_info *isa,
CHECK(special_requirements_for_handling_double_precision_data_types);
CHECK(instruction_restrictions);
CHECK(send_descriptor_restrictions);
CHECK(scalar_register_restrictions);
}
#undef CHECK
+162
View File
@@ -3375,3 +3375,165 @@ TEST_P(validation_test, dpas_src_subreg_nr)
clear_instructions(p);
}
}
static brw_reg
brw_s0(enum brw_reg_type type, unsigned subnr)
{
return brw_make_reg(ARF,
BRW_ARF_SCALAR,
subnr,
0,
0,
type,
BRW_VERTICAL_STRIDE_0,
BRW_WIDTH_1,
BRW_HORIZONTAL_STRIDE_0,
BRW_SWIZZLE_XYZW,
WRITEMASK_XYZW);
}
static brw_reg
brw_s0_with_region(enum brw_reg_type type, unsigned subnr, unsigned v, unsigned w, unsigned h)
{
return brw_make_reg(ARF,
BRW_ARF_SCALAR,
subnr,
0,
0,
type,
cvt(v),
cvt(w)-1,
cvt(h),
BRW_SWIZZLE_XYZW,
WRITEMASK_XYZW);
}
static brw_reg
brw_grf(enum brw_reg_type type, unsigned nr, unsigned subnr, unsigned v, unsigned w, unsigned h)
{
return brw_make_reg(FIXED_GRF,
nr,
subnr,
0,
0,
type,
cvt(v),
cvt(w)-1,
cvt(h),
BRW_SWIZZLE_XYZW,
WRITEMASK_XYZW);
}
TEST_P(validation_test, scalar_register_restrictions)
{
/* Restrictions from BSpec 71168 (r55736). */
if (devinfo.ver < 30)
return;
const brw_reg null_ud = retype(brw_null_reg(), BRW_TYPE_UD);
struct test {
enum opcode opcode;
unsigned exec_size;
struct {
enum brw_conditional_mod cmod;
} opts;
brw_reg dst, src0, src1;
bool expected_result;
};
static const struct test tests[] = {
{ BRW_OPCODE_MOV, 8, {}, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 1,1,0), {}, true },
/* When destination, opcode must be MOV. */
{ BRW_OPCODE_NOT, 8, {}, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 1,1,0), {}, false },
{ BRW_OPCODE_ADD, 8, {}, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 1,1,0), brw_imm_ud(1), false },
/* Source and destination types must match. */
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UQ, 0), brw_imm_uq(0x000036161836341E), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UQ, 0), brw_imm_ud(0x1836341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UQ, 0), brw_imm_uw(0x341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UD, 0), brw_imm_uq(0x000036161836341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UD, 0), brw_imm_ud(0x1836341E), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UD, 0), brw_imm_uw(0x341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UW, 0), brw_imm_uq(0x000036161836341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UW, 0), brw_imm_ud(0x1836341E), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UW, 0), brw_imm_uw(0x341E), {}, true },
/* When destination, must be integers of size 16, 32 or 64. */
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_B, 0), brw_grf(BRW_TYPE_B, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UB, 0), brw_grf(BRW_TYPE_UB, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_W, 0), brw_grf(BRW_TYPE_W, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UW, 0), brw_grf(BRW_TYPE_UW, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_D, 0), brw_grf(BRW_TYPE_D, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_Q, 0), brw_grf(BRW_TYPE_Q, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UQ, 0), brw_grf(BRW_TYPE_UQ, 1, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_F, 0), brw_grf(BRW_TYPE_F, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_HF, 0), brw_grf(BRW_TYPE_HF, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_DF, 0), brw_grf(BRW_TYPE_DF, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_V, 0), brw_grf(BRW_TYPE_V, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UV, 0), brw_grf(BRW_TYPE_UV, 1, 0, 0,1,0), {}, false },
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_VF, 0), brw_grf(BRW_TYPE_VF, 1, 0, 0,1,0), {}, false },
/* When destination with immediate source, execution size must be 1. */
{ BRW_OPCODE_MOV, 8, {}, brw_s0(BRW_TYPE_UW, 0), brw_imm_uw(0x1234), {}, false },
/* When destination with with immediate source, conditional modifier cannot be used. */
{ BRW_OPCODE_MOV, 1, {.cmod = BRW_CONDITIONAL_Z}, brw_s0(BRW_TYPE_UW, 0), brw_imm_uw(0x341E), {}, false },
{ BRW_OPCODE_MOV, 1, {.cmod = BRW_CONDITIONAL_Z}, brw_s0(BRW_TYPE_UW, 0), brw_grf(BRW_TYPE_UW, 1, 0, 0,1,0), {}, true },
/* When source is scalar, destination must not be scalar. */
{ BRW_OPCODE_MOV, 1, {}, brw_s0(BRW_TYPE_UW, 0), brw_s0(BRW_TYPE_UW, 4), {}, false },
/* When source of MOV is scalar, it must be a broadcast. */
{ BRW_OPCODE_MOV, 8, {}, brw_grf(BRW_TYPE_UW, 1, 0, 1,1,0), brw_s0_with_region(BRW_TYPE_UW, 0, 0,1,0), {}, true },
{ BRW_OPCODE_MOV, 8, {}, brw_grf(BRW_TYPE_UW, 1, 0, 1,1,0), brw_s0_with_region(BRW_TYPE_UW, 0, 1,1,0), {}, false },
{ BRW_OPCODE_MOV, 8, {}, brw_grf(BRW_TYPE_UW, 1, 0, 1,1,0), brw_s0_with_region(BRW_TYPE_UW, 0, 8,8,1), {}, false },
/* When source 0 of SEND/SENDC is scalar, source 1 must be null. */
{ BRW_OPCODE_SEND, 16, {}, null_ud, brw_s0(BRW_TYPE_UD, 0), null_ud, true },
{ BRW_OPCODE_SENDC, 16, {}, null_ud, brw_s0(BRW_TYPE_UD, 0), null_ud, true },
{ BRW_OPCODE_SEND, 16, {}, null_ud, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 0,1,0), false },
{ BRW_OPCODE_SENDC, 16, {}, null_ud, brw_s0(BRW_TYPE_UD, 0), brw_grf(BRW_TYPE_UD, 1, 0, 0,1,0), false },
/* When source is a scalar register, it must be on source 0. */
{ BRW_OPCODE_SEND, 16, {}, null_ud, brw_grf(BRW_TYPE_UD, 0, 0, 0,1,0), brw_grf(BRW_TYPE_UD, 2, 0, 0,1,0), true },
{ BRW_OPCODE_SEND, 16, {}, null_ud, brw_grf(BRW_TYPE_UD, 0, 0, 0,1,0), brw_s0(BRW_TYPE_UD, 0), false },
};
for (unsigned i = 0; i < ARRAY_SIZE(tests); i++) {
const struct test &t = tests[i];
switch (tests[i].opcode) {
case BRW_OPCODE_ADD:
brw_ADD(p, t.dst, t.src0, t.src1);
break;
case BRW_OPCODE_NOT:
brw_NOT(p, t.dst, t.src0);
break;
case BRW_OPCODE_MOV:
brw_MOV(p, t.dst, t.src0);
break;
case BRW_OPCODE_SEND:
case BRW_OPCODE_SENDC: {
brw_inst *send = brw_next_insn(p, tests[i].opcode);
brw_set_dest(p, send, t.dst);
brw_set_src0(p, send, t.src0);
brw_set_src1(p, send, t.src1);
break;
}
default:
unreachable("unexpected opcode in tests");
}
brw_inst_set_exec_size(&devinfo, last_inst, cvt(t.exec_size) - 1);
brw_inst_set_cond_modifier(&devinfo, last_inst, t.opts.cmod);
EXPECT_EQ(t.expected_result, validate(p)) <<
"test vector index = " << i;
clear_instructions(p);
}
}