• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Google LLC.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <vector>
16 
17 #include "gmock/gmock.h"
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20 
21 namespace spvtools {
22 namespace opt {
23 namespace {
24 
25 using AmdExtToKhrTest = PassTest<::testing::Test>;
26 
27 using ::testing::HasSubstr;
28 
GetTest(std::string op_code,std::string new_op_code)29 std::string GetTest(std::string op_code, std::string new_op_code) {
30   const std::string text = R"(
31 ; CHECK: OpCapability Shader
32 ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot"
33 ; CHECK: OpFunction
34 ; CHECK-NEXT: OpLabel
35 ; CHECK-NEXT: [[undef:%\w+]] = OpUndef %uint
36 ; CHECK-NEXT: )" + new_op_code +
37                            R"( %uint %uint_3 Reduce [[undef]]
38                OpCapability Shader
39                OpCapability Groups
40                OpExtension "SPV_AMD_shader_ballot"
41                OpMemoryModel Logical GLSL450
42                OpEntryPoint Fragment %1 "func"
43                OpExecutionMode %1 OriginUpperLeft
44        %void = OpTypeVoid
45           %3 = OpTypeFunction %void
46        %uint = OpTypeInt 32 0
47      %uint_3 = OpConstant %uint 3
48           %1 = OpFunction %void None %3
49           %6 = OpLabel
50           %7 = OpUndef %uint
51           %8 = )" + op_code +
52                            R"( %uint %uint_3 Reduce %7
53                OpReturn
54                OpFunctionEnd
55 
56 )";
57   return text;
58 }
59 
TEST_F(AmdExtToKhrTest,ReplaceGroupIAddNonUniformAMD)60 TEST_F(AmdExtToKhrTest, ReplaceGroupIAddNonUniformAMD) {
61   std::string text =
62       GetTest("OpGroupIAddNonUniformAMD", "OpGroupNonUniformIAdd");
63   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
64 }
TEST_F(AmdExtToKhrTest,ReplaceGroupFAddNonUniformAMD)65 TEST_F(AmdExtToKhrTest, ReplaceGroupFAddNonUniformAMD) {
66   std::string text =
67       GetTest("OpGroupFAddNonUniformAMD", "OpGroupNonUniformFAdd");
68   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
69 }
TEST_F(AmdExtToKhrTest,ReplaceGroupUMinNonUniformAMD)70 TEST_F(AmdExtToKhrTest, ReplaceGroupUMinNonUniformAMD) {
71   std::string text =
72       GetTest("OpGroupUMinNonUniformAMD", "OpGroupNonUniformUMin");
73   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
74 }
TEST_F(AmdExtToKhrTest,ReplaceGroupSMinNonUniformAMD)75 TEST_F(AmdExtToKhrTest, ReplaceGroupSMinNonUniformAMD) {
76   std::string text =
77       GetTest("OpGroupSMinNonUniformAMD", "OpGroupNonUniformSMin");
78   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
79 }
TEST_F(AmdExtToKhrTest,ReplaceGroupFMinNonUniformAMD)80 TEST_F(AmdExtToKhrTest, ReplaceGroupFMinNonUniformAMD) {
81   std::string text =
82       GetTest("OpGroupFMinNonUniformAMD", "OpGroupNonUniformFMin");
83   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
84 }
TEST_F(AmdExtToKhrTest,ReplaceGroupUMaxNonUniformAMD)85 TEST_F(AmdExtToKhrTest, ReplaceGroupUMaxNonUniformAMD) {
86   std::string text =
87       GetTest("OpGroupUMaxNonUniformAMD", "OpGroupNonUniformUMax");
88   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
89 }
TEST_F(AmdExtToKhrTest,ReplaceGroupSMaxNonUniformAMD)90 TEST_F(AmdExtToKhrTest, ReplaceGroupSMaxNonUniformAMD) {
91   std::string text =
92       GetTest("OpGroupSMaxNonUniformAMD", "OpGroupNonUniformSMax");
93   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
94 }
TEST_F(AmdExtToKhrTest,ReplaceGroupFMaxNonUniformAMD)95 TEST_F(AmdExtToKhrTest, ReplaceGroupFMaxNonUniformAMD) {
96   std::string text =
97       GetTest("OpGroupFMaxNonUniformAMD", "OpGroupNonUniformFMax");
98   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
99 }
100 
TEST_F(AmdExtToKhrTest,ReplaceMbcntAMD)101 TEST_F(AmdExtToKhrTest, ReplaceMbcntAMD) {
102   const std::string text = R"(
103 ; CHECK: OpCapability Shader
104 ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot"
105 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot"
106 ; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLtMask
107 ; CHECK: [[var]] = OpVariable %_ptr_Input_v4uint Input
108 ; CHECK: OpFunction
109 ; CHECK-NEXT: OpLabel
110 ; CHECK-NEXT: [[ld:%\w+]] = OpLoad %v4uint [[var]]
111 ; CHECK-NEXT: [[shuffle:%\w+]] = OpVectorShuffle %v2uint [[ld]] [[ld]] 0 1
112 ; CHECK-NEXT: [[bitcast:%\w+]] = OpBitcast %ulong [[shuffle]]
113 ; CHECK-NEXT: [[and:%\w+]] = OpBitwiseAnd %ulong [[bitcast]] %ulong_0
114 ; CHECK-NEXT: [[result:%\w+]] = OpBitCount %uint [[and]]
115                OpCapability Shader
116                OpCapability Int64
117                OpExtension "SPV_AMD_shader_ballot"
118           %1 = OpExtInstImport "SPV_AMD_shader_ballot"
119                OpMemoryModel Logical GLSL450
120                OpEntryPoint Fragment %2 "func"
121                OpExecutionMode %2 OriginUpperLeft
122        %void = OpTypeVoid
123           %4 = OpTypeFunction %void
124        %uint = OpTypeInt 32 0
125       %ulong = OpTypeInt 64 0
126     %ulong_0 = OpConstant %ulong 0
127           %2 = OpFunction %void None %4
128           %8 = OpLabel
129           %9 = OpExtInst %uint %1 MbcntAMD %ulong_0
130                OpReturn
131                OpFunctionEnd
132 )";
133 
134   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
135 }
136 
TEST_F(AmdExtToKhrTest,ReplaceSwizzleInvocationsAMD)137 TEST_F(AmdExtToKhrTest, ReplaceSwizzleInvocationsAMD) {
138   const std::string text = R"(
139 ; CHECK: OpCapability Shader
140 ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot"
141 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot"
142 ; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId
143 ; CHECK: [[subgroup:%\w+]] = OpConstant %uint 3
144 ; CHECK: [[offset:%\w+]] = OpConstantComposite %v4uint
145 ; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input
146 ; CHECK: [[uint_max:%\w+]] = OpConstant %uint 4294967295
147 ; CHECK: [[ballot_value:%\w+]] = OpConstantComposite %v4uint [[uint_max]] [[uint_max]] [[uint_max]] [[uint_max]]
148 ; CHECK: [[null:%\w+]] = OpConstantNull [[type:%\w+]]
149 ; CHECK: OpFunction
150 ; CHECK-NEXT: OpLabel
151 ; CHECK-NEXT: [[data:%\w+]] = OpUndef [[type]]
152 ; CHECK-NEXT: [[id:%\w+]] = OpLoad %uint [[var]]
153 ; CHECK-NEXT: [[quad_idx:%\w+]] = OpBitwiseAnd %uint [[id]] %uint_3
154 ; CHECK-NEXT: [[quad_ldr:%\w+]] = OpBitwiseXor %uint [[id]] [[quad_idx]]
155 ; CHECK-NEXT: [[my_offset:%\w+]] = OpVectorExtractDynamic %uint [[offset]] [[quad_idx]]
156 ; CHECK-NEXT: [[target_inv:%\w+]] = OpIAdd %uint [[quad_ldr]] [[my_offset]]
157 ; CHECK-NEXT: [[is_active:%\w+]] = OpGroupNonUniformBallotBitExtract %bool [[subgroup]] [[ballot_value]] [[target_inv]]
158 ; CHECK-NEXT: [[shuffle:%\w+]] = OpGroupNonUniformShuffle [[type]] [[subgroup]] [[data]] [[target_inv]]
159 ; CHECK-NEXT: [[result:%\w+]] = OpSelect [[type]] [[is_active]] [[shuffle]] [[null]]
160                OpCapability Shader
161                OpExtension "SPV_AMD_shader_ballot"
162         %ext = OpExtInstImport "SPV_AMD_shader_ballot"
163                OpMemoryModel Logical GLSL450
164                OpEntryPoint Fragment %1 "func"
165                OpExecutionMode %1 OriginUpperLeft
166        %void = OpTypeVoid
167           %3 = OpTypeFunction %void
168        %uint = OpTypeInt 32 0
169      %uint_x = OpConstant %uint 1
170      %uint_y = OpConstant %uint 2
171      %uint_z = OpConstant %uint 3
172      %uint_w = OpConstant %uint 0
173      %v4uint = OpTypeVector %uint 4
174      %offset = OpConstantComposite %v4uint %uint_x %uint_y %uint_z %uint_x
175           %1 = OpFunction %void None %3
176           %6 = OpLabel
177           %data = OpUndef %uint
178           %9 = OpExtInst %uint %ext SwizzleInvocationsAMD %data %offset
179                OpReturn
180                OpFunctionEnd
181 )";
182 
183   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
184 }
TEST_F(AmdExtToKhrTest,ReplaceSwizzleInvocationsMaskedAMD)185 TEST_F(AmdExtToKhrTest, ReplaceSwizzleInvocationsMaskedAMD) {
186   const std::string text = R"(
187 ; CHECK: OpCapability Shader
188 ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot"
189 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot"
190 ; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId
191 ; CHECK: [[x:%\w+]] = OpConstant %uint 19
192 ; CHECK: [[y:%\w+]] = OpConstant %uint 12
193 ; CHECK: [[z:%\w+]] = OpConstant %uint 16
194 ; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input
195 ; CHECK: [[mask_extend:%\w+]] = OpConstant %uint 4294967264
196 ; CHECK: [[uint_max:%\w+]] = OpConstant %uint 4294967295
197 ; CHECK: [[subgroup:%\w+]] = OpConstant %uint 3
198 ; CHECK: [[ballot_value:%\w+]] = OpConstantComposite %v4uint [[uint_max]] [[uint_max]] [[uint_max]] [[uint_max]]
199 ; CHECK: [[null:%\w+]] = OpConstantNull [[type:%\w+]]
200 ; CHECK: OpFunction
201 ; CHECK-NEXT: OpLabel
202 ; CHECK-NEXT: [[data:%\w+]] = OpUndef [[type]]
203 ; CHECK-NEXT: [[id:%\w+]] = OpLoad %uint [[var]]
204 ; CHECK-NEXT: [[and_mask:%\w+]] = OpBitwiseOr %uint [[x]] [[mask_extend]]
205 ; CHECK-NEXT: [[and:%\w+]] = OpBitwiseAnd %uint [[id]] [[and_mask]]
206 ; CHECK-NEXT: [[or:%\w+]] = OpBitwiseOr %uint [[and]] [[y]]
207 ; CHECK-NEXT: [[target_inv:%\w+]] = OpBitwiseXor %uint [[or]] [[z]]
208 ; CHECK-NEXT: [[is_active:%\w+]] = OpGroupNonUniformBallotBitExtract %bool [[subgroup]] [[ballot_value]] [[target_inv]]
209 ; CHECK-NEXT: [[shuffle:%\w+]] = OpGroupNonUniformShuffle [[type]] [[subgroup]] [[data]] [[target_inv]]
210 ; CHECK-NEXT: [[result:%\w+]] = OpSelect [[type]] [[is_active]] [[shuffle]] [[null]]
211                OpCapability Shader
212                OpExtension "SPV_AMD_shader_ballot"
213         %ext = OpExtInstImport "SPV_AMD_shader_ballot"
214                OpMemoryModel Logical GLSL450
215                OpEntryPoint Fragment %1 "func"
216                OpExecutionMode %1 OriginUpperLeft
217        %void = OpTypeVoid
218           %3 = OpTypeFunction %void
219        %uint = OpTypeInt 32 0
220      %uint_x = OpConstant %uint 19
221      %uint_y = OpConstant %uint 12
222      %uint_z = OpConstant %uint 16
223      %v3uint = OpTypeVector %uint 3
224        %mask = OpConstantComposite %v3uint %uint_x %uint_y %uint_z
225           %1 = OpFunction %void None %3
226           %6 = OpLabel
227           %data = OpUndef %uint
228           %9 = OpExtInst %uint %ext SwizzleInvocationsMaskedAMD %data %mask
229                OpReturn
230                OpFunctionEnd
231 )";
232 
233   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
234 }
235 
TEST_F(AmdExtToKhrTest,ReplaceWriteInvocationAMD)236 TEST_F(AmdExtToKhrTest, ReplaceWriteInvocationAMD) {
237   const std::string text = R"(
238 ; CHECK: OpCapability Shader
239 ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot"
240 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_ballot"
241 ; CHECK: OpDecorate [[var:%\w+]] BuiltIn SubgroupLocalInvocationId
242 ; CHECK: [[var]] = OpVariable %_ptr_Input_uint Input
243 ; CHECK: OpFunction
244 ; CHECK-NEXT: OpLabel
245 ; CHECK-NEXT: [[input_val:%\w+]] = OpUndef %uint
246 ; CHECK-NEXT: [[write_val:%\w+]] = OpUndef %uint
247 ; CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[var]]
248 ; CHECK-NEXT: [[cmp:%\w+]] = OpIEqual %bool [[ld]] %uint_3
249 ; CHECK-NEXT: [[result:%\w+]] = OpSelect %uint [[cmp]] [[write_val]] [[input_val]]
250                OpCapability Shader
251                OpExtension "SPV_AMD_shader_ballot"
252         %ext = OpExtInstImport "SPV_AMD_shader_ballot"
253                OpMemoryModel Logical GLSL450
254                OpEntryPoint Fragment %1 "func"
255                OpExecutionMode %1 OriginUpperLeft
256        %void = OpTypeVoid
257           %3 = OpTypeFunction %void
258        %uint = OpTypeInt 32 0
259      %uint_3 = OpConstant %uint 3
260           %1 = OpFunction %void None %3
261           %6 = OpLabel
262           %7 = OpUndef %uint
263           %8 = OpUndef %uint
264           %9 = OpExtInst %uint %ext WriteInvocationAMD %7 %8 %uint_3
265                OpReturn
266                OpFunctionEnd
267 )";
268 
269   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
270 }
271 
TEST_F(AmdExtToKhrTest,ReplaceFMin3AMD)272 TEST_F(AmdExtToKhrTest, ReplaceFMin3AMD) {
273   const std::string text = R"(
274 ; CHECK: OpCapability Shader
275 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
276 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
277 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
278 ; CHECK: [[type:%\w+]] = OpTypeFloat 32
279 ; CHECK: OpFunction
280 ; CHECK-NEXT: OpLabel
281 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
282 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
283 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
284 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[x]] [[y]]
285 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[temp]] [[z]]
286                OpCapability Shader
287                OpExtension "SPV_AMD_shader_trinary_minmax"
288         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
289                OpMemoryModel Logical GLSL450
290                OpEntryPoint Fragment %1 "func"
291                OpExecutionMode %1 OriginUpperLeft
292        %void = OpTypeVoid
293           %3 = OpTypeFunction %void
294        %uint = OpTypeInt 32 0
295       %float = OpTypeFloat 32
296      %uint_3 = OpConstant %uint 3
297           %1 = OpFunction %void None %3
298           %6 = OpLabel
299           %7 = OpUndef %float
300           %8 = OpUndef %float
301           %9 = OpUndef %float
302          %10 = OpExtInst %float %ext FMin3AMD %7 %8 %9
303                OpReturn
304                OpFunctionEnd
305 )";
306 
307   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
308 }
309 
TEST_F(AmdExtToKhrTest,ReplaceSMin3AMD)310 TEST_F(AmdExtToKhrTest, ReplaceSMin3AMD) {
311   const std::string text = R"(
312 ; CHECK: OpCapability Shader
313 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
314 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
315 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
316 ; CHECK: [[type:%\w+]] = OpTypeInt 32 1
317 ; CHECK: OpFunction
318 ; CHECK-NEXT: OpLabel
319 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
320 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
321 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
322 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[x]] [[y]]
323 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[temp]] [[z]]
324                OpCapability Shader
325                OpExtension "SPV_AMD_shader_trinary_minmax"
326         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
327                OpMemoryModel Logical GLSL450
328                OpEntryPoint Fragment %1 "func"
329                OpExecutionMode %1 OriginUpperLeft
330        %void = OpTypeVoid
331           %3 = OpTypeFunction %void
332        %uint = OpTypeInt 32 0
333        %int = OpTypeInt 32 1
334       %float = OpTypeFloat 32
335      %uint_3 = OpConstant %uint 3
336           %1 = OpFunction %void None %3
337           %6 = OpLabel
338           %7 = OpUndef %int
339           %8 = OpUndef %int
340           %9 = OpUndef %int
341          %10 = OpExtInst %int %ext SMin3AMD %7 %8 %9
342                OpReturn
343                OpFunctionEnd
344 )";
345 
346   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
347 }
348 
TEST_F(AmdExtToKhrTest,ReplaceUMin3AMD)349 TEST_F(AmdExtToKhrTest, ReplaceUMin3AMD) {
350   const std::string text = R"(
351 ; CHECK: OpCapability Shader
352 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
353 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
354 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
355 ; CHECK: [[type:%\w+]] = OpTypeInt 32 0
356 ; CHECK: OpFunction
357 ; CHECK-NEXT: OpLabel
358 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
359 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
360 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
361 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[x]] [[y]]
362 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[temp]] [[z]]
363                OpCapability Shader
364                OpExtension "SPV_AMD_shader_trinary_minmax"
365         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
366                OpMemoryModel Logical GLSL450
367                OpEntryPoint Fragment %1 "func"
368                OpExecutionMode %1 OriginUpperLeft
369        %void = OpTypeVoid
370           %3 = OpTypeFunction %void
371        %uint = OpTypeInt 32 0
372        %int = OpTypeInt 32 1
373       %float = OpTypeFloat 32
374      %uint_3 = OpConstant %uint 3
375           %1 = OpFunction %void None %3
376           %6 = OpLabel
377           %7 = OpUndef %uint
378           %8 = OpUndef %uint
379           %9 = OpUndef %uint
380          %10 = OpExtInst %uint %ext UMin3AMD %7 %8 %9
381                OpReturn
382                OpFunctionEnd
383 )";
384 
385   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
386 }
387 
TEST_F(AmdExtToKhrTest,ReplaceFMax3AMD)388 TEST_F(AmdExtToKhrTest, ReplaceFMax3AMD) {
389   const std::string text = R"(
390 ; CHECK: OpCapability Shader
391 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
392 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
393 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
394 ; CHECK: [[type:%\w+]] = OpTypeFloat 32
395 ; CHECK: OpFunction
396 ; CHECK-NEXT: OpLabel
397 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
398 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
399 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
400 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[x]] [[y]]
401 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[temp]] [[z]]
402                OpCapability Shader
403                OpExtension "SPV_AMD_shader_trinary_minmax"
404         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
405                OpMemoryModel Logical GLSL450
406                OpEntryPoint Fragment %1 "func"
407                OpExecutionMode %1 OriginUpperLeft
408        %void = OpTypeVoid
409           %3 = OpTypeFunction %void
410        %uint = OpTypeInt 32 0
411       %float = OpTypeFloat 32
412      %uint_3 = OpConstant %uint 3
413           %1 = OpFunction %void None %3
414           %6 = OpLabel
415           %7 = OpUndef %float
416           %8 = OpUndef %float
417           %9 = OpUndef %float
418          %10 = OpExtInst %float %ext FMax3AMD %7 %8 %9
419                OpReturn
420                OpFunctionEnd
421 )";
422 
423   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
424 }
425 
TEST_F(AmdExtToKhrTest,ReplaceSMax3AMD)426 TEST_F(AmdExtToKhrTest, ReplaceSMax3AMD) {
427   const std::string text = R"(
428 ; CHECK: OpCapability Shader
429 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
430 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
431 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
432 ; CHECK: [[type:%\w+]] = OpTypeInt 32 1
433 ; CHECK: OpFunction
434 ; CHECK-NEXT: OpLabel
435 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
436 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
437 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
438 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[x]] [[y]]
439 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[temp]] [[z]]
440                OpCapability Shader
441                OpExtension "SPV_AMD_shader_trinary_minmax"
442         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
443                OpMemoryModel Logical GLSL450
444                OpEntryPoint Fragment %1 "func"
445                OpExecutionMode %1 OriginUpperLeft
446        %void = OpTypeVoid
447           %3 = OpTypeFunction %void
448        %uint = OpTypeInt 32 0
449        %int = OpTypeInt 32 1
450       %float = OpTypeFloat 32
451      %uint_3 = OpConstant %uint 3
452           %1 = OpFunction %void None %3
453           %6 = OpLabel
454           %7 = OpUndef %int
455           %8 = OpUndef %int
456           %9 = OpUndef %int
457          %10 = OpExtInst %int %ext SMax3AMD %7 %8 %9
458                OpReturn
459                OpFunctionEnd
460 )";
461 
462   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
463 }
464 
TEST_F(AmdExtToKhrTest,ReplaceUMax3AMD)465 TEST_F(AmdExtToKhrTest, ReplaceUMax3AMD) {
466   const std::string text = R"(
467 ; CHECK: OpCapability Shader
468 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
469 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
470 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
471 ; CHECK: [[type:%\w+]] = OpTypeInt 32 0
472 ; CHECK: OpFunction
473 ; CHECK-NEXT: OpLabel
474 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
475 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
476 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
477 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[x]] [[y]]
478 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[temp]] [[z]]
479                OpCapability Shader
480                OpExtension "SPV_AMD_shader_trinary_minmax"
481         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
482                OpMemoryModel Logical GLSL450
483                OpEntryPoint Fragment %1 "func"
484                OpExecutionMode %1 OriginUpperLeft
485        %void = OpTypeVoid
486           %3 = OpTypeFunction %void
487        %uint = OpTypeInt 32 0
488        %int = OpTypeInt 32 1
489       %float = OpTypeFloat 32
490      %uint_3 = OpConstant %uint 3
491           %1 = OpFunction %void None %3
492           %6 = OpLabel
493           %7 = OpUndef %uint
494           %8 = OpUndef %uint
495           %9 = OpUndef %uint
496          %10 = OpExtInst %uint %ext UMax3AMD %7 %8 %9
497                OpReturn
498                OpFunctionEnd
499 )";
500 
501   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
502 }
503 
TEST_F(AmdExtToKhrTest,ReplaceVecUMax3AMD)504 TEST_F(AmdExtToKhrTest, ReplaceVecUMax3AMD) {
505   const std::string text = R"(
506 ; CHECK: OpCapability Shader
507 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
508 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
509 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
510 ; CHECK: [[type:%\w+]] = OpTypeVector
511 ; CHECK: OpFunction
512 ; CHECK-NEXT: OpLabel
513 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
514 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
515 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
516 ; CHECK-NEXT: [[temp:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[x]] [[y]]
517 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[temp]] [[z]]
518                OpCapability Shader
519                OpExtension "SPV_AMD_shader_trinary_minmax"
520         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
521                OpMemoryModel Logical GLSL450
522                OpEntryPoint Fragment %1 "func"
523                OpExecutionMode %1 OriginUpperLeft
524        %void = OpTypeVoid
525           %3 = OpTypeFunction %void
526        %uint = OpTypeInt 32 0
527         %vec = OpTypeVector %uint 4
528        %int = OpTypeInt 32 1
529       %float = OpTypeFloat 32
530      %uint_3 = OpConstant %uint 3
531           %1 = OpFunction %void None %3
532           %6 = OpLabel
533           %7 = OpUndef %vec
534           %8 = OpUndef %vec
535           %9 = OpUndef %vec
536          %10 = OpExtInst %vec %ext UMax3AMD %7 %8 %9
537                OpReturn
538                OpFunctionEnd
539 )";
540 
541   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
542 }
543 
TEST_F(AmdExtToKhrTest,ReplaceFMid3AMD)544 TEST_F(AmdExtToKhrTest, ReplaceFMid3AMD) {
545   const std::string text = R"(
546 ; CHECK: OpCapability Shader
547 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
548 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
549 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
550 ; CHECK: [[type:%\w+]] = OpTypeFloat 32
551 ; CHECK: OpFunction
552 ; CHECK-NEXT: OpLabel
553 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
554 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
555 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
556 ; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] FMin [[y]] [[z]]
557 ; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] FMax [[y]] [[z]]
558 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] FClamp [[x]] [[min]] [[max]]
559                OpCapability Shader
560                OpExtension "SPV_AMD_shader_trinary_minmax"
561         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
562                OpMemoryModel Logical GLSL450
563                OpEntryPoint Fragment %1 "func"
564                OpExecutionMode %1 OriginUpperLeft
565        %void = OpTypeVoid
566           %3 = OpTypeFunction %void
567        %uint = OpTypeInt 32 0
568       %float = OpTypeFloat 32
569      %uint_3 = OpConstant %uint 3
570           %1 = OpFunction %void None %3
571           %6 = OpLabel
572           %7 = OpUndef %float
573           %8 = OpUndef %float
574           %9 = OpUndef %float
575          %10 = OpExtInst %float %ext FMid3AMD %7 %8 %9
576                OpReturn
577                OpFunctionEnd
578 )";
579 
580   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
581 }
582 
TEST_F(AmdExtToKhrTest,ReplaceSMid3AMD)583 TEST_F(AmdExtToKhrTest, ReplaceSMid3AMD) {
584   const std::string text = R"(
585 ; CHECK: OpCapability Shader
586 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
587 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
588 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
589 ; CHECK: [[type:%\w+]] = OpTypeInt 32 1
590 ; CHECK: OpFunction
591 ; CHECK-NEXT: OpLabel
592 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
593 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
594 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
595 ; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] SMin [[y]] [[z]]
596 ; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] SMax [[y]] [[z]]
597 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] SClamp [[x]] [[min]] [[max]]
598                OpCapability Shader
599                OpExtension "SPV_AMD_shader_trinary_minmax"
600         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
601                OpMemoryModel Logical GLSL450
602                OpEntryPoint Fragment %1 "func"
603                OpExecutionMode %1 OriginUpperLeft
604        %void = OpTypeVoid
605           %3 = OpTypeFunction %void
606        %uint = OpTypeInt 32 0
607        %int = OpTypeInt 32 1
608       %float = OpTypeFloat 32
609      %uint_3 = OpConstant %uint 3
610           %1 = OpFunction %void None %3
611           %6 = OpLabel
612           %7 = OpUndef %int
613           %8 = OpUndef %int
614           %9 = OpUndef %int
615          %10 = OpExtInst %int %ext SMid3AMD %7 %8 %9
616                OpReturn
617                OpFunctionEnd
618 )";
619 
620   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
621 }
622 
TEST_F(AmdExtToKhrTest,ReplaceUMid3AMD)623 TEST_F(AmdExtToKhrTest, ReplaceUMid3AMD) {
624   const std::string text = R"(
625 ; CHECK: OpCapability Shader
626 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
627 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
628 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
629 ; CHECK: [[type:%\w+]] = OpTypeInt 32 0
630 ; CHECK: OpFunction
631 ; CHECK-NEXT: OpLabel
632 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
633 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
634 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
635 ; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[y]] [[z]]
636 ; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[y]] [[z]]
637 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UClamp [[x]] [[min]] [[max]]
638                OpCapability Shader
639                OpExtension "SPV_AMD_shader_trinary_minmax"
640         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
641                OpMemoryModel Logical GLSL450
642                OpEntryPoint Fragment %1 "func"
643                OpExecutionMode %1 OriginUpperLeft
644        %void = OpTypeVoid
645           %3 = OpTypeFunction %void
646        %uint = OpTypeInt 32 0
647        %int = OpTypeInt 32 1
648       %float = OpTypeFloat 32
649      %uint_3 = OpConstant %uint 3
650           %1 = OpFunction %void None %3
651           %6 = OpLabel
652           %7 = OpUndef %uint
653           %8 = OpUndef %uint
654           %9 = OpUndef %uint
655          %10 = OpExtInst %uint %ext UMid3AMD %7 %8 %9
656                OpReturn
657                OpFunctionEnd
658 )";
659 
660   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
661 }
662 
TEST_F(AmdExtToKhrTest,ReplaceVecUMid3AMD)663 TEST_F(AmdExtToKhrTest, ReplaceVecUMid3AMD) {
664   const std::string text = R"(
665 ; CHECK: OpCapability Shader
666 ; CHECK-NOT: OpExtension "SPV_AMD_shader_trinary_minmax"
667 ; CHECK-NOT: OpExtInstImport "SPV_AMD_shader_trinary_minmax"
668 ; CHECK: [[ext:%\w+]] = OpExtInstImport "GLSL.std.450"
669 ; CHECK: [[type:%\w+]] = OpTypeVector
670 ; CHECK: OpFunction
671 ; CHECK-NEXT: OpLabel
672 ; CHECK-NEXT: [[x:%\w+]] = OpUndef [[type]]
673 ; CHECK-NEXT: [[y:%\w+]] = OpUndef [[type]]
674 ; CHECK-NEXT: [[z:%\w+]] = OpUndef [[type]]
675 ; CHECK-NEXT: [[min:%\w+]] = OpExtInst [[type]] [[ext]] UMin [[y]] [[z]]
676 ; CHECK-NEXT: [[max:%\w+]] = OpExtInst [[type]] [[ext]] UMax [[y]] [[z]]
677 ; CHECK-NEXT: [[result:%\w+]] = OpExtInst [[type]] [[ext]] UClamp [[x]] [[min]] [[max]]
678                OpCapability Shader
679                OpExtension "SPV_AMD_shader_trinary_minmax"
680         %ext = OpExtInstImport "SPV_AMD_shader_trinary_minmax"
681                OpMemoryModel Logical GLSL450
682                OpEntryPoint Fragment %1 "func"
683                OpExecutionMode %1 OriginUpperLeft
684        %void = OpTypeVoid
685           %3 = OpTypeFunction %void
686        %uint = OpTypeInt 32 0
687        %vec = OpTypeVector %uint 3
688        %int = OpTypeInt 32 1
689       %float = OpTypeFloat 32
690      %uint_3 = OpConstant %uint 3
691           %1 = OpFunction %void None %3
692           %6 = OpLabel
693           %7 = OpUndef %vec
694           %8 = OpUndef %vec
695           %9 = OpUndef %vec
696          %10 = OpExtInst %vec %ext UMid3AMD %7 %8 %9
697                OpReturn
698                OpFunctionEnd
699 )";
700 
701   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
702 }
703 
TEST_F(AmdExtToKhrTest,ReplaceCubeFaceCoordAMD)704 TEST_F(AmdExtToKhrTest, ReplaceCubeFaceCoordAMD) {
705   // Sorry for the Check test.  The code sequence is so long, I do not think
706   // that a match test would be anymore legible.  This tests the replacement of
707   // the CubeFaceCoordAMD instruction.
708   const std::string before = R"(
709                OpCapability Shader
710                OpExtension "SPV_KHR_storage_buffer_storage_class"
711                OpExtension "SPV_AMD_gcn_shader"
712           %1 = OpExtInstImport "SPV_AMD_gcn_shader"
713                OpMemoryModel Logical GLSL450
714                OpEntryPoint GLCompute %2 "main"
715                OpExecutionMode %2 LocalSize 1 1 1
716        %void = OpTypeVoid
717           %4 = OpTypeFunction %void
718       %float = OpTypeFloat 32
719     %v2float = OpTypeVector %float 2
720     %v3float = OpTypeVector %float 3
721           %2 = OpFunction %void None %4
722           %8 = OpLabel
723           %9 = OpUndef %v3float
724          %10 = OpExtInst %v2float %1 CubeFaceCoordAMD %9
725                OpReturn
726                OpFunctionEnd
727 )";
728 
729   const std::string after = R"(OpCapability Shader
730 OpExtension "SPV_KHR_storage_buffer_storage_class"
731 %12 = OpExtInstImport "GLSL.std.450"
732 OpMemoryModel Logical GLSL450
733 OpEntryPoint GLCompute %2 "main"
734 OpExecutionMode %2 LocalSize 1 1 1
735 %void = OpTypeVoid
736 %4 = OpTypeFunction %void
737 %float = OpTypeFloat 32
738 %v2float = OpTypeVector %float 2
739 %v3float = OpTypeVector %float 3
740 %bool = OpTypeBool
741 %float_0 = OpConstant %float 0
742 %float_2 = OpConstant %float 2
743 %float_0_5 = OpConstant %float 0.5
744 %16 = OpConstantComposite %v2float %float_0_5 %float_0_5
745 %2 = OpFunction %void None %4
746 %8 = OpLabel
747 %9 = OpUndef %v3float
748 %17 = OpCompositeExtract %float %9 0
749 %18 = OpCompositeExtract %float %9 1
750 %19 = OpCompositeExtract %float %9 2
751 %20 = OpFNegate %float %17
752 %21 = OpFNegate %float %18
753 %22 = OpFNegate %float %19
754 %23 = OpExtInst %float %12 FAbs %17
755 %24 = OpExtInst %float %12 FAbs %18
756 %25 = OpExtInst %float %12 FAbs %19
757 %26 = OpFOrdLessThan %bool %19 %float_0
758 %27 = OpFOrdLessThan %bool %18 %float_0
759 %28 = OpFOrdLessThan %bool %17 %float_0
760 %29 = OpExtInst %float %12 FMax %23 %24
761 %30 = OpExtInst %float %12 FMax %25 %29
762 %31 = OpFMul %float %float_2 %30
763 %32 = OpFOrdGreaterThanEqual %bool %25 %29
764 %33 = OpLogicalNot %bool %32
765 %34 = OpFOrdGreaterThanEqual %bool %24 %23
766 %35 = OpLogicalAnd %bool %33 %34
767 %36 = OpSelect %float %26 %20 %17
768 %37 = OpSelect %float %28 %19 %22
769 %38 = OpSelect %float %35 %17 %37
770 %39 = OpSelect %float %32 %36 %38
771 %40 = OpSelect %float %27 %22 %19
772 %41 = OpSelect %float %35 %40 %21
773 %42 = OpCompositeConstruct %v2float %39 %41
774 %43 = OpCompositeConstruct %v2float %31 %31
775 %44 = OpFDiv %v2float %42 %43
776 %10 = OpFAdd %v2float %44 %16
777 OpReturn
778 OpFunctionEnd
779 )";
780 
781   SinglePassRunAndCheck<AmdExtensionToKhrPass>(before, after, true);
782 }
783 
TEST_F(AmdExtToKhrTest,ReplaceCubeFaceIndexAMD)784 TEST_F(AmdExtToKhrTest, ReplaceCubeFaceIndexAMD) {
785   // Sorry for the Check test.  The code sequence is so long, I do not think
786   // that a match test would be anymore legible.  This tests the replacement of
787   // the CubeFaceIndexAMD instruction.
788   const std::string before = R"(OpCapability Shader
789 OpExtension "SPV_KHR_storage_buffer_storage_class"
790 OpExtension "SPV_AMD_gcn_shader"
791 %1 = OpExtInstImport "SPV_AMD_gcn_shader"
792 OpMemoryModel Logical GLSL450
793 OpEntryPoint GLCompute %2 "main"
794 OpExecutionMode %2 LocalSize 1 1 1
795 %void = OpTypeVoid
796 %4 = OpTypeFunction %void
797 %float = OpTypeFloat 32
798 %v3float = OpTypeVector %float 3
799 %2 = OpFunction %void None %4
800 %7 = OpLabel
801 %8 = OpUndef %v3float
802 %9 = OpExtInst %float %1 CubeFaceIndexAMD %8
803 OpReturn
804 OpFunctionEnd
805 )";
806 
807   const std::string after = R"(OpCapability Shader
808 OpExtension "SPV_KHR_storage_buffer_storage_class"
809 %11 = OpExtInstImport "GLSL.std.450"
810 OpMemoryModel Logical GLSL450
811 OpEntryPoint GLCompute %2 "main"
812 OpExecutionMode %2 LocalSize 1 1 1
813 %void = OpTypeVoid
814 %4 = OpTypeFunction %void
815 %float = OpTypeFloat 32
816 %v3float = OpTypeVector %float 3
817 %bool = OpTypeBool
818 %float_0 = OpConstant %float 0
819 %float_1 = OpConstant %float 1
820 %float_2 = OpConstant %float 2
821 %float_3 = OpConstant %float 3
822 %float_4 = OpConstant %float 4
823 %float_5 = OpConstant %float 5
824 %2 = OpFunction %void None %4
825 %7 = OpLabel
826 %8 = OpUndef %v3float
827 %18 = OpCompositeExtract %float %8 0
828 %19 = OpCompositeExtract %float %8 1
829 %20 = OpCompositeExtract %float %8 2
830 %21 = OpExtInst %float %11 FAbs %18
831 %22 = OpExtInst %float %11 FAbs %19
832 %23 = OpExtInst %float %11 FAbs %20
833 %24 = OpFOrdLessThan %bool %20 %float_0
834 %25 = OpFOrdLessThan %bool %19 %float_0
835 %26 = OpFOrdLessThan %bool %18 %float_0
836 %27 = OpExtInst %float %11 FMax %21 %22
837 %28 = OpFOrdGreaterThanEqual %bool %23 %27
838 %29 = OpFOrdGreaterThanEqual %bool %22 %21
839 %30 = OpSelect %float %24 %float_5 %float_4
840 %31 = OpSelect %float %25 %float_3 %float_2
841 %32 = OpSelect %float %26 %float_1 %float_0
842 %33 = OpSelect %float %29 %31 %32
843 %9 = OpSelect %float %28 %30 %33
844 OpReturn
845 OpFunctionEnd
846 )";
847 
848   SinglePassRunAndCheck<AmdExtensionToKhrPass>(before, after, true);
849 }
850 
TEST_F(AmdExtToKhrTest,SetVersion)851 TEST_F(AmdExtToKhrTest, SetVersion) {
852   const std::string text = R"(
853                OpCapability Shader
854                OpCapability Int64
855                OpExtension "SPV_AMD_shader_ballot"
856           %1 = OpExtInstImport "SPV_AMD_shader_ballot"
857                OpMemoryModel Logical GLSL450
858                OpEntryPoint Fragment %2 "func"
859                OpExecutionMode %2 OriginUpperLeft
860        %void = OpTypeVoid
861           %4 = OpTypeFunction %void
862        %uint = OpTypeInt 32 0
863       %ulong = OpTypeInt 64 0
864     %ulong_0 = OpConstant %ulong 0
865           %2 = OpFunction %void None %4
866           %8 = OpLabel
867           %9 = OpExtInst %uint %1 MbcntAMD %ulong_0
868                OpReturn
869                OpFunctionEnd
870 )";
871 
872   // Set the version to 1.1 and make sure it is upgraded to 1.3.
873   SetTargetEnv(SPV_ENV_UNIVERSAL_1_1);
874   SetDisassembleOptions(0);
875   auto result = SinglePassRunAndDisassemble<AmdExtensionToKhrPass>(
876       text, /* skip_nop = */ true, /* skip_validation = */ false);
877 
878   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
879   const std::string& output = std::get<0>(result);
880   EXPECT_THAT(output, HasSubstr("Version: 1.3"));
881 }
882 
TEST_F(AmdExtToKhrTest,SetVersion1)883 TEST_F(AmdExtToKhrTest, SetVersion1) {
884   const std::string text = R"(
885                OpCapability Shader
886                OpCapability Int64
887                OpExtension "SPV_AMD_shader_ballot"
888           %1 = OpExtInstImport "SPV_AMD_shader_ballot"
889                OpMemoryModel Logical GLSL450
890                OpEntryPoint Fragment %2 "func"
891                OpExecutionMode %2 OriginUpperLeft
892        %void = OpTypeVoid
893           %4 = OpTypeFunction %void
894        %uint = OpTypeInt 32 0
895       %ulong = OpTypeInt 64 0
896     %ulong_0 = OpConstant %ulong 0
897           %2 = OpFunction %void None %4
898           %8 = OpLabel
899           %9 = OpExtInst %uint %1 MbcntAMD %ulong_0
900                OpReturn
901                OpFunctionEnd
902 )";
903 
904   // Set the version to 1.4 and make sure it is stays the same.
905   SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
906   SetDisassembleOptions(0);
907   auto result = SinglePassRunAndDisassemble<AmdExtensionToKhrPass>(
908       text, /* skip_nop = */ true, /* skip_validation = */ false);
909 
910   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
911   const std::string& output = std::get<0>(result);
912   EXPECT_THAT(output, HasSubstr("Version: 1.4"));
913 }
914 
TEST_F(AmdExtToKhrTest,TimeAMD)915 TEST_F(AmdExtToKhrTest, TimeAMD) {
916   const std::string text = R"(
917                OpCapability Shader
918                OpCapability Int64
919                OpExtension "SPV_AMD_gcn_shader"
920 ; CHECK-NOT: OpExtension "SPV_AMD_gcn_shader"
921 ; CHECK: OpExtension "SPV_KHR_shader_clock"
922           %1 = OpExtInstImport "GLSL.std.450"
923           %2 = OpExtInstImport "SPV_AMD_gcn_shader"
924 ; CHECK-NOT: OpExtInstImport "SPV_AMD_gcn_shader"
925                OpMemoryModel Logical GLSL450
926                OpEntryPoint Fragment %main "main"
927                OpExecutionMode %main OriginUpperLeft
928                OpSource GLSL 450
929                OpSourceExtension "GL_AMD_gcn_shader"
930                OpSourceExtension "GL_ARB_gpu_shader_int64"
931                OpName %main "main"
932                OpName %time "time"
933        %void = OpTypeVoid
934           %6 = OpTypeFunction %void
935       %ulong = OpTypeInt 64 0
936 %_ptr_Function_ulong = OpTypePointer Function %ulong
937        %main = OpFunction %void None %6
938           %9 = OpLabel
939        %time = OpVariable %_ptr_Function_ulong Function
940 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
941 ; CHECK: [[uint_3:%\w+]] = OpConstant [[uint]] 3
942          %10 = OpExtInst %ulong %2 TimeAMD
943 ; CHECK: %10 = OpReadClockKHR %ulong [[uint_3]]
944                OpStore %time %10
945                OpReturn
946                OpFunctionEnd
947 )";
948 
949   SinglePassRunAndMatch<AmdExtensionToKhrPass>(text, true);
950 }
951 }  // namespace
952 }  // namespace opt
953 }  // namespace spvtools
954