xref: /llvm-project/mlir/test/Target/SPIRV/phi.mlir (revision e4889c0a046e251bfaf27a637df606112659be89)
1// RUN: mlir-translate -no-implicit-module -split-input-file -test-spirv-roundtrip %s | FileCheck %s
2
3// Test branch with one block argument
4
5spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
6  spirv.func @foo() -> () "None" {
7// CHECK:        %[[CST:.*]] = spirv.Constant 0
8    %zero = spirv.Constant 0 : i32
9// CHECK-NEXT:   spirv.Branch ^bb1(%[[CST]] : i32)
10    spirv.Branch ^bb1(%zero : i32)
11// CHECK-NEXT: ^bb1(%{{.*}}: i32):
12  ^bb1(%arg0: i32):
13   spirv.Return
14  }
15
16  spirv.func @main() -> () "None" {
17    spirv.Return
18  }
19  spirv.EntryPoint "GLCompute" @main
20}
21
22// -----
23
24// Test branch with multiple block arguments
25
26spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
27  spirv.func @foo() -> () "None" {
28// CHECK:        %[[ZERO:.*]] = spirv.Constant 0
29    %zero = spirv.Constant 0 : i32
30// CHECK-NEXT:   %[[ONE:.*]] = spirv.Constant 1
31    %one = spirv.Constant 1.0 : f32
32// CHECK-NEXT:   spirv.Branch ^bb1(%[[ZERO]], %[[ONE]] : i32, f32)
33    spirv.Branch ^bb1(%zero, %one : i32, f32)
34
35// CHECK-NEXT: ^bb1(%{{.*}}: i32, %{{.*}}: f32):     // pred: ^bb0
36  ^bb1(%arg0: i32, %arg1: f32):
37   spirv.Return
38  }
39
40  spirv.func @main() -> () "None" {
41    spirv.Return
42  }
43  spirv.EntryPoint "GLCompute" @main
44}
45
46// -----
47
48// Test using block arguments within branch
49
50spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
51  spirv.func @foo() -> () "None" {
52// CHECK:        %[[CST0:.*]] = spirv.Constant 0
53    %zero = spirv.Constant 0 : i32
54// CHECK-NEXT:   spirv.Branch ^bb1(%[[CST0]] : i32)
55    spirv.Branch ^bb1(%zero : i32)
56
57// CHECK-NEXT: ^bb1(%[[ARG:.*]]: i32):
58  ^bb1(%arg0: i32):
59// CHECK-NEXT:   %[[ADD:.*]] = spirv.IAdd %[[ARG]], %[[ARG]] : i32
60    %0 = spirv.IAdd %arg0, %arg0 : i32
61// CHECK-NEXT:   %[[CST1:.*]] = spirv.Constant 0
62// CHECK-NEXT:   spirv.Branch ^bb2(%[[CST1]], %[[ADD]] : i32, i32)
63    spirv.Branch ^bb2(%zero, %0 : i32, i32)
64
65// CHECK-NEXT: ^bb2(%{{.*}}: i32, %{{.*}}: i32):
66  ^bb2(%arg1: i32, %arg2: i32):
67   spirv.Return
68  }
69
70  spirv.func @main() -> () "None" {
71    spirv.Return
72  }
73  spirv.EntryPoint "GLCompute" @main
74}
75
76// -----
77
78// Test block not following domination order
79
80spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
81  spirv.func @foo() -> () "None" {
82// CHECK:        spirv.Branch ^bb1
83    spirv.Branch ^bb1
84
85// CHECK-NEXT: ^bb1:
86// CHECK-NEXT:   %[[ZERO:.*]] = spirv.Constant 0
87// CHECK-NEXT:   %[[ONE:.*]] = spirv.Constant 1
88// CHECK-NEXT:   spirv.Branch ^bb2(%[[ZERO]], %[[ONE]] : i32, f32)
89
90// CHECK-NEXT: ^bb2(%{{.*}}: i32, %{{.*}}: f32):
91  ^bb2(%arg0: i32, %arg1: f32):
92// CHECK-NEXT:   spirv.Return
93   spirv.Return
94
95  // This block is reordered to follow domination order.
96  ^bb1:
97    %zero = spirv.Constant 0 : i32
98    %one = spirv.Constant 1.0 : f32
99    spirv.Branch ^bb2(%zero, %one : i32, f32)
100  }
101
102  spirv.func @main() -> () "None" {
103    spirv.Return
104  }
105  spirv.EntryPoint "GLCompute" @main
106}
107
108// -----
109
110// Test multiple predecessors
111
112spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
113  spirv.func @foo() -> () "None" {
114    %var = spirv.Variable : !spirv.ptr<i32, Function>
115
116// CHECK:      spirv.mlir.selection
117    spirv.mlir.selection {
118      %true = spirv.Constant true
119// CHECK:        spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
120      spirv.BranchConditional %true, ^true, ^false
121
122// CHECK-NEXT: ^bb1:
123    ^true:
124// CHECK-NEXT:   %[[ZERO:.*]] = spirv.Constant 0
125      %zero = spirv.Constant 0 : i32
126// CHECK-NEXT:   spirv.Branch ^bb3(%[[ZERO]] : i32)
127      spirv.Branch ^phi(%zero: i32)
128
129// CHECK-NEXT: ^bb2:
130    ^false:
131// CHECK-NEXT:   %[[ONE:.*]] = spirv.Constant 1
132      %one = spirv.Constant 1 : i32
133// CHECK-NEXT:   spirv.Branch ^bb3(%[[ONE]] : i32)
134      spirv.Branch ^phi(%one: i32)
135
136// CHECK-NEXT: ^bb3(%[[ARG:.*]]: i32):
137    ^phi(%arg: i32):
138// CHECK-NEXT:   spirv.Store "Function" %{{.*}}, %[[ARG]] : i32
139      spirv.Store "Function" %var, %arg : i32
140// CHECK-NEXT:   spirv.Return
141      spirv.Return
142
143// CHECK-NEXT: ^bb4:
144    ^merge:
145// CHECK-NEXT:   spirv.mlir.merge
146      spirv.mlir.merge
147    }
148    spirv.Return
149  }
150
151  spirv.func @main() -> () "None" {
152    spirv.Return
153  }
154  spirv.EntryPoint "GLCompute" @main
155}
156
157// -----
158
159// Test nested loops with block arguments
160
161spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
162  spirv.GlobalVariable @__builtin_var_NumWorkgroups__ built_in("NumWorkgroups") : !spirv.ptr<vector<3xi32>, Input>
163  spirv.GlobalVariable @__builtin_var_WorkgroupId__ built_in("WorkgroupId") : !spirv.ptr<vector<3xi32>, Input>
164  spirv.func @fmul_kernel() "None" {
165    %3 = spirv.Constant 12 : i32
166    %4 = spirv.Constant 32 : i32
167    %5 = spirv.Constant 4 : i32
168    %6 = spirv.mlir.addressof @__builtin_var_WorkgroupId__ : !spirv.ptr<vector<3xi32>, Input>
169    %7 = spirv.Load "Input" %6 : vector<3xi32>
170    %8 = spirv.CompositeExtract %7[0 : i32] : vector<3xi32>
171    %9 = spirv.mlir.addressof @__builtin_var_WorkgroupId__ : !spirv.ptr<vector<3xi32>, Input>
172    %10 = spirv.Load "Input" %9 : vector<3xi32>
173    %11 = spirv.CompositeExtract %10[1 : i32] : vector<3xi32>
174    %18 = spirv.mlir.addressof @__builtin_var_NumWorkgroups__ : !spirv.ptr<vector<3xi32>, Input>
175    %19 = spirv.Load "Input" %18 : vector<3xi32>
176    %20 = spirv.CompositeExtract %19[0 : i32] : vector<3xi32>
177    %21 = spirv.mlir.addressof @__builtin_var_NumWorkgroups__ : !spirv.ptr<vector<3xi32>, Input>
178    %22 = spirv.Load "Input" %21 : vector<3xi32>
179    %23 = spirv.CompositeExtract %22[1 : i32] : vector<3xi32>
180    %30 = spirv.IMul %11, %4 : i32
181    %31 = spirv.IMul %23, %4 : i32
182
183// CHECK:   spirv.Branch ^[[FN_BB:.*]](%{{.*}} : i32)
184// CHECK: ^[[FN_BB]](%[[FN_BB_ARG:.*]]: i32):
185// CHECK:   spirv.mlir.loop {
186    spirv.mlir.loop {
187// CHECK:     spirv.Branch ^bb1(%[[FN_BB_ARG]] : i32)
188      spirv.Branch ^bb1(%30 : i32)
189// CHECK:   ^[[LP1_HDR:.*]](%[[LP1_HDR_ARG:.*]]: i32):
190    ^bb1(%32: i32):
191// CHECK:     spirv.SLessThan
192      %33 = spirv.SLessThan %32, %3 : i32
193// CHECK:     spirv.BranchConditional %{{.*}}, ^[[LP1_BDY:.*]], ^[[LP1_MG:.*]]
194      spirv.BranchConditional %33, ^bb2, ^bb3
195// CHECK:   ^[[LP1_BDY]]:
196    ^bb2:
197// CHECK:     %[[MUL:.*]] = spirv.IMul
198      %34 = spirv.IMul %8, %5 : i32
199// CHECK:     spirv.IMul
200      %35 = spirv.IMul %20, %5 : i32
201// CHECK:     spirv.Branch ^[[LP1_CNT:.*]](%[[MUL]] : i32)
202// CHECK:   ^[[LP1_CNT]](%[[LP1_CNT_ARG:.*]]: i32):
203// CHECK:     spirv.mlir.loop {
204      spirv.mlir.loop {
205// CHECK:       spirv.Branch ^[[LP2_HDR:.*]](%[[LP1_CNT_ARG]] : i32)
206        spirv.Branch ^bb1(%34 : i32)
207// CHECK:     ^[[LP2_HDR]](%[[LP2_HDR_ARG:.*]]: i32):
208      ^bb1(%37: i32):
209// CHECK:       spirv.SLessThan %[[LP2_HDR_ARG]]
210        %38 = spirv.SLessThan %37, %5 : i32
211// CHECK:       spirv.BranchConditional %{{.*}}, ^[[LP2_BDY:.*]], ^[[LP2_MG:.*]]
212        spirv.BranchConditional %38, ^bb2, ^bb3
213// CHECK:     ^[[LP2_BDY]]:
214      ^bb2:
215// CHECK:       %[[ADD1:.*]] = spirv.IAdd
216        %48 = spirv.IAdd %37, %35 : i32
217// CHECK:       spirv.Branch ^[[LP2_HDR]](%[[ADD1]] : i32)
218        spirv.Branch ^bb1(%48 : i32)
219// CHECK:     ^[[LP2_MG]]:
220      ^bb3:
221// CHECK:       spirv.mlir.merge
222        spirv.mlir.merge
223      }
224// CHECK:     %[[ADD2:.*]] = spirv.IAdd %[[LP1_HDR_ARG]]
225      %36 = spirv.IAdd %32, %31 : i32
226// CHECK:     spirv.Branch ^[[LP1_HDR]](%[[ADD2]] : i32)
227      spirv.Branch ^bb1(%36 : i32)
228// CHECK:   ^[[LP1_MG]]:
229    ^bb3:
230// CHECK:     spirv.mlir.merge
231      spirv.mlir.merge
232    }
233    spirv.Return
234  }
235
236  spirv.EntryPoint "GLCompute" @fmul_kernel, @__builtin_var_WorkgroupId__, @__builtin_var_NumWorkgroups__
237  spirv.ExecutionMode @fmul_kernel "LocalSize", 32, 1, 1
238}
239
240// -----
241
242// Test back-to-back loops with block arguments
243
244spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
245  spirv.func @fmul_kernel() "None" {
246    %cst4 = spirv.Constant 4 : i32
247
248    %val1 = spirv.Constant 43 : i32
249    %val2 = spirv.Constant 44 : i32
250
251// CHECK:        spirv.Constant 43
252// CHECK-NEXT:   spirv.Branch ^[[BB1:.+]](%{{.+}} : i32)
253// CHECK-NEXT: ^[[BB1]](%{{.+}}: i32):
254// CHECK-NEXT:   spirv.mlir.loop
255    spirv.mlir.loop { // loop 1
256      spirv.Branch ^bb1(%val1 : i32)
257    ^bb1(%loop1_bb_arg: i32):
258      %loop1_lt = spirv.SLessThan %loop1_bb_arg, %cst4 : i32
259      spirv.BranchConditional %loop1_lt, ^bb2, ^bb3
260    ^bb2:
261      %loop1_add = spirv.IAdd %loop1_bb_arg, %cst4 : i32
262      spirv.Branch ^bb1(%loop1_add : i32)
263    ^bb3:
264      spirv.mlir.merge
265    }
266
267// CHECK:        spirv.Constant 44
268// CHECK-NEXT:   spirv.Branch ^[[BB2:.+]](%{{.+}} : i32)
269// CHECK-NEXT: ^[[BB2]](%{{.+}}: i32):
270// CHECK-NEXT:   spirv.mlir.loop
271    spirv.mlir.loop { // loop 2
272      spirv.Branch ^bb1(%val2 : i32)
273    ^bb1(%loop2_bb_arg: i32):
274      %loop2_lt = spirv.SLessThan %loop2_bb_arg, %cst4 : i32
275      spirv.BranchConditional %loop2_lt, ^bb2, ^bb3
276    ^bb2:
277      %loop2_add = spirv.IAdd %loop2_bb_arg, %cst4 : i32
278      spirv.Branch ^bb1(%loop2_add : i32)
279    ^bb3:
280      spirv.mlir.merge
281    }
282
283    spirv.Return
284  }
285
286  spirv.EntryPoint "GLCompute" @fmul_kernel
287  spirv.ExecutionMode @fmul_kernel "LocalSize", 32, 1, 1
288}
289
290// -----
291
292spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
293// CHECK-LABEL: @cond_branch_true_argument
294  spirv.func @cond_branch_true_argument() -> () "None" {
295    %true = spirv.Constant true
296    %zero = spirv.Constant 0 : i32
297    %one = spirv.Constant 1 : i32
298// CHECK:   spirv.BranchConditional %{{.*}}, ^[[true1:.*]](%{{.*}}, %{{.*}} : i32, i32), ^[[false1:.*]]
299    spirv.BranchConditional %true, ^true1(%zero, %zero: i32, i32), ^false1
300// CHECK: [[true1]](%{{.*}}: i32, %{{.*}}: i32)
301  ^true1(%arg0: i32, %arg1: i32):
302    spirv.Return
303// CHECK: [[false1]]:
304  ^false1:
305    spirv.Return
306  }
307}
308
309// -----
310
311spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
312// CHECK-LABEL: @cond_branch_false_argument
313  spirv.func @cond_branch_false_argument() -> () "None" {
314    %true = spirv.Constant true
315    %zero = spirv.Constant 0 : i32
316    %one = spirv.Constant 1 : i32
317// CHECK:   spirv.BranchConditional %{{.*}}, ^[[true1:.*]], ^[[false1:.*]](%{{.*}}, %{{.*}} : i32, i32)
318    spirv.BranchConditional %true, ^true1, ^false1(%zero, %zero: i32, i32)
319// CHECK: [[true1]]:
320  ^true1:
321    spirv.Return
322// CHECK: [[false1]](%{{.*}}: i32, %{{.*}}: i32):
323  ^false1(%arg0: i32, %arg1: i32):
324    spirv.Return
325  }
326}
327
328// -----
329
330spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
331// CHECK-LABEL: @cond_branch_true_and_false_argument
332  spirv.func @cond_branch_true_and_false_argument() -> () "None" {
333    %true = spirv.Constant true
334    %zero = spirv.Constant 0 : i32
335    %one = spirv.Constant 1 : i32
336// CHECK:   spirv.BranchConditional %{{.*}}, ^[[true1:.*]](%{{.*}} : i32), ^[[false1:.*]](%{{.*}}, %{{.*}} : i32, i32)
337    spirv.BranchConditional %true, ^true1(%one: i32), ^false1(%zero, %zero: i32, i32)
338// CHECK: [[true1]](%{{.*}}: i32):
339  ^true1(%arg0: i32):
340    spirv.Return
341// CHECK: [[false1]](%{{.*}}: i32, %{{.*}}: i32):
342  ^false1(%arg1: i32, %arg2: i32):
343    spirv.Return
344  }
345}
346