Fix GCC build problem with 288f05f related to SmallVector. (#116958)
[llvm-project.git] / mlir / test / Transforms / test-legalizer.mlir
blobe5503ee8920424d6cf7882f832e9f02eee3b27b1
1 // RUN: mlir-opt -allow-unregistered-dialect -split-input-file -test-legalize-patterns -verify-diagnostics %s | FileCheck %s
3 //      CHECK: notifyOperationInserted: test.legal_op_a, was unlinked
4 // CHECK-NEXT: notifyOperationReplaced: test.illegal_op_a
5 // CHECK-NEXT: notifyOperationModified: func.return
6 // CHECK-NEXT: notifyOperationErased: test.illegal_op_a
8 // CHECK-LABEL: verifyDirectPattern
9 func.func @verifyDirectPattern() -> i32 {
10   // CHECK-NEXT:  "test.legal_op_a"() <{status = "Success"}
11   %result = "test.illegal_op_a"() : () -> (i32)
12   // expected-remark@+1 {{op 'func.return' is not legalizable}}
13   return %result : i32
16 // -----
18 //      CHECK: notifyOperationInserted: test.illegal_op_e, was unlinked
19 // CHECK-NEXT: notifyOperationReplaced: test.illegal_op_c
20 // CHECK-NEXT: notifyOperationModified: func.return
21 // CHECK-NEXT: notifyOperationErased: test.illegal_op_c
22 // CHECK-NEXT: notifyOperationInserted: test.legal_op_a, was unlinked
23 // CHECK-NEXT: notifyOperationReplaced: test.illegal_op_e
24 // CHECK-NEXT: notifyOperationErased: test.illegal_op_e
26 // CHECK-LABEL: verifyLargerBenefit
27 func.func @verifyLargerBenefit() -> i32 {
28   // CHECK-NEXT:  "test.legal_op_a"() <{status = "Success"}
29   %result = "test.illegal_op_c"() : () -> (i32)
30   // expected-remark@+1 {{op 'func.return' is not legalizable}}
31   return %result : i32
34 // -----
36 // CHECK: notifyOperationModified: func.func
37 // Note: No block insertion because this function is external and no block
38 // signature conversion is performed.
40 // CHECK-LABEL: func private @remap_input_1_to_0()
41 func.func private @remap_input_1_to_0(i16)
43 // -----
45 // CHECK-LABEL: func @remap_input_1_to_1(%arg0: f64)
46 func.func @remap_input_1_to_1(%arg0: i64) {
47   // CHECK-NEXT: "test.valid"{{.*}} : (f64)
48   "test.invalid"(%arg0) : (i64) -> ()
51 // CHECK: func @remap_call_1_to_1(%arg0: f64)
52 func.func @remap_call_1_to_1(%arg0: i64) {
53   // CHECK-NEXT: call @remap_input_1_to_1(%arg0) : (f64) -> ()
54   call @remap_input_1_to_1(%arg0) : (i64) -> ()
55   // expected-remark@+1 {{op 'func.return' is not legalizable}}
56   return
59 // -----
61 // Block signature conversion: new block is inserted.
62 // CHECK:      notifyBlockInserted into func.func: was unlinked
64 // Contents of the old block are moved to the new block.
65 // CHECK-NEXT: notifyOperationInserted: test.return, was linked, exact position unknown
67 // The new block arguments are used in "test.return".
68 // CHECK-NEXT: notifyOperationModified: test.return
70 // The old block is erased.
71 // CHECK-NEXT: notifyBlockErased
73 // The function op gets a new type attribute.
74 // CHECK-NEXT: notifyOperationModified: func.func
76 // "test.return" is replaced.
77 // CHECK-NEXT: notifyOperationInserted: test.return, was unlinked
78 // CHECK-NEXT: notifyOperationReplaced: test.return
79 // CHECK-NEXT: notifyOperationErased: test.return
81 // CHECK-LABEL: func @remap_input_1_to_N({{.*}}f16, {{.*}}f16)
82 func.func @remap_input_1_to_N(%arg0: f32) -> f32 {
83   // CHECK-NEXT: "test.return"{{.*}} : (f16, f16) -> ()
84   "test.return"(%arg0) : (f32) -> ()
87 // -----
89 // CHECK-LABEL: func @remap_input_1_to_N_remaining_use(%arg0: f16, %arg1: f16)
90 func.func @remap_input_1_to_N_remaining_use(%arg0: f32) {
91   // CHECK-NEXT: [[CAST:%.*]] = "test.cast"(%arg0, %arg1) : (f16, f16) -> f32
92   // CHECK-NEXT: "work"([[CAST]]) : (f32) -> ()
93   // expected-remark@+1 {{op 'work' is not legalizable}}
94   "work"(%arg0) : (f32) -> ()
97 // CHECK-LABEL: func @remap_materialize_1_to_1(%{{.*}}: i43)
98 func.func @remap_materialize_1_to_1(%arg0: i42) {
99   // CHECK: %[[V:.*]] = "test.cast"(%arg0) : (i43) -> i42
100   // CHECK: "test.return"(%[[V]])
101   "test.return"(%arg0) : (i42) -> ()
104 // -----
106 // CHECK-LABEL: func @remap_input_to_self
107 func.func @remap_input_to_self(%arg0: index) {
108   // CHECK-NOT: test.cast
109   // CHECK: "work"
110   // expected-remark@+1 {{op 'work' is not legalizable}}
111   "work"(%arg0) : (index) -> ()
114 // CHECK-LABEL: func @remap_multi(%arg0: f64, %arg1: f64) -> (f64, f64)
115 func.func @remap_multi(%arg0: i64, %unused: i16, %arg1: i64) -> (i64, i64) {
116  // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64)
117  "test.invalid"(%arg0, %arg1) : (i64, i64) -> ()
120 // -----
122 // CHECK-LABEL: func @no_remap_nested
123 func.func @no_remap_nested() {
124   // CHECK-NEXT: "foo.region"
125   // expected-remark@+1 {{op 'foo.region' is not legalizable}}
126   "foo.region"() ({
127     // CHECK-NEXT: ^bb0(%{{.*}}: i64, %{{.*}}: i16, %{{.*}}: i64):
128     ^bb0(%i0: i64, %unused: i16, %i1: i64):
129       // CHECK-NEXT: "test.valid"{{.*}} : (i64, i64)
130       "test.invalid"(%i0, %i1) : (i64, i64) -> ()
131   }) : () -> ()
132   // expected-remark@+1 {{op 'func.return' is not legalizable}}
133   return
136 // -----
138 // CHECK-LABEL: func @remap_moved_region_args
139 func.func @remap_moved_region_args() {
140   // CHECK-NEXT: return
141   // CHECK-NEXT: ^bb1(%{{.*}}: f64, %{{.*}}: f64, %{{.*}}: f16, %{{.*}}: f16):
142   // CHECK-NEXT: "test.cast"{{.*}} : (f16, f16) -> f32
143   // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64, f32)
144   "test.region"() ({
145     ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32):
146       "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> ()
147   }) : () -> ()
148   // expected-remark@+1 {{op 'func.return' is not legalizable}}
149   return
152 // -----
154 // CHECK-LABEL: func @remap_cloned_region_args
155 func.func @remap_cloned_region_args() {
156   // CHECK-NEXT: return
157   // CHECK-NEXT: ^bb1(%{{.*}}: f64, %{{.*}}: f64, %{{.*}}: f16, %{{.*}}: f16):
158   // CHECK-NEXT: "test.cast"{{.*}} : (f16, f16) -> f32
159   // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64, f32)
160   "test.region"() ({
161     ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32):
162       "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> ()
163   }) {legalizer.should_clone} : () -> ()
164   // expected-remark@+1 {{op 'func.return' is not legalizable}}
165   return
168 // CHECK-LABEL: func @remap_drop_region
169 func.func @remap_drop_region() {
170   // CHECK-NEXT: return
171   // CHECK-NEXT: }
172   "test.drop_region_op"() ({
173     ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32):
174       "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> ()
175   }) : () -> ()
176   // expected-remark@+1 {{op 'func.return' is not legalizable}}
177   return
180 // -----
182 // CHECK-LABEL: func @dropped_input_in_use
183 func.func @dropped_input_in_use(%arg: i16, %arg2: i64) {
184   // CHECK-NEXT: "test.cast"{{.*}} : () -> i16
185   // CHECK-NEXT: "work"{{.*}} : (i16)
186   // expected-remark@+1 {{op 'work' is not legalizable}}
187   "work"(%arg) : (i16) -> ()
190 // -----
192 // CHECK-LABEL: func @up_to_date_replacement
193 func.func @up_to_date_replacement(%arg: i8) -> i8 {
194   // CHECK-NEXT: return
195   %repl_1 = "test.rewrite"(%arg) : (i8) -> i8
196   %repl_2 = "test.rewrite"(%repl_1) : (i8) -> i8
197   // expected-remark@+1 {{op 'func.return' is not legalizable}}
198   return %repl_2 : i8
201 // -----
203 // CHECK-LABEL: func @remove_foldable_op
204 // CHECK-SAME:                          (%[[ARG_0:[a-z0-9]*]]: i32)
205 func.func @remove_foldable_op(%arg0 : i32) -> (i32) {
206   // CHECK-NEXT: return %[[ARG_0]]
207   %0 = "test.op_with_region_fold"(%arg0) ({
208     "foo.op_with_region_terminator"() : () -> ()
209   }) : (i32) -> (i32)
210   // expected-remark@+1 {{op 'func.return' is not legalizable}}
211   return %0 : i32
214 // -----
216 // CHECK-LABEL: @create_block
217 func.func @create_block() {
218   // Check that we created a block with arguments.
219   // CHECK-NOT: test.create_block
220   // CHECK: ^{{.*}}(%{{.*}}: i32, %{{.*}}: i32):
221   "test.create_block"() : () -> ()
223   // expected-remark@+1 {{op 'func.return' is not legalizable}}
224   return
227 // -----
229 //      CHECK: notifyOperationModified: test.recursive_rewrite
230 // CHECK-NEXT: notifyOperationModified: test.recursive_rewrite
231 // CHECK-NEXT: notifyOperationModified: test.recursive_rewrite
233 // CHECK-LABEL: @bounded_recursion
234 func.func @bounded_recursion() {
235   // CHECK: test.recursive_rewrite 0
236   test.recursive_rewrite 3
237   // expected-remark@+1 {{op 'func.return' is not legalizable}}
238   return
241 // -----
243 // expected-remark@+1 {{applyPartialConversion failed}}
244 builtin.module {
246   func.func @fail_to_convert_illegal_op() -> i32 {
247     // expected-error@+1 {{failed to legalize operation 'test.illegal_op_f'}}
248     %result = "test.illegal_op_f"() : () -> (i32)
249     return %result : i32
250   }
254 // -----
256 // expected-remark@+1 {{applyPartialConversion failed}}
257 builtin.module {
259   func.func @fail_to_convert_illegal_op_in_region() {
260     // expected-error@+1 {{failed to legalize operation 'test.region_builder'}}
261     "test.region_builder"() : () -> ()
262     return
263   }
267 // -----
269 // Check that the entry block arguments of a region are untouched in the case
270 // of failure.
272 // expected-remark@+1 {{applyPartialConversion failed}}
273 builtin.module {
275   func.func @fail_to_convert_region() {
276     // CHECK: "test.region"
277     // CHECK-NEXT: ^bb{{.*}}(%{{.*}}: i64):
278     "test.region"() ({
279       ^bb1(%i0: i64):
280         // expected-error@+1 {{failed to legalize operation 'test.region_builder'}}
281         "test.region_builder"() : () -> ()
282         "test.valid"() : () -> ()
283     }) : () -> ()
284     return
285   }
289 // -----
291 // CHECK-LABEL: @create_illegal_block
292 func.func @create_illegal_block() {
293   // Check that we can undo block creation, i.e. that the block was removed.
294   // CHECK: test.create_illegal_block
295   // CHECK-NOT: ^{{.*}}(%{{.*}}: i32, %{{.*}}: i32):
296   // expected-remark@+1 {{op 'test.create_illegal_block' is not legalizable}}
297   "test.create_illegal_block"() : () -> ()
299   // expected-remark@+1 {{op 'func.return' is not legalizable}}
300   return
303 // -----
305 // CHECK-LABEL: @undo_block_arg_replace
306 func.func @undo_block_arg_replace() {
307   // expected-remark@+1 {{op 'test.undo_block_arg_replace' is not legalizable}}
308   "test.undo_block_arg_replace"() ({
309   ^bb0(%arg0: i32):
310     // CHECK: ^bb0(%[[ARG:.*]]: i32):
311     // CHECK-NEXT: "test.return"(%[[ARG]]) : (i32)
313     "test.return"(%arg0) : (i32) -> ()
314   }) : () -> ()
315   // expected-remark@+1 {{op 'func.return' is not legalizable}}
316   return
319 // -----
321 // The op in this function is rewritten to itself (and thus remains illegal) by
322 // a pattern that removes its second block after adding an operation into it.
323 // Check that we can undo block removal successfully.
324 // CHECK-LABEL: @undo_block_erase
325 func.func @undo_block_erase() {
326   // CHECK: test.undo_block_erase
327   "test.undo_block_erase"() ({
328     // expected-remark@-1 {{not legalizable}}
329     // CHECK: "unregistered.return"()[^[[BB:.*]]]
330     "unregistered.return"()[^bb1] : () -> ()
331     // expected-remark@-1 {{not legalizable}}
332   // CHECK: ^[[BB]]
333   ^bb1:
334     // CHECK: unregistered.return
335     "unregistered.return"() : () -> ()
336     // expected-remark@-1 {{not legalizable}}
337   }) : () -> ()
340 // -----
342 // The op in this function is attempted to be rewritten to another illegal op
343 // with an attached region containing an invalid terminator. The terminator is
344 // created before the parent op. The deletion should not crash when deleting
345 // created ops in the inverse order, i.e. deleting the parent op and then the
346 // child op.
347 // CHECK-LABEL: @undo_child_created_before_parent
348 func.func @undo_child_created_before_parent() {
349   // expected-remark@+1 {{is not legalizable}}
350   "test.illegal_op_with_region_anchor"() : () -> ()
351   // expected-remark@+1 {{op 'func.return' is not legalizable}}
352   return
355 // -----
357 // Check that a conversion pattern on `test.blackhole` can mark the producer
358 // for deletion.
359 // CHECK-LABEL: @blackhole
360 func.func @blackhole() {
361   %input = "test.blackhole_producer"() : () -> (i32)
362   "test.blackhole"(%input) : (i32) -> ()
363   // expected-remark@+1 {{op 'func.return' is not legalizable}}
364   return
367 // -----
369 // expected-remark@+1 {{applyPartialConversion failed}}
370 builtin.module {
372   func.func @create_unregistered_op_in_pattern() -> i32 {
373     // expected-error@+1 {{failed to legalize operation 'test.illegal_op_g'}}
374     %0 = "test.illegal_op_g"() : () -> (i32)
375     "test.return"(%0) : (i32) -> ()
376   }
380 // -----
382 // expected-remark @below {{applyPartialConversion failed}}
383 module {
384   func.func private @callee(%0 : f32) -> f32
386   func.func @caller( %arg: f32) {
387     // expected-error @below {{failed to legalize}}
388     %1 = func.call @callee(%arg) : (f32) -> f32
389     return
390   }
393 // -----
395 // CHECK-LABEL: func @test_move_op_before_rollback()
396 func.func @test_move_op_before_rollback() {
397   // CHECK: "test.one_region_op"()
398   // CHECK: "test.hoist_me"()
399   "test.one_region_op"() ({
400     // expected-remark @below{{'test.hoist_me' is not legalizable}}
401     %0 = "test.hoist_me"() : () -> (i32)
402     "test.valid"(%0) : (i32) -> ()
403   }) : () -> ()
404   "test.return"() : () -> ()
407 // -----
409 // CHECK-LABEL: func @test_properties_rollback()
410 func.func @test_properties_rollback() {
411   // CHECK: test.with_properties a = 32,
412   // expected-remark @below{{op 'test.with_properties' is not legalizable}}
413   test.with_properties
414       a = 32, b = "foo", c = "bar", flag = true, array = [1, 2, 3, 4]
415       {modify_inplace}
416   "test.return"() : () -> ()
419 // -----
421 //      CHECK: func.func @use_of_replaced_bbarg(
422 // CHECK-SAME:     %[[arg0:.*]]: f64)
423 //      CHECK:   "test.valid"(%[[arg0]])
424 func.func @use_of_replaced_bbarg(%arg0: i64) {
425   %0 = "test.op_with_region_fold"(%arg0) ({
426     "foo.op_with_region_terminator"() : () -> ()
427   }) : (i64) -> (i64)
428   "test.invalid"(%0) : (i64) -> ()
431 // -----
433 // CHECK-LABEL: @fold_legalization
434 func.func @fold_legalization() -> i32 {
435   // CHECK: op_in_place_self_fold
436   // CHECK-SAME: folded
437   %1 = "test.op_in_place_self_fold"() : () -> (i32)
438   "test.return"(%1) : (i32) -> ()
441 // -----
443 // CHECK-LABEL: func @convert_detached_signature()
444 //       CHECK:   "test.legal_op_with_region"() ({
445 //       CHECK:   ^bb0(%arg0: f64):
446 //       CHECK:     "test.return"() : () -> ()
447 //       CHECK:   }) : () -> ()
448 func.func @convert_detached_signature() {
449   "test.detached_signature_conversion"() ({
450   ^bb0(%arg0: i64):
451     "test.return"() : () -> ()
452   }) : () -> ()
453   "test.return"() : () -> ()
456 // -----
458 // CHECK-LABEL: func @circular_mapping()
459 //  CHECK-NEXT:   "test.valid"() : () -> ()
460 func.func @circular_mapping() {
461   // Regression test that used to crash due to circular
462   // unrealized_conversion_cast ops.
463   %0 = "test.erase_op"() : () -> (i64)
464   "test.drop_operands_and_replace_with_valid"(%0) : (i64) -> ()