Fix GCC build problem with 288f05f related to SmallVector. (#116958)
[llvm-project.git] / mlir / test / Transforms / sccp-callgraph.mlir
blobf31f749b6e75a361b11234e8392901cd9f82516b
1 // RUN: mlir-opt -allow-unregistered-dialect %s -sccp -split-input-file | FileCheck %s
2 // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(builtin.module(sccp))" -split-input-file | FileCheck %s --check-prefix=NESTED
3 // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(sccp))" -split-input-file | FileCheck %s --check-prefix=FUNC
5 /// Check that a constant is properly propagated through the arguments and
6 /// results of a private function.
8 // CHECK-LABEL: func private @private(
9 func.func private @private(%arg0 : i32) -> i32 {
10   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
11   // CHECK: return %[[CST]] : i32
13   return %arg0 : i32
16 // CHECK-LABEL: func @simple_private(
17 func.func @simple_private() -> i32 {
18   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
19   // CHECK: return %[[CST]] : i32
21   %1 = arith.constant 1 : i32
22   %result = call @private(%1) : (i32) -> i32
23   return %result : i32
26 // -----
28 /// Check that a constant is properly propagated through the arguments and
29 /// results of a visible nested function.
31 // CHECK: func nested @nested(
32 func.func nested @nested(%arg0 : i32) -> i32 {
33   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
34   // CHECK: return %[[CST]] : i32
36   return %arg0 : i32
39 // CHECK-LABEL: func @simple_nested(
40 func.func @simple_nested() -> i32 {
41   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
42   // CHECK: return %[[CST]] : i32
44   %1 = arith.constant 1 : i32
45   %result = call @nested(%1) : (i32) -> i32
46   return %result : i32
49 // -----
51 /// Check that non-visible nested functions do not track arguments.
52 module {
53   // NESTED-LABEL: module @nested_module
54   module @nested_module attributes { sym_visibility = "public" } {
56     // NESTED: func nested @nested(
57     func.func nested @nested(%arg0 : i32) -> (i32, i32) {
58       // NESTED: %[[CST:.*]] = arith.constant 1 : i32
59       // NESTED: return %[[CST]], %arg0 : i32, i32
61       %1 = arith.constant 1 : i32
62       return %1, %arg0 : i32, i32
63     }
65     // NESTED: func @nested_not_all_uses_visible(
66     func.func @nested_not_all_uses_visible() -> (i32, i32) {
67       // NESTED: %[[CST:.*]] = arith.constant 1 : i32
68       // NESTED: %[[CALL:.*]]:2 = call @nested
69       // NESTED: return %[[CST]], %[[CALL]]#1 : i32, i32
71       %1 = arith.constant 1 : i32
72       %result:2 = call @nested(%1) : (i32) -> (i32, i32)
73       return %result#0, %result#1 : i32, i32
74     }
75   }
78 // -----
80 /// Check that public functions do not track arguments.
82 // CHECK-LABEL: func @public(
83 func.func @public(%arg0 : i32) -> (i32, i32) {
84   %1 = arith.constant 1 : i32
85   return %1, %arg0 : i32, i32
88 // CHECK-LABEL: func @simple_public(
89 func.func @simple_public() -> (i32, i32) {
90   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
91   // CHECK: %[[CALL:.*]]:2 = call @public
92   // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32
94   %1 = arith.constant 1 : i32
95   %result:2 = call @public(%1) : (i32) -> (i32, i32)
96   return %result#0, %result#1 : i32, i32
99 // -----
101 /// Check that functions with non-call users don't have arguments tracked.
103 func.func private @callable(%arg0 : i32) -> (i32, i32) {
104   %1 = arith.constant 1 : i32
105   return %1, %arg0 : i32, i32
108 // CHECK-LABEL: func @non_call_users(
109 func.func @non_call_users() -> (i32, i32) {
110   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
111   // CHECK: %[[CALL:.*]]:2 = call @callable
112   // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32
114   %1 = arith.constant 1 : i32
115   %result:2 = call @callable(%1) : (i32) -> (i32, i32)
116   return %result#0, %result#1 : i32, i32
119 "live.user"() {uses = [@callable]} : () -> ()
121 // -----
123 /// Check that return values are overdefined in the presence of an unknown terminator.
125 func.func private @callable(%arg0 : i32) -> i32 {
126   "unknown.return"(%arg0) : (i32) -> ()
129 // CHECK-LABEL: func @unknown_terminator(
130 func.func @unknown_terminator() -> i32 {
131   // CHECK: %[[CALL:.*]] = call @callable
132   // CHECK: return %[[CALL]] : i32
134   %1 = arith.constant 1 : i32
135   %result = call @callable(%1) : (i32) -> i32
136   return %result : i32
139 // -----
141 /// Check that return values are overdefined when the constant conflicts.
143 func.func private @callable(%arg0 : i32) -> i32 {
144   return %arg0 : i32
147 // CHECK-LABEL: func @conflicting_constant(
148 func.func @conflicting_constant() -> (i32, i32) {
149   // CHECK: %[[CALL1:.*]] = call @callable
150   // CHECK: %[[CALL2:.*]] = call @callable
151   // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32
153   %1 = arith.constant 1 : i32
154   %2 = arith.constant 2 : i32
155   %result = call @callable(%1) : (i32) -> i32
156   %result2 = call @callable(%2) : (i32) -> i32
157   return %result, %result2 : i32, i32
160 // -----
162 /// Check that return values are overdefined when the constant conflicts with a
163 /// non-constant.
165 func.func private @callable(%arg0 : i32) -> i32 {
166   "unknown.return"(%arg0) : (i32) -> ()
169 // CHECK-LABEL: func @conflicting_constant(
170 func.func @conflicting_constant(%arg0 : i32) -> (i32, i32) {
171   // CHECK: %[[CALL1:.*]] = call @callable
172   // CHECK: %[[CALL2:.*]] = call @callable
173   // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32
175   %1 = arith.constant 1 : i32
176   %result = call @callable(%1) : (i32) -> i32
177   %result2 = call @callable(%arg0) : (i32) -> i32
178   return %result, %result2 : i32, i32
181 // -----
183 /// Check a more complex interaction with calls and control flow.
185 // CHECK-LABEL: func private @complex_inner_if(
186 func.func private @complex_inner_if(%arg0 : i32) -> i32 {
187   // CHECK-DAG: %[[TRUE:.*]] = arith.constant true
188   // CHECK-DAG: %[[CST:.*]] = arith.constant 1 : i32
189   // CHECK: cf.cond_br %[[TRUE]], ^bb1
191   %cst_20 = arith.constant 20 : i32
192   %cond = arith.cmpi ult, %arg0, %cst_20 : i32
193   cf.cond_br %cond, ^bb1, ^bb2
195 ^bb1:
196   // CHECK: ^bb1:
197   // CHECK: return %[[CST]] : i32
199   %cst_1 = arith.constant 1 : i32
200   return %cst_1 : i32
202 ^bb2:
203   %cst_1_2 = arith.constant 1 : i32
204   %arg_inc = arith.addi %arg0, %cst_1_2 : i32
205   return %arg_inc : i32
208 func.func private @complex_cond() -> i1
210 // CHECK-LABEL: func private @complex_callee(
211 func.func private @complex_callee(%arg0 : i32) -> i32 {
212   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
214   %loop_cond = call @complex_cond() : () -> i1
215   cf.cond_br %loop_cond, ^bb1, ^bb2
217 ^bb1:
218   // CHECK: ^bb1:
219   // CHECK-NEXT: return %[[CST]] : i32
220   return %arg0 : i32
222 ^bb2:
223   // CHECK: ^bb2:
224   // CHECK: call @complex_inner_if(%[[CST]]) : (i32) -> i32
225   // CHECK: call @complex_callee(%[[CST]]) : (i32) -> i32
226   // CHECK: return %[[CST]] : i32
228   %updated_arg = call @complex_inner_if(%arg0) : (i32) -> i32
229   %res = call @complex_callee(%updated_arg) : (i32) -> i32
230   return %res : i32
233 // CHECK-LABEL: func @complex_caller(
234 func.func @complex_caller(%arg0 : i32) -> i32 {
235   // CHECK: %[[CST:.*]] = arith.constant 1 : i32
236   // CHECK: return %[[CST]] : i32
238   %1 = arith.constant 1 : i32
239   %result = call @complex_callee(%1) : (i32) -> i32
240   return %result : i32
243 // -----
245 /// Check that non-symbol defining callables currently go to overdefined.
247 // CHECK-LABEL: func @non_symbol_defining_callable
248 func.func @non_symbol_defining_callable() -> i32 {
249   // CHECK: %[[RES:.*]] = call_indirect
250   // CHECK: return %[[RES]] : i32
252   %fn = "test.functional_region_op"() ({
253     %1 = arith.constant 1 : i32
254     "test.return"(%1) : (i32) -> ()
255   }) : () -> (() -> i32)
256   %res = call_indirect %fn() : () -> (i32)
257   return %res : i32
260 // -----
262 /// Check that private callables don't get processed if they have no uses.
264 // CHECK-LABEL: func private @unreferenced_private_function
265 func.func private @unreferenced_private_function() -> i32 {
266   // CHECK: %[[RES:.*]] = arith.select
267   // CHECK: return %[[RES]] : i32
268   %true = arith.constant true
269   %cst0 = arith.constant 0 : i32
270   %cst1 = arith.constant 1 : i32
271   %result = arith.select %true, %cst0, %cst1 : i32
272   return %result : i32
275 // -----
277 /// Check that callables outside the analysis scope are marked as external.
279 func.func private @foo() -> index {
280   %0 = arith.constant 10 : index
281   return %0 : index
284 // CHECK-LABEL: func @bar
285 // FUNC-LABEL: func @bar
286 func.func @bar(%arg0: index) -> index {
287   // CHECK: %[[C10:.*]] = arith.constant 10
288   %c0 = arith.constant 0 : index
289   %1 = arith.constant 420 : index
290   %7 = arith.cmpi eq, %arg0, %c0 : index
291   cf.cond_br %7, ^bb1(%1 : index), ^bb2
293 // CHECK: ^bb1(%[[ARG:.*]]: index):
294 // FUNC: ^bb1(%[[ARG:.*]]: index):
295 ^bb1(%8: index):  // 2 preds: ^bb0, ^bb4
296   // CHECK-NEXT: return %[[ARG]]
297   // FUNC-NEXT: return %[[ARG]]
298   return %8 : index
300 // CHECK: ^bb2
301 // FUNC: ^bb2
302 ^bb2:
303   // FUNC-NEXT: %[[FOO:.*]] = call @foo
304   %13 = call @foo() : () -> index
305   // CHECK: cf.br ^bb1(%[[C10]]
306   // FUNC: cf.br ^bb1(%[[FOO]]
307   cf.br ^bb1(%13 : index)