xref: /llvm-project/mlir/test/Conversion/SPIRVToLLVM/control-flow-ops-to-llvm.mlir (revision 5aa741d7ca21645572103d798d0b121f1a741a35)
1// RUN: mlir-opt -convert-spirv-to-llvm -split-input-file -verify-diagnostics %s | FileCheck %s
2
3//===----------------------------------------------------------------------===//
4// spirv.Branch
5//===----------------------------------------------------------------------===//
6
7spirv.module Logical GLSL450 {
8  spirv.func @branch_without_arguments() -> () "None" {
9	  // CHECK: llvm.br ^bb1
10    spirv.Branch ^label
11  // CHECK: ^bb1
12  ^label:
13    spirv.Return
14  }
15
16  spirv.func @branch_with_arguments() -> () "None" {
17    %0 = spirv.Constant 0 : i32
18    %1 = spirv.Constant true
19    // CHECK: llvm.br ^bb1(%{{.*}}, %{{.*}} : i32, i1)
20    spirv.Branch ^label(%0, %1: i32, i1)
21  // CHECK: ^bb1(%{{.*}}: i32, %{{.*}}: i1)
22  ^label(%arg0: i32, %arg1: i1):
23    spirv.Return
24  }
25}
26
27// -----
28
29//===----------------------------------------------------------------------===//
30// spirv.BranchConditional
31//===----------------------------------------------------------------------===//
32
33spirv.module Logical GLSL450 {
34  spirv.func @cond_branch_without_arguments() -> () "None" {
35    // CHECK: %[[COND:.*]] = llvm.mlir.constant(true) : i1
36    %cond = spirv.Constant true
37    // CHECK: lvm.cond_br %[[COND]], ^bb1, ^bb2
38    spirv.BranchConditional %cond, ^true, ^false
39    // CHECK: ^bb1:
40  ^true:
41    spirv.Return
42    // CHECK: ^bb2:
43  ^false:
44    spirv.Return
45  }
46
47  spirv.func @cond_branch_with_arguments_nested() -> () "None" {
48    // CHECK: %[[COND1:.*]] = llvm.mlir.constant(true) : i1
49    %cond = spirv.Constant true
50    %0 = spirv.Constant 0 : i32
51    // CHECK: %[[COND2:.*]] = llvm.mlir.constant(false) : i1
52    %false = spirv.Constant false
53    // CHECK: llvm.cond_br %[[COND1]], ^bb1(%{{.*}}, %[[COND2]] : i32, i1), ^bb2
54    spirv.BranchConditional %cond, ^outer_true(%0, %false: i32, i1), ^outer_false
55  // CHECK: ^bb1(%{{.*}}: i32, %[[COND:.*]]: i1):
56  ^outer_true(%arg0: i32, %arg1: i1):
57    // CHECK: llvm.cond_br %[[COND]], ^bb3, ^bb4(%{{.*}}, %{{.*}} : i32, i32)
58    spirv.BranchConditional %arg1, ^inner_true, ^inner_false(%arg0, %arg0: i32, i32)
59  // CHECK: ^bb2:
60  ^outer_false:
61    spirv.Return
62  // CHECK: ^bb3:
63  ^inner_true:
64    spirv.Return
65  // CHECK: ^bb4(%{{.*}}: i32, %{{.*}}: i32):
66  ^inner_false(%arg3: i32, %arg4: i32):
67    spirv.Return
68  }
69
70  spirv.func @cond_branch_with_weights(%cond: i1) -> () "None" {
71    // CHECK: llvm.cond_br %{{.*}} weights([1, 2]), ^bb1, ^bb2
72    spirv.BranchConditional %cond [1, 2], ^true, ^false
73  // CHECK: ^bb1:
74  ^true:
75    spirv.Return
76  // CHECK: ^bb2:
77  ^false:
78    spirv.Return
79  }
80}
81
82// -----
83
84//===----------------------------------------------------------------------===//
85// spirv.mlir.loop
86//===----------------------------------------------------------------------===//
87
88spirv.module Logical GLSL450 {
89  // CHECK-LABEL: @empty_loop
90  spirv.func @empty_loop() "None" {
91    // CHECK: llvm.return
92    spirv.mlir.loop {
93    }
94    spirv.Return
95  }
96
97  // CHECK-LABEL: @infinite_loop
98  spirv.func @infinite_loop(%count : i32) -> () "None" {
99    // CHECK:   llvm.br ^[[BB1:.*]]
100    // CHECK: ^[[BB1]]:
101    // CHECK:   %[[COND:.*]] = llvm.mlir.constant(true) : i1
102    // CHECK:   llvm.cond_br %[[COND]], ^[[BB2:.*]], ^[[BB4:.*]]
103    // CHECK: ^[[BB2]]:
104    // CHECK:   llvm.br ^[[BB3:.*]]
105    // CHECK: ^[[BB3]]:
106    // CHECK:   llvm.br ^[[BB1:.*]]
107    // CHECK: ^[[BB4]]:
108    // CHECK:   llvm.br ^[[BB5:.*]]
109    // CHECK: ^[[BB5]]:
110    // CHECK:   llvm.return
111    spirv.mlir.loop {
112      spirv.Branch ^header
113    ^header:
114      %cond = spirv.Constant true
115      spirv.BranchConditional %cond, ^body, ^merge
116    ^body:
117      // Do nothing
118      spirv.Branch ^continue
119    ^continue:
120      // Do nothing
121      spirv.Branch ^header
122    ^merge:
123      spirv.mlir.merge
124    }
125    spirv.Return
126  }
127}
128
129// -----
130
131//===----------------------------------------------------------------------===//
132// spirv.mlir.selection
133//===----------------------------------------------------------------------===//
134
135spirv.module Logical GLSL450 {
136  spirv.func @selection_empty() -> () "None" {
137    // CHECK: llvm.return
138    spirv.mlir.selection {
139    }
140    spirv.Return
141  }
142
143  spirv.func @selection_with_merge_block_only() -> () "None" {
144    %cond = spirv.Constant true
145    // CHECK: llvm.return
146    spirv.mlir.selection {
147      spirv.BranchConditional %cond, ^merge, ^merge
148    ^merge:
149      spirv.mlir.merge
150    }
151    spirv.Return
152  }
153
154  spirv.func @selection_with_true_block_only() -> () "None" {
155    // CHECK: %[[COND:.*]] = llvm.mlir.constant(true) : i1
156    %cond = spirv.Constant true
157    // CHECK: llvm.cond_br %[[COND]], ^bb1, ^bb2
158    spirv.mlir.selection {
159      spirv.BranchConditional %cond, ^true, ^merge
160    // CHECK: ^bb1:
161    ^true:
162    // CHECK: llvm.br ^bb2
163      spirv.Branch ^merge
164    // CHECK: ^bb2:
165    ^merge:
166      // CHECK: llvm.br ^bb3
167      spirv.mlir.merge
168    }
169    // CHECK: ^bb3:
170    // CHECK-NEXT: llvm.return
171    spirv.Return
172  }
173
174  spirv.func @selection_with_both_true_and_false_block() -> () "None" {
175    // CHECK: %[[COND:.*]] = llvm.mlir.constant(true) : i1
176    %cond = spirv.Constant true
177    // CHECK: llvm.cond_br %[[COND]], ^bb1, ^bb2
178    spirv.mlir.selection {
179      spirv.BranchConditional %cond, ^true, ^false
180    // CHECK: ^bb1:
181    ^true:
182    // CHECK: llvm.br ^bb3
183      spirv.Branch ^merge
184    // CHECK: ^bb2:
185    ^false:
186    // CHECK: llvm.br ^bb3
187      spirv.Branch ^merge
188    // CHECK: ^bb3:
189    ^merge:
190      // CHECK: llvm.br ^bb4
191      spirv.mlir.merge
192    }
193    // CHECK: ^bb4:
194    // CHECK-NEXT: llvm.return
195    spirv.Return
196  }
197
198  spirv.func @selection_with_early_return(%arg0: i1) -> i32 "None" {
199    // CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i32) : i32
200    %0 = spirv.Constant 0 : i32
201    // CHECK: llvm.cond_br %{{.*}}, ^bb1(%[[ZERO]] : i32), ^bb2
202    spirv.mlir.selection {
203      spirv.BranchConditional %arg0, ^true(%0 : i32), ^merge
204    // CHECK: ^bb1(%[[ARG:.*]]: i32):
205    ^true(%arg1: i32):
206      // CHECK: llvm.return %[[ARG]] : i32
207      spirv.ReturnValue %arg1 : i32
208    // CHECK: ^bb2:
209    ^merge:
210      // CHECK: llvm.br ^bb3
211      spirv.mlir.merge
212    }
213    // CHECK: ^bb3:
214    %one = spirv.Constant 1 : i32
215    spirv.ReturnValue %one : i32
216  }
217}
218