• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]) && is_uniform(inst->src[1]));
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 (devinfo->ver >= 10) {
123             for (unsigned i = 0; i < 3; i++) {
124                if (inst->src[i].file == ELK_IMMEDIATE_VALUE)
125                   continue;
126 
127                switch (inst->src[i].vstride) {
128                case ELK_VERTICAL_STRIDE_0:
129                case ELK_VERTICAL_STRIDE_4:
130                case ELK_VERTICAL_STRIDE_8:
131                case ELK_VERTICAL_STRIDE_16:
132                   break;
133 
134                case ELK_VERTICAL_STRIDE_1:
135                   fsv_assert_lte(12, devinfo->ver);
136                   break;
137 
138                case ELK_VERTICAL_STRIDE_2:
139                   fsv_assert_lte(devinfo->ver, 11);
140                   break;
141 
142                default:
143                   fsv_assert(!"invalid vstride");
144                   break;
145                }
146             }
147          } else if (grf_used != 0) {
148             /* Only perform the pre-Gfx10 checks after register allocation has
149              * occured.
150              *
151              * Many passes (e.g., constant copy propagation) will genenerate
152              * invalid 3-source instructions with the expectation that later
153              * passes (e.g., combine constants) will fix them.
154              */
155             for (unsigned i = 0; i < 3; i++) {
156                fsv_assert_ne(inst->src[i].file, ELK_IMMEDIATE_VALUE);
157 
158                /* A stride of 1 (the usual case) or 0, with a special
159                 * "repctrl" bit, is allowed. The repctrl bit doesn't work for
160                 * 64-bit datatypes, so if the source type is 64-bit then only
161                 * a stride of 1 is allowed. From the Broadwell PRM, Volume 7
162                 * "3D Media GPGPU", page 944:
163                 *
164                 *    This is applicable to 32b datatypes and 16b datatype. 64b
165                 *    datatypes cannot use the replicate control.
166                 */
167                fsv_assert_lte(inst->src[i].vstride, 1);
168 
169                if (type_sz(inst->src[i].type) > 4)
170                   fsv_assert_eq(inst->src[i].vstride, 1);
171             }
172          }
173       }
174 
175       if (inst->dst.file == VGRF) {
176          fsv_assert_lte(inst->dst.offset / REG_SIZE + regs_written(inst),
177                         alloc.sizes[inst->dst.nr]);
178       }
179 
180       for (unsigned i = 0; i < inst->sources; i++) {
181          if (inst->src[i].file == VGRF) {
182             fsv_assert_lte(inst->src[i].offset / REG_SIZE + regs_read(inst, i),
183                            alloc.sizes[inst->src[i].nr]);
184          }
185       }
186 
187       /* Accumulator Registers, bspec 47251:
188        *
189        * "When destination is accumulator with offset 0, destination
190        * horizontal stride must be 1."
191        */
192       if (intel_needs_workaround(devinfo, 14014617373) &&
193           inst->dst.is_accumulator() &&
194           inst->dst.offset == 0) {
195          fsv_assert_eq(inst->dst.stride, 1);
196       }
197    }
198 }
199 #endif
200