@@ -234,3 +234,229 @@ module attributes {transform.with_named_sequence} {
234
234
transform.yield
235
235
}
236
236
}
237
+
238
+ // -----
239
+
240
+ // Check simple move value definitions before insertion operation.
241
+ func.func @simple_move_values () -> f32 {
242
+ %0 = " before" () : () -> (f32 )
243
+ %1 = " moved_op_1" () : () -> (f32 )
244
+ %2 = " moved_op_2" () : () -> (f32 )
245
+ %3 = " foo" (%1 , %2 ) : (f32 , f32 ) -> (f32 )
246
+ return %3 : f32
247
+ }
248
+ // CHECK-LABEL: func @simple_move_values()
249
+ // CHECK: %[[MOVED1:.+]] = "moved_op_1"
250
+ // CHECK: %[[MOVED2:.+]] = "moved_op_2"
251
+ // CHECK: %[[BEFORE:.+]] = "before"
252
+ // CHECK: %[[FOO:.+]] = "foo"(%[[MOVED1]], %[[MOVED2]])
253
+ // CHECK: return %[[FOO]]
254
+
255
+ module attributes {transform.with_named_sequence } {
256
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
257
+ %op1 = transform.structured.match ops {[" moved_op_1" ]} in %arg0
258
+ : (!transform.any_op ) -> !transform.any_op
259
+ %op2 = transform.structured.match ops {[" moved_op_2" ]} in %arg0
260
+ : (!transform.any_op ) -> !transform.any_op
261
+ %op3 = transform.structured.match ops {[" before" ]} in %arg0
262
+ : (!transform.any_op ) -> !transform.any_op
263
+ %v1 = transform.get_result %op1 [0 ] : (!transform.any_op ) -> !transform.any_value
264
+ %v2 = transform.get_result %op2 [0 ] : (!transform.any_op ) -> !transform.any_value
265
+ transform.test.move_value_defns %v1 , %v2 before %op3
266
+ : (!transform.any_value , !transform.any_value ), !transform.any_op
267
+ transform.yield
268
+ }
269
+ }
270
+
271
+ // -----
272
+
273
+ // Compute slice including the implicitly captured values.
274
+ func.func @move_region_dependencies_values () -> f32 {
275
+ %0 = " before" () : () -> (f32 )
276
+ %1 = " moved_op_1" () : () -> (f32 )
277
+ %2 = " moved_op_2" () ({
278
+ %3 = " inner_op" (%1 ) : (f32 ) -> (f32 )
279
+ " yield" (%3 ) : (f32 ) -> ()
280
+ }) : () -> (f32 )
281
+ return %2 : f32
282
+ }
283
+ // CHECK-LABEL: func @move_region_dependencies_values()
284
+ // CHECK: %[[MOVED1:.+]] = "moved_op_1"
285
+ // CHECK: %[[MOVED2:.+]] = "moved_op_2"
286
+ // CHECK: %[[BEFORE:.+]] = "before"
287
+
288
+ module attributes {transform.with_named_sequence } {
289
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
290
+ %op1 = transform.structured.match ops {[" moved_op_2" ]} in %arg0
291
+ : (!transform.any_op ) -> !transform.any_op
292
+ %op2 = transform.structured.match ops {[" before" ]} in %arg0
293
+ : (!transform.any_op ) -> !transform.any_op
294
+ %v1 = transform.get_result %op1 [0 ] : (!transform.any_op ) -> !transform.any_value
295
+ transform.test.move_value_defns %v1 before %op2
296
+ : (!transform.any_value ), !transform.any_op
297
+ transform.yield
298
+ }
299
+ }
300
+
301
+ // -----
302
+
303
+ // Move operations in toplogical sort order
304
+ func.func @move_values_in_topological_sort_order () -> f32 {
305
+ %0 = " before" () : () -> (f32 )
306
+ %1 = " moved_op_1" () : () -> (f32 )
307
+ %2 = " moved_op_2" () : () -> (f32 )
308
+ %3 = " moved_op_3" (%1 ) : (f32 ) -> (f32 )
309
+ %4 = " moved_op_4" (%1 , %3 ) : (f32 , f32 ) -> (f32 )
310
+ %5 = " moved_op_5" (%2 ) : (f32 ) -> (f32 )
311
+ %6 = " foo" (%4 , %5 ) : (f32 , f32 ) -> (f32 )
312
+ return %6 : f32
313
+ }
314
+ // CHECK-LABEL: func @move_values_in_topological_sort_order()
315
+ // CHECK: %[[MOVED_1:.+]] = "moved_op_1"
316
+ // CHECK-DAG: %[[MOVED_2:.+]] = "moved_op_3"(%[[MOVED_1]])
317
+ // CHECK-DAG: %[[MOVED_3:.+]] = "moved_op_4"(%[[MOVED_1]], %[[MOVED_2]])
318
+ // CHECK-DAG: %[[MOVED_4:.+]] = "moved_op_2"
319
+ // CHECK-DAG: %[[MOVED_5:.+]] = "moved_op_5"(%[[MOVED_4]])
320
+ // CHECK: %[[BEFORE:.+]] = "before"
321
+ // CHECK: %[[FOO:.+]] = "foo"(%[[MOVED_3]], %[[MOVED_5]])
322
+ // CHECK: return %[[FOO]]
323
+
324
+ module attributes {transform.with_named_sequence } {
325
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
326
+ %op1 = transform.structured.match ops {[" moved_op_4" ]} in %arg0
327
+ : (!transform.any_op ) -> !transform.any_op
328
+ %op2 = transform.structured.match ops {[" moved_op_5" ]} in %arg0
329
+ : (!transform.any_op ) -> !transform.any_op
330
+ %op3 = transform.structured.match ops {[" before" ]} in %arg0
331
+ : (!transform.any_op ) -> !transform.any_op
332
+ %v1 = transform.get_result %op1 [0 ] : (!transform.any_op ) -> !transform.any_value
333
+ %v2 = transform.get_result %op2 [0 ] : (!transform.any_op ) -> !transform.any_value
334
+ transform.test.move_value_defns %v1 , %v2 before %op3
335
+ : (!transform.any_value , !transform.any_value ), !transform.any_op
336
+ transform.yield
337
+ }
338
+ }
339
+
340
+ // -----
341
+
342
+ // Move only those value definitions that are not dominated by insertion point
343
+
344
+ func.func @move_only_required_defns () -> (f32 , f32 , f32 , f32 ) {
345
+ %0 = " unmoved_op" () : () -> (f32 )
346
+ %1 = " dummy_op" () : () -> (f32 )
347
+ %2 = " before" () : () -> (f32 )
348
+ %3 = " moved_op" () : () -> (f32 )
349
+ return %0 , %1 , %2 , %3 : f32 , f32 , f32 , f32
350
+ }
351
+ // CHECK-LABEL: func @move_only_required_defns()
352
+ // CHECK: %[[UNMOVED:.+]] = "unmoved_op"
353
+ // CHECK: %[[DUMMY:.+]] = "dummy_op"
354
+ // CHECK: %[[MOVED:.+]] = "moved_op"
355
+ // CHECK: %[[BEFORE:.+]] = "before"
356
+
357
+ module attributes {transform.with_named_sequence } {
358
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
359
+ %op1 = transform.structured.match ops {[" unmoved_op" ]} in %arg0
360
+ : (!transform.any_op ) -> !transform.any_op
361
+ %op2 = transform.structured.match ops {[" dummy_op" ]} in %arg0
362
+ : (!transform.any_op ) -> !transform.any_op
363
+ %op3 = transform.structured.match ops {[" before" ]} in %arg0
364
+ : (!transform.any_op ) -> !transform.any_op
365
+ %op4 = transform.structured.match ops {[" moved_op" ]} in %arg0
366
+ : (!transform.any_op ) -> !transform.any_op
367
+ %v1 = transform.get_result %op1 [0 ] : (!transform.any_op ) -> !transform.any_value
368
+ %v2 = transform.get_result %op4 [0 ] : (!transform.any_op ) -> !transform.any_value
369
+ transform.test.move_value_defns %v1 , %v2 before %op3
370
+ : (!transform.any_value , !transform.any_value ), !transform.any_op
371
+ transform.yield
372
+ }
373
+ }
374
+
375
+ // -----
376
+
377
+ // Move only those value definitions that are not dominated by insertion point
378
+
379
+ func.func @move_only_required_defns () -> (f32 , f32 , f32 , f32 ) {
380
+ %0 = " unmoved_op" () : () -> (f32 )
381
+ %1 = " dummy_op" () : () -> (f32 )
382
+ %2 = " before" () : () -> (f32 )
383
+ %3 = " moved_op" () : () -> (f32 )
384
+ return %0 , %1 , %2 , %3 : f32 , f32 , f32 , f32
385
+ }
386
+ // CHECK-LABEL: func @move_only_required_defns()
387
+ // CHECK: %[[UNMOVED:.+]] = "unmoved_op"
388
+ // CHECK: %[[DUMMY:.+]] = "dummy_op"
389
+ // CHECK: %[[MOVED:.+]] = "moved_op"
390
+ // CHECK: %[[BEFORE:.+]] = "before"
391
+
392
+ module attributes {transform.with_named_sequence } {
393
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
394
+ %op1 = transform.structured.match ops {[" unmoved_op" ]} in %arg0
395
+ : (!transform.any_op ) -> !transform.any_op
396
+ %op2 = transform.structured.match ops {[" dummy_op" ]} in %arg0
397
+ : (!transform.any_op ) -> !transform.any_op
398
+ %op3 = transform.structured.match ops {[" before" ]} in %arg0
399
+ : (!transform.any_op ) -> !transform.any_op
400
+ %op4 = transform.structured.match ops {[" moved_op" ]} in %arg0
401
+ : (!transform.any_op ) -> !transform.any_op
402
+ %v1 = transform.get_result %op1 [0 ] : (!transform.any_op ) -> !transform.any_value
403
+ %v2 = transform.get_result %op4 [0 ] : (!transform.any_op ) -> !transform.any_value
404
+ transform.test.move_value_defns %v1 , %v2 before %op3
405
+ : (!transform.any_value , !transform.any_value ), !transform.any_op
406
+ transform.yield
407
+ }
408
+ }
409
+
410
+ // -----
411
+
412
+ // Check handling of block arguments
413
+ func.func @move_only_required_defns () -> (f32 , f32 ) {
414
+ %0 = " unmoved_op" () : () -> (f32 )
415
+ cf.br ^bb0 (%0 : f32 )
416
+ ^bb0 (%arg0 : f32 ) :
417
+ %1 = " before" () : () -> (f32 )
418
+ %2 = " moved_op" (%arg0 ) : (f32 ) -> (f32 )
419
+ return %1 , %2 : f32 , f32
420
+ }
421
+ // CHECK-LABEL: func @move_only_required_defns()
422
+ // CHECK: %[[MOVED:.+]] = "moved_op"
423
+ // CHECK: %[[BEFORE:.+]] = "before"
424
+
425
+ module attributes {transform.with_named_sequence } {
426
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
427
+ %op1 = transform.structured.match ops {[" before" ]} in %arg0
428
+ : (!transform.any_op ) -> !transform.any_op
429
+ %op2 = transform.structured.match ops {[" moved_op" ]} in %arg0
430
+ : (!transform.any_op ) -> !transform.any_op
431
+ %v1 = transform.get_result %op2 [0 ] : (!transform.any_op ) -> !transform.any_value
432
+ transform.test.move_value_defns %v1 before %op1
433
+ : (!transform.any_value ), !transform.any_op
434
+ transform.yield
435
+ }
436
+ }
437
+
438
+ // -----
439
+
440
+ // Do not move across basic blocks
441
+ func.func @no_move_across_basic_blocks () -> (f32 , f32 ) {
442
+ %0 = " unmoved_op" () : () -> (f32 )
443
+ %1 = " before" () : () -> (f32 )
444
+ cf.br ^bb0 (%0 : f32 )
445
+ ^bb0 (%arg0 : f32 ) :
446
+ %2 = " moved_op" (%arg0 ) : (f32 ) -> (f32 )
447
+ return %1 , %2 : f32 , f32
448
+ }
449
+
450
+ module attributes {transform.with_named_sequence } {
451
+ transform.named_sequence @__transform_main (%arg0 : !transform.any_op {transform.readonly }) {
452
+ %op1 = transform.structured.match ops {[" before" ]} in %arg0
453
+ : (!transform.any_op ) -> !transform.any_op
454
+ %op2 = transform.structured.match ops {[" moved_op" ]} in %arg0
455
+ : (!transform.any_op ) -> !transform.any_op
456
+ %v1 = transform.get_result %op2 [0 ] : (!transform.any_op ) -> !transform.any_value
457
+ // expected-remark@+1{{unsupported case of moving definition of value before an insertion point in a different basic block}}
458
+ transform.test.move_value_defns %v1 before %op1
459
+ : (!transform.any_value ), !transform.any_op
460
+ transform.yield
461
+ }
462
+ }
0 commit comments