1fd4e5da5Sopenharmony_ci// Copyright (c) 2015-2016 The Khronos Group Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci// Validation tests for SSA
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include <sstream>
18fd4e5da5Sopenharmony_ci#include <string>
19fd4e5da5Sopenharmony_ci#include <utility>
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
22fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
23fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h"
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_cinamespace spvtools {
26fd4e5da5Sopenharmony_cinamespace val {
27fd4e5da5Sopenharmony_cinamespace {
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
30fd4e5da5Sopenharmony_ciusing ::testing::MatchesRegex;
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_ciusing ValidateSSA = spvtest::ValidateBase<std::pair<std::string, bool>>;
33fd4e5da5Sopenharmony_ci
34fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, Default) {
35fd4e5da5Sopenharmony_ci  char str[] = R"(
36fd4e5da5Sopenharmony_ci     OpCapability Shader
37fd4e5da5Sopenharmony_ci     OpCapability Linkage
38fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
39fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %3 ""
40fd4e5da5Sopenharmony_ci     OpExecutionMode %3 LocalSize 1 1 1
41fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
42fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
43fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
44fd4e5da5Sopenharmony_ci%4 = OpLabel
45fd4e5da5Sopenharmony_ci     OpReturn
46fd4e5da5Sopenharmony_ci     OpFunctionEnd
47fd4e5da5Sopenharmony_ci)";
48fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
49fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
50fd4e5da5Sopenharmony_ci}
51fd4e5da5Sopenharmony_ci
52fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdUndefinedBad) {
53fd4e5da5Sopenharmony_ci  char str[] = R"(
54fd4e5da5Sopenharmony_ci          OpCapability Shader
55fd4e5da5Sopenharmony_ci          OpCapability Linkage
56fd4e5da5Sopenharmony_ci          OpMemoryModel Logical GLSL450
57fd4e5da5Sopenharmony_ci          OpName %missing "missing"
58fd4e5da5Sopenharmony_ci%voidt  = OpTypeVoid
59fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt
60fd4e5da5Sopenharmony_ci%func   = OpFunction %vfunct None %missing
61fd4e5da5Sopenharmony_ci%flabel = OpLabel
62fd4e5da5Sopenharmony_ci          OpReturn
63fd4e5da5Sopenharmony_ci          OpFunctionEnd
64fd4e5da5Sopenharmony_ci    )";
65fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
66fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
67fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
68fd4e5da5Sopenharmony_ci}
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdRedefinedBad) {
71fd4e5da5Sopenharmony_ci  char str[] = R"(
72fd4e5da5Sopenharmony_ci     OpCapability Shader
73fd4e5da5Sopenharmony_ci     OpCapability Linkage
74fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
75fd4e5da5Sopenharmony_ci     OpName %2 "redefined"
76fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
77fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
78fd4e5da5Sopenharmony_ci%2 = OpFunction %1 None %2
79fd4e5da5Sopenharmony_ci%4 = OpLabel
80fd4e5da5Sopenharmony_ci     OpReturn
81fd4e5da5Sopenharmony_ci     OpFunctionEnd
82fd4e5da5Sopenharmony_ci)";
83fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
84fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
85fd4e5da5Sopenharmony_ci}
86fd4e5da5Sopenharmony_ci
87fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageBad) {
88fd4e5da5Sopenharmony_ci  char str[] = R"(
89fd4e5da5Sopenharmony_ci     OpCapability Shader
90fd4e5da5Sopenharmony_ci     OpCapability Linkage
91fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
92fd4e5da5Sopenharmony_ci     OpName %1 "not_dominant"
93fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1              ; uses %1 before it's definition
94fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
95fd4e5da5Sopenharmony_ci)";
96fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
97fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
98fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("not_dominant"));
99fd4e5da5Sopenharmony_ci}
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageWithinBlockBad) {
102fd4e5da5Sopenharmony_ci  char str[] = R"(
103fd4e5da5Sopenharmony_ci     OpCapability Shader
104fd4e5da5Sopenharmony_ci     OpCapability Linkage
105fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
106fd4e5da5Sopenharmony_ci     OpName %bad "bad"
107fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid
108fd4e5da5Sopenharmony_ci%funct = OpTypeFunction %voidt
109fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0
110fd4e5da5Sopenharmony_ci%one   = OpConstant %uintt 1
111fd4e5da5Sopenharmony_ci%func  = OpFunction %voidt None %funct
112fd4e5da5Sopenharmony_ci%entry = OpLabel
113fd4e5da5Sopenharmony_ci%sum   = OpIAdd %uintt %one %bad
114fd4e5da5Sopenharmony_ci%bad   = OpCopyObject %uintt %sum
115fd4e5da5Sopenharmony_ci         OpReturn
116fd4e5da5Sopenharmony_ci         OpFunctionEnd
117fd4e5da5Sopenharmony_ci)";
118fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
119fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
120fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
121fd4e5da5Sopenharmony_ci              MatchesRegex("ID '.\\[%bad\\]' has not been defined\n"
122fd4e5da5Sopenharmony_ci                           "  %8 = OpIAdd %uint %uint_1 %bad\n"));
123fd4e5da5Sopenharmony_ci}
124fd4e5da5Sopenharmony_ci
125fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageSameInstructionBad) {
126fd4e5da5Sopenharmony_ci  char str[] = R"(
127fd4e5da5Sopenharmony_ci     OpCapability Shader
128fd4e5da5Sopenharmony_ci     OpCapability Linkage
129fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
130fd4e5da5Sopenharmony_ci     OpName %sum "sum"
131fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid
132fd4e5da5Sopenharmony_ci%funct = OpTypeFunction %voidt
133fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0
134fd4e5da5Sopenharmony_ci%one   = OpConstant %uintt 1
135fd4e5da5Sopenharmony_ci%func  = OpFunction %voidt None %funct
136fd4e5da5Sopenharmony_ci%entry = OpLabel
137fd4e5da5Sopenharmony_ci%sum   = OpIAdd %uintt %one %sum
138fd4e5da5Sopenharmony_ci         OpReturn
139fd4e5da5Sopenharmony_ci         OpFunctionEnd
140fd4e5da5Sopenharmony_ci)";
141fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
142fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
143fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
144fd4e5da5Sopenharmony_ci              MatchesRegex("ID '.\\[%sum\\]' has not been defined\n"
145fd4e5da5Sopenharmony_ci                           "  %sum = OpIAdd %uint %uint_1 %sum\n"));
146fd4e5da5Sopenharmony_ci}
147fd4e5da5Sopenharmony_ci
148fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardNameGood) {
149fd4e5da5Sopenharmony_ci  char str[] = R"(
150fd4e5da5Sopenharmony_ci     OpCapability Shader
151fd4e5da5Sopenharmony_ci     OpCapability Linkage
152fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
153fd4e5da5Sopenharmony_ci     OpName %3 "main"
154fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
155fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
156fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
157fd4e5da5Sopenharmony_ci%4 = OpLabel
158fd4e5da5Sopenharmony_ci     OpReturn
159fd4e5da5Sopenharmony_ci     OpFunctionEnd
160fd4e5da5Sopenharmony_ci)";
161fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
162fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
163fd4e5da5Sopenharmony_ci}
164fd4e5da5Sopenharmony_ci
165fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardNameMissingTargetBad) {
166fd4e5da5Sopenharmony_ci  char str[] = R"(
167fd4e5da5Sopenharmony_ci      OpCapability Shader
168fd4e5da5Sopenharmony_ci      OpCapability Linkage
169fd4e5da5Sopenharmony_ci      OpMemoryModel Logical GLSL450
170fd4e5da5Sopenharmony_ci      OpName %5 "main"              ; Target never defined
171fd4e5da5Sopenharmony_ci)";
172fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
173fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
174fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("main"));
175fd4e5da5Sopenharmony_ci}
176fd4e5da5Sopenharmony_ci
177fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberNameGood) {
178fd4e5da5Sopenharmony_ci  char str[] = R"(
179fd4e5da5Sopenharmony_ci           OpCapability Shader
180fd4e5da5Sopenharmony_ci           OpCapability Linkage
181fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
182fd4e5da5Sopenharmony_ci           OpMemberName %struct 0 "value"
183fd4e5da5Sopenharmony_ci           OpMemberName %struct 1 "size"
184fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
185fd4e5da5Sopenharmony_ci%uintt  =  OpTypeInt 32 0
186fd4e5da5Sopenharmony_ci%struct =  OpTypeStruct %intt %uintt
187fd4e5da5Sopenharmony_ci)";
188fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
189fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
190fd4e5da5Sopenharmony_ci}
191fd4e5da5Sopenharmony_ci
192fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) {
193fd4e5da5Sopenharmony_ci  char str[] = R"(
194fd4e5da5Sopenharmony_ci           OpCapability Shader
195fd4e5da5Sopenharmony_ci           OpCapability Linkage
196fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
197fd4e5da5Sopenharmony_ci           OpMemberName %struct 0 "value"
198fd4e5da5Sopenharmony_ci           OpMemberName %bad 1 "size"     ; Target is not defined
199fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
200fd4e5da5Sopenharmony_ci%uintt  =  OpTypeInt 32 0
201fd4e5da5Sopenharmony_ci%struct =  OpTypeStruct %intt %uintt
202fd4e5da5Sopenharmony_ci)";
203fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
204fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
205fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
206fd4e5da5Sopenharmony_ci              HasSubstr("The following forward referenced IDs have not been "
207fd4e5da5Sopenharmony_ci                        "defined:\n'2[%2]'"));
208fd4e5da5Sopenharmony_ci}
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateGood) {
211fd4e5da5Sopenharmony_ci  char str[] = R"(
212fd4e5da5Sopenharmony_ci           OpCapability Shader
213fd4e5da5Sopenharmony_ci           OpCapability Linkage
214fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
215fd4e5da5Sopenharmony_ci           OpDecorate %var Restrict
216fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
217fd4e5da5Sopenharmony_ci%ptrt   =  OpTypePointer UniformConstant %intt
218fd4e5da5Sopenharmony_ci%var    =  OpVariable %ptrt UniformConstant
219fd4e5da5Sopenharmony_ci)";
220fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
221fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
222fd4e5da5Sopenharmony_ci}
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) {
225fd4e5da5Sopenharmony_ci  char str[] = R"(
226fd4e5da5Sopenharmony_ci           OpCapability Shader
227fd4e5da5Sopenharmony_ci           OpCapability Linkage
228fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
229fd4e5da5Sopenharmony_ci           OpName %missing "missing"
230fd4e5da5Sopenharmony_ci           OpDecorate %missing Restrict        ;Missing ID
231fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
232fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
233fd4e5da5Sopenharmony_ci%ptrt   =  OpTypePointer UniformConstant %intt
234fd4e5da5Sopenharmony_ci%var    =  OpVariable %ptrt UniformConstant
235fd4e5da5Sopenharmony_ci%2      =  OpTypeFunction %voidt
236fd4e5da5Sopenharmony_ci%3      =  OpFunction %voidt None %2
237fd4e5da5Sopenharmony_ci%4      =  OpLabel
238fd4e5da5Sopenharmony_ci           OpReturn
239fd4e5da5Sopenharmony_ci           OpFunctionEnd
240fd4e5da5Sopenharmony_ci)";
241fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
242fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
243fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
244fd4e5da5Sopenharmony_ci}
245fd4e5da5Sopenharmony_ci
246fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberDecorateGood) {
247fd4e5da5Sopenharmony_ci  char str[] = R"(
248fd4e5da5Sopenharmony_ci           OpCapability Shader
249fd4e5da5Sopenharmony_ci           OpCapability Linkage
250fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
251fd4e5da5Sopenharmony_ci           OpMemberDecorate %struct 1 RowMajor
252fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
253fd4e5da5Sopenharmony_ci%f32    =  OpTypeFloat 32
254fd4e5da5Sopenharmony_ci%vec3   =  OpTypeVector %f32 3
255fd4e5da5Sopenharmony_ci%mat33  =  OpTypeMatrix %vec3 3
256fd4e5da5Sopenharmony_ci%struct =  OpTypeStruct %intt %mat33
257fd4e5da5Sopenharmony_ci)";
258fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
259fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
260fd4e5da5Sopenharmony_ci}
261fd4e5da5Sopenharmony_ci
262fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
263fd4e5da5Sopenharmony_ci  char str[] = R"(
264fd4e5da5Sopenharmony_ci           OpCapability Shader
265fd4e5da5Sopenharmony_ci           OpCapability Linkage
266fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
267fd4e5da5Sopenharmony_ci           OpName %missing "missing"
268fd4e5da5Sopenharmony_ci           OpMemberDecorate %missing 1 RowMajor ; Target not defined
269fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
270fd4e5da5Sopenharmony_ci%f32    =  OpTypeFloat 32
271fd4e5da5Sopenharmony_ci%vec3   =  OpTypeVector %f32 3
272fd4e5da5Sopenharmony_ci%mat33  =  OpTypeMatrix %vec3 3
273fd4e5da5Sopenharmony_ci%struct =  OpTypeStruct %intt %mat33
274fd4e5da5Sopenharmony_ci)";
275fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
276fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
277fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
278fd4e5da5Sopenharmony_ci}
279fd4e5da5Sopenharmony_ci
280fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateGood) {
281fd4e5da5Sopenharmony_ci  char str[] = R"(
282fd4e5da5Sopenharmony_ci          OpCapability Shader
283fd4e5da5Sopenharmony_ci          OpCapability Linkage
284fd4e5da5Sopenharmony_ci          OpMemoryModel Logical GLSL450
285fd4e5da5Sopenharmony_ci          OpDecorate %dgrp RowMajor
286fd4e5da5Sopenharmony_ci%dgrp   = OpDecorationGroup
287fd4e5da5Sopenharmony_ci          OpGroupDecorate %dgrp %mat33 %mat44
288fd4e5da5Sopenharmony_ci%f32    =  OpTypeFloat 32
289fd4e5da5Sopenharmony_ci%vec3   = OpTypeVector %f32 3
290fd4e5da5Sopenharmony_ci%vec4   = OpTypeVector %f32 4
291fd4e5da5Sopenharmony_ci%mat33  = OpTypeMatrix %vec3 3
292fd4e5da5Sopenharmony_ci%mat44  = OpTypeMatrix %vec4 4
293fd4e5da5Sopenharmony_ci)";
294fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
295fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
296fd4e5da5Sopenharmony_ci}
297fd4e5da5Sopenharmony_ci
298fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) {
299fd4e5da5Sopenharmony_ci  char str[] = R"(
300fd4e5da5Sopenharmony_ci           OpCapability Shader
301fd4e5da5Sopenharmony_ci           OpCapability Linkage
302fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
303fd4e5da5Sopenharmony_ci           OpName %missing "missing"
304fd4e5da5Sopenharmony_ci           OpDecorate %dgrp RowMajor
305fd4e5da5Sopenharmony_ci%dgrp   =  OpDecorationGroup
306fd4e5da5Sopenharmony_ci           OpGroupDecorate %missing %mat33 %mat44 ; Target not defined
307fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
308fd4e5da5Sopenharmony_ci%vec3   =  OpTypeVector %intt 3
309fd4e5da5Sopenharmony_ci%vec4   =  OpTypeVector %intt 4
310fd4e5da5Sopenharmony_ci%mat33  =  OpTypeMatrix %vec3 3
311fd4e5da5Sopenharmony_ci%mat44  =  OpTypeMatrix %vec4 4
312fd4e5da5Sopenharmony_ci)";
313fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
314fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
315fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
316fd4e5da5Sopenharmony_ci}
317fd4e5da5Sopenharmony_ci
318fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
319fd4e5da5Sopenharmony_ci  char str[] = R"(
320fd4e5da5Sopenharmony_ci           OpCapability Shader
321fd4e5da5Sopenharmony_ci           OpCapability Linkage
322fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
323fd4e5da5Sopenharmony_ci           OpName %missing "missing"
324fd4e5da5Sopenharmony_ci           OpDecorate %dgrp RowMajor
325fd4e5da5Sopenharmony_ci%dgrp   =  OpDecorationGroup
326fd4e5da5Sopenharmony_ci           OpGroupDecorate %dgrp %missing %mat44 ; Target not defined
327fd4e5da5Sopenharmony_ci%f32    =  OpTypeFloat 32
328fd4e5da5Sopenharmony_ci%vec3   =  OpTypeVector %f32 3
329fd4e5da5Sopenharmony_ci%vec4   =  OpTypeVector %f32 4
330fd4e5da5Sopenharmony_ci%mat33  =  OpTypeMatrix %vec3 3
331fd4e5da5Sopenharmony_ci%mat44  =  OpTypeMatrix %vec4 4
332fd4e5da5Sopenharmony_ci)";
333fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
334fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
335fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
336fd4e5da5Sopenharmony_ci}
337fd4e5da5Sopenharmony_ci
338fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) {
339fd4e5da5Sopenharmony_ci  char str[] = R"(
340fd4e5da5Sopenharmony_ci           OpCapability Shader
341fd4e5da5Sopenharmony_ci           OpCapability Linkage
342fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
343fd4e5da5Sopenharmony_ci           OpName %dgrp "group"
344fd4e5da5Sopenharmony_ci           OpDecorate %dgrp RowMajor
345fd4e5da5Sopenharmony_ci           OpGroupDecorate %dgrp %mat33 %mat44 ; Decoration group does not dominate usage
346fd4e5da5Sopenharmony_ci%dgrp   =  OpDecorationGroup
347fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
348fd4e5da5Sopenharmony_ci%vec3   =  OpTypeVector %intt 3
349fd4e5da5Sopenharmony_ci%vec4   =  OpTypeVector %intt 4
350fd4e5da5Sopenharmony_ci%mat33  =  OpTypeMatrix %vec3 3
351fd4e5da5Sopenharmony_ci%mat44  =  OpTypeMatrix %vec4 4
352fd4e5da5Sopenharmony_ci)";
353fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
354fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
355fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("group"));
356fd4e5da5Sopenharmony_ci}
357fd4e5da5Sopenharmony_ci
358fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) {
359fd4e5da5Sopenharmony_ci  char str[] = R"(
360fd4e5da5Sopenharmony_ci           OpCapability Shader
361fd4e5da5Sopenharmony_ci           OpCapability Linkage
362fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
363fd4e5da5Sopenharmony_ci           OpName %missing "missing"
364fd4e5da5Sopenharmony_ci           OpDecorate %missing Restrict        ; Missing target
365fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
366fd4e5da5Sopenharmony_ci%intt   =  OpTypeInt 32 1
367fd4e5da5Sopenharmony_ci%ptrt   =  OpTypePointer UniformConstant %intt
368fd4e5da5Sopenharmony_ci%var    =  OpVariable %ptrt UniformConstant
369fd4e5da5Sopenharmony_ci%2      =  OpTypeFunction %voidt
370fd4e5da5Sopenharmony_ci%3      =  OpFunction %voidt None %2
371fd4e5da5Sopenharmony_ci%4      =  OpLabel
372fd4e5da5Sopenharmony_ci           OpReturn
373fd4e5da5Sopenharmony_ci           OpFunctionEnd
374fd4e5da5Sopenharmony_ci)";
375fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
376fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
377fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
378fd4e5da5Sopenharmony_ci}
379fd4e5da5Sopenharmony_ci
380fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, FunctionCallGood) {
381fd4e5da5Sopenharmony_ci  char str[] = R"(
382fd4e5da5Sopenharmony_ci         OpCapability Shader
383fd4e5da5Sopenharmony_ci         OpCapability Linkage
384fd4e5da5Sopenharmony_ci         OpMemoryModel Logical GLSL450
385fd4e5da5Sopenharmony_ci%1    =  OpTypeVoid
386fd4e5da5Sopenharmony_ci%2    =  OpTypeInt 32 1
387fd4e5da5Sopenharmony_ci%3    =  OpTypeInt 32 0
388fd4e5da5Sopenharmony_ci%4    =  OpTypeFunction %1
389fd4e5da5Sopenharmony_ci%8    =  OpTypeFunction %1 %2 %3
390fd4e5da5Sopenharmony_ci%four =  OpConstant %2 4
391fd4e5da5Sopenharmony_ci%five =  OpConstant %3 5
392fd4e5da5Sopenharmony_ci%9    =  OpFunction %1 None %8
393fd4e5da5Sopenharmony_ci%10   =  OpFunctionParameter %2
394fd4e5da5Sopenharmony_ci%11   =  OpFunctionParameter %3
395fd4e5da5Sopenharmony_ci%12   =  OpLabel
396fd4e5da5Sopenharmony_ci         OpReturn
397fd4e5da5Sopenharmony_ci         OpFunctionEnd
398fd4e5da5Sopenharmony_ci%5    =  OpFunction %1 None %4
399fd4e5da5Sopenharmony_ci%6    =  OpLabel
400fd4e5da5Sopenharmony_ci%7    =  OpFunctionCall %1 %9 %four %five
401fd4e5da5Sopenharmony_ci         OpReturn
402fd4e5da5Sopenharmony_ci         OpFunctionEnd
403fd4e5da5Sopenharmony_ci)";
404fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
405fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
406fd4e5da5Sopenharmony_ci}
407fd4e5da5Sopenharmony_ci
408fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardFunctionCallGood) {
409fd4e5da5Sopenharmony_ci  char str[] = R"(
410fd4e5da5Sopenharmony_ci         OpCapability Shader
411fd4e5da5Sopenharmony_ci         OpCapability Linkage
412fd4e5da5Sopenharmony_ci         OpMemoryModel Logical GLSL450
413fd4e5da5Sopenharmony_ci%1    =  OpTypeVoid
414fd4e5da5Sopenharmony_ci%2    =  OpTypeInt 32 1
415fd4e5da5Sopenharmony_ci%3    =  OpTypeInt 32 0
416fd4e5da5Sopenharmony_ci%four =  OpConstant %2 4
417fd4e5da5Sopenharmony_ci%five =  OpConstant %3 5
418fd4e5da5Sopenharmony_ci%8    =  OpTypeFunction %1 %2 %3
419fd4e5da5Sopenharmony_ci%4    =  OpTypeFunction %1
420fd4e5da5Sopenharmony_ci%5    =  OpFunction %1 None %4
421fd4e5da5Sopenharmony_ci%6    =  OpLabel
422fd4e5da5Sopenharmony_ci%7    =  OpFunctionCall %1 %9 %four %five
423fd4e5da5Sopenharmony_ci         OpReturn
424fd4e5da5Sopenharmony_ci         OpFunctionEnd
425fd4e5da5Sopenharmony_ci%9    =  OpFunction %1 None %8
426fd4e5da5Sopenharmony_ci%10   =  OpFunctionParameter %2
427fd4e5da5Sopenharmony_ci%11   =  OpFunctionParameter %3
428fd4e5da5Sopenharmony_ci%12   =  OpLabel
429fd4e5da5Sopenharmony_ci         OpReturn
430fd4e5da5Sopenharmony_ci         OpFunctionEnd
431fd4e5da5Sopenharmony_ci)";
432fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
433fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
434fd4e5da5Sopenharmony_ci}
435fd4e5da5Sopenharmony_ci
436fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalGood) {
437fd4e5da5Sopenharmony_ci  char str[] = R"(
438fd4e5da5Sopenharmony_ci            OpCapability Shader
439fd4e5da5Sopenharmony_ci            OpCapability Linkage
440fd4e5da5Sopenharmony_ci            OpMemoryModel Logical GLSL450
441fd4e5da5Sopenharmony_ci%voidt  =   OpTypeVoid
442fd4e5da5Sopenharmony_ci%boolt  =   OpTypeBool
443fd4e5da5Sopenharmony_ci%vfunct =   OpTypeFunction %voidt
444fd4e5da5Sopenharmony_ci%true   =   OpConstantTrue %boolt
445fd4e5da5Sopenharmony_ci%main   =   OpFunction %voidt None %vfunct
446fd4e5da5Sopenharmony_ci%mainl  =   OpLabel
447fd4e5da5Sopenharmony_ci            OpSelectionMerge %endl None
448fd4e5da5Sopenharmony_ci            OpBranchConditional %true %truel %falsel
449fd4e5da5Sopenharmony_ci%truel  =   OpLabel
450fd4e5da5Sopenharmony_ci            OpNop
451fd4e5da5Sopenharmony_ci            OpBranch %endl
452fd4e5da5Sopenharmony_ci%falsel =   OpLabel
453fd4e5da5Sopenharmony_ci            OpNop
454fd4e5da5Sopenharmony_ci            OpBranch %endl
455fd4e5da5Sopenharmony_ci%endl    =  OpLabel
456fd4e5da5Sopenharmony_ci            OpReturn
457fd4e5da5Sopenharmony_ci            OpFunctionEnd
458fd4e5da5Sopenharmony_ci)";
459fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
460fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
461fd4e5da5Sopenharmony_ci}
462fd4e5da5Sopenharmony_ci
463fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) {
464fd4e5da5Sopenharmony_ci  char str[] = R"(
465fd4e5da5Sopenharmony_ci           OpCapability Shader
466fd4e5da5Sopenharmony_ci           OpCapability Linkage
467fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
468fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
469fd4e5da5Sopenharmony_ci%boolt  =  OpTypeBool
470fd4e5da5Sopenharmony_ci%vfunct =  OpTypeFunction %voidt
471fd4e5da5Sopenharmony_ci%true   =  OpConstantTrue %boolt
472fd4e5da5Sopenharmony_ci%main   =  OpFunction %voidt None %vfunct
473fd4e5da5Sopenharmony_ci%mainl  =  OpLabel
474fd4e5da5Sopenharmony_ci           OpSelectionMerge %endl None
475fd4e5da5Sopenharmony_ci           OpBranchConditional %true %truel %falsel 1 9
476fd4e5da5Sopenharmony_ci%truel  =  OpLabel
477fd4e5da5Sopenharmony_ci           OpNop
478fd4e5da5Sopenharmony_ci           OpBranch %endl
479fd4e5da5Sopenharmony_ci%falsel =  OpLabel
480fd4e5da5Sopenharmony_ci           OpNop
481fd4e5da5Sopenharmony_ci           OpBranch %endl
482fd4e5da5Sopenharmony_ci%endl   =  OpLabel
483fd4e5da5Sopenharmony_ci           OpReturn
484fd4e5da5Sopenharmony_ci           OpFunctionEnd
485fd4e5da5Sopenharmony_ci)";
486fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
487fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
488fd4e5da5Sopenharmony_ci}
489fd4e5da5Sopenharmony_ci
490fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) {
491fd4e5da5Sopenharmony_ci  char str[] = R"(
492fd4e5da5Sopenharmony_ci           OpCapability Shader
493fd4e5da5Sopenharmony_ci           OpCapability Linkage
494fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
495fd4e5da5Sopenharmony_ci           OpName %tcpy "conditional"
496fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
497fd4e5da5Sopenharmony_ci%boolt  =  OpTypeBool
498fd4e5da5Sopenharmony_ci%vfunct =  OpTypeFunction %voidt
499fd4e5da5Sopenharmony_ci%true   =  OpConstantTrue %boolt
500fd4e5da5Sopenharmony_ci%main   =  OpFunction %voidt None %vfunct
501fd4e5da5Sopenharmony_ci%mainl  =  OpLabel
502fd4e5da5Sopenharmony_ci           OpSelectionMerge %endl None
503fd4e5da5Sopenharmony_ci           OpBranchConditional %tcpy %truel %falsel ;
504fd4e5da5Sopenharmony_ci%truel  =  OpLabel
505fd4e5da5Sopenharmony_ci           OpNop
506fd4e5da5Sopenharmony_ci           OpBranch %endl
507fd4e5da5Sopenharmony_ci%falsel =  OpLabel
508fd4e5da5Sopenharmony_ci           OpNop
509fd4e5da5Sopenharmony_ci           OpBranch %endl
510fd4e5da5Sopenharmony_ci%endl   =  OpLabel
511fd4e5da5Sopenharmony_ci%tcpy   =  OpCopyObject %boolt %true
512fd4e5da5Sopenharmony_ci           OpReturn
513fd4e5da5Sopenharmony_ci           OpFunctionEnd
514fd4e5da5Sopenharmony_ci)";
515fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
516fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
517fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("conditional"));
518fd4e5da5Sopenharmony_ci}
519fd4e5da5Sopenharmony_ci
520fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) {
521fd4e5da5Sopenharmony_ci  char str[] = R"(
522fd4e5da5Sopenharmony_ci           OpCapability Shader
523fd4e5da5Sopenharmony_ci           OpCapability Linkage
524fd4e5da5Sopenharmony_ci           OpMemoryModel Logical GLSL450
525fd4e5da5Sopenharmony_ci           OpName %missing "missing"
526fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
527fd4e5da5Sopenharmony_ci%boolt  =  OpTypeBool
528fd4e5da5Sopenharmony_ci%vfunct =  OpTypeFunction %voidt
529fd4e5da5Sopenharmony_ci%true   =  OpConstantTrue %boolt
530fd4e5da5Sopenharmony_ci%main   =  OpFunction %voidt None %vfunct
531fd4e5da5Sopenharmony_ci%mainl  =  OpLabel
532fd4e5da5Sopenharmony_ci           OpSelectionMerge %endl None
533fd4e5da5Sopenharmony_ci           OpBranchConditional %true %missing %falsel
534fd4e5da5Sopenharmony_ci%truel  =  OpLabel
535fd4e5da5Sopenharmony_ci           OpNop
536fd4e5da5Sopenharmony_ci           OpBranch %endl
537fd4e5da5Sopenharmony_ci%falsel =  OpLabel
538fd4e5da5Sopenharmony_ci           OpNop
539fd4e5da5Sopenharmony_ci           OpBranch %endl
540fd4e5da5Sopenharmony_ci%endl   =  OpLabel
541fd4e5da5Sopenharmony_ci           OpReturn
542fd4e5da5Sopenharmony_ci           OpFunctionEnd
543fd4e5da5Sopenharmony_ci)";
544fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
545fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
546fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
547fd4e5da5Sopenharmony_ci}
548fd4e5da5Sopenharmony_ci
549fd4e5da5Sopenharmony_ci// Since Int8 requires the Kernel capability, the signedness of int types may
550fd4e5da5Sopenharmony_ci// not be "1".
551fd4e5da5Sopenharmony_ciconst std::string kHeader = R"(
552fd4e5da5Sopenharmony_ciOpCapability Int8
553fd4e5da5Sopenharmony_ciOpCapability DeviceEnqueue
554fd4e5da5Sopenharmony_ciOpCapability Linkage
555fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
556fd4e5da5Sopenharmony_ci)";
557fd4e5da5Sopenharmony_ci
558fd4e5da5Sopenharmony_ciconst std::string kBasicTypes = R"(
559fd4e5da5Sopenharmony_ci%voidt  =  OpTypeVoid
560fd4e5da5Sopenharmony_ci%boolt  =  OpTypeBool
561fd4e5da5Sopenharmony_ci%int8t  =  OpTypeInt 8 0
562fd4e5da5Sopenharmony_ci%uintt  =  OpTypeInt 32 0
563fd4e5da5Sopenharmony_ci%vfunct =  OpTypeFunction %voidt
564fd4e5da5Sopenharmony_ci%intptrt = OpTypePointer UniformConstant %uintt
565fd4e5da5Sopenharmony_ci%zero      = OpConstant %uintt 0
566fd4e5da5Sopenharmony_ci%one       = OpConstant %uintt 1
567fd4e5da5Sopenharmony_ci%ten       = OpConstant %uintt 10
568fd4e5da5Sopenharmony_ci%false     = OpConstantFalse %boolt
569fd4e5da5Sopenharmony_ci)";
570fd4e5da5Sopenharmony_ci
571fd4e5da5Sopenharmony_ciconst std::string kKernelTypesAndConstants = R"(
572fd4e5da5Sopenharmony_ci%queuet  = OpTypeQueue
573fd4e5da5Sopenharmony_ci
574fd4e5da5Sopenharmony_ci%three   = OpConstant %uintt 3
575fd4e5da5Sopenharmony_ci%arr3t   = OpTypeArray %uintt %three
576fd4e5da5Sopenharmony_ci%ndt     = OpTypeStruct %uintt %arr3t %arr3t %arr3t
577fd4e5da5Sopenharmony_ci
578fd4e5da5Sopenharmony_ci%eventt  = OpTypeEvent
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ci%offset = OpConstant %uintt 0
581fd4e5da5Sopenharmony_ci%local  = OpConstant %uintt 1
582fd4e5da5Sopenharmony_ci%gl     = OpConstant %uintt 1
583fd4e5da5Sopenharmony_ci
584fd4e5da5Sopenharmony_ci%nevent = OpConstant %uintt 0
585fd4e5da5Sopenharmony_ci%event  = OpConstantNull %eventt
586fd4e5da5Sopenharmony_ci
587fd4e5da5Sopenharmony_ci%firstp = OpConstant %int8t 0
588fd4e5da5Sopenharmony_ci%psize  = OpConstant %uintt 0
589fd4e5da5Sopenharmony_ci%palign = OpConstant %uintt 32
590fd4e5da5Sopenharmony_ci%lsize  = OpConstant %uintt 1
591fd4e5da5Sopenharmony_ci%flags  = OpConstant %uintt 0 ; NoWait
592fd4e5da5Sopenharmony_ci
593fd4e5da5Sopenharmony_ci%kfunct = OpTypeFunction %voidt %intptrt
594fd4e5da5Sopenharmony_ci)";
595fd4e5da5Sopenharmony_ci
596fd4e5da5Sopenharmony_ciconst std::string kKernelSetup = R"(
597fd4e5da5Sopenharmony_ci%dqueue = OpGetDefaultQueue %queuet
598fd4e5da5Sopenharmony_ci%ndval  = OpBuildNDRange %ndt %gl %local %offset
599fd4e5da5Sopenharmony_ci%revent = OpUndef %eventt
600fd4e5da5Sopenharmony_ci
601fd4e5da5Sopenharmony_ci)";
602fd4e5da5Sopenharmony_ci
603fd4e5da5Sopenharmony_ciconst std::string kKernelDefinition = R"(
604fd4e5da5Sopenharmony_ci%kfunc  = OpFunction %voidt None %kfunct
605fd4e5da5Sopenharmony_ci%iparam = OpFunctionParameter %intptrt
606fd4e5da5Sopenharmony_ci%kfuncl = OpLabel
607fd4e5da5Sopenharmony_ci          OpNop
608fd4e5da5Sopenharmony_ci          OpReturn
609fd4e5da5Sopenharmony_ci          OpFunctionEnd
610fd4e5da5Sopenharmony_ci)";
611fd4e5da5Sopenharmony_ci
612fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, EnqueueKernelGood) {
613fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
614fd4e5da5Sopenharmony_ci                    kKernelDefinition + R"(
615fd4e5da5Sopenharmony_ci                %main   = OpFunction %voidt None %vfunct
616fd4e5da5Sopenharmony_ci                %mainl  = OpLabel
617fd4e5da5Sopenharmony_ci                )" + kKernelSetup + R"(
618fd4e5da5Sopenharmony_ci                %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
619fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
620fd4e5da5Sopenharmony_ci                                        %palign %lsize
621fd4e5da5Sopenharmony_ci                          OpReturn
622fd4e5da5Sopenharmony_ci                          OpFunctionEnd
623fd4e5da5Sopenharmony_ci                 )";
624fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
625fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
626fd4e5da5Sopenharmony_ci}
627fd4e5da5Sopenharmony_ci
628fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelGood) {
629fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + R"(
630fd4e5da5Sopenharmony_ci                %main   = OpFunction %voidt None %vfunct
631fd4e5da5Sopenharmony_ci                %mainl  = OpLabel
632fd4e5da5Sopenharmony_ci                )" +
633fd4e5da5Sopenharmony_ci                    kKernelSetup + R"(
634fd4e5da5Sopenharmony_ci                %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
635fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
636fd4e5da5Sopenharmony_ci                                        %palign %lsize
637fd4e5da5Sopenharmony_ci                         OpReturn
638fd4e5da5Sopenharmony_ci                         OpFunctionEnd
639fd4e5da5Sopenharmony_ci                 )" + kKernelDefinition;
640fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
641fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
642fd4e5da5Sopenharmony_ci}
643fd4e5da5Sopenharmony_ci
644fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, EnqueueMissingFunctionBad) {
645fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %kfunc \"kfunc\"" + kBasicTypes +
646fd4e5da5Sopenharmony_ci                    kKernelTypesAndConstants + R"(
647fd4e5da5Sopenharmony_ci                %main   = OpFunction %voidt None %vfunct
648fd4e5da5Sopenharmony_ci                %mainl  = OpLabel
649fd4e5da5Sopenharmony_ci                )" + kKernelSetup + R"(
650fd4e5da5Sopenharmony_ci                %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
651fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
652fd4e5da5Sopenharmony_ci                                        %palign %lsize
653fd4e5da5Sopenharmony_ci                         OpReturn
654fd4e5da5Sopenharmony_ci                         OpFunctionEnd
655fd4e5da5Sopenharmony_ci                 )";
656fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
657fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
658fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("kfunc"));
659fd4e5da5Sopenharmony_ci}
660fd4e5da5Sopenharmony_ci
661fd4e5da5Sopenharmony_cistd::string forwardKernelNonDominantParameterBaseCode(
662fd4e5da5Sopenharmony_ci    std::string name = std::string()) {
663fd4e5da5Sopenharmony_ci  std::string op_name;
664fd4e5da5Sopenharmony_ci  if (name.empty()) {
665fd4e5da5Sopenharmony_ci    op_name = "";
666fd4e5da5Sopenharmony_ci  } else {
667fd4e5da5Sopenharmony_ci    op_name = "\nOpName %" + name + " \"" + name + "\"\n";
668fd4e5da5Sopenharmony_ci  }
669fd4e5da5Sopenharmony_ci  std::string out = kHeader + op_name + kBasicTypes + kKernelTypesAndConstants +
670fd4e5da5Sopenharmony_ci                    kKernelDefinition +
671fd4e5da5Sopenharmony_ci                    R"(
672fd4e5da5Sopenharmony_ci                %main   = OpFunction %voidt None %vfunct
673fd4e5da5Sopenharmony_ci                %mainl  = OpLabel
674fd4e5da5Sopenharmony_ci                )" + kKernelSetup;
675fd4e5da5Sopenharmony_ci  return out;
676fd4e5da5Sopenharmony_ci}
677fd4e5da5Sopenharmony_ci
678fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelMissingParameter1Bad) {
679fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("missing") + R"(
680fd4e5da5Sopenharmony_ci                %err    = OpEnqueueKernel %missing %dqueue %flags %ndval
681fd4e5da5Sopenharmony_ci                                        %nevent %event %revent %kfunc %firstp
682fd4e5da5Sopenharmony_ci                                        %psize %palign %lsize
683fd4e5da5Sopenharmony_ci                          OpReturn
684fd4e5da5Sopenharmony_ci                          OpFunctionEnd
685fd4e5da5Sopenharmony_ci                )";
686fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
687fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
688fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
689fd4e5da5Sopenharmony_ci}
690fd4e5da5Sopenharmony_ci
691fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter2Bad) {
692fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("dqueue2") + R"(
693fd4e5da5Sopenharmony_ci                %err     = OpEnqueueKernel %uintt %dqueue2 %flags %ndval
694fd4e5da5Sopenharmony_ci                                            %nevent %event %revent %kfunc
695fd4e5da5Sopenharmony_ci                                            %firstp %psize %palign %lsize
696fd4e5da5Sopenharmony_ci                %dqueue2 = OpGetDefaultQueue %queuet
697fd4e5da5Sopenharmony_ci                           OpReturn
698fd4e5da5Sopenharmony_ci                           OpFunctionEnd
699fd4e5da5Sopenharmony_ci                )";
700fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
701fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
702fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("dqueue2"));
703fd4e5da5Sopenharmony_ci}
704fd4e5da5Sopenharmony_ci
705fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter3Bad) {
706fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("ndval2") + R"(
707fd4e5da5Sopenharmony_ci                %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval2
708fd4e5da5Sopenharmony_ci                                        %nevent %event %revent %kfunc %firstp
709fd4e5da5Sopenharmony_ci                                        %psize %palign %lsize
710fd4e5da5Sopenharmony_ci                %ndval2  = OpBuildNDRange %ndt %gl %local %offset
711fd4e5da5Sopenharmony_ci                          OpReturn
712fd4e5da5Sopenharmony_ci                          OpFunctionEnd
713fd4e5da5Sopenharmony_ci                )";
714fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
715fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
716fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
717fd4e5da5Sopenharmony_ci}
718fd4e5da5Sopenharmony_ci
719fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter4Bad) {
720fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("nevent2") + R"(
721fd4e5da5Sopenharmony_ci              %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent2
722fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
723fd4e5da5Sopenharmony_ci                                        %palign %lsize
724fd4e5da5Sopenharmony_ci              %nevent2 = OpCopyObject %uintt %nevent
725fd4e5da5Sopenharmony_ci                        OpReturn
726fd4e5da5Sopenharmony_ci                        OpFunctionEnd
727fd4e5da5Sopenharmony_ci              )";
728fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
729fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
730fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("nevent2"));
731fd4e5da5Sopenharmony_ci}
732fd4e5da5Sopenharmony_ci
733fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter5Bad) {
734fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("event2") + R"(
735fd4e5da5Sopenharmony_ci              %err     = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
736fd4e5da5Sopenharmony_ci                                        %event2 %revent %kfunc %firstp %psize
737fd4e5da5Sopenharmony_ci                                        %palign %lsize
738fd4e5da5Sopenharmony_ci              %event2  = OpCopyObject %eventt %event
739fd4e5da5Sopenharmony_ci                         OpReturn
740fd4e5da5Sopenharmony_ci                         OpFunctionEnd
741fd4e5da5Sopenharmony_ci              )";
742fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
743fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
744fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("event2"));
745fd4e5da5Sopenharmony_ci}
746fd4e5da5Sopenharmony_ci
747fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter6Bad) {
748fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("revent2") + R"(
749fd4e5da5Sopenharmony_ci              %err     = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
750fd4e5da5Sopenharmony_ci                                        %event %revent2 %kfunc %firstp %psize
751fd4e5da5Sopenharmony_ci                                        %palign %lsize
752fd4e5da5Sopenharmony_ci              %revent2 = OpCopyObject %eventt %revent
753fd4e5da5Sopenharmony_ci                         OpReturn
754fd4e5da5Sopenharmony_ci                         OpFunctionEnd
755fd4e5da5Sopenharmony_ci              )";
756fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
757fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
758fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("revent2"));
759fd4e5da5Sopenharmony_ci}
760fd4e5da5Sopenharmony_ci
761fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter8Bad) {
762fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("firstp2") + R"(
763fd4e5da5Sopenharmony_ci              %err     = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
764fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp2 %psize
765fd4e5da5Sopenharmony_ci                                        %palign %lsize
766fd4e5da5Sopenharmony_ci              %firstp2 = OpCopyObject %int8t %firstp
767fd4e5da5Sopenharmony_ci                         OpReturn
768fd4e5da5Sopenharmony_ci                         OpFunctionEnd
769fd4e5da5Sopenharmony_ci              )";
770fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
771fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
772fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
773fd4e5da5Sopenharmony_ci}
774fd4e5da5Sopenharmony_ci
775fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter9Bad) {
776fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("psize2") + R"(
777fd4e5da5Sopenharmony_ci              %err    = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
778fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize2
779fd4e5da5Sopenharmony_ci                                        %palign %lsize
780fd4e5da5Sopenharmony_ci              %psize2 = OpCopyObject %uintt %psize
781fd4e5da5Sopenharmony_ci                        OpReturn
782fd4e5da5Sopenharmony_ci                        OpFunctionEnd
783fd4e5da5Sopenharmony_ci              )";
784fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
785fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
786fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
787fd4e5da5Sopenharmony_ci}
788fd4e5da5Sopenharmony_ci
789fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter10Bad) {
790fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("palign2") + R"(
791fd4e5da5Sopenharmony_ci              %err     = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
792fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
793fd4e5da5Sopenharmony_ci                                        %palign2 %lsize
794fd4e5da5Sopenharmony_ci              %palign2 = OpCopyObject %uintt %palign
795fd4e5da5Sopenharmony_ci                        OpReturn
796fd4e5da5Sopenharmony_ci                        OpFunctionEnd
797fd4e5da5Sopenharmony_ci              )";
798fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
799fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
800fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
801fd4e5da5Sopenharmony_ci}
802fd4e5da5Sopenharmony_ci
803fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter11Bad) {
804fd4e5da5Sopenharmony_ci  std::string str = forwardKernelNonDominantParameterBaseCode("lsize2") + R"(
805fd4e5da5Sopenharmony_ci              %err     = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
806fd4e5da5Sopenharmony_ci                                        %event %revent %kfunc %firstp %psize
807fd4e5da5Sopenharmony_ci                                        %palign %lsize2
808fd4e5da5Sopenharmony_ci              %lsize2  = OpCopyObject %uintt %lsize
809fd4e5da5Sopenharmony_ci                         OpReturn
810fd4e5da5Sopenharmony_ci                         OpFunctionEnd
811fd4e5da5Sopenharmony_ci              )";
812fd4e5da5Sopenharmony_ci
813fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
814fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
815fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("lsize2"));
816fd4e5da5Sopenharmony_ci}
817fd4e5da5Sopenharmony_ci
818fd4e5da5Sopenharmony_cistatic const bool kWithNDrange = true;
819fd4e5da5Sopenharmony_cistatic const bool kNoNDrange = false;
820fd4e5da5Sopenharmony_cistd::pair<std::string, bool> cases[] = {
821fd4e5da5Sopenharmony_ci    {"OpGetKernelNDrangeSubGroupCount", kWithNDrange},
822fd4e5da5Sopenharmony_ci    {"OpGetKernelNDrangeMaxSubGroupSize", kWithNDrange},
823fd4e5da5Sopenharmony_ci    {"OpGetKernelWorkGroupSize", kNoNDrange},
824fd4e5da5Sopenharmony_ci    {"OpGetKernelPreferredWorkGroupSizeMultiple", kNoNDrange}};
825fd4e5da5Sopenharmony_ci
826fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(KernelArgs, ValidateSSA, ::testing::ValuesIn(cases));
827fd4e5da5Sopenharmony_ci
828fd4e5da5Sopenharmony_cistatic const std::string return_instructions = R"(
829fd4e5da5Sopenharmony_ci  OpReturn
830fd4e5da5Sopenharmony_ci  OpFunctionEnd
831fd4e5da5Sopenharmony_ci)";
832fd4e5da5Sopenharmony_ci
833fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, GetKernelGood) {
834fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
835fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
836fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
837fd4e5da5Sopenharmony_ci
838fd4e5da5Sopenharmony_ci  std::stringstream ss;
839fd4e5da5Sopenharmony_ci  // clang-format off
840fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode() + " %numsg = "
841fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
842fd4e5da5Sopenharmony_ci     << return_instructions;
843fd4e5da5Sopenharmony_ci  // clang-format on
844fd4e5da5Sopenharmony_ci
845fd4e5da5Sopenharmony_ci  CompileSuccessfully(ss.str());
846fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
847fd4e5da5Sopenharmony_ci}
848fd4e5da5Sopenharmony_ci
849fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelGood) {
850fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
851fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
852fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
853fd4e5da5Sopenharmony_ci
854fd4e5da5Sopenharmony_ci  // clang-format off
855fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
856fd4e5da5Sopenharmony_ci               R"(
857fd4e5da5Sopenharmony_ci            %main    = OpFunction %voidt None %vfunct
858fd4e5da5Sopenharmony_ci            %mainl   = OpLabel
859fd4e5da5Sopenharmony_ci                )"
860fd4e5da5Sopenharmony_ci            + kKernelSetup + " %numsg = "
861fd4e5da5Sopenharmony_ci            + instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
862fd4e5da5Sopenharmony_ci            + return_instructions + kKernelDefinition;
863fd4e5da5Sopenharmony_ci  // clang-format on
864fd4e5da5Sopenharmony_ci
865fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
866fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
867fd4e5da5Sopenharmony_ci}
868fd4e5da5Sopenharmony_ci
869fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelMissingDefinitionBad) {
870fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
871fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
872fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
873fd4e5da5Sopenharmony_ci
874fd4e5da5Sopenharmony_ci  std::stringstream ss;
875fd4e5da5Sopenharmony_ci  // clang-format off
876fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
877fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%missing %firstp %psize %palign"
878fd4e5da5Sopenharmony_ci     << return_instructions;
879fd4e5da5Sopenharmony_ci  // clang-format on
880fd4e5da5Sopenharmony_ci
881fd4e5da5Sopenharmony_ci  CompileSuccessfully(ss.str());
882fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
883fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
884fd4e5da5Sopenharmony_ci}
885fd4e5da5Sopenharmony_ci
886fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelNDrangeSubGroupCountMissingParameter1Bad) {
887fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
888fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
889fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
890fd4e5da5Sopenharmony_ci
891fd4e5da5Sopenharmony_ci  std::stringstream ss;
892fd4e5da5Sopenharmony_ci  // clang-format off
893fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
894fd4e5da5Sopenharmony_ci     << instruction + " %missing" + ndrange_param + "%kfunc %firstp %psize %palign"
895fd4e5da5Sopenharmony_ci     << return_instructions;
896fd4e5da5Sopenharmony_ci  // clang-format on
897fd4e5da5Sopenharmony_ci
898fd4e5da5Sopenharmony_ci  CompileSuccessfully(ss.str());
899fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
900fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
901fd4e5da5Sopenharmony_ci}
902fd4e5da5Sopenharmony_ci
903fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA,
904fd4e5da5Sopenharmony_ci       ForwardGetKernelNDrangeSubGroupCountNonDominantParameter2Bad) {
905fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
906fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
907fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval2 " : " ";
908fd4e5da5Sopenharmony_ci
909fd4e5da5Sopenharmony_ci  std::stringstream ss;
910fd4e5da5Sopenharmony_ci  // clang-format off
911fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("ndval2") + " %numsg = "
912fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
913fd4e5da5Sopenharmony_ci     << "\n %ndval2  = OpBuildNDRange %ndt %gl %local %offset"
914fd4e5da5Sopenharmony_ci     << return_instructions;
915fd4e5da5Sopenharmony_ci  // clang-format on
916fd4e5da5Sopenharmony_ci
917fd4e5da5Sopenharmony_ci  if (GetParam().second) {
918fd4e5da5Sopenharmony_ci    CompileSuccessfully(ss.str());
919fd4e5da5Sopenharmony_ci    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
920fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
921fd4e5da5Sopenharmony_ci  }
922fd4e5da5Sopenharmony_ci}
923fd4e5da5Sopenharmony_ci
924fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA,
925fd4e5da5Sopenharmony_ci       ForwardGetKernelNDrangeSubGroupCountNonDominantParameter4Bad) {
926fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
927fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
928fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
929fd4e5da5Sopenharmony_ci
930fd4e5da5Sopenharmony_ci  std::stringstream ss;
931fd4e5da5Sopenharmony_ci  // clang-format off
932fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("firstp2") + " %numsg = "
933fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%kfunc %firstp2 %psize %palign"
934fd4e5da5Sopenharmony_ci     << "\n %firstp2 = OpCopyObject %int8t %firstp"
935fd4e5da5Sopenharmony_ci     << return_instructions;
936fd4e5da5Sopenharmony_ci  // clang-format on
937fd4e5da5Sopenharmony_ci
938fd4e5da5Sopenharmony_ci  CompileSuccessfully(ss.str());
939fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
940fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
941fd4e5da5Sopenharmony_ci}
942fd4e5da5Sopenharmony_ci
943fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA,
944fd4e5da5Sopenharmony_ci       ForwardGetKernelNDrangeSubGroupCountNonDominantParameter5Bad) {
945fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
946fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
947fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
948fd4e5da5Sopenharmony_ci
949fd4e5da5Sopenharmony_ci  std::stringstream ss;
950fd4e5da5Sopenharmony_ci  // clang-format off
951fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("psize2") + " %numsg = "
952fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize2 %palign"
953fd4e5da5Sopenharmony_ci     << "\n %psize2  = OpCopyObject %uintt %psize"
954fd4e5da5Sopenharmony_ci     << return_instructions;
955fd4e5da5Sopenharmony_ci  // clang-format on
956fd4e5da5Sopenharmony_ci
957fd4e5da5Sopenharmony_ci  CompileSuccessfully(ss.str());
958fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
959fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
960fd4e5da5Sopenharmony_ci}
961fd4e5da5Sopenharmony_ci
962fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA,
963fd4e5da5Sopenharmony_ci       ForwardGetKernelNDrangeSubGroupCountNonDominantParameter6Bad) {
964fd4e5da5Sopenharmony_ci  std::string instruction = GetParam().first;
965fd4e5da5Sopenharmony_ci  bool with_ndrange = GetParam().second;
966fd4e5da5Sopenharmony_ci  std::string ndrange_param = with_ndrange ? " %ndval " : " ";
967fd4e5da5Sopenharmony_ci
968fd4e5da5Sopenharmony_ci  std::stringstream ss;
969fd4e5da5Sopenharmony_ci  // clang-format off
970fd4e5da5Sopenharmony_ci  ss << forwardKernelNonDominantParameterBaseCode("palign2") + " %numsg = "
971fd4e5da5Sopenharmony_ci     << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign2"
972fd4e5da5Sopenharmony_ci     << "\n %palign2 = OpCopyObject %uintt %palign"
973fd4e5da5Sopenharmony_ci     << return_instructions;
974fd4e5da5Sopenharmony_ci  // clang-format on
975fd4e5da5Sopenharmony_ci
976fd4e5da5Sopenharmony_ci  if (GetParam().second) {
977fd4e5da5Sopenharmony_ci    CompileSuccessfully(ss.str());
978fd4e5da5Sopenharmony_ci    ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
979fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
980fd4e5da5Sopenharmony_ci  }
981fd4e5da5Sopenharmony_ci}
982fd4e5da5Sopenharmony_ci
983fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiGood) {
984fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes +
985fd4e5da5Sopenharmony_ci                    R"(
986fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %vfunct
987fd4e5da5Sopenharmony_ci%preheader = OpLabel
988fd4e5da5Sopenharmony_ci%init      = OpCopyObject %uintt %zero
989fd4e5da5Sopenharmony_ci             OpBranch %loop
990fd4e5da5Sopenharmony_ci%loop      = OpLabel
991fd4e5da5Sopenharmony_ci%i         = OpPhi %uintt %init %preheader %loopi %loop
992fd4e5da5Sopenharmony_ci%loopi     = OpIAdd %uintt %i %one
993fd4e5da5Sopenharmony_ci             OpNop
994fd4e5da5Sopenharmony_ci%cond      = OpSLessThan %boolt %i %ten
995fd4e5da5Sopenharmony_ci             OpLoopMerge %endl %loop None
996fd4e5da5Sopenharmony_ci             OpBranchConditional %cond %loop %endl
997fd4e5da5Sopenharmony_ci%endl      = OpLabel
998fd4e5da5Sopenharmony_ci             OpReturn
999fd4e5da5Sopenharmony_ci             OpFunctionEnd
1000fd4e5da5Sopenharmony_ci)";
1001fd4e5da5Sopenharmony_ci
1002fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1003fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1004fd4e5da5Sopenharmony_ci}
1005fd4e5da5Sopenharmony_ci
1006fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingTypeBad) {
1007fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
1008fd4e5da5Sopenharmony_ci                    R"(
1009fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %vfunct
1010fd4e5da5Sopenharmony_ci%preheader = OpLabel
1011fd4e5da5Sopenharmony_ci%init      = OpCopyObject %uintt %zero
1012fd4e5da5Sopenharmony_ci             OpBranch %loop
1013fd4e5da5Sopenharmony_ci%loop      = OpLabel
1014fd4e5da5Sopenharmony_ci%i         = OpPhi %missing %init %preheader %loopi %loop
1015fd4e5da5Sopenharmony_ci%loopi     = OpIAdd %uintt %i %one
1016fd4e5da5Sopenharmony_ci             OpNop
1017fd4e5da5Sopenharmony_ci%cond      = OpSLessThan %boolt %i %ten
1018fd4e5da5Sopenharmony_ci             OpLoopMerge %endl %loop None
1019fd4e5da5Sopenharmony_ci             OpBranchConditional %cond %loop %endl
1020fd4e5da5Sopenharmony_ci%endl      = OpLabel
1021fd4e5da5Sopenharmony_ci             OpReturn
1022fd4e5da5Sopenharmony_ci             OpFunctionEnd
1023fd4e5da5Sopenharmony_ci)";
1024fd4e5da5Sopenharmony_ci
1025fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1026fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1027fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
1028fd4e5da5Sopenharmony_ci}
1029fd4e5da5Sopenharmony_ci
1030fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingIdBad) {
1031fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
1032fd4e5da5Sopenharmony_ci                    R"(
1033fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %vfunct
1034fd4e5da5Sopenharmony_ci%preheader = OpLabel
1035fd4e5da5Sopenharmony_ci%init      = OpCopyObject %uintt %zero
1036fd4e5da5Sopenharmony_ci             OpBranch %loop
1037fd4e5da5Sopenharmony_ci%loop      = OpLabel
1038fd4e5da5Sopenharmony_ci%i         = OpPhi %uintt %missing %preheader %loopi %loop
1039fd4e5da5Sopenharmony_ci%loopi     = OpIAdd %uintt %i %one
1040fd4e5da5Sopenharmony_ci             OpNop
1041fd4e5da5Sopenharmony_ci%cond      = OpSLessThan %boolt %i %ten
1042fd4e5da5Sopenharmony_ci             OpLoopMerge %endl %loop None
1043fd4e5da5Sopenharmony_ci             OpBranchConditional %cond %loop %endl
1044fd4e5da5Sopenharmony_ci%endl      = OpLabel
1045fd4e5da5Sopenharmony_ci             OpReturn
1046fd4e5da5Sopenharmony_ci             OpFunctionEnd
1047fd4e5da5Sopenharmony_ci)";
1048fd4e5da5Sopenharmony_ci
1049fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1050fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1051fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
1052fd4e5da5Sopenharmony_ci}
1053fd4e5da5Sopenharmony_ci
1054fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingLabelBad) {
1055fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
1056fd4e5da5Sopenharmony_ci                    R"(
1057fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %vfunct
1058fd4e5da5Sopenharmony_ci%preheader = OpLabel
1059fd4e5da5Sopenharmony_ci%init      = OpCopyObject %uintt %zero
1060fd4e5da5Sopenharmony_ci             OpBranch %loop
1061fd4e5da5Sopenharmony_ci%loop      = OpLabel
1062fd4e5da5Sopenharmony_ci%i         = OpPhi %uintt %init %missing %loopi %loop
1063fd4e5da5Sopenharmony_ci%loopi     = OpIAdd %uintt %i %one
1064fd4e5da5Sopenharmony_ci             OpNop
1065fd4e5da5Sopenharmony_ci%cond      = OpSLessThan %boolt %i %ten
1066fd4e5da5Sopenharmony_ci             OpLoopMerge %endl %loop None
1067fd4e5da5Sopenharmony_ci             OpBranchConditional %cond %loop %endl
1068fd4e5da5Sopenharmony_ci%endl      = OpLabel
1069fd4e5da5Sopenharmony_ci             OpReturn
1070fd4e5da5Sopenharmony_ci             OpFunctionEnd
1071fd4e5da5Sopenharmony_ci)";
1072fd4e5da5Sopenharmony_ci
1073fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1074fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1075fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
1076fd4e5da5Sopenharmony_ci}
1077fd4e5da5Sopenharmony_ci
1078fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdDominatesItsUseGood) {
1079fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes +
1080fd4e5da5Sopenharmony_ci                    R"(
1081fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %vfunct
1082fd4e5da5Sopenharmony_ci%entry     = OpLabel
1083fd4e5da5Sopenharmony_ci%cond      = OpSLessThan %boolt %one %ten
1084fd4e5da5Sopenharmony_ci%eleven    = OpIAdd %uintt %one %ten
1085fd4e5da5Sopenharmony_ci             OpSelectionMerge %merge None
1086fd4e5da5Sopenharmony_ci             OpBranchConditional %cond %t %f
1087fd4e5da5Sopenharmony_ci%t         = OpLabel
1088fd4e5da5Sopenharmony_ci%twelve    = OpIAdd %uintt %eleven %one
1089fd4e5da5Sopenharmony_ci             OpBranch %merge
1090fd4e5da5Sopenharmony_ci%f         = OpLabel
1091fd4e5da5Sopenharmony_ci%twentytwo = OpIAdd %uintt %eleven %ten
1092fd4e5da5Sopenharmony_ci             OpBranch %merge
1093fd4e5da5Sopenharmony_ci%merge     = OpLabel
1094fd4e5da5Sopenharmony_ci             OpReturn
1095fd4e5da5Sopenharmony_ci             OpFunctionEnd
1096fd4e5da5Sopenharmony_ci)";
1097fd4e5da5Sopenharmony_ci
1098fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1099fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1100fd4e5da5Sopenharmony_ci}
1101fd4e5da5Sopenharmony_ci
1102fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdDoesNotDominateItsUseBad) {
1103fd4e5da5Sopenharmony_ci  std::string str = kHeader +
1104fd4e5da5Sopenharmony_ci                    "OpName %eleven \"eleven\"\n"
1105fd4e5da5Sopenharmony_ci                    "OpName %true_block \"true_block\"\n"
1106fd4e5da5Sopenharmony_ci                    "OpName %false_block \"false_block\"" +
1107fd4e5da5Sopenharmony_ci                    kBasicTypes +
1108fd4e5da5Sopenharmony_ci                    R"(
1109fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1110fd4e5da5Sopenharmony_ci%entry       = OpLabel
1111fd4e5da5Sopenharmony_ci%cond        = OpSLessThan %boolt %one %ten
1112fd4e5da5Sopenharmony_ci               OpSelectionMerge %merge None
1113fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %true_block %false_block
1114fd4e5da5Sopenharmony_ci%true_block  = OpLabel
1115fd4e5da5Sopenharmony_ci%eleven      = OpIAdd %uintt %one %ten
1116fd4e5da5Sopenharmony_ci%twelve      = OpIAdd %uintt %eleven %one
1117fd4e5da5Sopenharmony_ci               OpBranch %merge
1118fd4e5da5Sopenharmony_ci%false_block = OpLabel
1119fd4e5da5Sopenharmony_ci%twentytwo   = OpIAdd %uintt %eleven %ten
1120fd4e5da5Sopenharmony_ci               OpBranch %merge
1121fd4e5da5Sopenharmony_ci%merge       = OpLabel
1122fd4e5da5Sopenharmony_ci               OpReturn
1123fd4e5da5Sopenharmony_ci               OpFunctionEnd
1124fd4e5da5Sopenharmony_ci)";
1125fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1126fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1127fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1128fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1129fd4e5da5Sopenharmony_ci      MatchesRegex("ID '.\\[%eleven\\]' defined in block '.\\[%true_block\\]' "
1130fd4e5da5Sopenharmony_ci                   "does not dominate its use in block '.\\[%false_block\\]'\n"
1131fd4e5da5Sopenharmony_ci                   "  %false_block = OpLabel\n"));
1132fd4e5da5Sopenharmony_ci}
1133fd4e5da5Sopenharmony_ci
1134fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUseDoesntDominateDefinitionGood) {
1135fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes +
1136fd4e5da5Sopenharmony_ci                    R"(
1137fd4e5da5Sopenharmony_ci%funcintptrt = OpTypePointer Function %uintt
1138fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1139fd4e5da5Sopenharmony_ci%entry       = OpLabel
1140fd4e5da5Sopenharmony_ci%var_one     = OpVariable %funcintptrt Function %one
1141fd4e5da5Sopenharmony_ci%one_val     = OpLoad %uintt %var_one
1142fd4e5da5Sopenharmony_ci               OpBranch %loop
1143fd4e5da5Sopenharmony_ci%loop        = OpLabel
1144fd4e5da5Sopenharmony_ci%i           = OpPhi %uintt %one_val %entry %inew %cont
1145fd4e5da5Sopenharmony_ci%cond        = OpSLessThan %boolt %one %ten
1146fd4e5da5Sopenharmony_ci               OpLoopMerge %merge %cont None
1147fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %body %merge
1148fd4e5da5Sopenharmony_ci%body        = OpLabel
1149fd4e5da5Sopenharmony_ci               OpBranch %cont
1150fd4e5da5Sopenharmony_ci%cont        = OpLabel
1151fd4e5da5Sopenharmony_ci%inew        = OpIAdd %uintt %i %one
1152fd4e5da5Sopenharmony_ci               OpBranch %loop
1153fd4e5da5Sopenharmony_ci%merge       = OpLabel
1154fd4e5da5Sopenharmony_ci               OpReturn
1155fd4e5da5Sopenharmony_ci               OpFunctionEnd
1156fd4e5da5Sopenharmony_ci)";
1157fd4e5da5Sopenharmony_ci
1158fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1159fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1160fd4e5da5Sopenharmony_ci}
1161fd4e5da5Sopenharmony_ci
1162fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA,
1163fd4e5da5Sopenharmony_ci       PhiUseDoesntDominateUseOfPhiOperandUsedBeforeDefinitionBad) {
1164fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %inew \"inew\"" + kBasicTypes +
1165fd4e5da5Sopenharmony_ci                    R"(
1166fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1167fd4e5da5Sopenharmony_ci%entry       = OpLabel
1168fd4e5da5Sopenharmony_ci%var_one     = OpVariable %intptrt Function %one
1169fd4e5da5Sopenharmony_ci%one_val     = OpLoad %uintt %var_one
1170fd4e5da5Sopenharmony_ci               OpBranch %loop
1171fd4e5da5Sopenharmony_ci%loop        = OpLabel
1172fd4e5da5Sopenharmony_ci%i           = OpPhi %uintt %one_val %entry %inew %cont
1173fd4e5da5Sopenharmony_ci%bad         = OpIAdd %uintt %inew %one
1174fd4e5da5Sopenharmony_ci%cond        = OpSLessThan %boolt %one %ten
1175fd4e5da5Sopenharmony_ci               OpLoopMerge %merge %cont None
1176fd4e5da5Sopenharmony_ci               OpBranchConditional %cond %body %merge
1177fd4e5da5Sopenharmony_ci%body        = OpLabel
1178fd4e5da5Sopenharmony_ci               OpBranch %cont
1179fd4e5da5Sopenharmony_ci%cont        = OpLabel
1180fd4e5da5Sopenharmony_ci%inew        = OpIAdd %uintt %i %one
1181fd4e5da5Sopenharmony_ci               OpBranch %loop
1182fd4e5da5Sopenharmony_ci%merge       = OpLabel
1183fd4e5da5Sopenharmony_ci               OpReturn
1184fd4e5da5Sopenharmony_ci               OpFunctionEnd
1185fd4e5da5Sopenharmony_ci)";
1186fd4e5da5Sopenharmony_ci
1187fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1188fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1189fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1190fd4e5da5Sopenharmony_ci              MatchesRegex("ID '.\\[%inew\\]' has not been defined\n"
1191fd4e5da5Sopenharmony_ci                           "  %19 = OpIAdd %uint %inew %uint_1\n"));
1192fd4e5da5Sopenharmony_ci}
1193fd4e5da5Sopenharmony_ci
1194fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUseMayComeFromNonDominatingBlockGood) {
1195fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %if_true \"if_true\"\n" +
1196fd4e5da5Sopenharmony_ci                    "OpName %exit \"exit\"\n" + "OpName %copy \"copy\"\n" +
1197fd4e5da5Sopenharmony_ci                    kBasicTypes +
1198fd4e5da5Sopenharmony_ci                    R"(
1199fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1200fd4e5da5Sopenharmony_ci%entry       = OpLabel
1201fd4e5da5Sopenharmony_ci               OpBranchConditional %false %if_true %exit
1202fd4e5da5Sopenharmony_ci
1203fd4e5da5Sopenharmony_ci%if_true     = OpLabel
1204fd4e5da5Sopenharmony_ci%copy        = OpCopyObject %boolt %false
1205fd4e5da5Sopenharmony_ci               OpBranch %exit
1206fd4e5da5Sopenharmony_ci
1207fd4e5da5Sopenharmony_ci; The use of %copy here is ok, even though it was defined
1208fd4e5da5Sopenharmony_ci; in a block that does not dominate %exit.  That's the point
1209fd4e5da5Sopenharmony_ci; of an OpPhi.
1210fd4e5da5Sopenharmony_ci%exit        = OpLabel
1211fd4e5da5Sopenharmony_ci%value       = OpPhi %boolt %false %entry %copy %if_true
1212fd4e5da5Sopenharmony_ci               OpReturn
1213fd4e5da5Sopenharmony_ci               OpFunctionEnd
1214fd4e5da5Sopenharmony_ci)";
1215fd4e5da5Sopenharmony_ci
1216fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1217fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
1218fd4e5da5Sopenharmony_ci}
1219fd4e5da5Sopenharmony_ci
1220fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUsesItsOwnDefinitionGood) {
1221fd4e5da5Sopenharmony_ci  // See https://github.com/KhronosGroup/SPIRV-Tools/issues/415
1222fd4e5da5Sopenharmony_ci  //
1223fd4e5da5Sopenharmony_ci  // Non-phi instructions can't use their own definitions, as
1224fd4e5da5Sopenharmony_ci  // already checked in test DominateUsageSameInstructionBad.
1225fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %loop \"loop\"\n" +
1226fd4e5da5Sopenharmony_ci                    "OpName %value \"value\"\n" + kBasicTypes +
1227fd4e5da5Sopenharmony_ci                    R"(
1228fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1229fd4e5da5Sopenharmony_ci%entry       = OpLabel
1230fd4e5da5Sopenharmony_ci               OpBranch %loop
1231fd4e5da5Sopenharmony_ci
1232fd4e5da5Sopenharmony_ci%loop        = OpLabel
1233fd4e5da5Sopenharmony_ci%value       = OpPhi %boolt %false %entry %value %loop
1234fd4e5da5Sopenharmony_ci               OpBranch %loop
1235fd4e5da5Sopenharmony_ci
1236fd4e5da5Sopenharmony_ci               OpFunctionEnd
1237fd4e5da5Sopenharmony_ci)";
1238fd4e5da5Sopenharmony_ci
1239fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1240fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
1241fd4e5da5Sopenharmony_ci}
1242fd4e5da5Sopenharmony_ci
1243fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) {
1244fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %if_true \"if_true\"\n" +
1245fd4e5da5Sopenharmony_ci                    "OpName %if_false \"if_false\"\n" +
1246fd4e5da5Sopenharmony_ci                    "OpName %exit \"exit\"\n" + "OpName %value \"phi\"\n" +
1247fd4e5da5Sopenharmony_ci                    "OpName %true_copy \"true_copy\"\n" +
1248fd4e5da5Sopenharmony_ci                    "OpName %false_copy \"false_copy\"\n" + kBasicTypes +
1249fd4e5da5Sopenharmony_ci                    R"(
1250fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1251fd4e5da5Sopenharmony_ci%entry       = OpLabel
1252fd4e5da5Sopenharmony_ci               OpBranchConditional %false %if_true %if_false
1253fd4e5da5Sopenharmony_ci
1254fd4e5da5Sopenharmony_ci%if_true     = OpLabel
1255fd4e5da5Sopenharmony_ci%true_copy   = OpCopyObject %boolt %false
1256fd4e5da5Sopenharmony_ci               OpBranch %exit
1257fd4e5da5Sopenharmony_ci
1258fd4e5da5Sopenharmony_ci%if_false    = OpLabel
1259fd4e5da5Sopenharmony_ci%false_copy  = OpCopyObject %boolt %false
1260fd4e5da5Sopenharmony_ci               OpBranch %exit
1261fd4e5da5Sopenharmony_ci
1262fd4e5da5Sopenharmony_ci; The (variable,Id) pairs are swapped.
1263fd4e5da5Sopenharmony_ci%exit        = OpLabel
1264fd4e5da5Sopenharmony_ci%value       = OpPhi %boolt %true_copy %if_false %false_copy %if_true
1265fd4e5da5Sopenharmony_ci               OpReturn
1266fd4e5da5Sopenharmony_ci               OpFunctionEnd
1267fd4e5da5Sopenharmony_ci)";
1268fd4e5da5Sopenharmony_ci
1269fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1270fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1271fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1272fd4e5da5Sopenharmony_ci              MatchesRegex(
1273fd4e5da5Sopenharmony_ci                  "In OpPhi instruction '.\\[%phi\\]', ID '.\\[%true_copy\\]' "
1274fd4e5da5Sopenharmony_ci                  "definition does not dominate its parent '.\\[%if_false\\]'\n"
1275fd4e5da5Sopenharmony_ci                  "  %phi = OpPhi %bool %true_copy %if_false %false_copy "
1276fd4e5da5Sopenharmony_ci                  "%if_true\n"));
1277fd4e5da5Sopenharmony_ci}
1278fd4e5da5Sopenharmony_ci
1279fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) {
1280fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes +
1281fd4e5da5Sopenharmony_ci                    R"(
1282fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1283fd4e5da5Sopenharmony_ci%entry       = OpLabel
1284fd4e5da5Sopenharmony_ci               OpBranchConditional %false %if_true %if_false
1285fd4e5da5Sopenharmony_ci
1286fd4e5da5Sopenharmony_ci%if_true     = OpLabel
1287fd4e5da5Sopenharmony_ci%true_copy   = OpCopyObject %boolt %false
1288fd4e5da5Sopenharmony_ci               OpBranch %if_tnext
1289fd4e5da5Sopenharmony_ci%if_tnext    = OpLabel
1290fd4e5da5Sopenharmony_ci               OpBranch %exit
1291fd4e5da5Sopenharmony_ci
1292fd4e5da5Sopenharmony_ci%if_false    = OpLabel
1293fd4e5da5Sopenharmony_ci%false_copy  = OpCopyObject %boolt %false
1294fd4e5da5Sopenharmony_ci               OpBranch %if_fnext
1295fd4e5da5Sopenharmony_ci%if_fnext    = OpLabel
1296fd4e5da5Sopenharmony_ci               OpBranch %exit
1297fd4e5da5Sopenharmony_ci
1298fd4e5da5Sopenharmony_ci%exit        = OpLabel
1299fd4e5da5Sopenharmony_ci%value       = OpPhi %boolt %true_copy %if_tnext %false_copy %if_fnext
1300fd4e5da5Sopenharmony_ci               OpReturn
1301fd4e5da5Sopenharmony_ci               OpFunctionEnd
1302fd4e5da5Sopenharmony_ci)";
1303fd4e5da5Sopenharmony_ci
1304fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1305fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1306fd4e5da5Sopenharmony_ci}
1307fd4e5da5Sopenharmony_ci
1308fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA,
1309fd4e5da5Sopenharmony_ci       DominanceCheckIgnoresUsesInUnreachableBlocksDefInBlockGood) {
1310fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes +
1311fd4e5da5Sopenharmony_ci                    R"(
1312fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1313fd4e5da5Sopenharmony_ci%entry       = OpLabel
1314fd4e5da5Sopenharmony_ci%def         = OpCopyObject %boolt %false
1315fd4e5da5Sopenharmony_ci               OpReturn
1316fd4e5da5Sopenharmony_ci
1317fd4e5da5Sopenharmony_ci%unreach     = OpLabel
1318fd4e5da5Sopenharmony_ci%use         = OpCopyObject %boolt %def
1319fd4e5da5Sopenharmony_ci               OpReturn
1320fd4e5da5Sopenharmony_ci               OpFunctionEnd
1321fd4e5da5Sopenharmony_ci)";
1322fd4e5da5Sopenharmony_ci
1323fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1324fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
1325fd4e5da5Sopenharmony_ci}
1326fd4e5da5Sopenharmony_ci
1327fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableUnreachableDefNotInParentBlock) {
1328fd4e5da5Sopenharmony_ci  std::string str = kHeader + "OpName %unreachable \"unreachable\"\n" +
1329fd4e5da5Sopenharmony_ci                    kBasicTypes +
1330fd4e5da5Sopenharmony_ci                    R"(
1331fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %vfunct
1332fd4e5da5Sopenharmony_ci%entry       = OpLabel
1333fd4e5da5Sopenharmony_ci               OpBranch %if_false
1334fd4e5da5Sopenharmony_ci
1335fd4e5da5Sopenharmony_ci%unreachable = OpLabel
1336fd4e5da5Sopenharmony_ci%copy        = OpCopyObject %boolt %false
1337fd4e5da5Sopenharmony_ci               OpBranch %if_tnext
1338fd4e5da5Sopenharmony_ci%if_tnext    = OpLabel
1339fd4e5da5Sopenharmony_ci               OpBranch %exit
1340fd4e5da5Sopenharmony_ci
1341fd4e5da5Sopenharmony_ci%if_false    = OpLabel
1342fd4e5da5Sopenharmony_ci%false_copy  = OpCopyObject %boolt %false
1343fd4e5da5Sopenharmony_ci               OpBranch %if_fnext
1344fd4e5da5Sopenharmony_ci%if_fnext    = OpLabel
1345fd4e5da5Sopenharmony_ci               OpBranch %exit
1346fd4e5da5Sopenharmony_ci
1347fd4e5da5Sopenharmony_ci%exit        = OpLabel
1348fd4e5da5Sopenharmony_ci%value       = OpPhi %boolt %copy %if_tnext %false_copy %if_fnext
1349fd4e5da5Sopenharmony_ci               OpReturn
1350fd4e5da5Sopenharmony_ci               OpFunctionEnd
1351fd4e5da5Sopenharmony_ci)";
1352fd4e5da5Sopenharmony_ci
1353fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1354fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1355fd4e5da5Sopenharmony_ci}
1356fd4e5da5Sopenharmony_ci
1357fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA,
1358fd4e5da5Sopenharmony_ci       DominanceCheckIgnoresUsesInUnreachableBlocksDefIsParamGood) {
1359fd4e5da5Sopenharmony_ci  std::string str = kHeader + kBasicTypes +
1360fd4e5da5Sopenharmony_ci                    R"(
1361fd4e5da5Sopenharmony_ci%void_fn_int = OpTypeFunction %voidt %uintt
1362fd4e5da5Sopenharmony_ci%func        = OpFunction %voidt None %void_fn_int
1363fd4e5da5Sopenharmony_ci%int_param   = OpFunctionParameter %uintt
1364fd4e5da5Sopenharmony_ci%entry       = OpLabel
1365fd4e5da5Sopenharmony_ci               OpReturn
1366fd4e5da5Sopenharmony_ci
1367fd4e5da5Sopenharmony_ci%unreach     = OpLabel
1368fd4e5da5Sopenharmony_ci%use         = OpCopyObject %uintt %int_param
1369fd4e5da5Sopenharmony_ci               OpReturn
1370fd4e5da5Sopenharmony_ci               OpFunctionEnd
1371fd4e5da5Sopenharmony_ci)";
1372fd4e5da5Sopenharmony_ci
1373fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1374fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
1375fd4e5da5Sopenharmony_ci}
1376fd4e5da5Sopenharmony_ci
1377fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, UseFunctionParameterFromOtherFunctionBad) {
1378fd4e5da5Sopenharmony_ci  std::string str = kHeader +
1379fd4e5da5Sopenharmony_ci                    "OpName %first \"first\"\n"
1380fd4e5da5Sopenharmony_ci                    "OpName %func \"func\"\n" +
1381fd4e5da5Sopenharmony_ci                    "OpName %func2 \"func2\"\n" + kBasicTypes +
1382fd4e5da5Sopenharmony_ci                    R"(
1383fd4e5da5Sopenharmony_ci%viifunct  = OpTypeFunction %voidt %uintt %uintt
1384fd4e5da5Sopenharmony_ci%func      = OpFunction %voidt None %viifunct
1385fd4e5da5Sopenharmony_ci%first     = OpFunctionParameter %uintt
1386fd4e5da5Sopenharmony_ci%second    = OpFunctionParameter %uintt
1387fd4e5da5Sopenharmony_ci             OpFunctionEnd
1388fd4e5da5Sopenharmony_ci%func2     = OpFunction %voidt None %viifunct
1389fd4e5da5Sopenharmony_ci%first2    = OpFunctionParameter %uintt
1390fd4e5da5Sopenharmony_ci%second2   = OpFunctionParameter %uintt
1391fd4e5da5Sopenharmony_ci%entry2    = OpLabel
1392fd4e5da5Sopenharmony_ci%baduse    = OpIAdd %uintt %first %first2
1393fd4e5da5Sopenharmony_ci             OpReturn
1394fd4e5da5Sopenharmony_ci             OpFunctionEnd
1395fd4e5da5Sopenharmony_ci)";
1396fd4e5da5Sopenharmony_ci
1397fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1398fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1399fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1400fd4e5da5Sopenharmony_ci              MatchesRegex(
1401fd4e5da5Sopenharmony_ci                  "ID '.\\[%first\\]' used in function '.\\[%func2\\]' is used "
1402fd4e5da5Sopenharmony_ci                  "outside of it's defining function '.\\[%func\\]'\n"
1403fd4e5da5Sopenharmony_ci                  "  %func = OpFunction %void None %14\n"));
1404fd4e5da5Sopenharmony_ci}
1405fd4e5da5Sopenharmony_ci
1406fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, TypeForwardPointerForwardReference) {
1407fd4e5da5Sopenharmony_ci  // See https://github.com/KhronosGroup/SPIRV-Tools/issues/429
1408fd4e5da5Sopenharmony_ci  //
1409fd4e5da5Sopenharmony_ci  // ForwardPointers can references instructions that have not been defined
1410fd4e5da5Sopenharmony_ci  std::string str = R"(
1411fd4e5da5Sopenharmony_ci               OpCapability Kernel
1412fd4e5da5Sopenharmony_ci               OpCapability Addresses
1413fd4e5da5Sopenharmony_ci               OpCapability Linkage
1414fd4e5da5Sopenharmony_ci               OpMemoryModel Logical OpenCL
1415fd4e5da5Sopenharmony_ci               OpName %intptrt "intptrt"
1416fd4e5da5Sopenharmony_ci               OpTypeForwardPointer %intptrt UniformConstant
1417fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1418fd4e5da5Sopenharmony_ci     %struct = OpTypeStruct %uint
1419fd4e5da5Sopenharmony_ci    %intptrt = OpTypePointer UniformConstant %struct
1420fd4e5da5Sopenharmony_ci)";
1421fd4e5da5Sopenharmony_ci
1422fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1423fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1424fd4e5da5Sopenharmony_ci}
1425fd4e5da5Sopenharmony_ci
1426fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, TypeStructForwardReference) {
1427fd4e5da5Sopenharmony_ci  std::string str = R"(
1428fd4e5da5Sopenharmony_ci               OpCapability Kernel
1429fd4e5da5Sopenharmony_ci               OpCapability Addresses
1430fd4e5da5Sopenharmony_ci               OpCapability Linkage
1431fd4e5da5Sopenharmony_ci               OpMemoryModel Logical OpenCL
1432fd4e5da5Sopenharmony_ci               OpName %structptr "structptr"
1433fd4e5da5Sopenharmony_ci               OpTypeForwardPointer %structptr UniformConstant
1434fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
1435fd4e5da5Sopenharmony_ci   %structt1 = OpTypeStruct %structptr %uint
1436fd4e5da5Sopenharmony_ci   %structt2 = OpTypeStruct %uint %structptr
1437fd4e5da5Sopenharmony_ci   %structt3 = OpTypeStruct %uint %uint %structptr
1438fd4e5da5Sopenharmony_ci   %structt4 = OpTypeStruct %uint %uint %uint %structptr
1439fd4e5da5Sopenharmony_ci  %structptr = OpTypePointer UniformConstant %structt1
1440fd4e5da5Sopenharmony_ci)";
1441fd4e5da5Sopenharmony_ci
1442fd4e5da5Sopenharmony_ci  CompileSuccessfully(str);
1443fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1444fd4e5da5Sopenharmony_ci}
1445fd4e5da5Sopenharmony_ci
1446fd4e5da5Sopenharmony_ci// TODO(umar): OpGroupMemberDecorate
1447fd4e5da5Sopenharmony_ci
1448fd4e5da5Sopenharmony_ci}  // namespace
1449fd4e5da5Sopenharmony_ci}  // namespace val
1450fd4e5da5Sopenharmony_ci}  // namespace spvtools
1451