[mlir] Replace toy::DeadFunctionEliminationPass with symbolDCEPass.
authorRiver Riddle <riddleriver@gmail.com>
Tue, 28 Jan 2020 07:40:01 +0000 (23:40 -0800)
committerRiver Riddle <riddleriver@gmail.com>
Tue, 28 Jan 2020 07:48:06 +0000 (23:48 -0800)
Summary:
The dead function elimination pass in toy was a temporary stopgap until we had proper dead function elimination support in MLIR. Now that this functionality is available, this pass is no longer necessary.

Differential Revision: https://reviews.llvm.org/D72483

25 files changed:
mlir/examples/toy/Ch4/CMakeLists.txt
mlir/examples/toy/Ch4/include/toy/Passes.h
mlir/examples/toy/Ch4/mlir/DeadFunctionEliminationPass.cpp [deleted file]
mlir/examples/toy/Ch4/mlir/MLIRGen.cpp
mlir/examples/toy/Ch4/toyc.cpp
mlir/examples/toy/Ch5/CMakeLists.txt
mlir/examples/toy/Ch5/include/toy/Passes.h
mlir/examples/toy/Ch5/mlir/DeadFunctionEliminationPass.cpp [deleted file]
mlir/examples/toy/Ch5/mlir/MLIRGen.cpp
mlir/examples/toy/Ch5/toyc.cpp
mlir/examples/toy/Ch6/CMakeLists.txt
mlir/examples/toy/Ch6/include/toy/Passes.h
mlir/examples/toy/Ch6/mlir/DeadFunctionEliminationPass.cpp [deleted file]
mlir/examples/toy/Ch6/mlir/MLIRGen.cpp
mlir/examples/toy/Ch6/toyc.cpp
mlir/examples/toy/Ch7/CMakeLists.txt
mlir/examples/toy/Ch7/include/toy/Passes.h
mlir/examples/toy/Ch7/mlir/DeadFunctionEliminationPass.cpp [deleted file]
mlir/examples/toy/Ch7/mlir/MLIRGen.cpp
mlir/examples/toy/Ch7/toyc.cpp
mlir/test/Examples/Toy/Ch4/shape_inference.mlir
mlir/test/Examples/Toy/Ch5/shape_inference.mlir
mlir/test/Examples/Toy/Ch6/shape_inference.mlir
mlir/test/Examples/Toy/Ch7/shape_inference.mlir
mlir/test/Examples/Toy/Ch7/struct-codegen.toy

index d11e5ab..c9b0e71 100644 (file)
@@ -13,7 +13,6 @@ add_toy_chapter(toyc-ch4
   parser/AST.cpp
   mlir/MLIRGen.cpp
   mlir/Dialect.cpp
-  mlir/DeadFunctionEliminationPass.cpp
   mlir/ShapeInferencePass.cpp
   mlir/ToyCombine.cpp
   )
index 56f5ce1..1450801 100644 (file)
@@ -20,7 +20,6 @@ class Pass;
 
 namespace toy {
 std::unique_ptr<Pass> createShapeInferencePass();
-std::unique_ptr<Pass> createDeadFunctionEliminationPass();
 } // end namespace toy
 } // end namespace mlir
 
diff --git a/mlir/examples/toy/Ch4/mlir/DeadFunctionEliminationPass.cpp b/mlir/examples/toy/Ch4/mlir/DeadFunctionEliminationPass.cpp
deleted file mode 100644 (file)
index 56ab6a8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- DeadFunctionEliminationPass.cpp - Eliminate inlined functions ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a Module level pass performing dead function
-// elimination. This is required as a post-processing step after function
-// inlining.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Verifier.h"
-#include "mlir/IR/BlockAndValueMapping.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/MLIRContext.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/StandardTypes.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LogicalResult.h"
-#include "toy/Passes.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-namespace {
-/// This is a simple function DCE pass that deletes all non-main functions after
-/// inlining.
-/// TODO(riverriddle) This is only necessary because MLIR currently does not
-/// have generic DCE support for functions.
-class DeadFunctionEliminationPass
-    : public mlir::ModulePass<DeadFunctionEliminationPass> {
-public:
-  void runOnModule() override {
-    mlir::ModuleOp module = getModule();
-    mlir::SymbolTable moduleSymTable(module);
-
-    // Eliminate non-main functions.
-    auto mainFn = moduleSymTable.lookup<mlir::FuncOp>("main");
-    for (mlir::FuncOp func :
-         llvm::make_early_inc_range(module.getOps<mlir::FuncOp>())) {
-      if (func != mainFn)
-        func.erase();
-    }
-  }
-};
-} // end anonymous namespace
-
-/// Create a pass that eliminates inlined functions in toy.
-std::unique_ptr<mlir::Pass> mlir::toy::createDeadFunctionEliminationPass() {
-  return std::make_unique<DeadFunctionEliminationPass>();
-}
index 5e09e73..2be287c 100644 (file)
@@ -170,6 +170,10 @@ private:
                                                getType(VarType{})));
     }
 
