From d8f520172884000817b3d2006710779951694566 Mon Sep 17 00:00:00 2001 From: lanxianghit Date: Tue, 9 Jan 2024 07:24:13 +0000 Subject: [PATCH 1/5] polish some codes --- paddle/fluid/pybind/pir.cc | 11 ++++------- .../shape/utils/shape_optimization_utils.cc | 12 +----------- paddle/pir/dialect/shape/utils/shape_utils.cc | 19 +------------------ .../jit/dy2static/pir_partial_program.py | 12 ++---------- .../symbolic/test_cinn_sub_graph_symbolic.py | 4 ++-- 5 files changed, 10 insertions(+), 48 deletions(-) diff --git a/paddle/fluid/pybind/pir.cc b/paddle/fluid/pybind/pir.cc index d9d7eb3abe186b..0d9980f3e6928d 100644 --- a/paddle/fluid/pybind/pir.cc +++ b/paddle/fluid/pybind/pir.cc @@ -1608,13 +1608,10 @@ void AddCinnPass(std::shared_ptr &pass_manager, // NOLINT } void InferSymbolicShapePass( - std::shared_ptr &pass_manager, // NOLINT - Program &program) { // NOLINT - if (FLAGS_pir_apply_shape_optimization_pass) { - pir::IrContext *ctx = pir::IrContext::Instance(); - ctx->GetOrRegisterDialect(); - pass_manager->AddPass(pir::CreateShapeOptimizationPass()); - } + std::shared_ptr &pass_manager) { // NOLINT + pir::IrContext *ctx = pir::IrContext::Instance(); + ctx->GetOrRegisterDialect(); + pass_manager->AddPass(pir::CreateShapeOptimizationPass()); } void BindIrPass(pybind11::module *m) { diff --git a/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc b/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc index a2e8f4c6ee10a3..f855048181c4e7 100644 --- a/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc +++ b/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc @@ -48,17 +48,7 @@ bool CompareSymbolicDimProduct(SymbolicDimProduct& lhs, // NOLINT return false; } -SymbolicDimMgr::SymbolicDimMgr(ModuleOp m) : m_(m) { - for (auto& op : m.block()) { - if (op.isa()) { - symbol_table_ = SymbolTable(&op); - return; - } - } - Builder builder = Builder(m_.ir_context(), &m_.block(), m_.block().begin()); - shape::FuncOp func = builder.Build(); - symbol_table_ = SymbolTable(func); -} +SymbolicDimMgr::SymbolicDimMgr(ModuleOp m) : m_(m) {} bool SymbolicDimMgr::MapSymbolicDimProductEqual(const SymbolicDimProduct& lhs, const SymbolicDimProduct& rhs) { diff --git a/paddle/pir/dialect/shape/utils/shape_utils.cc b/paddle/pir/dialect/shape/utils/shape_utils.cc index 574805c61f020b..06619f9ae25357 100644 --- a/paddle/pir/dialect/shape/utils/shape_utils.cc +++ b/paddle/pir/dialect/shape/utils/shape_utils.cc @@ -46,24 +46,7 @@ bool ShapeAnalysis::IsProductEqual( } ShapeConstraintIRAnalysis::ShapeConstraintIRAnalysis(ModuleOp m) - : m_(m), mgr_(m) { - for (auto& op : m.block()) { - auto tie_shape_op = op.dyn_cast(); - if (!tie_shape_op) continue; - Value result = tie_shape_op.input(); - auto& symbols = value_to_sym_dims_[result]; - auto attrs = - tie_shape_op - .attribute(SymbolicDimOp::GetSymbolicDimAttrName()) - .AsVector(); - for (const auto& attr : attrs) { - auto sym_op = mgr_.symbolTable().Lookup( - attr.dyn_cast().AsString()); - if (!sym_op) continue; - symbols.push_back(sym_op); - } - } -} + : m_(m), mgr_(m) {} ShapeConstraintIRAnalysis::~ShapeConstraintIRAnalysis() {} diff --git a/python/paddle/jit/dy2static/pir_partial_program.py b/python/paddle/jit/dy2static/pir_partial_program.py index 574821ab5b3420..564cb6e0f89c8c 100644 --- a/python/paddle/jit/dy2static/pir_partial_program.py +++ b/python/paddle/jit/dy2static/pir_partial_program.py @@ -548,27 +548,19 @@ def _get_scope(self, program_id=None, use_scope_cache=False): @switch_to_static_graph def _create_program(self, is_infer_mode=False): if is_infer_mode: - # TODO(lanxianghit) mv this into pass_fn - def shape_pass_fn(forward_program, backward_program): - pm = paddle.base.libpaddle.pir.PassManager() - paddle.base.libpaddle.pir.infer_symbolic_shape_pass( - pm, forward_program - ) - pm.run(forward_program) - return forward_program, backward_program def pass_fn(forward_program, backward_program): pm = paddle.base.libpaddle.pir.PassManager() + paddle.base.libpaddle.pir.infer_symbolic_shape_pass(pm) if self._build_strategy.build_cinn_pass: paddle.base.libpaddle.pir.add_cinn_pass(pm, forward_program) - pm.run(forward_program) + pm.run(forward_program) return forward_program, backward_program # TODO(xiongkun) who to transfer the pruning program? infer_program = self.origin_runable_program.clone() if self._hooker: self._hooker.after_infer(infer_program) - infer_program.apply_pir_program_pass(shape_pass_fn) infer_program.apply_pir_program_pass(pass_fn) return infer_program else: diff --git a/test/ir/pir/cinn/symbolic/test_cinn_sub_graph_symbolic.py b/test/ir/pir/cinn/symbolic/test_cinn_sub_graph_symbolic.py index 0ff352acf590f5..25c508275df1b6 100644 --- a/test/ir/pir/cinn/symbolic/test_cinn_sub_graph_symbolic.py +++ b/test/ir/pir/cinn/symbolic/test_cinn_sub_graph_symbolic.py @@ -132,8 +132,8 @@ def test_eval_symbolic(self): import os is_debug = os.getenv('IS_DEBUG_DY_SHAPE') - # if is_debug: - # cinn_out = self.eval_symbolic(use_cinn=True) + if is_debug: + cinn_out = self.eval_symbolic(use_cinn=True) dy_out = self.eval_symbolic(use_cinn=False) # np.testing.assert_allclose(cinn_out.numpy(), dy_out.numpy(), atol=1e-8) From 8c4b24545b70381cc2980d8c66c38945a4b31132 Mon Sep 17 00:00:00 2001 From: lanxianghit Date: Tue, 9 Jan 2024 11:15:19 +0000 Subject: [PATCH 2/5] fix ci --- .../operator/transforms/pd_to_cinn_pass.cc | 10 +- .../operator/transforms/pd_to_cinn_pass.h | 2 + paddle/fluid/pybind/pir.cc | 3 +- test/cpp/pir/shape_dialect/CMakeLists.txt | 10 - test/cpp/pir/shape_dialect/shape_op_test.cc | 298 ------------------ .../pir/shape_dialect/shape_struct_test.cc | 88 ------ 6 files changed, 6 insertions(+), 405 deletions(-) delete mode 100644 test/cpp/pir/shape_dialect/shape_op_test.cc delete mode 100644 test/cpp/pir/shape_dialect/shape_struct_test.cc diff --git a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc index 66c6a7ddf8c599..41a82ac13525f4 100644 --- a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc +++ b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc @@ -677,14 +677,10 @@ bool PdOpToCinnOpPass::CanApplyOn(pir::Operation *op) const { return op->isa() && op->num_regions() > 0; } -void PdOp2CinnOpConverter(::pir::Program *program) { - pir::IrContext *ctx = pir::IrContext::Instance(); - - pir::PassManager pm(ctx); - pm.AddPass(std::make_unique()); - - pm.Run(program); +std::unique_ptr CreatePdOpToCinnOpPass() { + return std::make_unique(); } + } // namespace ir } // namespace dialect } // namespace cinn diff --git a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h index 31a686995584b3..fd54bae38a226e 100644 --- a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h +++ b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h @@ -33,6 +33,8 @@ class PdOpToCinnOpPass : public pir::PatternRewritePass { void PdOp2CinnOpConverter(::pir::Program *program); +IR_API std::unique_ptr CreatePdOpToCinnOpPass(); + } // namespace ir } // namespace dialect } // namespace cinn diff --git a/paddle/fluid/pybind/pir.cc b/paddle/fluid/pybind/pir.cc index 0d9980f3e6928d..9ba7f62bbf3b6c 100644 --- a/paddle/fluid/pybind/pir.cc +++ b/paddle/fluid/pybind/pir.cc @@ -1589,8 +1589,7 @@ void AddCinnPass(std::shared_ptr &pass_manager, // NOLINT has_dynamic_shape ? std::make_shared(ctx) : nullptr; - cinn::dialect::ir::PdOp2CinnOpConverter(&program); - + pass_manager->AddPass(cinn::dialect::ir::CreatePdOpToCinnOpPass()); pass_manager->AddPass( std::make_unique()); pass_manager->AddPass(pir::CreateDeadCodeEliminationPass()); diff --git a/test/cpp/pir/shape_dialect/CMakeLists.txt b/test/cpp/pir/shape_dialect/CMakeLists.txt index fc890d2f6b8c58..9f8d37a21e697e 100644 --- a/test/cpp/pir/shape_dialect/CMakeLists.txt +++ b/test/cpp/pir/shape_dialect/CMakeLists.txt @@ -1,7 +1,3 @@ -paddle_test(shape_op_test SRCS shape_op_test.cc) - -paddle_test(shape_struct_test SRCS shape_struct_test.cc) - paddle_test(symbol_dim_expr_test SRCS symbol_dim_expr_test.cc) if(WITH_CINN) @@ -10,9 +6,3 @@ if(WITH_CINN) shape_optimization_test PROPERTIES ENVIRONMENT "FLAGS_enable_pir_in_executor=true") endif() - -if(WITH_ONNXRUNTIME AND WIN32) - # Copy onnxruntime for some c++ test in Windows, since the test will - # be build only in CI, so suppose the generator in Windows is Ninja. - copy_onnx(shape_op_test) -endif() diff --git a/test/cpp/pir/shape_dialect/shape_op_test.cc b/test/cpp/pir/shape_dialect/shape_op_test.cc deleted file mode 100644 index 581d08ec2e0630..00000000000000 --- a/test/cpp/pir/shape_dialect/shape_op_test.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h" -#include "paddle/pir/dialect/shape/ir/shape_dialect.h" -#include "test/cpp/pir/tools/test_pir_utils.h" - -TEST(shape_op, symbolic_dim_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::shape::SymbolicDimOp sym_dim_op1 = - builder.Build( - "S0", 10, false, false, false, false); - pir::shape::SymbolicDimOp sym_dim_op2 = - builder.Build( - "S1", 10, false, false, false, false); - - EXPECT_EQ(sym_dim_op1.GetDimSize(), 10); - EXPECT_EQ(sym_dim_op1.GetSymName(), "S0"); - EXPECT_FALSE(sym_dim_op1.GetKnownNegativeOne()); - EXPECT_FALSE(sym_dim_op1.GetKnownNonSizeOne()); - EXPECT_FALSE(sym_dim_op1.GetKnownNonSizeZero()); - EXPECT_FALSE(sym_dim_op1.GetKnownNonNegative()); - - EXPECT_FALSE(sym_dim_op1.IsDynamic()); - EXPECT_TRUE(sym_dim_op1.Merge(sym_dim_op2)); - - sym_dim_op1.SetDimSize(20); - sym_dim_op1.SetSymName("S2"); - sym_dim_op1.UpdateKnownNegativeOne(true); - sym_dim_op1.UpdateKnownNonSizeOne(true); - sym_dim_op1.UpdateKnownNonSizeZero(true); - sym_dim_op1.UpdateKnownNonNegative(true); - - EXPECT_FALSE(sym_dim_op1.Merge(sym_dim_op2)); - - EXPECT_EQ(sym_dim_op1.GetDimSize(), 20); - EXPECT_EQ(sym_dim_op1.GetSymName(), "S2"); - EXPECT_TRUE(sym_dim_op1.GetKnownNegativeOne()); - EXPECT_TRUE(sym_dim_op1.GetKnownNonSizeOne()); - EXPECT_TRUE(sym_dim_op1.GetKnownNonSizeZero()); - EXPECT_TRUE(sym_dim_op1.GetKnownNonNegative()); -} - -TEST(shape_op, dim_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::shape::DimOp dim_op = builder.Build("S0"); - pir::OpResult res = dim_op.out(); - EXPECT_EQ(dim_op.GetName(), "S0"); - dim_op.SetName("S1"); - EXPECT_EQ(dim_op.GetName(), "S1"); - EXPECT_EQ(res.owner(), dim_op.operation()); - EXPECT_EQ(res.type(), pir::IndexType::get(ctx)); -} - -TEST(shape_op, tie_product_equal_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - pir::SymbolTable symbolt_table(program.module_op()); - - pir::OpResult dim_op0 = builder.Build("S0").out(); - pir::OpResult dim_op1 = builder.Build("S1").out(); - pir::OpResult dim_op2 = builder.Build("S2").out(); - pir::OpResult dim_op3 = builder.Build("S3").out(); - pir::OpResult dim_op4 = builder.Build("S4").out(); - - pir::shape::TieProductEqualOp tie_product_equal_op = - builder.Build( - 2, - 3, - std::vector{dim_op0, dim_op1, dim_op2, dim_op3, dim_op4}); - - std::vector lhs = tie_product_equal_op.lhs(); - std::vector rhs = tie_product_equal_op.rhs(); - - std::vector lhs_ref{dim_op0, dim_op1}; - std::vector rhs_ref{dim_op2, dim_op3, dim_op4}; - - EXPECT_EQ(symbolt_table.insert(tie_product_equal_op), "tie_product_equal"); - EXPECT_EQ( - symbolt_table.Lookup("tie_product_equal") - .size(), - static_cast(1)); - EXPECT_EQ(symbolt_table.Lookup( - "tie_product_equal")[0], - tie_product_equal_op); - EXPECT_EQ(lhs, lhs_ref); - EXPECT_EQ(rhs, rhs_ref); -} - -TEST(shape_op, tie_shape_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - ctx->GetOrRegisterDialect(); - - pir::Builder builder = pir::Builder(ctx, program.block()); - - auto op = test::CreateDenseTensorOp(ctx, {-1, 2}, {"op_attr"}, {"op_name"}); - pir::OpResult res = op->result(0); - - pir::shape::TieShapeOp tie_shape_op = - builder.Build(res); - pir::Value tie_shape_op_input = tie_shape_op.input(); - - pir::Attribute attr_s0 = pir::StrAttribute::get(ctx, "S0"); - pir::Attribute attr_s1 = pir::StrAttribute::get(ctx, "S1"); - - std::vector new_attrs = {attr_s0, attr_s1}; - - auto array_attr = pir::ArrayAttribute::get(ctx, new_attrs); - tie_shape_op->set_attribute( - pir::shape::SymbolicDimOp::GetSymbolicDimAttrName(), array_attr); - - std::vector arr_attr_vec = - tie_shape_op - ->attribute( - pir::shape::SymbolicDimOp::GetSymbolicDimAttrName()) - .AsVector(); - - EXPECT_EQ(tie_shape_op_input, res); - EXPECT_EQ(arr_attr_vec.size(), static_cast(2)); - EXPECT_EQ(arr_attr_vec[0].dyn_cast(), attr_s0); - EXPECT_EQ(arr_attr_vec[1].dyn_cast(), attr_s1); - EXPECT_TRUE(tie_shape_op->HasAttribute( - pir::shape::SymbolicDimOp::GetSymbolicDimAttrName())); -} - -TEST(shape_op, func_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - ::pir::Builder builder = ::pir::Builder(ctx, program.block()); - pir::shape::FuncOp func_op = builder.Build(); - auto func_block = func_op.block(); - builder.SetInsertionPointToStart(func_block); - builder.Build(pir::Int32Attribute::get(ctx, 2), - pir::Int32Type::get(ctx)); - EXPECT_EQ(func_block, &func_op->region(0).front()); - EXPECT_EQ(func_op->region(0).size(), static_cast(1)); - EXPECT_EQ(func_block->size(), static_cast(1)); -} - -TEST(shape_op, tensor_dim_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::Operation *op = - test::CreateDenseTensorOp(ctx, {-1, 2}, {"op_attr"}, {"op_name"}); - pir::OpResult res_dense_tensor_value = op->result(0); - - pir::shape::TensorDimOp tensor_dim_op0 = - builder.Build(res_dense_tensor_value, 0); - pir::OpResult res0 = tensor_dim_op0.out(); - std::optional index0 = tensor_dim_op0.GetConstantIndex(); - - pir::OpResult index_value = - builder - .Build( - pir::Int64Attribute::get(pir::IrContext::Instance(), 1), - pir::IndexType::get(pir::IrContext::Instance())) - ->result(0); - pir::shape::TensorDimOp tensor_dim_op1 = - builder.Build(res_dense_tensor_value, - index_value); - pir::OpResult res1 = tensor_dim_op1.out(); - - EXPECT_EQ(res0.type(), pir::IndexType::get(ctx)); - EXPECT_EQ(*index0, static_cast(0)); - EXPECT_EQ(res1.type(), pir::IndexType::get(ctx)); - EXPECT_EQ(tensor_dim_op0.source(), res_dense_tensor_value); - EXPECT_EQ(tensor_dim_op1.source(), res_dense_tensor_value); - EXPECT_EQ(tensor_dim_op1.index(), index_value); -} - -TEST(shape_op, shape_of_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - auto op = test::CreateDenseTensorOp(ctx, {-1, 2}, {"op_attr"}, {"op_name"}); - pir::OpResult res = op->result(0); - - pir::shape::ShapeOfOp shape_of_op = builder.Build(res); - pir::Value shape_of_op_input = shape_of_op.input(); - EXPECT_EQ(shape_of_op_input, res); -} - -TEST(shape_op, from_elements_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::Int32Attribute int32_attr0 = builder.int32_attr(0); - pir::Int32Attribute int32_attr1 = builder.int32_attr(1); - pir::Int32Attribute int32_attr2 = builder.int32_attr(2); - pir::Int32Type int32_type = builder.int32_type(); - - pir::OpResult element0 = - builder.Build(int32_attr0, int32_type).out(); - pir::OpResult element1 = - builder.Build(int32_attr1, int32_type).out(); - pir::OpResult element2 = - builder.Build(int32_attr2, int32_type).out(); - - std::vector elements_in = {element0, element1, element2}; - - pir::shape::FromElementsOp from_elements_op = - builder.Build(elements_in); - - std::vector elements_out = from_elements_op.elements(); - for (size_t i = 0; i < elements_in.size(); i++) { - EXPECT_EQ(elements_in[i], elements_out[i]); - } -} - -TEST(shape_op, extract_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - auto op = test::CreateDenseTensorOp(ctx, {3, 2}, {"op_attr"}, {"op_name"}); - pir::OpResult res = op->result(0); - - pir::Int32Attribute int32_attr = builder.int32_attr(1); - pir::Int32Type int32_type = builder.int32_type(); - pir::OpResult indice = - builder.Build(int32_attr, int32_type).out(); - std::vector indice_in = {indice, indice}; - - pir::shape::ExtractOp extract_op = - builder.Build(res, indice_in); - pir::Value input = extract_op.tensor(); - std::vector indice_out = extract_op.indices(); - - EXPECT_EQ(input, res); - for (size_t i = 0; i < indice_in.size(); i++) { - EXPECT_EQ(indice_in[i], indice_out[i]); - } -} - -TEST(shape_op, constant_index_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::shape::ConstantIndexOp constant_index_op = - builder.Build(1); - - EXPECT_EQ( - constant_index_op.value().dyn_cast().data() == 1, - true); -} - -TEST(shape_op, index_cast_op) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - - pir::IndexAttribute index_attr = builder.index_attr(1); - pir::IndexType index_type = builder.index_type(); - pir::OpResult in = - builder.Build(index_attr, index_type).out(); - - pir::shape::IndexCastOp index_cast_op = - builder.Build(builder.int32_type(), in); - pir::Value index_cast_op_input = index_cast_op.in(); - - EXPECT_EQ(index_cast_op_input, in); -} diff --git a/test/cpp/pir/shape_dialect/shape_struct_test.cc b/test/cpp/pir/shape_dialect/shape_struct_test.cc deleted file mode 100644 index 12fbb641ba90cc..00000000000000 --- a/test/cpp/pir/shape_dialect/shape_struct_test.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h" -#include "paddle/pir/dialect/shape/ir/shape_dialect.h" -#include "test/cpp/pir/tools/test_pir_utils.h" - -TEST(shape_struct_test, symbolic_dim_product) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - pir::shape::SymbolicDimOp sym_dim = builder.Build( - "S0", pir::ShapedTypeInterface::kDynamic, false, false, false, false); - pir::SymbolicDimProduct sym_dim_product1; - pir::SymbolicDimProduct sym_dim_product2; - sym_dim_product1.symbols.push_back(sym_dim); - sym_dim_product1.factor *= 10; - EXPECT_EQ(sym_dim_product1.factor, 10); - EXPECT_NE(sym_dim_product1, sym_dim_product2); - EXPECT_FALSE(sym_dim_product1.empty()); -} - -TEST(shape_struct_test, symbolic_dim_table) { - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - pir::Builder builder = pir::Builder(ctx, program.block()); - pir::shape::SymbolicDimOp sym_dim = builder.Build( - "S0", 10, false, false, false, false); - - pir::SymbolTable symbol_table(program.module_op()); - EXPECT_EQ(symbol_table.insert(sym_dim), "S0"); - EXPECT_EQ(symbol_table.Lookup("S0"), sym_dim); - EXPECT_EQ(symbol_table.getOp(), program.module_op()); - EXPECT_FALSE(symbol_table.Lookup("S1")); -} - -TEST(shape_struct_test, symbolic_dim_mgr_simple) { - /******************************************************/ - /* Mgr simple version, only SymbolicDimOp related func. */ - /******************************************************/ - pir::IrContext *ctx = pir::IrContext::Instance(); - pir::Program program(ctx); - ctx->GetOrRegisterDialect(); - ctx->GetOrRegisterDialect(); - - pir::SymbolicDimMgr sym_dim_mgr(program.module_op()); - pir::shape::SymbolicDimOp sym_dim_s0 = sym_dim_mgr.NewSymbolicDim(); - pir::shape::SymbolicDimOp sym_dim_s1 = sym_dim_mgr.NewSymbolicDim(); - pir::shape::SymbolicDimOp sym_dim_c10 = - sym_dim_mgr.NewConstantSymbolicDim(10); - sym_dim_mgr.MapSymbolicDimEqual(sym_dim_s0, sym_dim_s1); - - auto op = test::CreateDenseTensorOp( - ctx, {pir::ShapedTypeInterface::kDynamic, 2}, {"op_attr"}, {"op_name"}); - pir::Value res = op->result(0); - - std::vector sym_dim_vec = - sym_dim_mgr.CreateSymbolicDimsForRankedValue(res); - - EXPECT_EQ(sym_dim_s0.GetSymName(), "S0"); - EXPECT_EQ(sym_dim_s1.GetSymName(), "S1"); - EXPECT_EQ(sym_dim_s1.GetDimSize(), pir::ShapedTypeInterface::kDynamic); - EXPECT_EQ(sym_dim_c10.GetSymName(), "C10"); - EXPECT_EQ(sym_dim_c10.GetDimSize(), 10); - EXPECT_EQ(sym_dim_vec[0].GetSymName(), "S2"); - EXPECT_EQ(sym_dim_vec[1].GetSymName(), "C2"); - EXPECT_EQ(sym_dim_mgr.symbolTable().Lookup("S0"), - sym_dim_s0); - EXPECT_EQ(sym_dim_mgr.symbolTable().Lookup("C10"), - sym_dim_c10); - EXPECT_EQ(sym_dim_mgr.GetRootSymbolicDim(sym_dim_s1), sym_dim_s0); - EXPECT_TRUE(sym_dim_mgr.IsSymbolicDimEqual(sym_dim_s0, sym_dim_s1)); - EXPECT_FALSE(sym_dim_mgr.IsSymbolicDimEqual(sym_dim_s0, sym_dim_c10)); -} From 501f439d2fdc414c826304e488648d55d16d923a Mon Sep 17 00:00:00 2001 From: lanxianghit Date: Tue, 9 Jan 2024 12:03:22 +0000 Subject: [PATCH 3/5] fix ci --- .../operator/transforms/pd_to_cinn_pass.cc | 9 + .../operator/transforms/pd_to_cinn_pass.h | 2 + .../pir/transforms/shape_optimization_pass.cc | 297 ------------------ paddle/fluid/pybind/pir.cc | 8 +- 4 files changed, 16 insertions(+), 300 deletions(-) diff --git a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc index 41a82ac13525f4..042f2f0d0e84bf 100644 --- a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc +++ b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.cc @@ -677,6 +677,15 @@ bool PdOpToCinnOpPass::CanApplyOn(pir::Operation *op) const { return op->isa() && op->num_regions() > 0; } +void PdOp2CinnOpConverter(::pir::Program *program) { + pir::IrContext *ctx = pir::IrContext::Instance(); + + pir::PassManager pm(ctx); + pm.AddPass(std::make_unique()); + + pm.Run(program); +} + std::unique_ptr CreatePdOpToCinnOpPass() { return std::make_unique(); } diff --git a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h index fd54bae38a226e..d69fd78fb1c67a 100644 --- a/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h +++ b/paddle/cinn/hlir/dialect/operator/transforms/pd_to_cinn_pass.h @@ -31,6 +31,8 @@ class PdOpToCinnOpPass : public pir::PatternRewritePass { bool CanApplyOn(pir::Operation *op) const override; }; +// TODO(lanxianghit): delete this and use CreatePdOpToCinnOpPass() in +// corresponding unit tests. void PdOp2CinnOpConverter(::pir::Program *program); IR_API std::unique_ptr CreatePdOpToCinnOpPass(); diff --git a/paddle/fluid/pir/transforms/shape_optimization_pass.cc b/paddle/fluid/pir/transforms/shape_optimization_pass.cc index 2bf33603fa7beb..33ee31b66b4d63 100644 --- a/paddle/fluid/pir/transforms/shape_optimization_pass.cc +++ b/paddle/fluid/pir/transforms/shape_optimization_pass.cc @@ -29,306 +29,9 @@ namespace pir { namespace { -bool InsertTieShapeOnValue(pir::Value value, - pir::Builder& builder) { // NOLINT - // Insert TieShapeOp only for non-zero ranked tensor type. - auto type = value.type().dyn_cast(); - if (!type || type.dims().size() == 0) return true; - - std::vector dim_sizes; - for (int64_t dim = 0, rank = type.dims().size(); dim < rank; ++dim) { - auto dim_op = builder.Build(value, dim); - dim_sizes.push_back(dim_op.out()); - } - builder.Build(value, dim_sizes); - return true; -} - -// Forward declaration -bool InsertTieShapeOnRegion(pir::Region* region); - -bool InsertTieShapeOnOperation(pir::Operation* op, - pir::Builder& builder) { // NOLINT - // TODO(zhangbopd): skip more specialized Ops. - if (op->isa() || op->isa()) return true; - - for (size_t i = 0; i < op->num_regions(); ++i) { - if (!InsertTieShapeOnRegion(&(op->region(i)))) return false; - } - builder.SetInsertionPointAfter(op); - for (pir::OpResult v : op->results()) { - if (!InsertTieShapeOnValue(v, builder)) return false; - } - - return true; -} - -bool InsertTieShapeOnBlock(pir::Block* block) { - pir::Builder builder = - pir::Builder(pir::IrContext::Instance(), block, block->begin()); - // TODO(zhangbopd): mapping block arguments - - std::vector op_list; - for (auto& op : *block) op_list.push_back(&op); - for (pir::Operation* op : op_list) { - if (!InsertTieShapeOnOperation(op, builder)) return false; - } - return true; -} - -bool InsertTieShapeOnRegion(pir::Region* region) { - for (auto& block : *region) { - if (!InsertTieShapeOnBlock(&block)) return false; - } - return true; -} - -// Convert: -// %shape = shape.shape_of %0 : tensor -> tensor<2xindex> -// To: -// %d0 = tensor.dim %0, %c0 : tensor -// %d1 = tensor.dim %0, %c1 : tensor -// %shape = tensor.from_elements %d0, %d1 : tensor<2xindex> -struct ExpandShapeOfOpPattern : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - bool MatchAndRewrite(shape::ShapeOfOp op, - PatternRewriter& rewriter) const override { - VLOG(3) << "Apply ExpandShapeOfOpPattern..."; - - auto type = op.out().type().dyn_cast(); - - if (!type || !type.dyn_cast().HasStaticShape() || - !type.dyn_cast().GetElementType().IsIndex()) - return false; - - std::vector dim_sizes; - for (int dim = 0, - rank = type.dyn_cast().GetDyShape()[0]; - dim < rank; - ++dim) { - dim_sizes.push_back( - rewriter.Build(op.input(), dim).out()); - } - rewriter.ReplaceOpWithNewOp(op, dim_sizes); - return true; - } -}; - -// Fold dim of an operation that implements the InferSymbolicShapeInterface -template -struct DimOfShapedTypeOpInterfacePattern : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - bool MatchAndRewrite(OpTy dim_op, PatternRewriter& rewriter) const override { - return true; - } -}; - using PassPipelineRunner = std::function; -// Returns true if the type is possible to be a shape tensor type. -// Shape tensor type : -// - rank-1 static-shaped tensor type -// - element type of the tensor is int or index -// - number of elements of the tensor < 32, supposing that the -// higiest possible rank is smaller than 32. -bool IsCandidateShapeTensorType(Type type) { - auto tensor_type = type.dyn_cast(); - auto shaped_type = tensor_type.dyn_cast(); - - return (tensor_type && tensor_type && shaped_type.GetRank() == 1 && - shaped_type.HasStaticShape() && - shaped_type.GetElementType().IsIntOrIndex() && - shaped_type.GetDyShape()[0] < 32); -} - -class ShapeComputationIRAnalysis { - public: - using func = std::function; - explicit ShapeComputationIRAnalysis(ModuleOp m, - SymbolicDimMgr& mgr); // NOLINT - bool Run(); - - private: - bool RunOnRegion(Region* region, func fn); - bool RunOnBlock(Block* block, func fn); - bool RunOnOperation(Operation* op, func fn); - - bool BuildShapeOnOperation(Operation* op); - bool BuildShapeOnValue(Value value); - - bool ApplyOpConstraint(Operation* op); - bool ApplyIndexOpConstraint(Operation* op); - bool ApplyTieShapeOpConstraint(Operation* op); - - bool initialized_ = false; - ModuleOp m_; - SymbolicDimMgr& mgr_; - - std::unordered_map value_to_sym_dim_; - - // shape tensor is the 1D ranked tensor with int/index dtype. - std::unordered_map> - shape_tensor_to_sym_dims_; - - std::unordered_map> - dense_tensor_to_sym_dims_; -}; - -ShapeComputationIRAnalysis::ShapeComputationIRAnalysis(ModuleOp m, - SymbolicDimMgr& mgr) - : m_(m), mgr_(mgr) {} - -bool ShapeComputationIRAnalysis::Run() { - // Make sure only run once. - if (initialized_) return false; - initialized_ = true; - return true; -} - -bool ShapeComputationIRAnalysis::RunOnRegion(Region* region, func fn) { - for (auto& block : *region) { - if (!RunOnBlock(&block, fn)) return false; - } - return true; -} - -bool ShapeComputationIRAnalysis::RunOnBlock(Block* block, func fn) { - // TODO(zhangbopd): mapping block arguments - - std::vector op_list; - for (auto& op : *block) op_list.push_back(&op); - for (Operation* op : op_list) { - if (!RunOnOperation(op, fn)) return false; - } - return true; -} - -bool ShapeComputationIRAnalysis::RunOnOperation(Operation* op, func fn) { - for (size_t i = 0; i < op->num_regions(); ++i) { - if (!RunOnRegion(&(op->region(i)), fn)) return false; - } - return fn(op); -} - -bool ShapeComputationIRAnalysis::BuildShapeOnOperation(Operation* op) { - if (op->isa()) return true; - if (op->isa()) { - Value value = op->operand_source(0); - std::vector symbols; - if (op->HasAttribute(SymbolicDimOp::GetSymbolicDimAttrName())) { - auto attrs = - op->attribute(SymbolicDimOp::GetSymbolicDimAttrName()) - .AsVector(); - for (Attribute attr : attrs) { - auto sym = mgr_.symbolTable().Lookup( - attr.dyn_cast().AsString()); - IR_ENFORCE(sym); - SymbolicDimOp root = mgr_.GetRootSymbolicDim(sym); - symbols.push_back(root); - } - } else { - symbols = mgr_.CreateSymbolicDimsForRankedValue(value); - std::vector attrs; - for (SymbolicDimOp sym : symbols) { - Attribute rootSymbol = - StrAttribute::get(m_->ir_context(), sym.GetSymName()); - attrs.push_back(rootSymbol); - } - op->set_attribute(SymbolicDimOp::GetSymbolicDimAttrName(), - ArrayAttribute::get(m_->ir_context(), attrs)); - } - dense_tensor_to_sym_dims_[value] = std::move(symbols); - return true; - } - for (auto& result : op->results()) { - if (!BuildShapeOnValue(result)) return false; - } - return true; -} - -bool ShapeComputationIRAnalysis::BuildShapeOnValue(Value value) { - Type type = value.type(); - if (type.IsIntOrIndex()) { - SymbolicDimOp sym = mgr_.NewSymbolicDim(); - value_to_sym_dim_[value] = sym; - } else if (IsCandidateShapeTensorType(type)) { - auto shaped_type = type.dyn_cast(); - std::vector symbols; - for (size_t i = 0, d = shaped_type.GetDyShape()[0]; i < d; ++i) - symbols.push_back(mgr_.NewSymbolicDim()); - shape_tensor_to_sym_dims_[value] = std::move(symbols); - } - return true; -} - -bool ShapeComputationIRAnalysis::ApplyOpConstraint(Operation* op) { - IR_ENFORCE(ApplyIndexOpConstraint(op), - "Fail to apply constraint for index op"); - IR_ENFORCE(ApplyTieShapeOpConstraint(op), - "Fail to apply constraint for tie_shape op"); - - // TODO(zhangbopd): add more constraints - return true; -} - -bool ShapeComputationIRAnalysis::ApplyIndexOpConstraint(Operation* op) { - if (op->num_results() == 0) return true; - - Type type = op->result(0).type(); - if (!type.IsIntOrIndex()) return true; - - if (auto dim_op = op->dyn_cast()) { - int64_t dim_index = dim_op.index() - .dyn_cast() - .owner() - ->attribute("value") - .data(); - value_to_sym_dim_[dim_op.out()].UpdateKnownNonNegative(true); - if (!mgr_.MapSymbolicDimEqual( - value_to_sym_dim_[dim_op.out()], - dense_tensor_to_sym_dims_[dim_op.source()][dim_index])) { - return false; - } - - } else if (auto const_op = op->dyn_cast()) { - int64_t val = const_op.value().dyn_cast().data(); - if (!mgr_.MapSymbolicDimEqual(value_to_sym_dim_[op->result(0)], - mgr_.NewConstantSymbolicDim(val))) { - return false; - } - } - // TODO(zhangbopd): add support for reifyInferShape. (e.g. mul/add) - return true; -} - -bool ShapeComputationIRAnalysis::ApplyTieShapeOpConstraint(Operation* op) { - if (auto tie_shape = op->dyn_cast()) { - auto& value = dense_tensor_to_sym_dims_[op->operand_source(0)]; - for (size_t idx = 0; idx < tie_shape.dims().size(); ++idx) { - if (!mgr_.MapSymbolicDimEqual(value_to_sym_dim_[tie_shape.dims()[idx]], - value[idx])) - return false; - mgr_.GetRootSymbolicDim(value[idx]).UpdateKnownNonNegative(true); - } - } - return true; -} - -bool OptimizeShapeComputation(pir::ModuleOp m, PassPipelineRunner runner) { - // TODO(zhangbopd): Do some Canonicalizer. - pir::SymbolicDimMgr mgr(m); - - ShapeComputationIRAnalysis analysis(m, mgr); - if (!analysis.Run()) { - return false; - } - - return true; -} - void PrintProgram(pir::ModuleOp m, std::string mgs) { std::ostringstream print_stream; print_stream << "\n\n"; diff --git a/paddle/fluid/pybind/pir.cc b/paddle/fluid/pybind/pir.cc index 9ba7f62bbf3b6c..07f041ad05e613 100644 --- a/paddle/fluid/pybind/pir.cc +++ b/paddle/fluid/pybind/pir.cc @@ -1608,9 +1608,11 @@ void AddCinnPass(std::shared_ptr &pass_manager, // NOLINT void InferSymbolicShapePass( std::shared_ptr &pass_manager) { // NOLINT - pir::IrContext *ctx = pir::IrContext::Instance(); - ctx->GetOrRegisterDialect(); - pass_manager->AddPass(pir::CreateShapeOptimizationPass()); + if (FLAGS_pir_apply_shape_optimization_pass) { + pir::IrContext *ctx = pir::IrContext::Instance(); + ctx->GetOrRegisterDialect(); + pass_manager->AddPass(pir::CreateShapeOptimizationPass()); + } } void BindIrPass(pybind11::module *m) { From a2d4abb7738fdfab4a265fcef4d47964964a7b77 Mon Sep 17 00:00:00 2001 From: lanxianghit Date: Wed, 10 Jan 2024 02:58:54 +0000 Subject: [PATCH 4/5] fix ci --- paddle/pir/dialect/shape/utils/shape_optimization_utils.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc b/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc index f855048181c4e7..f0f2539e352fb5 100644 --- a/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc +++ b/paddle/pir/dialect/shape/utils/shape_optimization_utils.cc @@ -166,9 +166,7 @@ const std::string SymbolicDimMgr::GetNextName() { } SymbolicDimOp SymbolicDimMgr::NewSymbolicDim(const std::string& name) { - auto func_op = symbol_table_.getOp()->dyn_cast(); - IR_ENFORCE(func_op); - Builder builder = Builder(m_.ir_context(), func_op.block()); + Builder builder = Builder(m_.ir_context(), nullptr, Block::Iterator{}, false); // default settting dim != 0 SymbolicDimOp symbol = builder.Build(name.empty() ? GetNextName() : name, From aba8e49bd7a477c5431f1101214febabdb1ce794 Mon Sep 17 00:00:00 2001 From: lanxianghit Date: Wed, 10 Jan 2024 08:00:14 +0000 Subject: [PATCH 5/5] fix win ci --- test/cpp/pir/shape_dialect/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/cpp/pir/shape_dialect/CMakeLists.txt b/test/cpp/pir/shape_dialect/CMakeLists.txt index 9f8d37a21e697e..5b0e88d6310056 100644 --- a/test/cpp/pir/shape_dialect/CMakeLists.txt +++ b/test/cpp/pir/shape_dialect/CMakeLists.txt @@ -6,3 +6,9 @@ if(WITH_CINN) shape_optimization_test PROPERTIES ENVIRONMENT "FLAGS_enable_pir_in_executor=true") endif() + +if(WITH_ONNXRUNTIME AND WIN32) + # Copy onnxruntime for some c++ test in Windows, since the test will + # be build only in CI, so suppose the generator in Windows is Ninja. + copy_onnx(symbol_dim_expr_test) +endif()