// RUN: mlir-opt -allow-unregistered-dialect %s -inline -split-input-file | FileCheck %s // This file tests the callgraph dead code elimination performed by the inliner. // Function is already dead. // CHECK-NOT: func private @dead_function func.func private @dead_function() { return } // Function becomes dead after inlining. // CHECK-NOT: func private @dead_function_b func.func @dead_function_b() { return } // CHECK: func @live_function() func.func @live_function() { call @dead_function_b() : () -> () return } // Same as above, but a transitive example. // CHECK: func @live_function_b func.func @live_function_b() { return } // CHECK-NOT: func private @dead_function_c func.func private @dead_function_c() { call @live_function_b() : () -> () return } // CHECK-NOT: func private @dead_function_d func.func private @dead_function_d() { call @dead_function_c() : () -> () call @dead_function_c() : () -> () return } // CHECK: func @live_function_c func.func @live_function_c() { call @dead_function_c() : () -> () call @dead_function_d() : () -> () return } // Function is referenced by non-callable top-level user. // CHECK: func private @live_function_d func.func private @live_function_d() { return } "live.user"() {use = @live_function_d} : () -> () // ----- // This test checks that the inliner can properly handle the deletion of // functions in different SCCs that are referenced by calls materialized during // canonicalization. // CHECK: func @live_function_e func.func @live_function_e() { call @dead_function_e() : () -> () return } // CHECK-NOT: func @dead_function_e func.func private @dead_function_e() -> () { "test.fold_to_call_op"() {callee=@dead_function_f} : () -> () return } // CHECK-NOT: func private @dead_function_f func.func private @dead_function_f() { return }