xref: /llvm-project/mlir/test/Dialect/SPIRV/Transforms/inlining.mlir (revision bdf00e2216280edef1ec91ccc07987db92197b59)
1// RUN: mlir-opt %s -split-input-file -pass-pipeline='builtin.module(spirv.module(inline{default-pipeline=''}))' | FileCheck %s
2
3spirv.module Logical GLSL450 {
4  spirv.func @callee() "None" {
5    spirv.Return
6  }
7
8  // CHECK-LABEL: @calling_single_block_ret_func
9  spirv.func @calling_single_block_ret_func() "None" {
10    // CHECK-NEXT: spirv.Return
11    spirv.FunctionCall @callee() : () -> ()
12    spirv.Return
13  }
14}
15
16// -----
17
18spirv.module Logical GLSL450 {
19  spirv.func @callee() -> i32 "None" {
20    %0 = spirv.Constant 42 : i32
21    spirv.ReturnValue %0 : i32
22  }
23
24  // CHECK-LABEL: @calling_single_block_retval_func
25  spirv.func @calling_single_block_retval_func() -> i32 "None" {
26    // CHECK-NEXT: %[[CST:.*]] = spirv.Constant 42
27    %0 = spirv.FunctionCall @callee() : () -> (i32)
28    // CHECK-NEXT: spirv.ReturnValue %[[CST]]
29    spirv.ReturnValue %0 : i32
30  }
31}
32
33// -----
34
35spirv.module Logical GLSL450 {
36  spirv.GlobalVariable @data bind(0, 0) : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer>
37  spirv.func @callee() "None" {
38    %0 = spirv.mlir.addressof @data : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer>
39    %1 = spirv.Constant 0: i32
40    %2 = spirv.AccessChain %0[%1, %1] : !spirv.ptr<!spirv.struct<(!spirv.rtarray<i32> [0])>, StorageBuffer>, i32, i32 -> !spirv.ptr<i32, StorageBuffer>
41    spirv.Branch ^next
42
43  ^next:
44    %3 = spirv.Constant 42: i32
45    spirv.Store "StorageBuffer" %2, %3 : i32
46    spirv.Return
47  }
48
49  // CHECK-LABEL: @calling_multi_block_ret_func
50  spirv.func @calling_multi_block_ret_func() "None" {
51    // CHECK-NEXT:   spirv.mlir.addressof
52    // CHECK-NEXT:   spirv.Constant 0
53    // CHECK-NEXT:   spirv.AccessChain
54    // CHECK-NEXT:   spirv.Branch ^bb1
55    // CHECK-NEXT: ^bb1:
56    // CHECK-NEXT:   spirv.Constant
57    // CHECK-NEXT:   spirv.Store
58    // CHECK-NEXT:   spirv.Branch ^bb2
59    spirv.FunctionCall @callee() : () -> ()
60    // CHECK-NEXT: ^bb2:
61    // CHECK-NEXT:   spirv.Return
62    spirv.Return
63  }
64}
65
66// TODO: calling_multi_block_retval_func
67
68// -----
69
70spirv.module Logical GLSL450 {
71  spirv.func @callee(%cond : i1) -> () "None" {
72    spirv.mlir.selection {
73      spirv.BranchConditional %cond, ^then, ^merge
74    ^then:
75      spirv.Return
76    ^merge:
77      spirv.mlir.merge
78    }
79    spirv.Return
80  }
81
82  // CHECK-LABEL: @calling_selection_ret_func
83  spirv.func @calling_selection_ret_func() "None" {
84    %0 = spirv.Constant true
85    // CHECK: spirv.FunctionCall
86    spirv.FunctionCall @callee(%0) : (i1) -> ()
87    spirv.Return
88  }
89}
90
91// -----
92
93spirv.module Logical GLSL450 {
94  spirv.func @callee(%cond : i1) -> () "None" {
95    spirv.mlir.selection {
96      spirv.BranchConditional %cond, ^then, ^merge
97    ^then:
98      spirv.Branch ^merge
99    ^merge:
100      spirv.mlir.merge
101    }
102    spirv.Return
103  }
104
105  // CHECK-LABEL: @calling_selection_no_ret_func
106  spirv.func @calling_selection_no_ret_func() "None" {
107    // CHECK-NEXT: %[[TRUE:.*]] = spirv.Constant true
108    %0 = spirv.Constant true
109    // CHECK-NEXT: spirv.mlir.selection
110    // CHECK-NEXT:   spirv.BranchConditional %[[TRUE]], ^bb1, ^bb2
111    // CHECK-NEXT: ^bb1:
112    // CHECK-NEXT:   spirv.Branch ^bb2
113    // CHECK-NEXT: ^bb2:
114    // CHECK-NEXT:   spirv.mlir.merge
115    spirv.FunctionCall @callee(%0) : (i1) -> ()
116    spirv.Return
117  }
118}
119
120// -----
121
122spirv.module Logical GLSL450 {
123  spirv.func @callee(%cond : i1) -> () "None" {
124    spirv.mlir.loop {
125      spirv.Branch ^header
126    ^header:
127      spirv.BranchConditional %cond, ^body, ^merge
128    ^body:
129      spirv.Return
130    ^continue:
131      spirv.Branch ^header
132    ^merge:
133      spirv.mlir.merge
134    }
135    spirv.Return
136  }
137
138  // CHECK-LABEL: @calling_loop_ret_func
139  spirv.func @calling_loop_ret_func() "None" {
140    %0 = spirv.Constant true
141    // CHECK: spirv.FunctionCall
142    spirv.FunctionCall @callee(%0) : (i1) -> ()
143    spirv.Return
144  }
145}
146
147// -----
148
149spirv.module Logical GLSL450 {
150  spirv.func @callee(%cond : i1) -> () "None" {
151    spirv.mlir.loop {
152      spirv.Branch ^header
153    ^header:
154      spirv.BranchConditional %cond, ^body, ^merge
155    ^body:
156      spirv.Branch ^continue
157    ^continue:
158      spirv.Branch ^header
159    ^merge:
160      spirv.mlir.merge
161    }
162    spirv.Return
163  }
164
165  // CHECK-LABEL: @calling_loop_no_ret_func
166  spirv.func @calling_loop_no_ret_func() "None" {
167    // CHECK-NEXT: %[[TRUE:.*]] = spirv.Constant true
168    %0 = spirv.Constant true
169    // CHECK-NEXT: spirv.mlir.loop
170    // CHECK-NEXT:   spirv.Branch ^bb1
171    // CHECK-NEXT: ^bb1:
172    // CHECK-NEXT:   spirv.BranchConditional %[[TRUE]], ^bb2, ^bb4
173    // CHECK-NEXT: ^bb2:
174    // CHECK-NEXT:   spirv.Branch ^bb3
175    // CHECK-NEXT: ^bb3:
176    // CHECK-NEXT:   spirv.Branch ^bb1
177    // CHECK-NEXT: ^bb4:
178    // CHECK-NEXT:   spirv.mlir.merge
179    spirv.FunctionCall @callee(%0) : (i1) -> ()
180    spirv.Return
181  }
182}
183
184// -----
185
186spirv.module Logical GLSL450 {
187  spirv.GlobalVariable @arg_0 bind(0, 0) : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>
188  spirv.GlobalVariable @arg_1 bind(0, 1) : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>
189
190  // CHECK: @inline_into_selection_region
191  spirv.func @inline_into_selection_region() "None" {
192    %1 = spirv.Constant 0 : i32
193    // CHECK-DAG: [[ADDRESS_ARG0:%.*]] = spirv.mlir.addressof @arg_0
194    // CHECK-DAG: [[ADDRESS_ARG1:%.*]] = spirv.mlir.addressof @arg_1
195    // CHECK-DAG: [[LOADPTR:%.*]] = spirv.AccessChain [[ADDRESS_ARG0]]
196    // CHECK: [[VAL:%.*]] = spirv.Load "StorageBuffer" [[LOADPTR]]
197    %2 = spirv.mlir.addressof @arg_0 : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>
198    %3 = spirv.mlir.addressof @arg_1 : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>
199    %4 = spirv.AccessChain %2[%1] : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>, i32 -> !spirv.ptr<i32, StorageBuffer>
200    %5 = spirv.Load "StorageBuffer" %4 : i32
201    %6 = spirv.SGreaterThan %5, %1 : i32
202    // CHECK: spirv.mlir.selection
203    spirv.mlir.selection {
204      spirv.BranchConditional %6, ^bb1, ^bb2
205    ^bb1: // pred: ^bb0
206      // CHECK: [[STOREPTR:%.*]] = spirv.AccessChain [[ADDRESS_ARG1]]
207      %7 = spirv.AccessChain %3[%1] : !spirv.ptr<!spirv.struct<(i32 [0])>, StorageBuffer>, i32 -> !spirv.ptr<i32, StorageBuffer>
208      // CHECK-NOT: spirv.FunctionCall
209      // CHECK: spirv.AtomicIAdd <Device> <AcquireRelease> [[STOREPTR]], [[VAL]]
210      // CHECK: spirv.Branch
211      spirv.FunctionCall @atomic_add(%5, %7) : (i32, !spirv.ptr<i32, StorageBuffer>) -> ()
212      spirv.Branch ^bb2
213    ^bb2 : // 2 preds: ^bb0, ^bb1
214      spirv.mlir.merge
215    }
216    // CHECK: spirv.Return
217    spirv.Return
218  }
219  spirv.func @atomic_add(%arg0: i32, %arg1: !spirv.ptr<i32, StorageBuffer>) "None" {
220    %0 = spirv.AtomicIAdd <Device> <AcquireRelease> %arg1, %arg0 : !spirv.ptr<i32, StorageBuffer>
221    spirv.Return
222  }
223  spirv.EntryPoint "GLCompute" @inline_into_selection_region
224  spirv.ExecutionMode @inline_into_selection_region "LocalSize", 32, 1, 1
225}
226
227// -----
228
229spirv.module Logical GLSL450 {
230  // CHECK-LABEL: @foo
231  spirv.func @foo(%arg0: i32) -> i32 "None" {
232    // CHECK-NOT: spirv.FunctionCall
233    // CHECK-NEXT: spirv.Constant 1
234    %res = spirv.FunctionCall @bar(%arg0) : (i32) -> i32
235    spirv.ReturnValue %res : i32
236  }
237
238  spirv.func @bar(%arg1: i32) -> i32 "None" attributes {sym_visibility = "private"} {
239    %cst1_i32 = spirv.Constant 1 : i32
240    %0 = spirv.IEqual %arg1, %cst1_i32 : i32
241    spirv.BranchConditional %0, ^bb1(%cst1_i32 : i32), ^bb2
242  ^bb1(%1: i32):
243    spirv.ReturnValue %1 : i32
244  ^bb2:
245    spirv.ReturnValue %cst1_i32 : i32
246  }
247}
248
249// TODO: Add tests for inlining structured control flow into
250// structured control flow.
251