+    // If this function isn't main, then set the visibility to private.
+    if (funcAST.getProto()->getName() != "main")
+      function.setVisibility(mlir::FuncOp::Visibility::Private);
+
     return function;
   }
 
index 13ab458..5570ed3 100644 (file)
@@ -119,7 +119,7 @@ int dumpMLIR() {
 
     // Inline all functions into main and then delete them.
     pm.addPass(mlir::createInlinerPass());
-    pm.addPass(mlir::toy::createDeadFunctionEliminationPass());
+    pm.addPass(mlir::createSymbolDCEPass());
 
     // Now that there is only one function, we can infer the shapes of each of
     // the operations.
index df52395..de868da 100644 (file)
@@ -13,7 +13,6 @@ add_toy_chapter(toyc-ch5
   parser/AST.cpp
   mlir/MLIRGen.cpp
   mlir/Dialect.cpp
-  mlir/DeadFunctionEliminationPass.cpp
   mlir/LowerToAffineLoops.cpp
   mlir/ShapeInferencePass.cpp
   mlir/ToyCombine.cpp
index 560f2aa..6f07ba6 100644 (file)
@@ -19,7 +19,6 @@ namespace mlir {
 class Pass;
 
 namespace toy {
-std::unique_ptr<Pass> createDeadFunctionEliminationPass();
 std::unique_ptr<Pass> createShapeInferencePass();
 
 /// Create a pass for lowering to operations in the `Affine` and `Std` dialects,
diff --git a/mlir/examples/toy/Ch5/mlir/DeadFunctionEliminationPass.cpp b/mlir/examples/toy/Ch5/mlir/DeadFunctionEliminationPass.cpp
deleted file mode 100644 (file)
index 56ab6a8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- DeadFunctionEliminationPass.cpp - Eliminate inlined functions ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a Module level pass performing dead function
-// elimination. This is required as a post-processing step after function
-// inlining.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Verifier.h"
-#include "mlir/IR/BlockAndValueMapping.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/MLIRContext.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/StandardTypes.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LogicalResult.h"
-#include "toy/Passes.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-namespace {
-/// This is a simple function DCE pass that deletes all non-main functions after
-/// inlining.
-/// TODO(riverriddle) This is only necessary because MLIR currently does not
-/// have generic DCE support for functions.
-class DeadFunctionEliminationPass
-    : public mlir::ModulePass<DeadFunctionEliminationPass> {
-public:
-  void runOnModule() override {
-    mlir::ModuleOp module = getModule();
-    mlir::SymbolTable moduleSymTable(module);
-
-    // Eliminate non-main functions.
-    auto mainFn = moduleSymTable.lookup<mlir::FuncOp>("main");
-    for (mlir::FuncOp func :
-         llvm::make_early_inc_range(module.getOps<mlir::FuncOp>())) {
-      if (func != mainFn)
-        func.erase();
-    }
-  }
-};
-} // end anonymous namespace
-
-/// Create a pass that eliminates inlined functions in toy.
-std::unique_ptr<mlir::Pass> mlir::toy::createDeadFunctionEliminationPass() {
-  return std::make_unique<DeadFunctionEliminationPass>();
-}
index 5e09e73..2be287c 100644 (file)
@@ -170,6 +170,10 @@ private:
                                                getType(VarType{})));
     }
 
+    // If this function isn't main, then set the visibility to private.
+    if (funcAST.getProto()->getName() != "main")
+      function.setVisibility(mlir::FuncOp::Visibility::Private);
+
     return function;
   }
 
