radv: always initialize HTILE when the src layout is UNDEFINED
[mesa.git] / src / intel / compiler / brw_eu_validate.c
index 6ee6b4ffbe74f33f10efa5b2ed1f41c47dc319af..358a0347a9314e7bc821f5f36e5813fd77c0e28f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2015 Intel Corporation
+ * Copyright © 2015-2019 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 /** @file brw_eu_validate.c
  *
  * This file implements a pass that validates shader assembly.
+ *
+ * The restrictions implemented herein are intended to verify that instructions
+ * in shader assembly do not violate restrictions documented in the graphics
+ * programming reference manuals.
+ *
+ * The restrictions are difficult for humans to quickly verify due to their
+ * complexity and abundance.
+ *
+ * It is critical that this code is thoroughly unit tested because false
+ * results will lead developers astray, which is worse than having no validator
+ * at all. Functional changes to this file without corresponding unit tests (in
+ * test_eu_validate.cpp) will be rejected.
  */
 
 #include "brw_eu.h"
@@ -90,6 +102,18 @@ inst_is_send(const struct gen_device_info *devinfo, const brw_inst *inst)
    }
 }
 
+static bool
+inst_is_split_send(const struct gen_device_info *devinfo, const brw_inst *inst)
+{
+   switch (brw_inst_opcode(devinfo, inst)) {
+   case BRW_OPCODE_SENDS:
+   case BRW_OPCODE_SENDSC:
+      return true;
+   default:
+      return false;
+   }
+}
+
 static unsigned
 signed_type(unsigned type)
 {
@@ -236,6 +260,12 @@ sources_not_null(const struct gen_device_info *devinfo,
    if (num_sources == 3)
       return (struct string){};
 
+   /* Nothing to test.  Split sends can only encode a file in sources that are
+    * allowed to be NULL.
+    */
+   if (inst_is_split_send(devinfo, inst))
+      return (struct string){};
+
    if (num_sources >= 1)
       ERROR_IF(src0_is_null(devinfo, inst), "src0 is null");
 
@@ -251,7 +281,41 @@ send_restrictions(const struct gen_device_info *devinfo,
 {
    struct string error_msg = { .str = NULL, .len = 0 };
 
-   if (brw_inst_opcode(devinfo, inst) == BRW_OPCODE_SEND) {
+   if (inst_is_split_send(devinfo, inst)) {
+      ERROR_IF(brw_inst_send_src1_reg_file(devinfo, inst) == BRW_ARCHITECTURE_REGISTER_FILE &&
+               brw_inst_send_src1_reg_nr(devinfo, inst) != BRW_ARF_NULL,
+               "src1 of split send must be a GRF or NULL");
+
+      ERROR_IF(brw_inst_eot(devinfo, inst) &&
+               brw_inst_src0_da_reg_nr(devinfo, inst) < 112,
+               "send with EOT must use g112-g127");
+      ERROR_IF(brw_inst_eot(devinfo, inst) &&
+               brw_inst_send_src1_reg_file(devinfo, inst) == BRW_GENERAL_REGISTER_FILE &&
+               brw_inst_send_src1_reg_nr(devinfo, inst) < 112,
+               "send with EOT must use g112-g127");
+
+      if (brw_inst_send_src1_reg_file(devinfo, inst) == BRW_GENERAL_REGISTER_FILE) {
+         /* Assume minimums if we don't know */
+         unsigned mlen = 1;
+         if (!brw_inst_send_sel_reg32_desc(devinfo, inst)) {
+            const uint32_t desc = brw_inst_send_desc(devinfo, inst);
+            mlen = brw_message_desc_mlen(devinfo, desc);
+         }
+
+         unsigned ex_mlen = 1;
+         if (!brw_inst_send_sel_reg32_ex_desc(devinfo, inst)) {
+            const uint32_t ex_desc = brw_inst_send_ex_desc(devinfo, inst);
+            ex_mlen = brw_message_ex_desc_ex_mlen(devinfo, ex_desc);
+         }
+         const unsigned src0_reg_nr = brw_inst_src0_da_reg_nr(devinfo, inst);
+         const unsigned src1_reg_nr = brw_inst_send_src1_reg_nr(devinfo, inst);
+         ERROR_IF((src0_reg_nr <= src1_reg_nr &&
+                   src1_reg_nr < src0_reg_nr + mlen) ||
+                  (src1_reg_nr <= src0_reg_nr &&
+                   src0_reg_nr < src1_reg_nr + ex_mlen),
+                   "split send payloads must not overlap");
+      }
+   } else if (inst_is_send(devinfo, inst)) {
       ERROR_IF(brw_inst_src0_address_mode(devinfo, inst) != BRW_ADDRESS_DIRECT,
                "send must use direct addressing");
 
@@ -261,6 +325,17 @@ send_restrictions(const struct gen_device_info *devinfo,
                   brw_inst_src0_da_reg_nr(devinfo, inst) < 112,
                   "send with EOT must use g112-g127");
       }
+
+      if (devinfo->gen >= 8) {
+         ERROR_IF(!dst_is_null(devinfo, inst) &&
+                  (brw_inst_dst_da_reg_nr(devinfo, inst) +
+                   brw_inst_rlen(devinfo, inst) > 127) &&
+                  (brw_inst_src0_da_reg_nr(devinfo, inst) +
+                   brw_inst_mlen(devinfo, inst) >
+                   brw_inst_dst_da_reg_nr(devinfo, inst)),
+                  "r127 must not be used for return address when there is "
+                  "a src and dest overlap");
+      }
    }
 
    return error_msg;
@@ -277,6 +352,7 @@ static enum brw_reg_type
 execution_type_for_type(enum brw_reg_type type)
 {
    switch (type) {
+   case BRW_REGISTER_TYPE_NF:
    case BRW_REGISTER_TYPE_DF:
    case BRW_REGISTER_TYPE_F:
    case BRW_REGISTER_TYPE_HF:
@@ -460,9 +536,11 @@ general_restrictions_based_on_operand_types(const struct gen_device_info *devinf
       dst_type_size = 8;
 
    if (exec_type_size > dst_type_size) {
-      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");
+      if (!(dst_type_is_byte && inst_is_raw_move(devinfo, inst))) {
+         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);
 
@@ -507,6 +585,12 @@ general_restrictions_on_region_parameters(const struct gen_device_info *devinfo,
    if (num_sources == 3)
       return (struct string){};
 
+   /* Split sends don't have the bits in the instruction to encode regions so
+    * there's nothing to check.
+    */
+   if (inst_is_split_send(devinfo, inst))
+      return (struct string){};
+
    if (brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_16) {
       if (desc->ndst != 0 && !dst_is_null(devinfo, inst))
          ERROR_IF(brw_inst_dst_hstride(devinfo, inst) != BRW_HORIZONTAL_STRIDE_1,
@@ -1097,6 +1181,10 @@ special_requirements_for_handling_double_precision_data_types(
    if (num_sources == 3 || num_sources == 0)
       return (struct string){};
 
+   /* Split sends don't have types so there's no doubles there. */
+   if (inst_is_split_send(devinfo, inst))
+      return (struct string){};
+
    enum brw_reg_type exec_type = execution_type(devinfo, inst);
    unsigned exec_type_size = brw_reg_type_to_size(exec_type);