summaryrefslogtreecommitdiffstats
path: root/src/intel/compiler
diff options
context:
space:
mode:
authorMatt Turner <[email protected]>2017-07-27 18:29:50 -0700
committerMatt Turner <[email protected]>2017-08-21 14:05:23 -0700
commitce6b8627d87f14e15f2f4bbc6034b32c34557cb3 (patch)
tree84dea3972d5094dbd49094012ec16a7d7274a222 /src/intel/compiler
parent1d79c828d80f289de51b12efc2a5448fe7ebafd6 (diff)
i965: Validate destination restrictions with vector immediates
Reviewed-by: Scott D Phillips <[email protected]>
Diffstat (limited to 'src/intel/compiler')
-rw-r--r--src/intel/compiler/brw_eu_emit.c13
-rw-r--r--src/intel/compiler/brw_eu_validate.c61
-rw-r--r--src/intel/compiler/test_eu_validate.cpp79
3 files changed, 141 insertions, 12 deletions
diff --git a/src/intel/compiler/brw_eu_emit.c b/src/intel/compiler/brw_eu_emit.c
index 8a6ec035ccd..6673e0741a8 100644
--- a/src/intel/compiler/brw_eu_emit.c
+++ b/src/intel/compiler/brw_eu_emit.c
@@ -279,19 +279,8 @@ validate_reg(const struct gen_device_info *devinfo,
const int execsize_for_reg[] = {1, 2, 4, 8, 16, 32};
int width, hstride, vstride, execsize;
- if (reg.file == BRW_IMMEDIATE_VALUE) {
- /* 3.3.6: Region Parameters. Restriction: Immediate vectors
- * mean the destination has to be 128-bit aligned and the
- * destination horiz stride has to be a word.
- */
- if (reg.type == BRW_REGISTER_TYPE_V) {
- unsigned UNUSED elem_size = brw_element_size(devinfo, inst, dst);
- assert(hstride_for_reg[brw_inst_dst_hstride(devinfo, inst)] *
- elem_size == 2);
- }
-
+ if (reg.file == BRW_IMMEDIATE_VALUE)
return;
- }
if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
reg.file == BRW_ARF_NULL)
diff --git a/src/intel/compiler/brw_eu_validate.c b/src/intel/compiler/brw_eu_validate.c
index 827cd707c70..7f0595e6f8e 100644
--- a/src/intel/compiler/brw_eu_validate.c
+++ b/src/intel/compiler/brw_eu_validate.c
@@ -1036,6 +1036,66 @@ region_alignment_rules(const struct gen_device_info *devinfo,
return error_msg;
}
+static struct string
+vector_immediate_restrictions(const struct gen_device_info *devinfo,
+ const brw_inst *inst)
+{
+ unsigned num_sources = num_sources_from_inst(devinfo, inst);
+ struct string error_msg = { .str = NULL, .len = 0 };
+
+ if (num_sources == 3 || num_sources == 0)
+ return (struct string){};
+
+ unsigned file = num_sources == 1 ?
+ brw_inst_src0_reg_file(devinfo, inst) :
+ brw_inst_src1_reg_file(devinfo, inst);
+ if (file != BRW_IMMEDIATE_VALUE)
+ return (struct string){};
+
+ unsigned dst_type_size = brw_element_size(devinfo, inst, dst);
+ unsigned dst_subreg = brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1 ?
+ brw_inst_dst_da1_subreg_nr(devinfo, inst) : 0;
+ unsigned dst_stride = 1 << (brw_inst_dst_hstride(devinfo, inst) - 1);
+ unsigned type = num_sources == 1 ?
+ brw_inst_src0_reg_type(devinfo, inst) :
+ brw_inst_src1_reg_type(devinfo, inst);
+
+ /* The PRMs say:
+ *
+ * When an immediate vector is used in an instruction, the destination
+ * must be 128-bit aligned with destination horizontal stride equivalent
+ * to a word for an immediate integer vector (v) and equivalent to a
+ * DWord for an immediate float vector (vf).
+ *
+ * The text has not been updated for the addition of the immediate unsigned
+ * integer vector type (uv) on SNB, but presumably the same restriction
+ * applies.
+ */
+ switch (type) {
+ case BRW_HW_REG_IMM_TYPE_V:
+ case BRW_HW_REG_IMM_TYPE_UV:
+ case BRW_HW_REG_IMM_TYPE_VF:
+ ERROR_IF(dst_subreg % (128 / 8) != 0,
+ "Destination must be 128-bit aligned in order to use immediate "
+ "vector types");
+
+ if (type == BRW_HW_REG_IMM_TYPE_VF) {
+ ERROR_IF(dst_type_size * dst_stride != 4,
+ "Destination must have stride equivalent to dword in order "
+ "to use the VF type");
+ } else {
+ ERROR_IF(dst_type_size * dst_stride != 2,
+ "Destination must have stride equivalent to word in order "
+ "to use the V or UV type");
+ }
+ break;
+ default:
+ break;
+ }
+
+ return error_msg;
+}
+
bool
brw_validate_instructions(const struct gen_device_info *devinfo,
void *assembly, int start_offset, int end_offset,
@@ -1063,6 +1123,7 @@ brw_validate_instructions(const struct gen_device_info *devinfo,
CHECK(general_restrictions_based_on_operand_types);
CHECK(general_restrictions_on_region_parameters);
CHECK(region_alignment_rules);
+ CHECK(vector_immediate_restrictions);
}
if (error_msg.str && annotation) {
diff --git a/src/intel/compiler/test_eu_validate.cpp b/src/intel/compiler/test_eu_validate.cpp
index 09f4cc142a5..b43c41704b4 100644
--- a/src/intel/compiler/test_eu_validate.cpp
+++ b/src/intel/compiler/test_eu_validate.cpp
@@ -132,6 +132,7 @@ validate(struct brw_codegen *p)
#define last_inst (&p->store[p->nr_insn - 1])
#define g0 brw_vec8_grf(0, 0)
#define null brw_null_reg()
+#define zero brw_imm_f(0.0f)
static void
clear_instructions(struct brw_codegen *p)
@@ -844,5 +845,83 @@ TEST_P(validation_test, byte_destination_relaxed_alignment)
} else {
EXPECT_FALSE(validate(p));
}
+}
+
+TEST_P(validation_test, vector_immediate_destination_alignment)
+{
+ static const struct {
+ enum brw_reg_type dst_type;
+ enum brw_reg_type src_type;
+ unsigned subnr;
+ unsigned exec_size;
+ bool expected_result;
+ } move[] = {
+ { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 0, BRW_EXECUTE_4, true },
+ { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 16, BRW_EXECUTE_4, true },
+ { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 1, BRW_EXECUTE_4, false },
+
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 0, BRW_EXECUTE_8, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 16, BRW_EXECUTE_8, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 1, BRW_EXECUTE_8, false },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 0, BRW_EXECUTE_8, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 16, BRW_EXECUTE_8, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 1, BRW_EXECUTE_8, false },
+ };
+
+ for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
+ /* UV type is Gen6+ */
+ if (devinfo.gen < 6 &&
+ move[i].src_type == BRW_REGISTER_TYPE_UV)
+ continue;
+
+ brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type));
+ brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, move[i].subnr);
+ brw_inst_set_exec_size(&devinfo, last_inst, move[i].exec_size);
+
+ EXPECT_EQ(move[i].expected_result, validate(p));
+
+ clear_instructions(p);
+ }
+}
+
+TEST_P(validation_test, vector_immediate_destination_stride)
+{
+ static const struct {
+ enum brw_reg_type dst_type;
+ enum brw_reg_type src_type;
+ unsigned stride;
+ bool expected_result;
+ } move[] = {
+ { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true },
+ { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false },
+ { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true },
+ { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, true },
+ { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_4, true },
+
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_1, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, false },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_4, false },
+ { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, true },
+
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_1, true },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, false },
+ { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_4, false },
+ { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, true },
+ };
+
+ for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
+ /* UV type is Gen6+ */
+ if (devinfo.gen < 6 &&
+ move[i].src_type == BRW_REGISTER_TYPE_UV)
+ continue;
+
+ brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type));
+ brw_inst_set_dst_hstride(&devinfo, last_inst, move[i].stride);
+
+ EXPECT_EQ(move[i].expected_result, validate(p));
+
+ clear_instructions(p);
+ }
}