xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/elk/elk_fs_validate.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /** @file elk_fs_validate.cpp
25  *
26  * Implements a pass that validates various invariants of the IR.  The current
27  * pass only validates that GRF's uses are sane.  More can be added later.
28  */
29 
30 #include "elk_fs.h"
31 #include "elk_cfg.h"
32 
33 #define fsv_assert(assertion)                                           \
34    {                                                                    \
35       if (!(assertion)) {                                               \
36          fprintf(stderr, "ASSERT: Scalar %s validation failed!\n",      \
37                  _mesa_shader_stage_to_abbrev(stage));                  \
38          dump_instruction(inst, stderr);                                \
39          fprintf(stderr, "%s:%d: '%s' failed\n", __FILE__, __LINE__, #assertion);  \
40          abort();                                                       \
41       }                                                                 \
42    }
43 
44 #define fsv_assert_eq(first, second)                                    \
45    {                                                                    \
46       unsigned f = (first);                                             \
47       unsigned s = (second);                                            \
48       if (f != s) {                                                     \
49          fprintf(stderr, "ASSERT: Scalar %s validation failed!\n",      \
50                  _mesa_shader_stage_to_abbrev(stage));                  \
51          dump_instruction(inst, stderr);                                \
52          fprintf(stderr, "%s:%d: A == B failed\n", __FILE__, __LINE__); \
53          fprintf(stderr, "  A = %s = %u\n", #first, f);                 \
54          fprintf(stderr, "  B = %s = %u\n", #second, s);                \
55          abort();                                                       \
56       }                                                                 \
57    }
58 
59 #define fsv_assert_ne(first, second)                                    \
60    {                                                                    \
61       unsigned f = (first);                                             \
62       unsigned s = (second);                                            \
63       if (f == s) {                                                     \
64          fprintf(stderr, "ASSERT: Scalar %s validation failed!\n",      \
65                  _mesa_shader_stage_to_abbrev(stage));                  \
66          dump_instruction(inst, stderr);                                \
67          fprintf(stderr, "%s:%d: A != B failed\n", __FILE__, __LINE__); \
68          fprintf(stderr, "  A = %s = %u\n", #first, f);                 \
69          fprintf(stderr, "  B = %s = %u\n", #second, s);                \
70          abort();                                                       \
71       }                                                                 \
72    }
73 
74 #define fsv_assert_lte(first, second)                                   \
75    {                                                                    \
76       unsigned f = (first);                                             \
77       unsigned s = (second);                                            \
78       if (f > s) {                                                      \
79          fprintf(stderr, "ASSERT: Scalar %s validation failed!\n",      \
80                  _mesa_shader_stage_to_abbrev(stage));                  \
81          dump_instruction(inst, stderr);                                \
82          fprintf(stderr, "%s:%d: A <= B failed\n", __FILE__, __LINE__); \
83          fprintf(stderr, "  A = %s = %u\n", #first, f);                 \
84          fprintf(stderr, "  B = %s = %u\n", #second, s);                \
85          abort();                                                       \
86       }                                                                 \
87    }
88 
89 #ifndef NDEBUG
90 void
validate()91 elk_fs_visitor::validate()
92 {
93    cfg->validate(_mesa_shader_stage_to_abbrev(stage));
94 
95    foreach_block_and_inst (block, elk_fs_inst, inst, cfg) {
96       switch (inst->opcode) {
97       case ELK_SHADER_OPCODE_SEND:
98          fsv_assert(is_uniform(inst->src[0]));
99          break;
100 
101       case ELK_OPCODE_MOV:
102          fsv_assert(inst->sources == 1);
103          break;
104 
105       default:
106          break;
107       }
108 
109       if (inst->elk_is_3src(compiler)) {
110          const unsigned integer_sources =
111             elk_reg_type_is_integer(inst->src[0].type) +
112             elk_reg_type_is_integer(inst->src[1].type) +
113             elk_reg_type_is_integer(inst->src[2].type);
114          const unsigned float_sources =
115             elk_reg_type_is_floating_point(inst->src[0].type) +
116             elk_reg_type_is_floating_point(inst->src[1].type) +
117             elk_reg_type_is_floating_point(inst->src[2].type);
118 
119          fsv_assert((integer_sources == 3 && float_sources == 0) ||
120                     (integer_sources == 0 && float_sources == 3));
121 
122          if (grf_used != 0) {
123             /* Only perform the pre-Gfx10 checks after register allocation has
124              * occured.
125              *
126              * Many passes (e.g., constant copy propagation) will genenerate
127              * invalid 3-source instructions with the expectation that later
128              * passes (e.g., combine constants) will fix them.
129              */
130             for (unsigned i = 0; i < 3; i++) {
131                fsv_assert_ne(inst->src[i].file, ELK_IMMEDIATE_VALUE);
132 
133                /* A stride of 1 (the usual case) or 0, with a special
134                 * "repctrl" bit, is allowed. The repctrl bit doesn't work for
135                 * 64-bit datatypes, so if the source type is 64-bit then only
136                 * a stride of 1 is allowed. From the Broadwell PRM, Volume 7
137                 * "3D Media GPGPU", page 944:
138                 *
139                 *    This is applicable to 32b datatypes and 16b datatype. 64b
140                 *    datatypes cannot use the replicate control.
141                 */
142                fsv_assert_lte(inst->src[i].vstride, 1);
143 
144                if (type_sz(inst->src[i].type) > 4)
145                   fsv_assert_eq(inst->src[i].vstride, 1);
146             }
147          }
148       }
149 
150       if (inst->dst.file == VGRF) {
151          fsv_assert_lte(inst->dst.offset / REG_SIZE + regs_written(inst),
152                         alloc.sizes[inst->dst.nr]);
153       }
154 
155       for (unsigned i = 0; i < inst->sources; i++) {
156          if (inst->src[i].file == VGRF) {
157             fsv_assert_lte(inst->src[i].offset / REG_SIZE + regs_read(inst, i),
158                            alloc.sizes[inst->src[i].nr]);
159          }
160       }
161    }
162 }
163 #endif
164