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