i965: Validate "Special Cases for Byte Operations"

Do this in general_restrictions_based_on_operand_types() because the two
rules that "Special Cases for Byte Operations" relax are checked there.
This commit is contained in:
Matt Turner
2016-11-21 10:26:57 -08:00
parent 75b7f5a269
commit f57bdd4849
2 changed files with 150 additions and 9 deletions
+61 -9
View File
@@ -78,6 +78,34 @@ inst_is_send(const struct gen_device_info *devinfo, const brw_inst *inst)
}
}
static unsigned
signed_type(unsigned type)
{
switch (type) {
case BRW_HW_REG_TYPE_UD: return BRW_HW_REG_TYPE_D;
case BRW_HW_REG_TYPE_UW: return BRW_HW_REG_TYPE_W;
case BRW_HW_REG_NON_IMM_TYPE_UB: return BRW_HW_REG_NON_IMM_TYPE_B;
case GEN8_HW_REG_TYPE_UQ: return GEN8_HW_REG_TYPE_Q;
default: return type;
}
}
static bool
inst_is_raw_move(const struct gen_device_info *devinfo, const brw_inst *inst)
{
unsigned dst_type = signed_type(brw_inst_dst_reg_type(devinfo, inst));
unsigned src_type = signed_type(brw_inst_src0_reg_type(devinfo, inst));
if (brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE &&
(brw_inst_src0_negate(devinfo, inst) ||
brw_inst_src0_abs(devinfo, inst)))
return false;
return brw_inst_opcode(devinfo, inst) == BRW_OPCODE_MOV &&
brw_inst_saturate(devinfo, inst) == 0 &&
dst_type == src_type;
}
static bool
dst_is_null(const struct gen_device_info *devinfo, const brw_inst *inst)
{
@@ -417,10 +445,21 @@ general_restrictions_based_on_operand_types(const struct gen_device_info *devinf
if (desc->ndst == 0)
return (struct string){};
/* FINISHME: check special cases for byte operations */
if (brw_inst_dst_reg_type(devinfo, inst) == BRW_HW_REG_NON_IMM_TYPE_B ||
brw_inst_dst_reg_type(devinfo, inst) == BRW_HW_REG_NON_IMM_TYPE_UB)
return (struct string){};
unsigned dst_stride = 1 << (brw_inst_dst_hstride(devinfo, inst) - 1);
bool dst_type_is_byte =
brw_inst_dst_reg_type(devinfo, inst) == BRW_HW_REG_NON_IMM_TYPE_B ||
brw_inst_dst_reg_type(devinfo, inst) == BRW_HW_REG_NON_IMM_TYPE_UB;
if (dst_type_is_byte) {
if (is_packed(exec_size * dst_stride, exec_size, dst_stride)) {
if (!inst_is_raw_move(devinfo, inst)) {
ERROR("Only raw MOV supports a packed-byte destination");
return error_msg;
} else {
return (struct string){};
}
}
}
unsigned exec_type = execution_type(devinfo, inst);
unsigned exec_type_size =
@@ -428,17 +467,30 @@ general_restrictions_based_on_operand_types(const struct gen_device_info *devinf
unsigned dst_type_size = brw_element_size(devinfo, inst, dst);
if (exec_type_size > dst_type_size) {
unsigned dst_stride = 1 << (brw_inst_dst_hstride(devinfo, inst) - 1);
ERROR_IF(dst_stride * dst_type_size != exec_type_size,
"Destination stride must be equal to the ratio of the sizes of "
"the execution data type to the destination type");
unsigned subreg = brw_inst_dst_da1_subreg_nr(devinfo, inst);
if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1 &&
brw_inst_dst_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT) {
unsigned subreg = brw_inst_dst_da1_subreg_nr(devinfo, inst);
ERROR_IF(subreg % exec_type_size != 0,
"Destination subreg must be aligned to the size of the "
"execution data type");
/* The i965 PRM says:
*
* Implementation Restriction: The relaxed alignment rule for byte
* destination (#10.5) is not supported.
*/
if ((devinfo->gen > 4 || devinfo->is_g4x) && dst_type_is_byte) {
ERROR_IF(subreg % exec_type_size != 0 &&
subreg % exec_type_size != 1,
"Destination subreg must be aligned to the size of the "
"execution data type (or to the next lowest byte for byte "
"destinations)");
} else {
ERROR_IF(subreg % exec_type_size != 0,
"Destination subreg must be aligned to the size of the "
"execution data type");
}
}
}
@@ -756,3 +756,92 @@ TEST_P(validation_test, one_src_two_dst)
EXPECT_FALSE(validate(p));
}
}
TEST_P(validation_test, packed_byte_destination)
{
static const struct {
enum brw_reg_type dst_type;
enum brw_reg_type src_type;
bool neg, abs, sat;
bool expected_result;
} move[] = {
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 0, true },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 0, true },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 0, true },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 0, true },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 1, 0, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 1, 0, 0, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 1, 0, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 1, 0, 0, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 1, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 1, 0, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 1, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 1, 0, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 1, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 1, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 1, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 1, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UW, 0, 0, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_W , 0, 0, 0, false },
{ BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UD, 0, 0, 0, false },
{ BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_D , 0, 0, 0, false },
};
for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
brw_MOV(p, retype(g0, move[i].dst_type), retype(g0, move[i].src_type));
brw_inst_set_src0_negate(&devinfo, last_inst, move[i].neg);
brw_inst_set_src0_abs(&devinfo, last_inst, move[i].abs);
brw_inst_set_saturate(&devinfo, last_inst, move[i].sat);
EXPECT_EQ(move[i].expected_result, validate(p));
clear_instructions(p);
}
brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_UB),
retype(g0, BRW_REGISTER_TYPE_UB),
retype(g0, BRW_REGISTER_TYPE_UB));
brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
EXPECT_FALSE(validate(p));
clear_instructions(p);
brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
retype(g0, BRW_REGISTER_TYPE_B),
retype(g0, BRW_REGISTER_TYPE_B));
brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
EXPECT_FALSE(validate(p));
}
TEST_P(validation_test, byte_destination_relaxed_alignment)
{
brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
retype(g0, BRW_REGISTER_TYPE_W),
retype(g0, BRW_REGISTER_TYPE_W));
brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
EXPECT_TRUE(validate(p));
clear_instructions(p);
brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
retype(g0, BRW_REGISTER_TYPE_W),
retype(g0, BRW_REGISTER_TYPE_W));
brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 1);
if (devinfo.gen > 4 || devinfo.is_g4x) {
EXPECT_TRUE(validate(p));
} else {
EXPECT_FALSE(validate(p));
}
}