Fix GCC build problem with 288f05f related to SmallVector. (#116958)
[llvm-project.git] / mlir / test / Transforms / decompose-call-graph-types.mlir
blobb8fad63eb4de67938eef36848c47d849482199a2
1 // RUN: mlir-opt %s -split-input-file -test-decompose-call-graph-types | FileCheck %s
3 // RUN: mlir-opt %s -split-input-file \
4 // RUN:   -test-one-to-n-type-conversion="convert-func-ops" \
5 // RUN: | FileCheck %s --check-prefix=CHECK-12N
7 // Test case: Most basic case of a 1:N decomposition, an identity function.
9 // CHECK-LABEL:   func @identity(
10 // CHECK-SAME:                   %[[ARG0:.*]]: i1,
11 // CHECK-SAME:                   %[[ARG1:.*]]: i32) -> (i1, i32) {
12 // CHECK:           %[[ARG_MATERIALIZED:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) : (i1, i32) -> tuple<i1, i32>
13 // CHECK:           %[[RET0:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) <{index = 0 : i32}> : (tuple<i1, i32>) -> i1
14 // CHECK:           %[[RET1:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) <{index = 1 : i32}> : (tuple<i1, i32>) -> i32
15 // CHECK:           return %[[RET0]], %[[RET1]] : i1, i32
16 // CHECK-12N-LABEL:   func @identity(
17 // CHECK-12N-SAME:                   %[[ARG0:.*]]: i1,
18 // CHECK-12N-SAME:                   %[[ARG1:.*]]: i32) -> (i1, i32) {
19 // CHECK-12N:           return %[[ARG0]], %[[ARG1]] : i1, i32
20 func.func @identity(%arg0: tuple<i1, i32>) -> tuple<i1, i32> {
21   return %arg0 : tuple<i1, i32>
24 // -----
26 // Test case: Ensure no materializations in the case of 1:1 decomposition.
28 // CHECK-LABEL:   func @identity_1_to_1_no_materializations(
29 // CHECK-SAME:                                              %[[ARG0:.*]]: i1) -> i1 {
30 // CHECK:           return %[[ARG0]] : i1
31 // CHECK-12N-LABEL:   func @identity_1_to_1_no_materializations(
32 // CHECK-12N-SAME:                                              %[[ARG0:.*]]: i1) -> i1 {
33 // CHECK-12N:           return %[[ARG0]] : i1
34 func.func @identity_1_to_1_no_materializations(%arg0: tuple<i1>) -> tuple<i1> {
35   return %arg0 : tuple<i1>
38 // -----
40 // Test case: Type that needs to be recursively decomposed.
42 // CHECK-LABEL:   func @recursive_decomposition(
43 // CHECK-SAME:                                   %[[ARG0:.*]]: i1) -> i1 {
44 // CHECK:           return %[[ARG0]] : i1
45 // CHECK-12N-LABEL:   func @recursive_decomposition(
46 // CHECK-12N-SAME:                                   %[[ARG0:.*]]: i1) -> i1 {
47 // CHECK-12N:           return %[[ARG0]] : i1
48 func.func @recursive_decomposition(%arg0: tuple<tuple<tuple<i1>>>) -> tuple<tuple<tuple<i1>>> {
49   return %arg0 : tuple<tuple<tuple<i1>>>
52 // -----
54 // Test case: Type that needs to be recursively decomposed at different recursion depths.
56 // CHECK-LABEL:   func @mixed_recursive_decomposition(
57 // CHECK-SAME:                 %[[ARG0:.*]]: i1,
58 // CHECK-SAME:                 %[[ARG1:.*]]: i2) -> (i1, i2) {
59 // CHECK:           %[[V0:.*]] = "test.make_tuple"() : () -> tuple<>
60 // CHECK:           %[[V1:.*]] = "test.make_tuple"(%[[ARG0]]) : (i1) -> tuple<i1>
61 // CHECK:           %[[V2:.*]] = "test.make_tuple"(%[[ARG1]]) : (i2) -> tuple<i2>
62 // CHECK:           %[[V3:.*]] = "test.make_tuple"(%[[V2]]) : (tuple<i2>) -> tuple<tuple<i2>>
63 // CHECK:           %[[V4:.*]] = "test.make_tuple"(%[[V0]], %[[V1]], %[[V3]]) : (tuple<>, tuple<i1>, tuple<tuple<i2>>) -> tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>
64 // CHECK:           %[[V5:.*]] = "test.get_tuple_element"(%[[V4]]) <{index = 0 : i32}> : (tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>) -> tuple<>
65 // CHECK:           %[[V6:.*]] = "test.get_tuple_element"(%[[V4]]) <{index = 1 : i32}> : (tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>) -> tuple<i1>
66 // CHECK:           %[[V7:.*]] = "test.get_tuple_element"(%[[V6]]) <{index = 0 : i32}> : (tuple<i1>) -> i1
67 // CHECK:           %[[V8:.*]] = "test.get_tuple_element"(%[[V4]]) <{index = 2 : i32}> : (tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>) -> tuple<tuple<i2>>
68 // CHECK:           %[[V9:.*]] = "test.get_tuple_element"(%[[V8]]) <{index = 0 : i32}> : (tuple<tuple<i2>>) -> tuple<i2>
69 // CHECK:           %[[V10:.*]] = "test.get_tuple_element"(%[[V9]]) <{index = 0 : i32}> : (tuple<i2>) -> i2
70 // CHECK:           return %[[V7]], %[[V10]] : i1, i2
71 // CHECK-12N-LABEL:   func @mixed_recursive_decomposition(
72 // CHECK-12N-SAME:                 %[[ARG0:.*]]: i1,
73 // CHECK-12N-SAME:                 %[[ARG1:.*]]: i2) -> (i1, i2) {
74 // CHECK-12N:           return %[[ARG0]], %[[ARG1]] : i1, i2
75 func.func @mixed_recursive_decomposition(%arg0: tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>) -> tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>> {
76   return %arg0 : tuple<tuple<>, tuple<i1>, tuple<tuple<i2>>>
79 // -----
81 // Test case: Check decomposition of calls.
83 // CHECK-LABEL:   func private @callee(i1, i32) -> (i1, i32)
84 // CHECK-12N-LABEL:   func private @callee(i1, i32) -> (i1, i32)
85 func.func private @callee(tuple<i1, i32>) -> tuple<i1, i32>
87 // CHECK-LABEL:   func @caller(
88 // CHECK-SAME:                 %[[ARG0:.*]]: i1,
89 // CHECK-SAME:                 %[[ARG1:.*]]: i32) -> (i1, i32) {
90 // CHECK:           %[[ARG_MATERIALIZED:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) : (i1, i32) -> tuple<i1, i32>
91 // CHECK:           %[[CALL_ARG0:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) <{index = 0 : i32}> : (tuple<i1, i32>) -> i1
92 // CHECK:           %[[CALL_ARG1:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) <{index = 1 : i32}> : (tuple<i1, i32>) -> i32
93 // CHECK:           %[[DECOMPOSED:.*]]:2 = call @callee(%[[CALL_ARG0]], %[[CALL_ARG1]]) : (i1, i32) -> (i1, i32)
94 // CHECK:           %[[CALL_RESULT_RECOMPOSED:.*]] = "test.make_tuple"(%[[DECOMPOSED]]#0, %[[DECOMPOSED]]#1) : (i1, i32) -> tuple<i1, i32>
95 // CHECK:           %[[RET0:.*]] = "test.get_tuple_element"(%[[CALL_RESULT_RECOMPOSED]]) <{index = 0 : i32}> : (tuple<i1, i32>) -> i1
96 // CHECK:           %[[RET1:.*]] = "test.get_tuple_element"(%[[CALL_RESULT_RECOMPOSED]]) <{index = 1 : i32}> : (tuple<i1, i32>) -> i32
97 // CHECK:           return %[[RET0]], %[[RET1]] : i1, i32
98 // CHECK-12N-LABEL:   func @caller(
99 // CHECK-12N-SAME:                 %[[ARG0:.*]]: i1,
100 // CHECK-12N-SAME:                 %[[ARG1:.*]]: i32) -> (i1, i32) {
101 // CHECK-12N:           %[[V0:.*]]:2 = call @callee(%[[ARG0]], %[[ARG1]]) : (i1, i32) -> (i1, i32)
102 // CHECK-12N:           return %[[V0]]#0, %[[V0]]#1 : i1, i32
103 func.func @caller(%arg0: tuple<i1, i32>) -> tuple<i1, i32> {
104   %0 = call @callee(%arg0) : (tuple<i1, i32>) -> tuple<i1, i32>
105   return %0 : tuple<i1, i32>
108 // -----
110 // Test case: Type that decomposes to nothing (that is, a 1:0 decomposition).
112 // CHECK-LABEL:   func private @callee()
113 // CHECK-12N-LABEL:   func private @callee()
114 func.func private @callee(tuple<>) -> tuple<>
116 // CHECK-LABEL:   func @caller() {
117 // CHECK:           call @callee() : () -> ()
118 // CHECK:           return
119 // CHECK-12N-LABEL:   func @caller() {
120 // CHECK-12N:           call @callee() : () -> ()
121 // CHECK-12N:           return
122 func.func @caller(%arg0: tuple<>) -> tuple<> {
123   %0 = call @callee(%arg0) : (tuple<>) -> (tuple<>)
124   return %0 : tuple<>
127 // -----
129 // Test case: Ensure decompositions are inserted properly around results of
130 // unconverted ops.
132 // CHECK-LABEL:   func @unconverted_op_result() -> (i1, i32) {
133 // CHECK:           %[[UNCONVERTED_VALUE:.*]] = "test.source"() : () -> tuple<i1, i32>
134 // CHECK:           %[[RET0:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) <{index = 0 : i32}> : (tuple<i1, i32>) -> i1
135 // CHECK:           %[[RET1:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) <{index = 1 : i32}> : (tuple<i1, i32>) -> i32
136 // CHECK:           return %[[RET0]], %[[RET1]] : i1, i32
137 // CHECK-12N-LABEL:   func @unconverted_op_result() -> (i1, i32) {
138 // CHECK-12N:           %[[UNCONVERTED_VALUE:.*]] = "test.source"() : () -> tuple<i1, i32>
139 // CHECK-12N:           %[[RET0:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) <{index = 0 : i32}> : (tuple<i1, i32>) -> i1
140 // CHECK-12N:           %[[RET1:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) <{index = 1 : i32}> : (tuple<i1, i32>) -> i32
141 // CHECK-12N:           return %[[RET0]], %[[RET1]] : i1, i32
142 func.func @unconverted_op_result() -> tuple<i1, i32> {
143   %0 = "test.source"() : () -> (tuple<i1, i32>)
144   return %0 : tuple<i1, i32>
147 // -----
149 // Test case: Ensure decompositions are inserted properly around results of
150 // unconverted ops in the case of different nesting levels.
152 // CHECK-LABEL:   func @nested_unconverted_op_result(
153 // CHECK-SAME:                 %[[ARG0:.*]]: i1,
154 // CHECK-SAME:                 %[[ARG1:.*]]: i32) -> (i1, i32) {
155 // CHECK:           %[[V0:.*]] = "test.make_tuple"(%[[ARG1]]) : (i32) -> tuple<i32>
156 // CHECK:           %[[V1:.*]] = "test.make_tuple"(%[[ARG0]], %[[V0]]) : (i1, tuple<i32>) -> tuple<i1, tuple<i32>>
157 // CHECK:           %[[V2:.*]] = "test.op"(%[[V1]]) : (tuple<i1, tuple<i32>>) -> tuple<i1, tuple<i32>>
158 // CHECK:           %[[V3:.*]] = "test.get_tuple_element"(%[[V2]]) <{index = 0 : i32}> : (tuple<i1, tuple<i32>>) -> i1
159 // CHECK:           %[[V4:.*]] = "test.get_tuple_element"(%[[V2]]) <{index = 1 : i32}> : (tuple<i1, tuple<i32>>) -> tuple<i32>
160 // CHECK:           %[[V5:.*]] = "test.get_tuple_element"(%[[V4]]) <{index = 0 : i32}> : (tuple<i32>) -> i32
161 // CHECK:           return %[[V3]], %[[V5]] : i1, i32
162 // CHECK-12N-LABEL:   func @nested_unconverted_op_result(
163 // CHECK-12N-SAME:                 %[[ARG0:.*]]: i1,
164 // CHECK-12N-SAME:                 %[[ARG1:.*]]: i32) -> (i1, i32) {
165 // CHECK-12N:           %[[V0:.*]] = "test.make_tuple"(%[[ARG1]]) : (i32) -> tuple<i32>
166 // CHECK-12N:           %[[V1:.*]] = "test.make_tuple"(%[[ARG0]], %[[V0]]) : (i1, tuple<i32>) -> tuple<i1, tuple<i32>>
167 // CHECK-12N:           %[[V2:.*]] = "test.op"(%[[V1]]) : (tuple<i1, tuple<i32>>) -> tuple<i1, tuple<i32>>
168 // CHECK-12N:           %[[V3:.*]] = "test.get_tuple_element"(%[[V2]]) <{index = 0 : i32}> : (tuple<i1, tuple<i32>>) -> i1
169 // CHECK-12N:           %[[V4:.*]] = "test.get_tuple_element"(%[[V2]]) <{index = 1 : i32}> : (tuple<i1, tuple<i32>>) -> tuple<i32>
170 // CHECK-12N:           %[[V5:.*]] = "test.get_tuple_element"(%[[V4]]) <{index = 0 : i32}> : (tuple<i32>) -> i32
171 // CHECK-12N:           return %[[V3]], %[[V5]] : i1, i32
172 func.func @nested_unconverted_op_result(%arg: tuple<i1, tuple<i32>>) -> tuple<i1, tuple<i32>> {
173   %0 = "test.op"(%arg) : (tuple<i1, tuple<i32>>) -> (tuple<i1, tuple<i32>>)
174   return %0 : tuple<i1, tuple<i32>>
177 // -----
179 // Test case: Check mixed decomposed and non-decomposed args.
180 // This makes sure to test the cases if 1:0, 1:1, and 1:N decompositions.
182 // CHECK-LABEL:   func private @callee(i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6)
183 // CHECK-12N-LABEL:   func private @callee(i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6)
184 func.func private @callee(tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6) -> (tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6)
186 // CHECK-LABEL:   func @caller(
187 // CHECK-SAME:                 %[[I1:.*]]: i1,
188 // CHECK-SAME:                 %[[I2:.*]]: i2,
189 // CHECK-SAME:                 %[[I3:.*]]: i3,
190 // CHECK-SAME:                 %[[I4:.*]]: i4,
191 // CHECK-SAME:                 %[[I5:.*]]: i5,
192 // CHECK-SAME:                 %[[I6:.*]]: i6) -> (i1, i2, i3, i4, i5, i6) {
193 // CHECK:           %[[ARG_TUPLE:.*]] = "test.make_tuple"(%[[I4]], %[[I5]]) : (i4, i5) -> tuple<i4, i5>
194 // CHECK:           %[[ARG_TUPLE_0:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) <{index = 0 : i32}> : (tuple<i4, i5>) -> i4
195 // CHECK:           %[[ARG_TUPLE_1:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) <{index = 1 : i32}> : (tuple<i4, i5>) -> i5
196 // CHECK:           %[[CALL:.*]]:6 = call @callee(%[[I1]], %[[I2]], %[[I3]], %[[ARG_TUPLE_0]], %[[ARG_TUPLE_1]], %[[I6]]) : (i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6)
197 // CHECK:           %[[RET_TUPLE:.*]] = "test.make_tuple"(%[[CALL]]#3, %[[CALL]]#4) : (i4, i5) -> tuple<i4, i5>
198 // CHECK:           %[[RET_TUPLE_0:.*]] = "test.get_tuple_element"(%[[RET_TUPLE]]) <{index = 0 : i32}> : (tuple<i4, i5>) -> i4
199 // CHECK:           %[[RET_TUPLE_1:.*]] = "test.get_tuple_element"(%[[RET_TUPLE]]) <{index = 1 : i32}> : (tuple<i4, i5>) -> i5
200 // CHECK:           return %[[CALL]]#0, %[[CALL]]#1, %[[CALL]]#2, %[[RET_TUPLE_0]], %[[RET_TUPLE_1]], %[[CALL]]#5 : i1, i2, i3, i4, i5, i6
201 // CHECK-12N-LABEL:   func @caller(
202 // CHECK-12N-SAME:                 %[[I1:.*]]: i1,
203 // CHECK-12N-SAME:                 %[[I2:.*]]: i2,
204 // CHECK-12N-SAME:                 %[[I3:.*]]: i3,
205 // CHECK-12N-SAME:                 %[[I4:.*]]: i4,
206 // CHECK-12N-SAME:                 %[[I5:.*]]: i5,
207 // CHECK-12N-SAME:                 %[[I6:.*]]: i6) -> (i1, i2, i3, i4, i5, i6) {
208 // CHECK-12N:           %[[CALL:.*]]:6 = call @callee(%[[I1]], %[[I2]], %[[I3]], %[[I4]], %[[I5]], %[[I6]]) : (i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6)
209 // CHECK-12N:           return %[[CALL]]#0, %[[CALL]]#1, %[[CALL]]#2, %[[CALL]]#3, %[[CALL]]#4, %[[CALL]]#5 : i1, i2, i3, i4, i5, i6
210 func.func @caller(%arg0: tuple<>, %arg1: i1, %arg2: tuple<i2>, %arg3: i3, %arg4: tuple<i4, i5>, %arg5: i6) -> (tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6) {
211   %0, %1, %2, %3, %4, %5 = call @callee(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) : (tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6) -> (tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6)
212   return %0, %1, %2, %3, %4, %5 : tuple<>, i1, tuple<i2>, i3, tuple<i4, i5>, i6