1// RUN: mlir-translate -split-input-file -test-spirv-roundtrip %s | FileCheck %s
2
3// Single loop
4
5spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
6  // for (int i = 0; i < count; ++i) {}
7  spv.func @loop(%count : i32) -> () "None" {
8    %zero = spv.Constant 0: i32
9    %one = spv.Constant 1: i32
10    %var = spv.Variable init(%zero) : !spv.ptr<i32, Function>
11
12// CHECK:        spv.Branch ^bb1
13// CHECK-NEXT: ^bb1:
14// CHECK-NEXT:   spv.mlir.loop
15    spv.mlir.loop {
16// CHECK-NEXT:     spv.Branch ^bb1
17      spv.Branch ^header
18
19// CHECK-NEXT:   ^bb1:
20    ^header:
21// CHECK-NEXT:     spv.Load
22      %val0 = spv.Load "Function" %var : i32
23// CHECK-NEXT:     spv.SLessThan
24      %cmp = spv.SLessThan %val0, %count : i32
25// CHECK-NEXT:     spv.BranchConditional %{{.*}} [1, 1], ^bb2, ^bb4
26      spv.BranchConditional %cmp [1, 1], ^body, ^merge
27
28// CHECK-NEXT:   ^bb2:
29    ^body:
30      // Do nothing
31// CHECK-NEXT:     spv.Branch ^bb3
32      spv.Branch ^continue
33
34// CHECK-NEXT:   ^bb3:
35    ^continue:
36// CHECK-NEXT:     spv.Load
37      %val1 = spv.Load "Function" %var : i32
38// CHECK-NEXT:     spv.Constant 1
39// CHECK-NEXT:     spv.IAdd
40      %add = spv.IAdd %val1, %one : i32
41// CHECK-NEXT:     spv.Store
42      spv.Store "Function" %var, %add : i32
43// CHECK-NEXT:     spv.Branch ^bb1
44      spv.Branch ^header
45
46// CHECK-NEXT:   ^bb4:
47// CHECK-NEXT:     spv.mlir.merge
48    ^merge:
49      spv.mlir.merge
50    }
51    spv.Return
52  }
53
54  spv.func @main() -> () "None" {
55    spv.Return
56  }
57  spv.EntryPoint "GLCompute" @main
58}
59
60// -----
61
62spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
63  spv.GlobalVariable @GV1 bind(0, 0) : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>
64  spv.GlobalVariable @GV2 bind(0, 1) : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>
65  spv.func @loop_kernel() "None" {
66    %0 = spv.mlir.addressof @GV1 : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>
67    %1 = spv.Constant 0 : i32
68    %2 = spv.AccessChain %0[%1] : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>, i32
69    %3 = spv.mlir.addressof @GV2 : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>
70    %5 = spv.AccessChain %3[%1] : !spv.ptr<!spv.struct<(!spv.array<10 x f32, stride=4> [0])>, StorageBuffer>, i32
71    %6 = spv.Constant 4 : i32
72    %7 = spv.Constant 42 : i32
73    %8 = spv.Constant 2 : i32
74// CHECK:        spv.Branch ^bb1(%{{.*}} : i32)
75// CHECK-NEXT: ^bb1(%[[OUTARG:.*]]: i32):
76// CHECK-NEXT:   spv.mlir.loop {
77    spv.mlir.loop {
78// CHECK-NEXT:     spv.Branch ^bb1(%[[OUTARG]] : i32)
79      spv.Branch ^header(%6 : i32)
80// CHECK-NEXT:   ^bb1(%[[HEADARG:.*]]: i32):
81    ^header(%9: i32):
82      %10 = spv.SLessThan %9, %7 : i32
83// CHECK:          spv.BranchConditional %{{.*}}, ^bb2, ^bb3
84      spv.BranchConditional %10, ^body, ^merge
85// CHECK-NEXT:   ^bb2:     // pred: ^bb1
86    ^body:
87      %11 = spv.AccessChain %2[%9] : !spv.ptr<!spv.array<10 x f32, stride=4>, StorageBuffer>, i32
88      %12 = spv.Load "StorageBuffer" %11 : f32
89      %13 = spv.AccessChain %5[%9] : !spv.ptr<!spv.array<10 x f32, stride=4>, StorageBuffer>, i32
90      spv.Store "StorageBuffer" %13, %12 : f32
91// CHECK:          %[[ADD:.*]] = spv.IAdd
92      %14 = spv.IAdd %9, %8 : i32
93// CHECK-NEXT:     spv.Branch ^bb1(%[[ADD]] : i32)
94      spv.Branch ^header(%14 : i32)
95// CHECK-NEXT:   ^bb3:
96    ^merge:
97// CHECK-NEXT:     spv.mlir.merge
98      spv.mlir.merge
99    }
100    spv.Return
101  }
102  spv.EntryPoint "GLCompute" @loop_kernel
103  spv.ExecutionMode @loop_kernel "LocalSize", 1, 1, 1
104}
105
106// -----
107
108// Nested loop
109
110spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
111  // for (int i = 0; i < count; ++i) {
112  //   for (int j = 0; j < count; ++j) { }
113  // }
114  spv.func @loop(%count : i32) -> () "None" {
115    %zero = spv.Constant 0: i32
116    %one = spv.Constant 1: i32
117    %ivar = spv.Variable init(%zero) : !spv.ptr<i32, Function>
118    %jvar = spv.Variable init(%zero) : !spv.ptr<i32, Function>
119
120// CHECK:        spv.Branch ^bb1
121// CHECK-NEXT: ^bb1:
122// CHECK-NEXT:   spv.mlir.loop control(Unroll)
123    spv.mlir.loop control(Unroll) {
124// CHECK-NEXT:     spv.Branch ^bb1
125      spv.Branch ^header
126
127// CHECK-NEXT:   ^bb1:
128    ^header:
129// CHECK-NEXT:     spv.Load
130      %ival0 = spv.Load "Function" %ivar : i32
131// CHECK-NEXT:     spv.SLessThan
132      %icmp = spv.SLessThan %ival0, %count : i32
133// CHECK-NEXT:     spv.BranchConditional %{{.*}}, ^bb2, ^bb5
134      spv.BranchConditional %icmp, ^body, ^merge
135
136// CHECK-NEXT:   ^bb2:
137    ^body:
138// CHECK-NEXT:     spv.Constant 0
139// CHECK-NEXT: 		 spv.Store
140      spv.Store "Function" %jvar, %zero : i32
141// CHECK-NEXT:     spv.Branch ^bb3
142// CHECK-NEXT:   ^bb3:
143// CHECK-NEXT:     spv.mlir.loop control(DontUnroll)
144      spv.mlir.loop control(DontUnroll) {
145// CHECK-NEXT:       spv.Branch ^bb1
146        spv.Branch ^header
147
148// CHECK-NEXT:     ^bb1:
149      ^header:
150// CHECK-NEXT:       spv.Load
151        %jval0 = spv.Load "Function" %jvar : i32
152// CHECK-NEXT:       spv.SLessThan
153        %jcmp = spv.SLessThan %jval0, %count : i32
154// CHECK-NEXT:       spv.BranchConditional %{{.*}}, ^bb2, ^bb4
155        spv.BranchConditional %jcmp, ^body, ^merge
156
157// CHECK-NEXT:     ^bb2:
158      ^body:
159        // Do nothing
160// CHECK-NEXT:       spv.Branch ^bb3
161        spv.Branch ^continue
162
163// CHECK-NEXT:     ^bb3:
164      ^continue:
165// CHECK-NEXT:       spv.Load
166        %jval1 = spv.Load "Function" %jvar : i32
167// CHECK-NEXT:       spv.Constant 1
168// CHECK-NEXT:       spv.IAdd
169        %add = spv.IAdd %jval1, %one : i32
170// CHECK-NEXT:       spv.Store
171        spv.Store "Function" %jvar, %add : i32
172// CHECK-NEXT:       spv.Branch ^bb1
173        spv.Branch ^header
174
175// CHECK-NEXT:     ^bb4:
176      ^merge:
177// CHECK-NEXT:       spv.mlir.merge
178        spv.mlir.merge
179      } // end inner loop
180
181// CHECK:          spv.Branch ^bb4
182      spv.Branch ^continue
183
184// CHECK-NEXT:   ^bb4:
185    ^continue:
186// CHECK-NEXT:     spv.Load
187      %ival1 = spv.Load "Function" %ivar : i32
188// CHECK-NEXT:     spv.Constant 1
189// CHECK-NEXT:     spv.IAdd
190      %add = spv.IAdd %ival1, %one : i32
191// CHECK-NEXT:     spv.Store
192      spv.Store "Function" %ivar, %add : i32
193// CHECK-NEXT:     spv.Branch ^bb1
194      spv.Branch ^header
195
196// CHECK-NEXT:   ^bb5:
197// CHECK-NEXT:     spv.mlir.merge
198    ^merge:
199      spv.mlir.merge
200    } // end outer loop
201    spv.Return
202  }
203
204  spv.func @main() -> () "None" {
205    spv.Return
206  }
207  spv.EntryPoint "GLCompute" @main
208}
209
210