2022-10-18 18:44:11 +00:00
|
|
|
// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -pass-pipeline='builtin.module(func.func(canonicalize))' | FileCheck %s
|
2019-11-20 19:48:57 +00:00
|
|
|
|
|
|
|
// Test case: Simple case of deleting a dead pure op.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32) {
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2021-10-12 23:14:57 +00:00
|
|
|
%0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32
|
2019-11-20 19:48:57 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Simple case of deleting a block argument.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
2019-11-20 23:23:52 +00:00
|
|
|
// CHECK-NEXT: "test.br"()[^bb1]
|
2019-11-20 19:48:57 +00:00
|
|
|
// CHECK-NEXT: ^bb1:
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2020-03-05 20:48:28 +00:00
|
|
|
"test.br"(%arg0)[^succ] : (f32) -> ()
|
2019-11-20 19:48:57 +00:00
|
|
|
^succ(%0: f32):
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Deleting recursively dead block arguments.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
2022-02-04 04:59:43 +00:00
|
|
|
// CHECK-NEXT: cf.br ^bb1
|
2019-11-20 19:48:57 +00:00
|
|
|
// CHECK-NEXT: ^bb1:
|
2022-02-04 04:59:43 +00:00
|
|
|
// CHECK-NEXT: cf.br ^bb1
|
2019-11-20 19:48:57 +00:00
|
|
|
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2022-02-04 04:59:43 +00:00
|
|
|
cf.br ^loop(%arg0: f32)
|
2019-11-20 19:48:57 +00:00
|
|
|
^loop(%loop: f32):
|
2022-02-04 04:59:43 +00:00
|
|
|
cf.br ^loop(%loop: f32)
|
2019-11-20 19:48:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Deleting recursively dead block arguments with pure ops in between.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
2022-02-04 04:59:43 +00:00
|
|
|
// CHECK-NEXT: cf.br ^bb1
|
2019-11-20 19:48:57 +00:00
|
|
|
// CHECK-NEXT: ^bb1:
|
2022-02-04 04:59:43 +00:00
|
|
|
// CHECK-NEXT: cf.br ^bb1
|
2019-11-20 19:48:57 +00:00
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2022-02-04 04:59:43 +00:00
|
|
|
cf.br ^loop(%arg0: f32)
|
2019-11-20 19:48:57 +00:00
|
|
|
^loop(%0: f32):
|
2021-02-12 09:34:42 +00:00
|
|
|
%1 = "math.exp"(%0) : (f32) -> f32
|
2022-02-04 04:59:43 +00:00
|
|
|
cf.br ^loop(%1: f32)
|
2019-11-20 19:48:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2022-02-04 04:59:43 +00:00
|
|
|
// Test case: Delete block arguments for cf.cond_br.
|
2019-11-20 19:48:57 +00:00
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32, %arg1: i1)
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32, %pred: i1) {
|
2021-02-12 09:34:42 +00:00
|
|
|
%exp = "math.exp"(%arg0) : (f32) -> f32
|
2022-02-04 04:59:43 +00:00
|
|
|
cf.cond_br %pred, ^true(%exp: f32), ^false(%exp: f32)
|
2019-11-20 19:48:57 +00:00
|
|
|
^true(%0: f32):
|
|
|
|
return
|
|
|
|
^false(%1: f32):
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Recursively DCE into enclosed regions.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
|
|
|
// CHECK-NEXT: func @g(%arg1: f32)
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2022-03-08 03:16:03 +00:00
|
|
|
func.func @g(%arg1: f32) {
|
2021-10-12 23:14:57 +00:00
|
|
|
%0 = "arith.addf"(%arg1, %arg1) : (f32, f32) -> f32
|
2019-11-20 19:48:57 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Don't delete pure ops that feed into returns.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32) -> f32
|
2021-10-12 23:14:57 +00:00
|
|
|
// CHECK-NEXT: [[VAL0:%.+]] = arith.addf %arg0, %arg0 : f32
|
2019-11-20 19:48:57 +00:00
|
|
|
// CHECK-NEXT: return [[VAL0]] : f32
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) -> f32 {
|
2021-10-12 23:14:57 +00:00
|
|
|
%0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32
|
2019-11-20 19:48:57 +00:00
|
|
|
return %0 : f32
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Don't delete potentially side-effecting ops.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
|
|
|
// CHECK-NEXT: "foo.print"(%arg0) : (f32) -> ()
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2019-11-20 19:48:57 +00:00
|
|
|
"foo.print"(%arg0) : (f32) -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Uses in nested regions are deleted correctly.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: f32)
|
|
|
|
// CHECK-NEXT: "foo.has_region"
|
|
|
|
// CHECK-NEXT: "foo.return"
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(%arg0: f32) {
|
2021-02-12 09:34:42 +00:00
|
|
|
%0 = "math.exp"(%arg0) : (f32) -> f32
|
2019-11-20 19:48:57 +00:00
|
|
|
"foo.has_region"() ({
|
2021-02-12 09:34:42 +00:00
|
|
|
%1 = "math.exp"(%0) : (f32) -> f32
|
2019-11-20 19:48:57 +00:00
|
|
|
"foo.return"() : () -> ()
|
|
|
|
}) : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Test the mechanics of deleting multiple block arguments.
|
|
|
|
|
|
|
|
// CHECK: func @f(%arg0: tensor<1xf32>, %arg1: tensor<2xf32>, %arg2: tensor<3xf32>, %arg3: tensor<4xf32>, %arg4: tensor<5xf32>)
|
2020-03-05 20:48:28 +00:00
|
|
|
// CHECK-NEXT: "test.br"(%arg1, %arg3)[^bb1] : (tensor<2xf32>, tensor<4xf32>)
|
2019-11-20 19:48:57 +00:00
|
|
|
// CHECK-NEXT: ^bb1([[VAL0:%.+]]: tensor<2xf32>, [[VAL1:%.+]]: tensor<4xf32>):
|
|
|
|
// CHECK-NEXT: "foo.print"([[VAL0]])
|
|
|
|
// CHECK-NEXT: "foo.print"([[VAL1]])
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f(
|
2019-11-20 19:48:57 +00:00
|
|
|
%arg0: tensor<1xf32>,
|
|
|
|
%arg1: tensor<2xf32>,
|
|
|
|
%arg2: tensor<3xf32>,
|
|
|
|
%arg3: tensor<4xf32>,
|
|
|
|
%arg4: tensor<5xf32>) {
|
2020-03-05 20:48:28 +00:00
|
|
|
"test.br"(%arg0, %arg1, %arg2, %arg3, %arg4)[^succ] : (tensor<1xf32>, tensor<2xf32>, tensor<3xf32>, tensor<4xf32>, tensor<5xf32>) -> ()
|
2019-11-20 19:48:57 +00:00
|
|
|
^succ(%t1: tensor<1xf32>, %t2: tensor<2xf32>, %t3: tensor<3xf32>, %t4: tensor<4xf32>, %t5: tensor<5xf32>):
|
|
|
|
"foo.print"(%t2) : (tensor<2xf32>) -> ()
|
|
|
|
"foo.print"(%t4) : (tensor<4xf32>) -> ()
|
|
|
|
return
|
|
|
|
}
|
2021-03-19 03:06:02 +00:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test case: Test values with use-def cycles are deleted properly.
|
|
|
|
|
|
|
|
// CHECK: func @f()
|
|
|
|
// CHECK-NEXT: test.graph_region
|
|
|
|
// CHECK-NEXT: "test.terminator"() : () -> ()
|
|
|
|
|
2022-04-20 23:22:21 +00:00
|
|
|
func.func @f() {
|
2021-03-19 03:06:02 +00:00
|
|
|
test.graph_region {
|
|
|
|
%0 = "math.exp"(%1) : (f32) -> f32
|
|
|
|
%1 = "math.exp"(%0) : (f32) -> f32
|
|
|
|
"test.terminator"() : ()->()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2022-07-19 08:58:25 +00:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
|
|
|
|
// Test case: Delete ops that only have side-effects on an allocated result.
|
|
|
|
|
|
|
|
// CHECK: func @f()
|
|
|
|
// CHECK-NOT: test_effects_result
|
|
|
|
// CHECK-NEXT: return
|
|
|
|
|
|
|
|
func.func @f() {
|
|
|
|
%0 = "test.test_effects_result"() : () -> i32
|
|
|
|
return
|
|
|
|
}
|