llvm-project/mlir/test/Transforms/canonicalize-dce.mlir
River Riddle 3655069234 [mlir] Move the Builtin FuncOp to the Func dialect
This commit moves FuncOp out of the builtin dialect, and into the Func
dialect. This move has been planned in some capacity from the moment
we made FuncOp an operation (years ago). This commit handles the
functional aspects of the move, but various aspects are left untouched
to ease migration: func::FuncOp is re-exported into mlir to reduce
the actual API churn, the assembly format still accepts the unqualified
`func`. These temporary measures will remain for a little while to
simplify migration before being removed.

Differential Revision: https://reviews.llvm.org/D121266
2022-03-16 17:07:03 -07:00

176 lines
4.0 KiB
MLIR

// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -pass-pipeline='func.func(canonicalize)' | FileCheck %s
// Test case: Simple case of deleting a dead pure op.
// CHECK: func @f(%arg0: f32) {
// CHECK-NEXT: return
func @f(%arg0: f32) {
%0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32
return
}
// -----
// Test case: Simple case of deleting a block argument.
// CHECK: func @f(%arg0: f32)
// CHECK-NEXT: "test.br"()[^bb1]
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: return
func @f(%arg0: f32) {
"test.br"(%arg0)[^succ] : (f32) -> ()
^succ(%0: f32):
return
}
// -----
// Test case: Deleting recursively dead block arguments.
// CHECK: func @f(%arg0: f32)
// CHECK-NEXT: cf.br ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: cf.br ^bb1
func @f(%arg0: f32) {
cf.br ^loop(%arg0: f32)
^loop(%loop: f32):
cf.br ^loop(%loop: f32)
}
// -----
// Test case: Deleting recursively dead block arguments with pure ops in between.
// CHECK: func @f(%arg0: f32)
// CHECK-NEXT: cf.br ^bb1
// CHECK-NEXT: ^bb1:
// CHECK-NEXT: cf.br ^bb1
func @f(%arg0: f32) {
cf.br ^loop(%arg0: f32)
^loop(%0: f32):
%1 = "math.exp"(%0) : (f32) -> f32
cf.br ^loop(%1: f32)
}
// -----
// Test case: Delete block arguments for cf.cond_br.
// CHECK: func @f(%arg0: f32, %arg1: i1)
// CHECK-NEXT: return
func @f(%arg0: f32, %pred: i1) {
%exp = "math.exp"(%arg0) : (f32) -> f32
cf.cond_br %pred, ^true(%exp: f32), ^false(%exp: f32)
^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
func @f(%arg0: f32) {
func.func @g(%arg1: f32) {
%0 = "arith.addf"(%arg1, %arg1) : (f32, f32) -> f32
return
}
return
}
// -----
// Test case: Don't delete pure ops that feed into returns.
// CHECK: func @f(%arg0: f32) -> f32
// CHECK-NEXT: [[VAL0:%.+]] = arith.addf %arg0, %arg0 : f32
// CHECK-NEXT: return [[VAL0]] : f32
func @f(%arg0: f32) -> f32 {
%0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32
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
func @f(%arg0: f32) {
"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"
func @f(%arg0: f32) {
%0 = "math.exp"(%arg0) : (f32) -> f32
"foo.has_region"() ({
%1 = "math.exp"(%0) : (f32) -> f32
"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>)
// CHECK-NEXT: "test.br"(%arg1, %arg3)[^bb1] : (tensor<2xf32>, tensor<4xf32>)
// CHECK-NEXT: ^bb1([[VAL0:%.+]]: tensor<2xf32>, [[VAL1:%.+]]: tensor<4xf32>):
// CHECK-NEXT: "foo.print"([[VAL0]])
// CHECK-NEXT: "foo.print"([[VAL1]])
// CHECK-NEXT: return
func @f(
%arg0: tensor<1xf32>,
%arg1: tensor<2xf32>,
%arg2: tensor<3xf32>,
%arg3: tensor<4xf32>,
%arg4: tensor<5xf32>) {
"test.br"(%arg0, %arg1, %arg2, %arg3, %arg4)[^succ] : (tensor<1xf32>, tensor<2xf32>, tensor<3xf32>, tensor<4xf32>, tensor<5xf32>) -> ()
^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
}
// -----
// Test case: Test values with use-def cycles are deleted properly.
// CHECK: func @f()
// CHECK-NEXT: test.graph_region
// CHECK-NEXT: "test.terminator"() : () -> ()
func @f() {
test.graph_region {
%0 = "math.exp"(%1) : (f32) -> f32
%1 = "math.exp"(%0) : (f32) -> f32
"test.terminator"() : ()->()
}
return
}