index 579a417..cdfe933 100644 (file)
@@ -124,7 +124,7 @@ int dumpMLIR() {
   if (enableOpt || isLoweringToAffine) {
     // Inline all functions into main and then delete them.
     pm.addPass(mlir::createInlinerPass());
-    pm.addPass(mlir::toy::createDeadFunctionEliminationPass());
+    pm.addPass(mlir::createSymbolDCEPass());
 
     // Now that there is only one function, we can infer the shapes of each of
     // the operations.
index c342ed1..a539d59 100644 (file)
@@ -14,7 +14,6 @@ add_toy_chapter(toyc-ch6
   parser/AST.cpp
   mlir/MLIRGen.cpp
   mlir/Dialect.cpp
-  mlir/DeadFunctionEliminationPass.cpp
   mlir/LowerToAffineLoops.cpp
   mlir/LowerToLLVM.cpp
   mlir/ShapeInferencePass.cpp
index c3ece4b..e878d71 100644 (file)
@@ -19,7 +19,6 @@ namespace mlir {
 class Pass;
 
 namespace toy {
-std::unique_ptr<Pass> createDeadFunctionEliminationPass();
 std::unique_ptr<Pass> createShapeInferencePass();
 
 /// Create a pass for lowering to operations in the `Affine` and `Std` dialects,
diff --git a/mlir/examples/toy/Ch6/mlir/DeadFunctionEliminationPass.cpp b/mlir/examples/toy/Ch6/mlir/DeadFunctionEliminationPass.cpp
deleted file mode 100644 (file)
index 56ab6a8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- DeadFunctionEliminationPass.cpp - Eliminate inlined functions ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a Module level pass performing dead function
-// elimination. This is required as a post-processing step after function
-// inlining.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Verifier.h"
-#include "mlir/IR/BlockAndValueMapping.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/MLIRContext.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/StandardTypes.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LogicalResult.h"
-#include "toy/Passes.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-namespace {
-/// This is a simple function DCE pass that deletes all non-main functions after
-/// inlining.
-/// TODO(riverriddle) This is only necessary because MLIR currently does not
-/// have generic DCE support for functions.
-class DeadFunctionEliminationPass
-    : public mlir::ModulePass<DeadFunctionEliminationPass> {
-public:
-  void runOnModule() override {
-    mlir::ModuleOp module = getModule();
-    mlir::SymbolTable moduleSymTable(module);
-
-    // Eliminate non-main functions.
-    auto mainFn = moduleSymTable.lookup<mlir::FuncOp>("main");
-    for (mlir::FuncOp func :
-         llvm::make_early_inc_range(module.getOps<mlir::FuncOp>())) {
-      if (func != mainFn)
-        func.erase();
-    }
-  }
-};
-} // end anonymous namespace
-
-/// Create a pass that eliminates inlined functions in toy.
-std::unique_ptr<mlir::Pass> mlir::toy::createDeadFunctionEliminationPass() {
-  return std::make_unique<DeadFunctionEliminationPass>();
-}
index 5e09e73..2be287c 100644 (file)
@@ -170,6 +170,10 @@ private:
                                                getType(VarType{})));
     }
 
+    // If this function isn't main, then set the visibility to private.
+    if (funcAST.getProto()->getName() != "main")
+      function.setVisibility(mlir::FuncOp::Visibility::Private);
+
     return function;
   }
 
