From f11c913e8da6efc3159a6d135fdbcb380c760679 Mon Sep 17 00:00:00 2001 From: zhangbo9674 <82555433+zhangbo9674@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:08:48 +0800 Subject: [PATCH] [IR] Type system stage1: add class TypeId, class AbstractType, class TypeStorage (#50242) * add TypeID * Specification comment code * refine code * add AbstractType * add TypeStorage * fix unittest bug * change dir * change dir * refine code * fix bug * Refine code by comment * delete unused code * normative naming rules * refine code by comment * refine doc * refine codestyle --- CMakeLists.txt | 1 + paddle/CMakeLists.txt | 2 + paddle/ir/CMakeLists.txt | 5 ++ paddle/ir/type/CMakeLists.txt | 4 + paddle/ir/type/type_support.h | 122 ++++++++++++++++++++++++++++ paddle/ir/type/type_support_test.cc | 57 +++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 paddle/ir/CMakeLists.txt create mode 100644 paddle/ir/type/CMakeLists.txt create mode 100644 paddle/ir/type/type_support.h create mode 100644 paddle/ir/type/type_support_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6722ae8e25b..2b8caf7addd 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,6 +315,7 @@ option(WITH_CUDNN_FRONTEND "Compile with CUDNN Frontend API support (experimental)" OFF) option(WITH_CUDNN_DSO "Compile PaddlePaddle with cuDNN dynamic-link libraries" OFF) +option(WITH_NEWIR "Compile PaddlePaddle with NEWIR" OFF) if(WITH_RECORD_BUILDTIME) set_property( diff --git a/paddle/CMakeLists.txt b/paddle/CMakeLists.txt index e7f788631b7..25848620326 100644 --- a/paddle/CMakeLists.txt +++ b/paddle/CMakeLists.txt @@ -13,6 +13,8 @@ add_subdirectory(phi) add_subdirectory(infrt) add_subdirectory(fluid) +add_subdirectory(ir) + # NOTE(zhiqiu): The changes of cc tests # Before, (1) the source file of cc tests are distributed in different sub-directories, # (2) the tests are added and configured by calling `cc_test()` in each `CMakeLists.txt`, diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt new file mode 100644 index 00000000000..d104ae066b5 --- /dev/null +++ b/paddle/ir/CMakeLists.txt @@ -0,0 +1,5 @@ +if(NOT WITH_NEWIR) + return() +endif() + +add_subdirectory(type) diff --git a/paddle/ir/type/CMakeLists.txt b/paddle/ir/type/CMakeLists.txt new file mode 100644 index 00000000000..649ac7d74b4 --- /dev/null +++ b/paddle/ir/type/CMakeLists.txt @@ -0,0 +1,4 @@ +cc_test( + type_support_test + SRCS type_support_test.cc + DEPS gtest) diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h new file mode 100644 index 00000000000..fc2a3977685 --- /dev/null +++ b/paddle/ir/type/type_support.h @@ -0,0 +1,122 @@ +// 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. + +#pragma once + +#include + +namespace ir { + +/// \brief TypeId is the unique identification of Type, each Type corresponds to +/// a unique TypeId, the same id indicates the same Type class. TypeId provides +/// an instantiation interface: TypeId::get. +/// Example: +/// \code{cpp} +/// class TypeA {}; +/// TypeId type_a_id = TypeId::get(); +/// \endcode +class TypeId { + struct Storage {}; + + public: + /// \brief Returns the unique TypeId of Type T. + /// \return The unique TypeId of Type T. + template + static TypeId get() { + static Storage instance; + return TypeId(&instance); + } + + /// \brief Comparison operations. + inline bool operator==(const TypeId &other) const { + return storage_ == other.storage_; + } + + /// \brief Comparison operations. + inline bool operator!=(const TypeId &other) const { + return !(*this == other); + } + + /// \brief Enable hashing TypeId instances. + friend struct std::hash; + + private: + /// \brief Construct a TypeId and initialize storage. + /// \param storage The storage of this TypeId. + explicit TypeId(const Storage *storage) : storage_(storage) {} + + const Storage *storage_; +}; + +/// \brief Abstract the properties and behaviors common to all Type classes into +/// an AbstractType class. There are two types in Type system: +/// on-parameter/singleton type and parameter-type. The common attributes of all +/// types is TypeId (and possibly others). Therefore, construct a class with +/// TypeId as its member. +class AbstractType { + public: + /// \brief Construct an AbstractType by TypeId directly. + /// \param type_id The type id of the AbstractType. + static AbstractType get(TypeId type_id) { return AbstractType(type_id); } + + /// \brief Returns the type id of the AbstractType. + /// \return The type id of the AbstractType. + TypeId type_id() const { return type_id_; } + + /* TODO(zhangbo9674): After the IRContext is designed, AbstractType will be + * cached to IRContext with TypeId as key. + */ + + private: + /// \brief The constructor is set to private and provides the user with the + /// get method to obtain and manage the AstractType. + /// \param type_id The type id of the AbstractType. + explicit AbstractType(TypeId type_id) : type_id_(type_id) {} + + TypeId type_id_; +}; + +/// \brief TypeStorage is used to store all information of a Type. A Type object +/// contains a TypeStorage. For non-parameter type, the information includes: +/// TypeId, so TypeStorage only needs to include AbstractType; For parameter +/// type, in addition to AbstractType/TypeId, parameter information needs to be +/// included. So that, non-parameter type can be constructed by TypeStorage +/// directly but parameter type should be constructed by Derived TypeStorage. +class TypeStorage { + public: + /// \brief Construct a TypeStorage and initialize abstract_type. + /// \param abstract_type The abstract_type of this TypeStorage. + explicit TypeStorage(AbstractType *abstract_type) + : abstract_type_(abstract_type) {} + + /// \brief Returns the AbstractType of the TypeStorage. + /// \return The AbstractType of the TypeStorage. + const AbstractType &abstract_type() { return *abstract_type_; } + + private: + AbstractType *abstract_type_{nullptr}; +}; + +} // namespace ir + +// Custom specialization of std::hash can be injected in namespace std. +namespace std { +/// \brief Enable hashing TypeId instances. +template <> +struct hash { + std::size_t operator()(const ir::TypeId &obj) const { + return std::hash()(obj.storage_); + } +}; +} // namespace std diff --git a/paddle/ir/type/type_support_test.cc b/paddle/ir/type/type_support_test.cc new file mode 100644 index 00000000000..061ef8e31c8 --- /dev/null +++ b/paddle/ir/type/type_support_test.cc @@ -0,0 +1,57 @@ +/* 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 "paddle/ir/type/type_support.h" +#include +#include + +TEST(type_support, type_id) { + class TypeA {}; + class TypeB {}; + + // (1) Test construct TypeId by TypeId::Get() + ir::TypeId a_id = ir::TypeId::get(); + ir::TypeId a_other_id = ir::TypeId::get(); + ir::TypeId b_id = ir::TypeId::get(); + EXPECT_EQ(a_id, a_other_id); + EXPECT_NE(a_id, b_id); + + // (2) Test TypeId hash + std::unordered_map type_id_register; + type_id_register.emplace(a_id, &a_id); + type_id_register.emplace(b_id, &b_id); + for (auto kv : type_id_register) { + EXPECT_EQ(kv.first, *kv.second); + } +} + +TEST(type_support, abstract_type) { + class TypeA {}; + + ir::TypeId a_id = ir::TypeId::get(); + ir::AbstractType abstract_type_a = ir::AbstractType::get(a_id); + + EXPECT_EQ(abstract_type_a.type_id(), a_id); +} + +TEST(type_support, type_storage) { + class TypeA {}; + + ir::TypeId a_id = ir::TypeId::get(); + ir::AbstractType abstract_type_a = ir::AbstractType::get(a_id); + + ir::TypeStorage storage_a(&abstract_type_a); + + EXPECT_EQ(storage_a.abstract_type().type_id(), abstract_type_a.type_id()); +} -- GitLab