1// Copyright (c) 2018 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 "assembly_builder.h"
16#include "pass_fixture.h"
17#include "pass_utils.h"
18
19namespace {
20
21using namespace spvtools;
22
23using UpgradeMemoryModelTest = opt::PassTest<::testing::Test>;
24
25TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelOpenCL) {
26  const std::string text = R"(
27; CHECK: OpMemoryModel Logical OpenCL
28OpCapability Kernel
29OpCapability Linkage
30OpMemoryModel Logical OpenCL
31)";
32
33  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
34}
35
36TEST_F(UpgradeMemoryModelTest, InvalidMemoryModelVulkan) {
37  const std::string text = R"(
38; CHECK: OpMemoryModel Logical Vulkan
39OpCapability Shader
40OpCapability Linkage
41OpCapability VulkanMemoryModel
42OpExtension "SPV_KHR_vulkan_memory_model"
43OpMemoryModel Logical Vulkan
44)";
45
46  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
47}
48
49TEST_F(UpgradeMemoryModelTest, JustMemoryModel) {
50  const std::string text = R"(
51; CHECK: OpCapability VulkanMemoryModel
52; CHECK: OpExtension "SPV_KHR_vulkan_memory_model"
53; CHECK: OpMemoryModel Logical Vulkan
54OpCapability Shader
55OpCapability Linkage
56OpMemoryModel Logical GLSL450
57)";
58
59  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
60}
61
62TEST_F(UpgradeMemoryModelTest, RemoveDecorations) {
63  const std::string text = R"(
64; CHECK-NOT: OpDecorate
65OpCapability Shader
66OpCapability Linkage
67OpMemoryModel Logical GLSL450
68OpDecorate %var Volatile
69OpDecorate %var Coherent
70%int = OpTypeInt 32 0
71%ptr_int_Uniform = OpTypePointer Uniform %int
72%var = OpVariable %ptr_int_Uniform Uniform
73)";
74
75  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
76}
77
78TEST_F(UpgradeMemoryModelTest, WorkgroupVariable) {
79  const std::string text = R"(
80; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2
81; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
82; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
83OpCapability Shader
84OpCapability Linkage
85OpMemoryModel Logical GLSL450
86%void = OpTypeVoid
87%int = OpTypeInt 32 0
88%ptr_int_Workgroup = OpTypePointer Workgroup %int
89%var = OpVariable %ptr_int_Workgroup Workgroup
90%func_ty = OpTypeFunction %void
91%func = OpFunction %void None %func_ty
92%1 = OpLabel
93%ld = OpLoad %int %var
94OpStore %var %ld
95OpReturn
96OpFunctionEnd
97)";
98
99  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
100}
101
102TEST_F(UpgradeMemoryModelTest, WorkgroupFunctionParameter) {
103  const std::string text = R"(
104; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 2
105; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
106; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
107OpCapability Shader
108OpCapability Linkage
109OpMemoryModel Logical GLSL450
110%void = OpTypeVoid
111%int = OpTypeInt 32 0
112%ptr_int_Workgroup = OpTypePointer Workgroup %int
113%func_ty = OpTypeFunction %void %ptr_int_Workgroup
114%func = OpFunction %void None %func_ty
115%param = OpFunctionParameter %ptr_int_Workgroup
116%1 = OpLabel
117%ld = OpLoad %int %param
118OpStore %param %ld
119OpReturn
120OpFunctionEnd
121)";
122
123  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
124}
125
126TEST_F(UpgradeMemoryModelTest, SimpleUniformVariable) {
127  const std::string text = R"(
128; CHECK-NOT: OpDecorate
129; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
130; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
131; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
132OpCapability Shader
133OpCapability Linkage
134OpMemoryModel Logical GLSL450
135OpDecorate %var Coherent
136OpDecorate %var Volatile
137%void = OpTypeVoid
138%int = OpTypeInt 32 0
139%ptr_int_Uniform = OpTypePointer Uniform %int
140%var = OpVariable %ptr_int_Uniform Uniform
141%func_ty = OpTypeFunction %void
142%func = OpFunction %void None %func_ty
143%1 = OpLabel
144%ld = OpLoad %int %var
145OpStore %var %ld
146OpReturn
147OpFunctionEnd
148)";
149
150  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
151}
152
153TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameter) {
154  const std::string text = R"(
155; CHECK-NOT: OpDecorate
156; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
157; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
158; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
159OpCapability Shader
160OpCapability Linkage
161OpMemoryModel Logical GLSL450
162OpDecorate %param Coherent
163OpDecorate %param Volatile
164%void = OpTypeVoid
165%int = OpTypeInt 32 0
166%ptr_int_Uniform = OpTypePointer Uniform %int
167%func_ty = OpTypeFunction %void %ptr_int_Uniform
168%func = OpFunction %void None %func_ty
169%param = OpFunctionParameter %ptr_int_Uniform
170%1 = OpLabel
171%ld = OpLoad %int %param
172OpStore %param %ld
173OpReturn
174OpFunctionEnd
175)";
176
177  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
178}
179
180TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableOnlyVolatile) {
181  const std::string text = R"(
182; CHECK-NOT: OpDecorate
183; CHECK-NOT: OpConstant
184; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile
185; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile
186OpCapability Shader
187OpCapability Linkage
188OpMemoryModel Logical GLSL450
189OpDecorate %var Volatile
190%void = OpTypeVoid
191%int = OpTypeInt 32 0
192%ptr_int_Uniform = OpTypePointer Uniform %int
193%var = OpVariable %ptr_int_Uniform Uniform
194%func_ty = OpTypeFunction %void
195%func = OpFunction %void None %func_ty
196%1 = OpLabel
197%ld = OpLoad %int %var
198OpStore %var %ld
199OpReturn
200OpFunctionEnd
201)";
202
203  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
204}
205
206TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableCopied) {
207  const std::string text = R"(
208; CHECK-NOT: OpDecorate
209; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
210; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
211; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
212OpCapability Shader
213OpCapability Linkage
214OpMemoryModel Logical GLSL450
215OpDecorate %var Coherent
216OpDecorate %var Volatile
217%void = OpTypeVoid
218%int = OpTypeInt 32 0
219%ptr_int_Uniform = OpTypePointer Uniform %int
220%var = OpVariable %ptr_int_Uniform Uniform
221%func_ty = OpTypeFunction %void
222%func = OpFunction %void None %func_ty
223%1 = OpLabel
224%copy = OpCopyObject %ptr_int_Uniform %var
225%ld = OpLoad %int %copy
226OpStore %copy %ld
227OpReturn
228OpFunctionEnd
229)";
230
231  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
232}
233
234TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterCopied) {
235  const std::string text = R"(
236; CHECK-NOT: OpDecorate
237; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
238; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
239; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
240OpCapability Shader
241OpCapability Linkage
242OpMemoryModel Logical GLSL450
243OpDecorate %param Coherent
244OpDecorate %param Volatile
245%void = OpTypeVoid
246%int = OpTypeInt 32 0
247%ptr_int_Uniform = OpTypePointer Uniform %int
248%func_ty = OpTypeFunction %void %ptr_int_Uniform
249%func = OpFunction %void None %func_ty
250%param = OpFunctionParameter %ptr_int_Uniform
251%1 = OpLabel
252%copy = OpCopyObject %ptr_int_Uniform %param
253%ld = OpLoad %int %copy
254%copy2 = OpCopyObject %ptr_int_Uniform %param
255OpStore %copy2 %ld
256OpReturn
257OpFunctionEnd
258)";
259
260  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
261}
262
263TEST_F(UpgradeMemoryModelTest, SimpleUniformVariableAccessChain) {
264  const std::string text = R"(
265; CHECK-NOT: OpDecorate
266; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
267; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
268; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
269OpCapability Shader
270OpCapability Linkage
271OpMemoryModel Logical GLSL450
272OpDecorate %var Coherent
273OpDecorate %var Volatile
274%void = OpTypeVoid
275%int = OpTypeInt 32 0
276%int0 = OpConstant %int 0
277%int3 = OpConstant %int 3
278%int_array_3 = OpTypeArray %int %int3
279%ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3
280%ptr_int_Uniform = OpTypePointer Uniform %int
281%var = OpVariable %ptr_intarray_Uniform Uniform
282%func_ty = OpTypeFunction %void
283%func = OpFunction %void None %func_ty
284%1 = OpLabel
285%gep = OpAccessChain %ptr_int_Uniform %var %int0
286%ld = OpLoad %int %gep
287OpStore %gep %ld
288OpReturn
289OpFunctionEnd
290)";
291
292  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
293}
294
295TEST_F(UpgradeMemoryModelTest, SimpleUniformFunctionParameterAccessChain) {
296  const std::string text = R"(
297; CHECK-NOT: OpDecorate
298; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
299; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
300; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
301OpCapability Shader
302OpCapability Linkage
303OpMemoryModel Logical GLSL450
304OpDecorate %param Coherent
305OpDecorate %param Volatile
306%void = OpTypeVoid
307%int = OpTypeInt 32 0
308%int0 = OpConstant %int 0
309%int3 = OpConstant %int 3
310%int_array_3 = OpTypeArray %int %int3
311%ptr_intarray_Uniform = OpTypePointer Uniform %int_array_3
312%ptr_int_Uniform = OpTypePointer Uniform %int
313%func_ty = OpTypeFunction %void %ptr_intarray_Uniform
314%func = OpFunction %void None %func_ty
315%param = OpFunctionParameter %ptr_intarray_Uniform
316%1 = OpLabel
317%ld_gep = OpAccessChain %ptr_int_Uniform %param %int0
318%ld = OpLoad %int %ld_gep
319%st_gep = OpAccessChain %ptr_int_Uniform %param %int0
320OpStore %st_gep %ld
321OpReturn
322OpFunctionEnd
323)";
324
325  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
326}
327
328TEST_F(UpgradeMemoryModelTest, VariablePointerSelect) {
329  const std::string text = R"(
330; CHECK-NOT: OpDecorate
331; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
332; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
333; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
334OpCapability Shader
335OpCapability Linkage
336OpCapability VariablePointers
337OpExtension "SPV_KHR_variable_pointers"
338OpMemoryModel Logical GLSL450
339OpDecorate %var Coherent
340OpDecorate %var Volatile
341%void = OpTypeVoid
342%int = OpTypeInt 32 0
343%bool = OpTypeBool
344%true = OpConstantTrue %bool
345%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
346%null = OpConstantNull %ptr_int_StorageBuffer
347%var = OpVariable %ptr_int_StorageBuffer StorageBuffer
348%func_ty = OpTypeFunction %void
349%func = OpFunction %void None %func_ty
350%1 = OpLabel
351%select = OpSelect %ptr_int_StorageBuffer %true %var %null
352%ld = OpLoad %int %select
353OpStore %var %ld
354OpReturn
355OpFunctionEnd
356)";
357
358  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
359}
360
361TEST_F(UpgradeMemoryModelTest, VariablePointerSelectConservative) {
362  const std::string text = R"(
363; CHECK-NOT: OpDecorate
364; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
365; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[scope]]
366; CHECK: OpStore {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[scope]]
367OpCapability Shader
368OpCapability Linkage
369OpCapability VariablePointers
370OpExtension "SPV_KHR_variable_pointers"
371OpMemoryModel Logical GLSL450
372OpDecorate %var1 Coherent
373OpDecorate %var2 Volatile
374%void = OpTypeVoid
375%int = OpTypeInt 32 0
376%bool = OpTypeBool
377%true = OpConstantTrue %bool
378%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
379%var1 = OpVariable %ptr_int_StorageBuffer StorageBuffer
380%var2 = OpVariable %ptr_int_StorageBuffer StorageBuffer
381%func_ty = OpTypeFunction %void
382%func = OpFunction %void None %func_ty
383%1 = OpLabel
384%select = OpSelect %ptr_int_StorageBuffer %true %var1 %var2
385%ld = OpLoad %int %select
386OpStore %select %ld
387OpReturn
388OpFunctionEnd
389)";
390
391  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
392}
393
394TEST_F(UpgradeMemoryModelTest, VariablePointerIncrement) {
395  const std::string text = R"(
396; CHECK-NOT: OpDecorate {{%\w+}} Coherent
397; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
398; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
399; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
400OpCapability Shader
401OpCapability Linkage
402OpCapability VariablePointers
403OpExtension "SPV_KHR_variable_pointers"
404OpMemoryModel Logical GLSL450
405OpDecorate %param Coherent
406OpDecorate %ptr_int_StorageBuffer ArrayStride 4
407%void = OpTypeVoid
408%bool = OpTypeBool
409%int = OpTypeInt 32 0
410%int0 = OpConstant %int 0
411%int1 = OpConstant %int 1
412%int10 = OpConstant %int 10
413%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
414%func_ty = OpTypeFunction %void %ptr_int_StorageBuffer
415%func = OpFunction %void None %func_ty
416%param = OpFunctionParameter %ptr_int_StorageBuffer
417%1 = OpLabel
418OpBranch %2
419%2 = OpLabel
420%phi = OpPhi %ptr_int_StorageBuffer %param %1 %ptr_next %2
421%iv = OpPhi %int %int0 %1 %inc %2
422%inc = OpIAdd %int %iv %int1
423%ptr_next = OpPtrAccessChain %ptr_int_StorageBuffer %phi %int1
424%cmp = OpIEqual %bool %iv %int10
425OpLoopMerge %3 %2 None
426OpBranchConditional %cmp %3 %2
427%3 = OpLabel
428%ld = OpLoad %int %phi
429OpStore %phi %ld
430OpReturn
431OpFunctionEnd
432)";
433
434  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
435}
436
437TEST_F(UpgradeMemoryModelTest, CoherentStructElement) {
438  const std::string text = R"(
439; CHECK-NOT: OpMemberDecorate
440; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
441; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
442; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
443OpCapability Shader
444OpCapability Linkage
445OpExtension "SPV_KHR_storage_buffer_storage_class"
446OpMemoryModel Logical GLSL450
447OpMemberDecorate %struct 0 Coherent
448%void = OpTypeVoid
449%int = OpTypeInt 32 0
450%int0 = OpConstant %int 0
451%struct = OpTypeStruct %int
452%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct
453%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
454%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer
455%func = OpFunction %void None %func_ty
456%param = OpFunctionParameter %ptr_struct_StorageBuffer
457%1 = OpLabel
458%gep = OpAccessChain %ptr_int_StorageBuffer %param %int0
459%ld = OpLoad %int %gep
460OpStore %gep %ld
461OpReturn
462OpFunctionEnd
463)";
464
465  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
466}
467
468TEST_F(UpgradeMemoryModelTest, CoherentElementFullStructAccess) {
469  const std::string text = R"(
470; CHECK-NOT: OpMemberDecorate
471; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
472; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
473; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
474OpCapability Shader
475OpCapability Linkage
476OpExtension "SPV_KHR_storage_buffer_storage_class"
477OpMemoryModel Logical GLSL450
478OpMemberDecorate %struct 0 Coherent
479%void = OpTypeVoid
480%int = OpTypeInt 32 0
481%struct = OpTypeStruct %int
482%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct
483%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer
484%func = OpFunction %void None %func_ty
485%param = OpFunctionParameter %ptr_struct_StorageBuffer
486%1 = OpLabel
487%ld = OpLoad %struct %param
488OpStore %param %ld
489OpReturn
490OpFunctionEnd
491)";
492
493  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
494}
495
496TEST_F(UpgradeMemoryModelTest, CoherentElementNotAccessed) {
497  const std::string text = R"(
498; CHECK-NOT: OpMemberDecorate
499; CHECK-NOT: MakePointerAvailable
500; CHECK-NOT: NonPrivatePointer
501; CHECK-NOT: MakePointerVisible
502OpCapability Shader
503OpCapability Linkage
504OpExtension "SPV_KHR_storage_buffer_storage_class"
505OpMemoryModel Logical GLSL450
506OpMemberDecorate %struct 1 Coherent
507%void = OpTypeVoid
508%int = OpTypeInt 32 0
509%int0 = OpConstant %int 0
510%struct = OpTypeStruct %int %int
511%ptr_struct_StorageBuffer = OpTypePointer StorageBuffer %struct
512%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
513%func_ty = OpTypeFunction %void %ptr_struct_StorageBuffer
514%func = OpFunction %void None %func_ty
515%param = OpFunctionParameter %ptr_struct_StorageBuffer
516%1 = OpLabel
517%gep = OpAccessChain %ptr_int_StorageBuffer %param %int0
518%ld = OpLoad %int %gep
519OpStore %gep %ld
520OpReturn
521OpFunctionEnd
522)";
523
524  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
525}
526
527TEST_F(UpgradeMemoryModelTest, MultiIndexAccessCoherent) {
528  const std::string text = R"(
529; CHECK-NOT: OpMemberDecorate
530; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
531; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
532; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
533OpCapability Shader
534OpCapability Linkage
535OpExtension "SPV_KHR_storage_buffer_storage_class"
536OpMemoryModel Logical GLSL450
537OpMemberDecorate %inner 1 Coherent
538%void = OpTypeVoid
539%int = OpTypeInt 32 0
540%int0 = OpConstant %int 0
541%int1 = OpConstant %int 1
542%inner = OpTypeStruct %int %int
543%middle = OpTypeStruct %inner
544%outer = OpTypeStruct %middle %middle
545%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
546%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
547%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
548%func = OpFunction %void None %func_ty
549%param = OpFunctionParameter %ptr_outer_StorageBuffer
550%1 = OpLabel
551%ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int1
552%ld = OpLoad %int %ld_gep
553%st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int1
554OpStore %st_gep %ld
555OpReturn
556OpFunctionEnd
557)";
558
559  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
560}
561
562TEST_F(UpgradeMemoryModelTest, MultiIndexAccessNonCoherent) {
563  const std::string text = R"(
564; CHECK-NOT: OpMemberDecorate
565; CHECK-NOT: MakePointerAvailable
566; CHECK-NOT: NonPrivatePointer
567; CHECK-NOT: MakePointerVisible
568OpCapability Shader
569OpCapability Linkage
570OpExtension "SPV_KHR_storage_buffer_storage_class"
571OpMemoryModel Logical GLSL450
572OpMemberDecorate %inner 1 Coherent
573%void = OpTypeVoid
574%int = OpTypeInt 32 0
575%int0 = OpConstant %int 0
576%int1 = OpConstant %int 1
577%inner = OpTypeStruct %int %int
578%middle = OpTypeStruct %inner
579%outer = OpTypeStruct %middle %middle
580%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
581%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
582%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
583%func = OpFunction %void None %func_ty
584%param = OpFunctionParameter %ptr_outer_StorageBuffer
585%1 = OpLabel
586%ld_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int0 %int0 %int0
587%ld = OpLoad %int %ld_gep
588%st_gep = OpInBoundsAccessChain %ptr_int_StorageBuffer %param %int1 %int0 %int0
589OpStore %st_gep %ld
590OpReturn
591OpFunctionEnd
592)";
593
594  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
595}
596
597TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainCoherent) {
598  const std::string text = R"(
599; CHECK-NOT: OpMemberDecorate
600; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
601; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
602; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
603OpCapability Shader
604OpCapability Linkage
605OpExtension "SPV_KHR_storage_buffer_storage_class"
606OpMemoryModel Logical GLSL450
607OpMemberDecorate %inner 1 Coherent
608%void = OpTypeVoid
609%int = OpTypeInt 32 0
610%int0 = OpConstant %int 0
611%int1 = OpConstant %int 1
612%inner = OpTypeStruct %int %int
613%middle = OpTypeStruct %inner
614%outer = OpTypeStruct %middle %middle
615%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
616%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle
617%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner
618%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
619%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
620%func = OpFunction %void None %func_ty
621%param = OpFunctionParameter %ptr_outer_StorageBuffer
622%1 = OpLabel
623%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0
624%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0
625%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1
626%ld = OpLoad %int %ld_gep3
627%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1
628%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0
629%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1
630OpStore %st_gep3 %ld
631OpReturn
632OpFunctionEnd
633)";
634
635  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
636}
637
638TEST_F(UpgradeMemoryModelTest, ConsecutiveAccessChainNonCoherent) {
639  const std::string text = R"(
640; CHECK-NOT: OpMemberDecorate
641; CHECK-NOT: MakePointerAvailable
642; CHECK-NOT: NonPrivatePointer
643; CHECK-NOT: MakePointerVisible
644OpCapability Shader
645OpCapability Linkage
646OpExtension "SPV_KHR_storage_buffer_storage_class"
647OpMemoryModel Logical GLSL450
648OpMemberDecorate %inner 1 Coherent
649%void = OpTypeVoid
650%int = OpTypeInt 32 0
651%int0 = OpConstant %int 0
652%int1 = OpConstant %int 1
653%inner = OpTypeStruct %int %int
654%middle = OpTypeStruct %inner
655%outer = OpTypeStruct %middle %middle
656%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
657%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle
658%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner
659%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
660%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
661%func = OpFunction %void None %func_ty
662%param = OpFunctionParameter %ptr_outer_StorageBuffer
663%1 = OpLabel
664%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0
665%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0
666%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int0
667%ld = OpLoad %int %ld_gep3
668%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1
669%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0
670%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int0
671OpStore %st_gep3 %ld
672OpReturn
673OpFunctionEnd
674)";
675
676  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
677}
678
679TEST_F(UpgradeMemoryModelTest, CoherentStructElementAccess) {
680  const std::string text = R"(
681; CHECK-NOT: OpMemberDecorate
682; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
683; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
684; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
685OpCapability Shader
686OpCapability Linkage
687OpExtension "SPV_KHR_storage_buffer_storage_class"
688OpMemoryModel Logical GLSL450
689OpMemberDecorate %middle 0 Coherent
690%void = OpTypeVoid
691%int = OpTypeInt 32 0
692%int0 = OpConstant %int 0
693%int1 = OpConstant %int 1
694%inner = OpTypeStruct %int %int
695%middle = OpTypeStruct %inner
696%outer = OpTypeStruct %middle %middle
697%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
698%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle
699%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner
700%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
701%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
702%func = OpFunction %void None %func_ty
703%param = OpFunctionParameter %ptr_outer_StorageBuffer
704%1 = OpLabel
705%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0
706%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0
707%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1
708%ld = OpLoad %int %ld_gep3
709%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1
710%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0
711%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1
712OpStore %st_gep3 %ld
713OpReturn
714OpFunctionEnd
715)";
716
717  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
718}
719
720TEST_F(UpgradeMemoryModelTest, NonCoherentLoadCoherentStore) {
721  const std::string text = R"(
722; CHECK-NOT: OpMemberDecorate
723; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
724; CHECK-NOT: MakePointerVisible
725; CHECK: OpStore {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]]
726OpCapability Shader
727OpCapability Linkage
728OpExtension "SPV_KHR_storage_buffer_storage_class"
729OpMemoryModel Logical GLSL450
730OpMemberDecorate %outer 1 Coherent
731%void = OpTypeVoid
732%int = OpTypeInt 32 0
733%int0 = OpConstant %int 0
734%int1 = OpConstant %int 1
735%inner = OpTypeStruct %int %int
736%middle = OpTypeStruct %inner
737%outer = OpTypeStruct %middle %middle
738%ptr_outer_StorageBuffer = OpTypePointer StorageBuffer %outer
739%ptr_middle_StorageBuffer = OpTypePointer StorageBuffer %middle
740%ptr_inner_StorageBuffer = OpTypePointer StorageBuffer %inner
741%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
742%func_ty = OpTypeFunction %void %ptr_outer_StorageBuffer
743%func = OpFunction %void None %func_ty
744%param = OpFunctionParameter %ptr_outer_StorageBuffer
745%1 = OpLabel
746%ld_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int0
747%ld_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %ld_gep1 %int0
748%ld_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %ld_gep2 %int1
749%ld = OpLoad %int %ld_gep3
750%st_gep1 = OpInBoundsAccessChain %ptr_middle_StorageBuffer %param %int1
751%st_gep2 = OpInBoundsAccessChain %ptr_inner_StorageBuffer %st_gep1 %int0
752%st_gep3 = OpInBoundsAccessChain %ptr_int_StorageBuffer %st_gep2 %int1
753OpStore %st_gep3 %ld
754OpReturn
755OpFunctionEnd
756)";
757
758  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
759}
760
761TEST_F(UpgradeMemoryModelTest, CopyMemory) {
762  const std::string text = R"(
763; CHECK-NOT: OpDecorate
764; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5
765; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|MakePointerVisible|NonPrivatePointer [[queuefamily]]
766; CHECK-NOT: [[queuefamily]]
767OpCapability Shader
768OpCapability Linkage
769OpExtension "SPV_KHR_storage_buffer_storage_class"
770OpMemoryModel Logical GLSL450
771OpDecorate %in_var Coherent
772OpDecorate %out_var Volatile
773%void = OpTypeVoid
774%int = OpTypeInt 32 0
775%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
776%in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer
777%out_var = OpVariable %ptr_int_StorageBuffer StorageBuffer
778%func_ty = OpTypeFunction %void
779%func = OpFunction %void None %func_ty
780%1 = OpLabel
781OpCopyMemory %out_var %in_var
782OpReturn
783OpFunctionEnd
784)";
785
786  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
787}
788
789TEST_F(UpgradeMemoryModelTest, CopyMemorySized) {
790  const std::string text = R"(
791; CHECK-NOT: OpDecorate
792; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5
793; CHECK: OpCopyMemorySized {{%\w+}} {{%\w+}} {{%\w+}} Volatile|MakePointerAvailable|NonPrivatePointer [[queuefamily]]
794; CHECK-NOT: [[queuefamily]]
795OpCapability Shader
796OpCapability Linkage
797OpCapability Addresses
798OpExtension "SPV_KHR_storage_buffer_storage_class"
799OpMemoryModel Logical GLSL450
800OpDecorate %out_param Coherent
801OpDecorate %in_param Volatile
802%void = OpTypeVoid
803%int = OpTypeInt 32 0
804%int4 = OpConstant %int 4
805%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
806%func_ty = OpTypeFunction %void %ptr_int_StorageBuffer %ptr_int_StorageBuffer
807%func = OpFunction %void None %func_ty
808%in_param = OpFunctionParameter %ptr_int_StorageBuffer
809%out_param = OpFunctionParameter %ptr_int_StorageBuffer
810%1 = OpLabel
811OpCopyMemorySized %out_param %in_param %int4
812OpReturn
813OpFunctionEnd
814)";
815
816  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
817}
818
819TEST_F(UpgradeMemoryModelTest, CopyMemoryTwoScopes) {
820  const std::string text = R"(
821; CHECK-NOT: OpDecorate
822; CHECK-DAG: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5
823; CHECK-DAG: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
824; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|MakePointerVisible|NonPrivatePointer [[workgroup]] [[queuefamily]]
825OpCapability Shader
826OpCapability Linkage
827OpExtension "SPV_KHR_storage_buffer_storage_class"
828OpMemoryModel Logical GLSL450
829OpDecorate %in_var Coherent
830OpDecorate %out_var Coherent
831%void = OpTypeVoid
832%int = OpTypeInt 32 0
833%ptr_int_Workgroup = OpTypePointer Workgroup %int
834%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
835%in_var = OpVariable %ptr_int_StorageBuffer StorageBuffer
836%out_var = OpVariable %ptr_int_Workgroup Workgroup
837%func_ty = OpTypeFunction %void
838%func = OpFunction %void None %func_ty
839%1 = OpLabel
840OpCopyMemory %out_var %in_var
841OpReturn
842OpFunctionEnd
843)";
844
845  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
846}
847
848TEST_F(UpgradeMemoryModelTest, VolatileImageRead) {
849  const std::string text = R"(
850; CHECK-NOT: OpDecorate
851; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile
852; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel
853OpCapability Shader
854OpCapability Linkage
855OpCapability StorageImageReadWithoutFormat
856OpExtension "SPV_KHR_storage_buffer_storage_class"
857OpMemoryModel Logical GLSL450
858OpDecorate %var Volatile
859%void = OpTypeVoid
860%int = OpTypeInt 32 0
861%v2int = OpTypeVector %int 2
862%float = OpTypeFloat 32
863%int0 = OpConstant %int 0
864%v2int_0 = OpConstantComposite %v2int %int0 %int0
865%image = OpTypeImage %float 2D 0 0 0 2 Unknown
866%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
867%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
868%func_ty = OpTypeFunction %void
869%func = OpFunction %void None %func_ty
870%1 = OpLabel
871%ld = OpLoad %image %var
872%rd = OpImageRead %float %ld %v2int_0
873OpReturn
874OpFunctionEnd
875)";
876
877  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
878}
879
880TEST_F(UpgradeMemoryModelTest, CoherentImageRead) {
881  const std::string text = R"(
882; CHECK-NOT: OpDecorate
883; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
884; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
885; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]]
886OpCapability Shader
887OpCapability Linkage
888OpCapability StorageImageReadWithoutFormat
889OpExtension "SPV_KHR_storage_buffer_storage_class"
890OpMemoryModel Logical GLSL450
891OpDecorate %var Coherent
892%void = OpTypeVoid
893%int = OpTypeInt 32 0
894%v2int = OpTypeVector %int 2
895%float = OpTypeFloat 32
896%int0 = OpConstant %int 0
897%v2int_0 = OpConstantComposite %v2int %int0 %int0
898%image = OpTypeImage %float 2D 0 0 0 2 Unknown
899%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
900%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
901%func_ty = OpTypeFunction %void
902%func = OpFunction %void None %func_ty
903%1 = OpLabel
904%ld = OpLoad %image %var
905%rd = OpImageRead %float %ld %v2int_0
906OpReturn
907OpFunctionEnd
908)";
909
910  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
911}
912
913TEST_F(UpgradeMemoryModelTest, CoherentImageReadExtractedFromSampledImage) {
914  const std::string text = R"(
915; CHECK-NOT: OpDecorate
916; CHECK: [[image:%\w+]] = OpTypeImage
917; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
918; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
919; CHECK-NOT: NonPrivatePointer
920; CHECK: OpImageRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]]
921OpCapability Shader
922OpCapability Linkage
923OpCapability StorageImageReadWithoutFormat
924OpExtension "SPV_KHR_storage_buffer_storage_class"
925OpMemoryModel Logical GLSL450
926OpDecorate %var Coherent
927%void = OpTypeVoid
928%int = OpTypeInt 32 0
929%v2int = OpTypeVector %int 2
930%float = OpTypeFloat 32
931%int0 = OpConstant %int 0
932%v2int_0 = OpConstantComposite %v2int %int0 %int0
933%image = OpTypeImage %float 2D 0 0 0 0 Unknown
934%sampled_image = OpTypeSampledImage %image
935%sampler = OpTypeSampler
936%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
937%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler
938%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
939%sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer
940%func_ty = OpTypeFunction %void
941%func = OpFunction %void None %func_ty
942%1 = OpLabel
943%ld = OpLoad %image %var
944%ld_sampler = OpLoad %sampler %sampler_var
945%sample = OpSampledImage %sampled_image %ld %ld_sampler
946%extract = OpImage %image %sample
947%rd = OpImageRead %float %extract %v2int_0
948OpReturn
949OpFunctionEnd
950)";
951
952  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
953}
954
955TEST_F(UpgradeMemoryModelTest, VolatileImageWrite) {
956  const std::string text = R"(
957; CHECK-NOT: OpDecorate
958; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile
959; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel
960OpCapability Shader
961OpCapability Linkage
962OpCapability StorageImageWriteWithoutFormat
963OpExtension "SPV_KHR_storage_buffer_storage_class"
964OpMemoryModel Logical GLSL450
965OpDecorate %param Volatile
966%void = OpTypeVoid
967%int = OpTypeInt 32 0
968%v2int = OpTypeVector %int 2
969%float = OpTypeFloat 32
970%float0 = OpConstant %float 0
971%v2int_null = OpConstantNull %v2int
972%image = OpTypeImage %float 2D 0 0 0 0 Unknown
973%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
974%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer
975%func = OpFunction %void None %func_ty
976%param = OpFunctionParameter %ptr_image_StorageBuffer
977%1 = OpLabel
978%ld = OpLoad %image %param
979OpImageWrite %ld %v2int_null %float0
980OpReturn
981OpFunctionEnd
982)";
983
984  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
985}
986
987TEST_F(UpgradeMemoryModelTest, CoherentImageWrite) {
988  const std::string text = R"(
989; CHECK-NOT: OpDecorate
990; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
991; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer
992; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]]
993OpCapability Shader
994OpCapability Linkage
995OpCapability StorageImageWriteWithoutFormat
996OpExtension "SPV_KHR_storage_buffer_storage_class"
997OpMemoryModel Logical GLSL450
998OpDecorate %param Coherent
999%void = OpTypeVoid
1000%int = OpTypeInt 32 0
1001%v2int = OpTypeVector %int 2
1002%float = OpTypeFloat 32
1003%float0 = OpConstant %float 0
1004%v2int_null = OpConstantNull %v2int
1005%image = OpTypeImage %float 2D 0 0 0 0 Unknown
1006%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
1007%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer
1008%func = OpFunction %void None %func_ty
1009%param = OpFunctionParameter %ptr_image_StorageBuffer
1010%1 = OpLabel
1011%ld = OpLoad %image %param
1012OpImageWrite %ld %v2int_null %float0
1013OpReturn
1014OpFunctionEnd
1015)";
1016
1017  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1018}
1019
1020TEST_F(UpgradeMemoryModelTest, CoherentImageWriteExtractFromSampledImage) {
1021  const std::string text = R"(
1022; CHECK-NOT: OpDecorate
1023; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1024; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer
1025; CHECK-NOT: NonPrivatePointer
1026; CHECK: OpImageWrite {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelAvailable|NonPrivateTexel [[scope]]
1027OpCapability Shader
1028OpCapability Linkage
1029OpCapability StorageImageWriteWithoutFormat
1030OpExtension "SPV_KHR_storage_buffer_storage_class"
1031OpMemoryModel Logical GLSL450
1032OpDecorate %param Coherent
1033%void = OpTypeVoid
1034%int = OpTypeInt 32 0
1035%v2int = OpTypeVector %int 2
1036%float = OpTypeFloat 32
1037%float0 = OpConstant %float 0
1038%v2int_null = OpConstantNull %v2int
1039%image = OpTypeImage %float 2D 0 0 0 0 Unknown
1040%sampled_image = OpTypeSampledImage %image
1041%sampler = OpTypeSampler
1042%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
1043%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler
1044%func_ty = OpTypeFunction %void %ptr_image_StorageBuffer %ptr_sampler_StorageBuffer
1045%func = OpFunction %void None %func_ty
1046%param = OpFunctionParameter %ptr_image_StorageBuffer
1047%sampler_param = OpFunctionParameter %ptr_sampler_StorageBuffer
1048%1 = OpLabel
1049%ld = OpLoad %image %param
1050%ld_sampler = OpLoad %sampler %sampler_param
1051%sample = OpSampledImage %sampled_image %ld %ld_sampler
1052%extract = OpImage %image %sample
1053OpImageWrite %extract %v2int_null %float0
1054OpReturn
1055OpFunctionEnd
1056)";
1057
1058  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1059}
1060
1061TEST_F(UpgradeMemoryModelTest, VolatileImageSparseRead) {
1062  const std::string text = R"(
1063; CHECK-NOT: OpDecorate
1064; CHECK: OpLoad {{%\w+}} {{%\w+}} Volatile
1065; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} VolatileTexel
1066OpCapability Shader
1067OpCapability Linkage
1068OpCapability StorageImageReadWithoutFormat
1069OpCapability SparseResidency
1070OpExtension "SPV_KHR_storage_buffer_storage_class"
1071OpMemoryModel Logical GLSL450
1072OpDecorate %var Volatile
1073%void = OpTypeVoid
1074%int = OpTypeInt 32 0
1075%v2int = OpTypeVector %int 2
1076%float = OpTypeFloat 32
1077%int0 = OpConstant %int 0
1078%v2int_0 = OpConstantComposite %v2int %int0 %int0
1079%image = OpTypeImage %float 2D 0 0 0 2 Unknown
1080%struct = OpTypeStruct %int %float
1081%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
1082%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
1083%func_ty = OpTypeFunction %void
1084%func = OpFunction %void None %func_ty
1085%1 = OpLabel
1086%ld = OpLoad %image %var
1087%rd = OpImageSparseRead %struct %ld %v2int_0
1088OpReturn
1089OpFunctionEnd
1090)";
1091
1092  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1093}
1094
1095TEST_F(UpgradeMemoryModelTest, CoherentImageSparseRead) {
1096  const std::string text = R"(
1097; CHECK-NOT: OpDecorate
1098; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1099; CHECK: OpLoad {{%\w+}} {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
1100; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]]
1101OpCapability Shader
1102OpCapability Linkage
1103OpCapability StorageImageReadWithoutFormat
1104OpCapability SparseResidency
1105OpExtension "SPV_KHR_storage_buffer_storage_class"
1106OpMemoryModel Logical GLSL450
1107OpDecorate %var Coherent
1108%void = OpTypeVoid
1109%int = OpTypeInt 32 0
1110%v2int = OpTypeVector %int 2
1111%float = OpTypeFloat 32
1112%int0 = OpConstant %int 0
1113%v2int_0 = OpConstantComposite %v2int %int0 %int0
1114%image = OpTypeImage %float 2D 0 0 0 2 Unknown
1115%struct = OpTypeStruct %int %float
1116%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
1117%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
1118%func_ty = OpTypeFunction %void
1119%func = OpFunction %void None %func_ty
1120%1 = OpLabel
1121%ld = OpLoad %image %var
1122%rd = OpImageSparseRead %struct %ld %v2int_0
1123OpReturn
1124OpFunctionEnd
1125)";
1126
1127  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1128}
1129
1130TEST_F(UpgradeMemoryModelTest,
1131       CoherentImageSparseReadExtractedFromSampledImage) {
1132  const std::string text = R"(
1133; CHECK-NOT: OpDecorate
1134; CHECK: [[image:%\w+]] = OpTypeImage
1135; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1136; CHECK: OpLoad [[image]] {{%\w+}} MakePointerVisible|NonPrivatePointer [[scope]]
1137; CHECK-NOT: NonPrivatePointer
1138; CHECK: OpImageSparseRead {{%\w+}} {{%\w+}} {{%\w+}} MakeTexelVisible|NonPrivateTexel [[scope]]
1139OpCapability Shader
1140OpCapability Linkage
1141OpCapability StorageImageReadWithoutFormat
1142OpCapability SparseResidency
1143OpExtension "SPV_KHR_storage_buffer_storage_class"
1144OpMemoryModel Logical GLSL450
1145OpDecorate %var Coherent
1146%void = OpTypeVoid
1147%int = OpTypeInt 32 0
1148%v2int = OpTypeVector %int 2
1149%float = OpTypeFloat 32
1150%int0 = OpConstant %int 0
1151%v2int_0 = OpConstantComposite %v2int %int0 %int0
1152%image = OpTypeImage %float 2D 0 0 0 0 Unknown
1153%struct = OpTypeStruct %int %float
1154%sampled_image = OpTypeSampledImage %image
1155%sampler = OpTypeSampler
1156%ptr_image_StorageBuffer = OpTypePointer StorageBuffer %image
1157%ptr_sampler_StorageBuffer = OpTypePointer StorageBuffer %sampler
1158%var = OpVariable %ptr_image_StorageBuffer StorageBuffer
1159%sampler_var = OpVariable %ptr_sampler_StorageBuffer StorageBuffer
1160%func_ty = OpTypeFunction %void
1161%func = OpFunction %void None %func_ty
1162%1 = OpLabel
1163%ld = OpLoad %image %var
1164%ld_sampler = OpLoad %sampler %sampler_var
1165%sample = OpSampledImage %sampled_image %ld %ld_sampler
1166%extract = OpImage %image %sample
1167%rd = OpImageSparseRead %struct %extract %v2int_0
1168OpReturn
1169OpFunctionEnd
1170)";
1171
1172  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1173}
1174
1175TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierNoChange) {
1176  const std::string text = R"(
1177; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0
1178; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1179; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[none]]
1180OpCapability Tessellation
1181OpMemoryModel Logical GLSL450
1182OpEntryPoint TessellationControl %func "func"
1183%void = OpTypeVoid
1184%int = OpTypeInt 32 0
1185%none = OpConstant %int 0
1186%workgroup = OpConstant %int 2
1187%func_ty = OpTypeFunction %void
1188%func = OpFunction %void None %func_ty
1189%1 = OpLabel
1190OpControlBarrier %workgroup %workgroup %none
1191OpReturn
1192OpFunctionEnd
1193)";
1194
1195  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1196}
1197
1198TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutput) {
1199  const std::string text = R"(
1200; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1201; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096
1202; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]]
1203OpCapability Tessellation
1204OpMemoryModel Logical GLSL450
1205OpEntryPoint TessellationControl %func "func" %var
1206%void = OpTypeVoid
1207%int = OpTypeInt 32 0
1208%none = OpConstant %int 0
1209%workgroup = OpConstant %int 2
1210%ptr_int_Output = OpTypePointer Output %int
1211%var = OpVariable %ptr_int_Output Output
1212%func_ty = OpTypeFunction %void
1213%func = OpFunction %void None %func_ty
1214%1 = OpLabel
1215%ld = OpLoad %int %var
1216OpControlBarrier %workgroup %workgroup %none
1217OpStore %var %ld
1218OpReturn
1219OpFunctionEnd
1220)";
1221
1222  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1223}
1224
1225TEST_F(UpgradeMemoryModelTest, TessellationMemoryBarrierNoChange) {
1226  const std::string text = R"(
1227; CHECK: [[none:%\w+]] = OpConstant {{%\w+}} 0
1228; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1229; CHECK: OpMemoryBarrier [[workgroup]] [[none]]
1230OpCapability Tessellation
1231OpMemoryModel Logical GLSL450
1232OpEntryPoint TessellationControl %func "func" %var
1233%void = OpTypeVoid
1234%int = OpTypeInt 32 0
1235%none = OpConstant %int 0
1236%workgroup = OpConstant %int 2
1237%ptr_int_Output = OpTypePointer Output %int
1238%var = OpVariable %ptr_int_Output Output
1239%func_ty = OpTypeFunction %void
1240%func = OpFunction %void None %func_ty
1241%1 = OpLabel
1242%ld = OpLoad %int %var
1243OpMemoryBarrier %workgroup %none
1244OpStore %var %ld
1245OpReturn
1246OpFunctionEnd
1247)";
1248
1249  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1250}
1251
1252TEST_F(UpgradeMemoryModelTest, TessellationControlBarrierAddOutputSubFunction) {
1253  const std::string text = R"(
1254; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1255; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096
1256; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]]
1257OpCapability Tessellation
1258OpMemoryModel Logical GLSL450
1259OpEntryPoint TessellationControl %func "func" %var
1260%void = OpTypeVoid
1261%int = OpTypeInt 32 0
1262%none = OpConstant %int 0
1263%workgroup = OpConstant %int 2
1264%ptr_int_Output = OpTypePointer Output %int
1265%var = OpVariable %ptr_int_Output Output
1266%func_ty = OpTypeFunction %void
1267%func = OpFunction %void None %func_ty
1268%1 = OpLabel
1269%call = OpFunctionCall %void %sub_func
1270OpReturn
1271OpFunctionEnd
1272%sub_func = OpFunction %void None %func_ty
1273%2 = OpLabel
1274%ld = OpLoad %int %var
1275OpControlBarrier %workgroup %workgroup %none
1276OpStore %var %ld
1277OpReturn
1278OpFunctionEnd
1279)";
1280
1281  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1282}
1283
1284TEST_F(UpgradeMemoryModelTest,
1285       TessellationControlBarrierAddOutputDifferentFunctions) {
1286  const std::string text = R"(
1287; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1288; CHECK: [[output:%\w+]] = OpConstant {{%\w+}} 4096
1289; CHECK: OpControlBarrier [[workgroup]] [[workgroup]] [[output]]
1290OpCapability Tessellation
1291OpMemoryModel Logical GLSL450
1292OpEntryPoint TessellationControl %func "func" %var
1293%void = OpTypeVoid
1294%int = OpTypeInt 32 0
1295%none = OpConstant %int 0
1296%workgroup = OpConstant %int 2
1297%ptr_int_Output = OpTypePointer Output %int
1298%var = OpVariable %ptr_int_Output Output
1299%func_ty = OpTypeFunction %void
1300%ld_func_ty = OpTypeFunction %int
1301%st_func_ty = OpTypeFunction %void %int
1302%func = OpFunction %void None %func_ty
1303%1 = OpLabel
1304%call_ld = OpFunctionCall %int %ld_func
1305%call_barrier = OpFunctionCall %void %barrier_func
1306%call_st = OpFunctionCall %void %st_func %call_ld
1307OpReturn
1308OpFunctionEnd
1309%ld_func = OpFunction %int None %ld_func_ty
1310%2 = OpLabel
1311%ld = OpLoad %int %var
1312OpReturnValue %ld
1313OpFunctionEnd
1314%barrier_func = OpFunction %void None %func_ty
1315%3 = OpLabel
1316OpControlBarrier %workgroup %workgroup %none
1317OpReturn
1318OpFunctionEnd
1319%st_func = OpFunction %void None %st_func_ty
1320%param = OpFunctionParameter %int
1321%4 = OpLabel
1322OpStore %var %param
1323OpReturn
1324OpFunctionEnd
1325)";
1326
1327  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1328}
1329
1330TEST_F(UpgradeMemoryModelTest, ChangeControlBarrierMemoryScope) {
1331  std::string text = R"(
1332; CHECK: [[workgroup:%\w+]] = OpConstant {{%\w+}} 2
1333; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5
1334; CHECK: OpControlBarrier [[workgroup]] [[queuefamily]]
1335OpCapability Shader
1336OpMemoryModel Logical GLSL450
1337OpEntryPoint GLCompute %func "func"
1338%void = OpTypeVoid
1339%int = OpTypeInt 32 0
1340%none = OpConstant %int 0
1341%device = OpConstant %int 1
1342%workgroup = OpConstant %int 2
1343%func_ty = OpTypeFunction %void
1344%func = OpFunction %void None %func_ty
1345%1 = OpLabel
1346OpControlBarrier %workgroup %device %none
1347OpReturn
1348OpFunctionEnd
1349)";
1350
1351  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1352}
1353
1354TEST_F(UpgradeMemoryModelTest, ChangeMemoryBarrierMemoryScope) {
1355  std::string text = R"(
1356; CHECK: [[queuefamily:%\w+]] = OpConstant {{%\w+}} 5
1357; CHECK: OpMemoryBarrier [[queuefamily]]
1358OpCapability Shader
1359OpMemoryModel Logical GLSL450
1360OpEntryPoint GLCompute %func "func"
1361%void = OpTypeVoid
1362%int = OpTypeInt 32 0
1363%none = OpConstant %int 0
1364%device = OpConstant %int 1
1365%func_ty = OpTypeFunction %void
1366%func = OpFunction %void None %func_ty
1367%1 = OpLabel
1368OpMemoryBarrier %device %none
1369OpReturn
1370OpFunctionEnd
1371)";
1372
1373  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1374}
1375
1376TEST_F(UpgradeMemoryModelTest, ChangeAtomicMemoryScope) {
1377  std::string text = R"(
1378; CHECK: [[int:%\w+]] = OpTypeInt
1379; CHECK: [[var:%\w+]] = OpVariable
1380; CHECK: [[qf:%\w+]] = OpConstant [[int]] 5
1381; CHECK: OpAtomicLoad [[int]] [[var]] [[qf]]
1382; CHECK: OpAtomicStore [[var]] [[qf]]
1383; CHECK: OpAtomicExchange [[int]] [[var]] [[qf]]
1384; CHECK: OpAtomicCompareExchange [[int]] [[var]] [[qf]]
1385; CHECK: OpAtomicIIncrement [[int]] [[var]] [[qf]]
1386; CHECK: OpAtomicIDecrement [[int]] [[var]] [[qf]]
1387; CHECK: OpAtomicIAdd [[int]] [[var]] [[qf]]
1388; CHECK: OpAtomicISub [[int]] [[var]] [[qf]]
1389; CHECK: OpAtomicSMin [[int]] [[var]] [[qf]]
1390; CHECK: OpAtomicSMax [[int]] [[var]] [[qf]]
1391; CHECK: OpAtomicUMin [[int]] [[var]] [[qf]]
1392; CHECK: OpAtomicUMax [[int]] [[var]] [[qf]]
1393; CHECK: OpAtomicAnd [[int]] [[var]] [[qf]]
1394; CHECK: OpAtomicOr [[int]] [[var]] [[qf]]
1395; CHECK: OpAtomicXor [[int]] [[var]] [[qf]]
1396OpCapability Shader
1397OpExtension "SPV_KHR_storage_buffer_storage_class"
1398OpMemoryModel Logical GLSL450
1399OpEntryPoint GLCompute %func "func"
1400%void = OpTypeVoid
1401%int = OpTypeInt 32 0
1402%none = OpConstant %int 0
1403%device = OpConstant %int 1
1404%func_ty = OpTypeFunction %void
1405%ptr_int_StorageBuffer = OpTypePointer StorageBuffer %int
1406%var = OpVariable %ptr_int_StorageBuffer StorageBuffer
1407%func = OpFunction %void None %func_ty
1408%1 = OpLabel
1409%ld = OpAtomicLoad %int %var %device %none
1410OpAtomicStore %var %device %none %ld
1411%ex = OpAtomicExchange %int %var %device %none %ld
1412%cmp_ex = OpAtomicCompareExchange %int %var %device %none %none %ld %ld
1413%inc = OpAtomicIIncrement %int %var %device %none
1414%dec = OpAtomicIDecrement %int %var %device %none
1415%add = OpAtomicIAdd %int %var %device %none %ld
1416%sub = OpAtomicISub %int %var %device %none %ld
1417%smin = OpAtomicSMin %int %var %device %none %ld
1418%smax = OpAtomicSMax %int %var %device %none %ld
1419%umin = OpAtomicUMin %int %var %device %none %ld
1420%umax = OpAtomicUMax %int %var %device %none %ld
1421%and = OpAtomicAnd %int %var %device %none %ld
1422%or = OpAtomicOr %int %var %device %none %ld
1423%xor = OpAtomicXor %int %var %device %none %ld
1424OpReturn
1425OpFunctionEnd
1426)";
1427
1428  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1429}
1430
1431TEST_F(UpgradeMemoryModelTest, UpgradeModfNoFlags) {
1432  const std::string text = R"(
1433; CHECK: [[float:%\w+]] = OpTypeFloat 32
1434; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1435; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]]
1436; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1437; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]]
1438; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]]
1439; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1440; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1
1441; CHECK: OpStore [[var]] [[ex1]]
1442; CHECK-NOT: NonPrivatePointer
1443; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1444OpCapability Shader
1445OpMemoryModel Logical GLSL450
1446%import = OpExtInstImport "GLSL.std.450"
1447OpEntryPoint GLCompute %func "func"
1448%void = OpTypeVoid
1449%float = OpTypeFloat 32
1450%float_0 = OpConstant %float 0
1451%ptr_ssbo_float = OpTypePointer StorageBuffer %float
1452%ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer
1453%func_ty = OpTypeFunction %void
1454%func = OpFunction %void None %func_ty
1455%1 = OpLabel
1456%2 = OpExtInst %float %import Modf %float_0 %ssbo_var
1457%3 = OpFAdd %float %float_0 %2
1458OpReturn
1459OpFunctionEnd
1460)";
1461
1462  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1463}
1464
1465TEST_F(UpgradeMemoryModelTest, UpgradeModfWorkgroupCoherent) {
1466  const std::string text = R"(
1467; CHECK: [[float:%\w+]] = OpTypeFloat 32
1468; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1469; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[float]]
1470; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup
1471; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]]
1472; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2
1473; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]]
1474; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1475; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1
1476; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]]
1477; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1478OpCapability Shader
1479OpMemoryModel Logical GLSL450
1480%import = OpExtInstImport "GLSL.std.450"
1481OpEntryPoint GLCompute %func "func"
1482OpDecorate %wg_var Coherent
1483%void = OpTypeVoid
1484%float = OpTypeFloat 32
1485%float_0 = OpConstant %float 0
1486%ptr_wg_float = OpTypePointer Workgroup %float
1487%wg_var = OpVariable %ptr_wg_float Workgroup
1488%func_ty = OpTypeFunction %void
1489%func = OpFunction %void None %func_ty
1490%1 = OpLabel
1491%2 = OpExtInst %float %import Modf %float_0 %wg_var
1492%3 = OpFAdd %float %float_0 %2
1493OpReturn
1494OpFunctionEnd
1495)";
1496
1497  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1498}
1499
1500TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOCoherent) {
1501  const std::string text = R"(
1502; CHECK: [[float:%\w+]] = OpTypeFloat 32
1503; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1504; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]]
1505; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1506; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]]
1507; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5
1508; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]]
1509; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1510; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1
1511; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]]
1512; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1513OpCapability Shader
1514OpMemoryModel Logical GLSL450
1515%import = OpExtInstImport "GLSL.std.450"
1516OpEntryPoint GLCompute %func "func"
1517OpDecorate %ssbo_var Coherent
1518%void = OpTypeVoid
1519%float = OpTypeFloat 32
1520%float_0 = OpConstant %float 0
1521%ptr_ssbo_float = OpTypePointer StorageBuffer %float
1522%ssbo_var = OpVariable %ptr_ssbo_float StorageBuffer
1523%func_ty = OpTypeFunction %void
1524%func = OpFunction %void None %func_ty
1525%1 = OpLabel
1526%2 = OpExtInst %float %import Modf %float_0 %ssbo_var
1527%3 = OpFAdd %float %float_0 %2
1528OpReturn
1529OpFunctionEnd
1530)";
1531
1532  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1533}
1534
1535TEST_F(UpgradeMemoryModelTest, UpgradeModfSSBOVolatile) {
1536  const std::string text = R"(
1537; CHECK: [[float:%\w+]] = OpTypeFloat 32
1538; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1539; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[float]]
1540; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1541; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[float]]
1542; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} ModfStruct [[float_0]]
1543; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1544; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 1
1545; CHECK: OpStore [[var]] [[ex1]] Volatile
1546; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1547OpCapability Shader
1548OpMemoryModel Logical GLSL450
1549%import = OpExtInstImport "GLSL.std.450"
1550OpEntryPoint GLCompute %func "func"
1551OpDecorate %wg_var Volatile
1552%void = OpTypeVoid
1553%float = OpTypeFloat 32
1554%float_0 = OpConstant %float 0
1555%ptr_ssbo_float = OpTypePointer StorageBuffer %float
1556%wg_var = OpVariable %ptr_ssbo_float StorageBuffer
1557%func_ty = OpTypeFunction %void
1558%func = OpFunction %void None %func_ty
1559%1 = OpLabel
1560%2 = OpExtInst %float %import Modf %float_0 %wg_var
1561%3 = OpFAdd %float %float_0 %2
1562OpReturn
1563OpFunctionEnd
1564)";
1565
1566  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1567}
1568
1569TEST_F(UpgradeMemoryModelTest, UpgradeFrexpNoFlags) {
1570  const std::string text = R"(
1571; CHECK: [[float:%\w+]] = OpTypeFloat 32
1572; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1573; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1574; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]]
1575; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1576; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]]
1577; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]]
1578; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1579; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1
1580; CHECK: OpStore [[var]] [[ex1]]
1581; CHECK-NOT: NonPrivatePointer
1582; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1583OpCapability Shader
1584OpMemoryModel Logical GLSL450
1585%import = OpExtInstImport "GLSL.std.450"
1586OpEntryPoint GLCompute %func "func"
1587%void = OpTypeVoid
1588%float = OpTypeFloat 32
1589%float_0 = OpConstant %float 0
1590%int = OpTypeInt 32 0
1591%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1592%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
1593%func_ty = OpTypeFunction %void
1594%func = OpFunction %void None %func_ty
1595%1 = OpLabel
1596%2 = OpExtInst %float %import Frexp %float_0 %ssbo_var
1597%3 = OpFAdd %float %float_0 %2
1598OpReturn
1599OpFunctionEnd
1600)";
1601
1602  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1603}
1604
1605TEST_F(UpgradeMemoryModelTest, UpgradeFrexpWorkgroupCoherent) {
1606  const std::string text = R"(
1607; CHECK: [[float:%\w+]] = OpTypeFloat 32
1608; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1609; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1610; CHECK: [[ptr:%\w+]] = OpTypePointer Workgroup [[int]]
1611; CHECK: [[var:%\w+]] = OpVariable [[ptr]] Workgroup
1612; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]]
1613; CHECK: [[wg_scope:%\w+]] = OpConstant {{%\w+}} 2
1614; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]]
1615; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1616; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1
1617; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[wg_scope]]
1618; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1619OpCapability Shader
1620OpMemoryModel Logical GLSL450
1621%import = OpExtInstImport "GLSL.std.450"
1622OpEntryPoint GLCompute %func "func"
1623OpDecorate %wg_var Coherent
1624%void = OpTypeVoid
1625%float = OpTypeFloat 32
1626%float_0 = OpConstant %float 0
1627%int = OpTypeInt 32 0
1628%ptr_wg_int = OpTypePointer Workgroup %int
1629%wg_var = OpVariable %ptr_wg_int Workgroup
1630%func_ty = OpTypeFunction %void
1631%func = OpFunction %void None %func_ty
1632%1 = OpLabel
1633%2 = OpExtInst %float %import Frexp %float_0 %wg_var
1634%3 = OpFAdd %float %float_0 %2
1635OpReturn
1636OpFunctionEnd
1637)";
1638
1639  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1640}
1641
1642TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOCoherent) {
1643  const std::string text = R"(
1644; CHECK: [[float:%\w+]] = OpTypeFloat 32
1645; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1646; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1647; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]]
1648; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1649; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]]
1650; CHECK: [[qf_scope:%\w+]] = OpConstant {{%\w+}} 5
1651; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]]
1652; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1653; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1
1654; CHECK: OpStore [[var]] [[ex1]] MakePointerAvailable|NonPrivatePointer [[qf_scope]]
1655; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1656OpCapability Shader
1657OpMemoryModel Logical GLSL450
1658%import = OpExtInstImport "GLSL.std.450"
1659OpEntryPoint GLCompute %func "func"
1660OpDecorate %ssbo_var Coherent
1661%void = OpTypeVoid
1662%float = OpTypeFloat 32
1663%float_0 = OpConstant %float 0
1664%int = OpTypeInt 32 0
1665%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1666%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
1667%func_ty = OpTypeFunction %void
1668%func = OpFunction %void None %func_ty
1669%1 = OpLabel
1670%2 = OpExtInst %float %import Frexp %float_0 %ssbo_var
1671%3 = OpFAdd %float %float_0 %2
1672OpReturn
1673OpFunctionEnd
1674)";
1675
1676  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1677}
1678
1679TEST_F(UpgradeMemoryModelTest, UpgradeFrexpSSBOVolatile) {
1680  const std::string text = R"(
1681; CHECK: [[float:%\w+]] = OpTypeFloat 32
1682; CHECK: [[float_0:%\w+]] = OpConstant [[float]] 0
1683; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1684; CHECK: [[ptr:%\w+]] = OpTypePointer StorageBuffer [[int]]
1685; CHECK: [[var:%\w+]] = OpVariable [[ptr]] StorageBuffer
1686; CHECK: [[struct:%\w+]] = OpTypeStruct [[float]] [[int]]
1687; CHECK: [[modfstruct:%\w+]] = OpExtInst [[struct]] {{%\w+}} FrexpStruct [[float_0]]
1688; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[float]] [[modfstruct]] 0
1689; CHECK: [[ex1:%\w+]] = OpCompositeExtract [[int]] [[modfstruct]] 1
1690; CHECK: OpStore [[var]] [[ex1]] Volatile
1691; CHECK: OpFAdd [[float]] [[float_0]] [[ex0]]
1692OpCapability Shader
1693OpMemoryModel Logical GLSL450
1694%import = OpExtInstImport "GLSL.std.450"
1695OpEntryPoint GLCompute %func "func"
1696OpDecorate %wg_var Volatile
1697%void = OpTypeVoid
1698%float = OpTypeFloat 32
1699%float_0 = OpConstant %float 0
1700%int = OpTypeInt 32 0
1701%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1702%wg_var = OpVariable %ptr_ssbo_int StorageBuffer
1703%func_ty = OpTypeFunction %void
1704%func = OpFunction %void None %func_ty
1705%1 = OpLabel
1706%2 = OpExtInst %float %import Frexp %float_0 %wg_var
1707%3 = OpFAdd %float %float_0 %2
1708OpReturn
1709OpFunctionEnd
1710)";
1711
1712  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1713}
1714
1715TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryAddOperands) {
1716  const std::string text = R"(
1717; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None None
1718OpCapability Shader
1719OpMemoryModel Logical GLSL450
1720OpEntryPoint GLCompute %func "func" %src %dst
1721%void = OpTypeVoid
1722%int = OpTypeInt 32 0
1723%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1724%src = OpVariable %ptr_ssbo_int StorageBuffer
1725%dst = OpVariable %ptr_ssbo_int StorageBuffer
1726%void_fn = OpTypeFunction %void
1727%func = OpFunction %void None %void_fn
1728%entry = OpLabel
1729OpCopyMemory %dst %src
1730OpReturn
1731OpFunctionEnd
1732)";
1733
1734  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1735  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1736}
1737
1738TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperand) {
1739  const std::string text = R"(
1740; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Nontemporal Nontemporal
1741OpCapability Shader
1742OpMemoryModel Logical GLSL450
1743OpEntryPoint GLCompute %func "func" %src %dst
1744%void = OpTypeVoid
1745%int = OpTypeInt 32 0
1746%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1747%src = OpVariable %ptr_ssbo_int StorageBuffer
1748%dst = OpVariable %ptr_ssbo_int StorageBuffer
1749%void_fn = OpTypeFunction %void
1750%func = OpFunction %void None %void_fn
1751%entry = OpLabel
1752OpCopyMemory %dst %src Nontemporal
1753OpReturn
1754OpFunctionEnd
1755)";
1756
1757  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1758  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1759}
1760
1761TEST_F(UpgradeMemoryModelTest, SPV14NormalizeCopyMemoryDuplicateOperands) {
1762  const std::string text = R"(
1763; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned 4
1764OpCapability Shader
1765OpMemoryModel Logical GLSL450
1766OpEntryPoint GLCompute %func "func" %src %dst
1767%void = OpTypeVoid
1768%int = OpTypeInt 32 0
1769%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1770%src = OpVariable %ptr_ssbo_int StorageBuffer
1771%dst = OpVariable %ptr_ssbo_int StorageBuffer
1772%void_fn = OpTypeFunction %void
1773%func = OpFunction %void None %void_fn
1774%entry = OpLabel
1775OpCopyMemory %dst %src Aligned 4
1776OpReturn
1777OpFunctionEnd
1778)";
1779
1780  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1781  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1782}
1783
1784TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherent) {
1785  const std::string text = R"(
1786; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1787; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None
1788OpCapability Shader
1789OpMemoryModel Logical GLSL450
1790OpEntryPoint GLCompute %func "func" %src %dst
1791OpDecorate %dst Coherent
1792%void = OpTypeVoid
1793%int = OpTypeInt 32 0
1794%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1795%src = OpVariable %ptr_ssbo_int StorageBuffer
1796%dst = OpVariable %ptr_ssbo_int StorageBuffer
1797%void_fn = OpTypeFunction %void
1798%func = OpFunction %void None %void_fn
1799%entry = OpLabel
1800OpCopyMemory %dst %src
1801OpReturn
1802OpFunctionEnd
1803)";
1804
1805  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1806  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1807}
1808
1809TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentPreviousArgs) {
1810  const std::string text = R"(
1811; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1812; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 4
1813OpCapability Shader
1814OpMemoryModel Logical GLSL450
1815OpEntryPoint GLCompute %func "func" %src %dst
1816OpDecorate %dst Coherent
1817%void = OpTypeVoid
1818%int = OpTypeInt 32 0
1819%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1820%src = OpVariable %ptr_ssbo_int StorageBuffer
1821%dst = OpVariable %ptr_ssbo_int StorageBuffer
1822%void_fn = OpTypeFunction %void
1823%func = OpFunction %void None %void_fn
1824%entry = OpLabel
1825OpCopyMemory %dst %src Aligned 4
1826OpReturn
1827OpFunctionEnd
1828)";
1829
1830  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1831  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1832}
1833
1834TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherent) {
1835  const std::string text = R"(
1836; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1837; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} None MakePointerVisible|NonPrivatePointer [[scope]]
1838OpCapability Shader
1839OpMemoryModel Logical GLSL450
1840OpEntryPoint GLCompute %func "func" %src %dst
1841OpDecorate %src Coherent
1842%void = OpTypeVoid
1843%int = OpTypeInt 32 0
1844%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1845%src = OpVariable %ptr_ssbo_int StorageBuffer
1846%dst = OpVariable %ptr_ssbo_int StorageBuffer
1847%void_fn = OpTypeFunction %void
1848%func = OpFunction %void None %void_fn
1849%entry = OpLabel
1850OpCopyMemory %dst %src
1851OpReturn
1852OpFunctionEnd
1853)";
1854
1855  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1856  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1857}
1858
1859TEST_F(UpgradeMemoryModelTest, SPV14CopyMemorySrcCoherentPreviousArgs) {
1860  const std::string text = R"(
1861; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1862; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned 4 Aligned|MakePointerVisible|NonPrivatePointer 4 [[scope]]
1863OpCapability Shader
1864OpMemoryModel Logical GLSL450
1865OpEntryPoint GLCompute %func "func" %src %dst
1866OpDecorate %src Coherent
1867%void = OpTypeVoid
1868%int = OpTypeInt 32 0
1869%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1870%src = OpVariable %ptr_ssbo_int StorageBuffer
1871%dst = OpVariable %ptr_ssbo_int StorageBuffer
1872%void_fn = OpTypeFunction %void
1873%func = OpFunction %void None %void_fn
1874%entry = OpLabel
1875OpCopyMemory %dst %src Aligned 4
1876OpReturn
1877OpFunctionEnd
1878)";
1879
1880  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1881  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1882}
1883
1884TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherent) {
1885  const std::string text = R"(
1886; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5
1887; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2
1888; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[wg]] MakePointerVisible|NonPrivatePointer [[queue]]
1889OpCapability Shader
1890OpMemoryModel Logical GLSL450
1891OpEntryPoint GLCompute %func "func" %src %dst
1892OpDecorate %src Coherent
1893%void = OpTypeVoid
1894%int = OpTypeInt 32 0
1895%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1896%ptr_wg_int = OpTypePointer Workgroup %int
1897%src = OpVariable %ptr_ssbo_int StorageBuffer
1898%dst = OpVariable %ptr_wg_int Workgroup
1899%void_fn = OpTypeFunction %void
1900%func = OpFunction %void None %void_fn
1901%entry = OpLabel
1902OpCopyMemory %dst %src
1903OpReturn
1904OpFunctionEnd
1905)";
1906
1907  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1908  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1909}
1910
1911TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothCoherentPreviousArgs) {
1912  const std::string text = R"(
1913; CHECK-DAG: [[queue:%\w+]] = OpConstant {{%\w+}} 5
1914; CHECK-DAG: [[wg:%\w+]] = OpConstant {{%\w+}} 2
1915; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[queue]] Aligned|MakePointerVisible|NonPrivatePointer 4 [[wg]]
1916OpCapability Shader
1917OpMemoryModel Logical GLSL450
1918OpEntryPoint GLCompute %func "func" %src %dst
1919OpDecorate %dst Coherent
1920%void = OpTypeVoid
1921%int = OpTypeInt 32 0
1922%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1923%ptr_wg_int = OpTypePointer Workgroup %int
1924%src = OpVariable %ptr_wg_int Workgroup
1925%dst = OpVariable %ptr_ssbo_int StorageBuffer
1926%void_fn = OpTypeFunction %void
1927%func = OpFunction %void None %void_fn
1928%entry = OpLabel
1929OpCopyMemory %dst %src Aligned 4
1930OpReturn
1931OpFunctionEnd
1932)";
1933
1934  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1935  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1936}
1937
1938TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatile) {
1939  const std::string text = R"(
1940; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile Volatile
1941OpCapability Shader
1942OpMemoryModel Logical GLSL450
1943OpEntryPoint GLCompute %func "func" %src %dst
1944OpDecorate %src Volatile
1945OpDecorate %dst Volatile
1946%void = OpTypeVoid
1947%int = OpTypeInt 32 0
1948%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1949%src = OpVariable %ptr_ssbo_int StorageBuffer
1950%dst = OpVariable %ptr_ssbo_int StorageBuffer
1951%void_fn = OpTypeFunction %void
1952%func = OpFunction %void None %void_fn
1953%entry = OpLabel
1954OpCopyMemory %dst %src
1955OpReturn
1956OpFunctionEnd
1957)";
1958
1959  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1960  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1961}
1962
1963TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryBothVolatilePreviousArgs) {
1964  const std::string text = R"(
1965; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Volatile|Aligned 4 Volatile|Aligned 4
1966OpCapability Shader
1967OpMemoryModel Logical GLSL450
1968OpEntryPoint GLCompute %func "func" %src %dst
1969OpDecorate %src Volatile
1970OpDecorate %dst Volatile
1971%void = OpTypeVoid
1972%int = OpTypeInt 32 0
1973%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1974%src = OpVariable %ptr_ssbo_int StorageBuffer
1975%dst = OpVariable %ptr_ssbo_int StorageBuffer
1976%void_fn = OpTypeFunction %void
1977%func = OpFunction %void None %void_fn
1978%entry = OpLabel
1979OpCopyMemory %dst %src Aligned 4
1980OpReturn
1981OpFunctionEnd
1982)";
1983
1984  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
1985  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
1986}
1987
1988TEST_F(UpgradeMemoryModelTest, SPV14CopyMemoryDstCoherentTwoOperands) {
1989  const std::string text = R"(
1990; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
1991; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} MakePointerAvailable|NonPrivatePointer [[scope]] None
1992OpCapability Shader
1993OpMemoryModel Logical GLSL450
1994OpEntryPoint GLCompute %func "func" %src %dst
1995OpDecorate %dst Coherent
1996%void = OpTypeVoid
1997%int = OpTypeInt 32 0
1998%ptr_ssbo_int = OpTypePointer StorageBuffer %int
1999%src = OpVariable %ptr_ssbo_int StorageBuffer
2000%dst = OpVariable %ptr_ssbo_int StorageBuffer
2001%void_fn = OpTypeFunction %void
2002%func = OpFunction %void None %void_fn
2003%entry = OpLabel
2004OpCopyMemory %dst %src None None
2005OpReturn
2006OpFunctionEnd
2007)";
2008
2009  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
2010  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2011}
2012
2013TEST_F(UpgradeMemoryModelTest,
2014       SPV14CopyMemoryDstCoherentPreviousArgsTwoOperands) {
2015  const std::string text = R"(
2016; CHECK: [[scope:%\w+]] = OpConstant {{%\w+}} 5
2017; CHECK: OpCopyMemory {{%\w+}} {{%\w+}} Aligned|MakePointerAvailable|NonPrivatePointer 4 [[scope]] Aligned 8
2018OpCapability Shader
2019OpMemoryModel Logical GLSL450
2020OpEntryPoint GLCompute %func "func" %src %dst
2021OpDecorate %dst Coherent
2022%void = OpTypeVoid
2023%int = OpTypeInt 32 0
2024%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2025%src = OpVariable %ptr_ssbo_int StorageBuffer
2026%dst = OpVariable %ptr_ssbo_int StorageBuffer
2027%void_fn = OpTypeFunction %void
2028%func = OpFunction %void None %void_fn
2029%entry = OpLabel
2030OpCopyMemory %dst %src Aligned 4 Aligned 8
2031OpReturn
2032OpFunctionEnd
2033)";
2034
2035  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
2036  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2037}
2038
2039TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoad) {
2040  const std::string text = R"(
2041; CHECK-NOT: OpDecorate {{.*}} Volatile
2042; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768
2043; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]]
2044OpCapability Shader
2045OpCapability Linkage
2046OpMemoryModel Logical GLSL450
2047OpDecorate %ssbo_var Volatile
2048%void = OpTypeVoid
2049%int = OpTypeInt 32 0
2050%device = OpConstant %int 1
2051%relaxed = OpConstant %int 0
2052%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2053%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2054%void_fn = OpTypeFunction %void
2055%func = OpFunction %void None %void_fn
2056%entry = OpLabel
2057%ld = OpAtomicLoad %int %ssbo_var %device %relaxed
2058OpReturn
2059OpFunctionEnd
2060)";
2061
2062  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2063}
2064
2065TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadPreviousFlags) {
2066  const std::string text = R"(
2067; CHECK-NOT: OpDecorate {{.*}} Volatile
2068; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834
2069; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]]
2070OpCapability Shader
2071OpCapability Linkage
2072OpMemoryModel Logical GLSL450
2073OpDecorate %ssbo_var Volatile
2074%void = OpTypeVoid
2075%int = OpTypeInt 32 0
2076%device = OpConstant %int 1
2077%acquire_ssbo = OpConstant %int 66
2078%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2079%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2080%void_fn = OpTypeFunction %void
2081%func = OpFunction %void None %void_fn
2082%entry = OpLabel
2083%ld = OpAtomicLoad %int %ssbo_var %device %acquire_ssbo
2084OpReturn
2085OpFunctionEnd
2086)";
2087
2088  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2089}
2090
2091TEST_F(UpgradeMemoryModelTest, VolatileAtomicStore) {
2092  const std::string text = R"(
2093; CHECK-NOT: OpDecorate {{.*}} Volatile
2094; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32768
2095; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]]
2096OpCapability Shader
2097OpCapability Linkage
2098OpMemoryModel Logical GLSL450
2099OpDecorate %ssbo_var Volatile
2100%void = OpTypeVoid
2101%int = OpTypeInt 32 0
2102%int_0 = OpConstant %int 0
2103%device = OpConstant %int 1
2104%relaxed = OpConstant %int 0
2105%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2106%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2107%void_fn = OpTypeFunction %void
2108%func = OpFunction %void None %void_fn
2109%entry = OpLabel
2110OpAtomicStore %ssbo_var %device %relaxed %int_0
2111OpReturn
2112OpFunctionEnd
2113)";
2114
2115  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2116}
2117
2118TEST_F(UpgradeMemoryModelTest, VolatileAtomicStorePreviousFlags) {
2119  const std::string text = R"(
2120; CHECK-NOT: OpDecorate {{.*}} Volatile
2121; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 32836
2122; CHECK: OpAtomicStore {{.*}} {{.*}} [[volatile]]
2123OpCapability Shader
2124OpCapability Linkage
2125OpMemoryModel Logical GLSL450
2126OpDecorate %ssbo_var Volatile
2127%void = OpTypeVoid
2128%int = OpTypeInt 32 0
2129%int_0 = OpConstant %int 0
2130%device = OpConstant %int 1
2131%release_ssbo = OpConstant %int 68
2132%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2133%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2134%void_fn = OpTypeFunction %void
2135%func = OpFunction %void None %void_fn
2136%entry = OpLabel
2137OpAtomicStore %ssbo_var %device %release_ssbo %int_0
2138OpReturn
2139OpFunctionEnd
2140)";
2141
2142  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2143}
2144
2145TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchange) {
2146  const std::string text = R"(
2147; CHECK-NOT: OpDecorate {{.*}} Volatile
2148; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768
2149; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile]] [[volatile]]
2150OpCapability Shader
2151OpCapability Linkage
2152OpMemoryModel Logical GLSL450
2153OpDecorate %ssbo_var Volatile
2154%void = OpTypeVoid
2155%int = OpTypeInt 32 0
2156%int_0 = OpConstant %int 0
2157%int_1 = OpConstant %int 1
2158%device = OpConstant %int 1
2159%relaxed = OpConstant %int 0
2160%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2161%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2162%void_fn = OpTypeFunction %void
2163%func = OpFunction %void None %void_fn
2164%entry = OpLabel
2165%ld = OpAtomicCompareExchange %int %ssbo_var %device %relaxed %relaxed %int_0 %int_1
2166OpReturn
2167OpFunctionEnd
2168)";
2169
2170  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2171}
2172
2173TEST_F(UpgradeMemoryModelTest, VolatileAtomicCompareExchangePreviousFlags) {
2174  const std::string text = R"(
2175; CHECK-NOT: OpDecorate {{.*}} Volatile
2176; CHECK: [[volatile_acq_rel:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32840
2177; CHECK: [[volatile_acq:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32834
2178; CHECK: OpAtomicCompareExchange [[int]] {{.*}} {{.*}} [[volatile_acq_rel]] [[volatile_acq]]
2179OpCapability Shader
2180OpCapability Linkage
2181OpMemoryModel Logical GLSL450
2182OpDecorate %ssbo_var Volatile
2183%void = OpTypeVoid
2184%int = OpTypeInt 32 0
2185%int_0 = OpConstant %int 0
2186%int_1 = OpConstant %int 1
2187%device = OpConstant %int 1
2188%acq_ssbo = OpConstant %int 66
2189%acq_rel_ssbo = OpConstant %int 72
2190%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2191%ssbo_var = OpVariable %ptr_ssbo_int StorageBuffer
2192%void_fn = OpTypeFunction %void
2193%func = OpFunction %void None %void_fn
2194%entry = OpLabel
2195%ld = OpAtomicCompareExchange %int %ssbo_var %device %acq_rel_ssbo %acq_ssbo %int_0 %int_1
2196OpReturn
2197OpFunctionEnd
2198)";
2199
2200  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2201}
2202
2203TEST_F(UpgradeMemoryModelTest, VolatileAtomicLoadMemberDecoration) {
2204  const std::string text = R"(
2205; CHECK-NOT: OpMemberDecorate {{.*}} {{.*}} Volatile
2206; CHECK: [[relaxed:%[a-zA-Z0-9_]+]] = OpConstant {{.*}} 0
2207; CHECK: [[volatile:%[a-zA-Z0-9_]+]] = OpConstant [[int:%[a-zA-Z0-9_]+]] 32768
2208; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[relaxed]]
2209; CHECK: OpAtomicLoad [[int]] {{.*}} {{.*}} [[volatile]]
2210OpCapability Shader
2211OpCapability Linkage
2212OpMemoryModel Logical GLSL450
2213OpMemberDecorate %struct 1 Volatile
2214%void = OpTypeVoid
2215%int = OpTypeInt 32 0
2216%device = OpConstant %int 1
2217%relaxed = OpConstant %int 0
2218%int_0 = OpConstant %int 0
2219%int_1 = OpConstant %int 1
2220%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2221%struct = OpTypeStruct %int %int
2222%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
2223%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer
2224%void_fn = OpTypeFunction %void
2225%func = OpFunction %void None %void_fn
2226%entry = OpLabel
2227%gep0 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0
2228%ld0 = OpAtomicLoad %int %gep0 %device %relaxed
2229%gep1 = OpAccessChain %ptr_ssbo_int %ssbo_var %int_1
2230%ld1 = OpAtomicLoad %int %gep1 %device %relaxed
2231OpReturn
2232OpFunctionEnd
2233)";
2234
2235  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2236}
2237
2238TEST_F(UpgradeMemoryModelTest, CoherentStructMemberInArray) {
2239  const std::string text = R"(
2240; CHECK-NOT: OpMemberDecorate
2241; CHECK: [[int:%[a-zA-Z0-9_]+]] = OpTypeInt 32 0
2242; CHECK: [[device:%[a-zA-Z0-9_]+]] = OpConstant [[int]] 1
2243; CHECK: OpLoad [[int]] {{.*}} MakePointerVisible|NonPrivatePointer
2244OpCapability Shader
2245OpCapability Linkage
2246OpMemoryModel Logical GLSL450
2247OpMemberDecorate %inner 1 Coherent
2248%void = OpTypeVoid
2249%int = OpTypeInt 32 0
2250%int_0 = OpConstant %int 0
2251%int_1 = OpConstant %int 1
2252%int_4 = OpConstant %int 4
2253%inner = OpTypeStruct %int %int
2254%array = OpTypeArray %inner %int_4
2255%struct = OpTypeStruct %array
2256%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
2257%ptr_ssbo_int = OpTypePointer StorageBuffer %int
2258%ssbo_var = OpVariable %ptr_ssbo_struct StorageBuffer
2259%void_fn = OpTypeFunction %void
2260%func = OpFunction %void None %void_fn
2261%entry = OpLabel
2262%gep = OpAccessChain %ptr_ssbo_int %ssbo_var %int_0 %int_0 %int_1
2263%ld = OpLoad %int %gep
2264OpReturn
2265OpFunctionEnd
2266)";
2267
2268  SinglePassRunAndMatch<opt::UpgradeMemoryModel>(text, true);
2269}
2270
2271}  // namespace
2272