index b1ddd73..2598d82 100644 (file)
@@ -138,7 +138,7 @@ int loadAndProcessMLIR(mlir::MLIRContext &context,
   if (enableOpt || isLoweringToAffine) {
     // Inline all functions into main and then delete them.
     pm.addPass(mlir::createInlinerPass());
-    pm.addPass(mlir::toy::createDeadFunctionEliminationPass());
+    pm.addPass(mlir::createSymbolDCEPass());
 
     // Now that there is only one function, we can infer the shapes of each of
     // the operations.
index 5956d7f..66d5439 100644 (file)
@@ -14,7 +14,6 @@ add_toy_chapter(toyc-ch7
   parser/AST.cpp
   mlir/MLIRGen.cpp
   mlir/Dialect.cpp
-  mlir/DeadFunctionEliminationPass.cpp
   mlir/LowerToAffineLoops.cpp
   mlir/LowerToLLVM.cpp
   mlir/ShapeInferencePass.cpp
index c3ece4b..e878d71 100644 (file)
@@ -19,7 +19,6 @@ namespace mlir {
 class Pass;
 
 namespace toy {
-std::unique_ptr<Pass> createDeadFunctionEliminationPass();
 std::unique_ptr<Pass> createShapeInferencePass();
 
 /// Create a pass for lowering to operations in the `Affine` and `Std` dialects,
diff --git a/mlir/examples/toy/Ch7/mlir/DeadFunctionEliminationPass.cpp b/mlir/examples/toy/Ch7/mlir/DeadFunctionEliminationPass.cpp
deleted file mode 100644 (file)
index 56ab6a8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- DeadFunctionEliminationPass.cpp - Eliminate inlined functions ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a Module level pass performing dead function
-// elimination. This is required as a post-processing step after function
-// inlining.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Verifier.h"
-#include "mlir/IR/BlockAndValueMapping.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/MLIRContext.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/StandardTypes.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LogicalResult.h"
-#include "toy/Passes.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-namespace {
-/// This is a simple function DCE pass that deletes all non-main functions after
-/// inlining.
-/// TODO(riverriddle) This is only necessary because MLIR currently does not
-/// have generic DCE support for functions.
-class DeadFunctionEliminationPass
-    : public mlir::ModulePass<DeadFunctionEliminationPass> {
-public:
-  void runOnModule() override {
-    mlir::ModuleOp module = getModule();
-    mlir::SymbolTable moduleSymTable(module);
-
-    // Eliminate non-main functions.
-    auto mainFn = moduleSymTable.lookup<mlir::FuncOp>("main");
-    for (mlir::FuncOp func :
-         llvm::make_early_inc_range(module.getOps<mlir::FuncOp>())) {
-      if (func != mainFn)
-        func.erase();
-    }
-  }
-};
-} // end anonymous namespace
-
-/// Create a pass that eliminates inlined functions in toy.
-std::unique_ptr<mlir::Pass> mlir::toy::createDeadFunctionEliminationPass() {
-  return std::make_unique<DeadFunctionEliminationPass>();
-}
index fca0d3f..eeab86d 100644 (file)
@@ -223,6 +223,10 @@ private:
                                                *returnOp.operand_type_begin()));
     }
 
+    // If this function isn't main, then set the visibility to private.
+    if (funcAST.getProto()->getName() != "main")
+      function.setVisibility(mlir::FuncOp::Visibility::Private);
+
     return function;
   }
 
index 2f698a3..e872ec1 100644 (file)
@@ -138,7 +138,7 @@ int loadAndProcessMLIR(mlir::MLIRContext &context,
   if (enableOpt || isLoweringToAffine) {
     // Inline all functions into main and then delete them.
     pm.addPass(mlir::createInlinerPass());
-    pm.addPass(mlir::toy::createDeadFunctionEliminationPass());
+    pm.addPass(mlir::createSymbolDCEPass());
 
     // Now that there is only one function, we can infer the shapes of each of
     // the operations.
index d1c07e4..c5d38f3 100644 (file)
@@ -2,7 +2,8 @@
 
 // Check the result of inlining+shape inference on an input module.
 
-func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
+    attributes { sym_visibility = "private" } {
   %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
   %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
   %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
index 9e44ac5..89b4271 100644 (file)
@@ -2,7 +2,8 @@
 
 // Check the result of inlining+shape inference on an input module.
 
-func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
+    attributes { sym_visibility = "private" } {
   %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
   %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
   %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
index 199446c..d1c4397 100644 (file)
@@ -2,7 +2,8 @@
 
 // Check the result of inlining+shape inference on an input module.
 
-func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
+    attributes { sym_visibility = "private" } {
   %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
   %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
   %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
index b9355cf..096c041 100644 (file)
@@ -2,7 +2,8 @@
 
 // Check the result of inlining+shape inference on an input module.
 
-func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
+func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
+    attributes { sym_visibility = "private" } {
   %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64>
   %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64>
   %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64>
index 66eaf8a..4c5ed13 100644 (file)
@@ -1,4 +1,4 @@
-# RUN: toyc-ch7 %s -emit=mlir 2>&1
+# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s
 # RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s --check-prefix=OPT
 
 struct Struct {
@@ -23,6 +23,7 @@ def main() {
 
 # CHECK-LABEL:   func @multiply_transpose(
 # CHECK-SAME:                             [[VAL_0:%.*]]: !toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
+# CHECK-SAME:        attributes {sym_visibility = "private"}
 # CHECK-NEXT:      [[VAL_1:%.*]] = "toy.struct_access"([[VAL_0]]) {index = 0 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
 # CHECK-NEXT:      [[VAL_2:%.*]] = "toy.transpose"([[VAL_1]]) : (tensor<*xf64>) -> tensor<*xf64>
 # CHECK-NEXT:      [[VAL_3:%.*]] = "toy.struct_access"([[VAL_0]]) {index = 1 : i64} : (!toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>