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