forked from huawei/mindspore2022
395 lines
13 KiB
C++
395 lines
13 KiB
C++
/**
|
|
* Copyright 2019 Huawei Technologies Co., Ltd
|
|
*
|
|
* 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.
|
|
*/
|
|
#ifndef MINDSPORE_CCSRC_UTILS_BASE_REF_H_
|
|
#define MINDSPORE_CCSRC_UTILS_BASE_REF_H_
|
|
|
|
#include <type_traits>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <set>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <utility>
|
|
#include <iterator>
|
|
|
|
#include "ir/value.h"
|
|
|
|
namespace mindspore {
|
|
class BaseRef;
|
|
class VectorRef;
|
|
class SetRef;
|
|
class PyObjectRef;
|
|
class RunFunctionRef;
|
|
|
|
using iterator = std::vector<BaseRef>::iterator;
|
|
|
|
using const_iterator = std::vector<BaseRef>::const_iterator;
|
|
using const_reverse_iterator = std::vector<BaseRef>::const_reverse_iterator;
|
|
|
|
using RunFunc = std::function<VectorRef(const VectorRef& args)>;
|
|
using RunFuncPtr = std::shared_ptr<RunFunc>;
|
|
|
|
template <typename T>
|
|
using remove_reference_t = typename std::remove_reference<T>::type;
|
|
template <typename T>
|
|
using remove_const_t = typename std::remove_const<T>::type;
|
|
template <typename T>
|
|
using is_base = std::is_base_of<Base, remove_reference_t<T>>;
|
|
template <typename T>
|
|
using is_value = std::is_base_of<Value, remove_reference_t<T>>;
|
|
template <typename T>
|
|
using is_base_ref = std::is_base_of<BaseRef, remove_reference_t<T>>;
|
|
|
|
iterator ConstIteratorCast(std::vector<BaseRef>* v, const_iterator iter);
|
|
|
|
inline std::shared_ptr<VectorRef> MakeNode(const std::vector<BaseRef>& elements) {
|
|
return std::make_shared<VectorRef>(elements);
|
|
}
|
|
|
|
inline std::shared_ptr<VectorRef> MakeNode(std::initializer_list<BaseRef> elements) {
|
|
return std::make_shared<VectorRef>(elements);
|
|
}
|
|
|
|
// Anfnode, Funcgraph and some not value node class
|
|
template <typename T,
|
|
typename std::enable_if<is_shared_ptr<remove_const_t<T>>::value && is_base<typename T::element_type>::value,
|
|
int>::type = 0>
|
|
inline BasePtr MakeNode(const T& v) {
|
|
return v;
|
|
}
|
|
|
|
template <typename T,
|
|
typename std::enable_if<!is_shared_ptr<remove_const_t<T>>::value && !is_base_ref<T>::value, int>::type = 0>
|
|
inline BasePtr MakeNode(const T& v) {
|
|
return MakeValue(v);
|
|
}
|
|
|
|
inline std::shared_ptr<VectorRef> MakeNode(const VectorRef& a) { return std::make_shared<VectorRef>(std::move(a)); }
|
|
inline std::shared_ptr<VectorRef> MakeNode(const AnfNodePtrList& a) {
|
|
std::vector<BaseRef> ret;
|
|
(void)std::transform(a.begin(), a.end(), std::back_inserter(ret), [](const AnfNodePtr& v) { return v; });
|
|
return std::make_shared<VectorRef>(ret);
|
|
}
|
|
inline std::shared_ptr<SetRef> MakeNode(const SetRef& a) { return std::make_shared<SetRef>(std::move(a)); }
|
|
inline std::shared_ptr<RunFunctionRef> MakeNode(const RunFuncPtr& a) { return std::make_shared<RunFunctionRef>(a); }
|
|
inline std::shared_ptr<PyObjectRef> MakeNode(const py::object& a) { return std::make_shared<PyObjectRef>(a); }
|
|
inline std::shared_ptr<PyObjectRef> MakeNode(const py::tuple& a) { return std::make_shared<PyObjectRef>(a); }
|
|
|
|
class BaseRef : public Base {
|
|
public:
|
|
BaseRef() : m_ptr(nullptr) {}
|
|
BaseRef(const BaseRef& other);
|
|
virtual std::shared_ptr<Base> copy() const { return m_ptr; }
|
|
|
|
BaseRef(BaseRef&& other) : Base(other) {
|
|
m_ptr = other.m_ptr;
|
|
other.m_ptr = nullptr;
|
|
}
|
|
|
|
// right reference constructor
|
|
template <class T,
|
|
class = typename std::enable_if<!std::is_same<typename std::decay<T>::type, BaseRef>::value, T>::type>
|
|
BaseRef(T&& t) { // NOLINT
|
|
m_ptr = MakeNode(t);
|
|
}
|
|
|
|
~BaseRef() override { m_ptr = nullptr; }
|
|
|
|
MS_DECLARE_PARENT(BaseRef, Base)
|
|
|
|
bool operator!=(const BaseRef& other) const { return !(operator==(other)); }
|
|
|
|
virtual bool operator==(const BaseRef& other) const;
|
|
|
|
// left reference
|
|
virtual BaseRef& operator=(const BaseRef& other);
|
|
// right reference
|
|
virtual BaseRef& operator=(BaseRef&& other);
|
|
|
|
std::size_t hash() const override {
|
|
if (m_ptr == nullptr) {
|
|
MS_LOG(ERROR) << "Invalid m_ptr";
|
|
return 0;
|
|
}
|
|
return m_ptr->hash();
|
|
}
|
|
|
|
std::string ToString() const override;
|
|
|
|
bool is_null() const { return m_ptr == nullptr; }
|
|
|
|
virtual uint32_t type() const;
|
|
|
|
BasePtr m_ptr; // point to real data
|
|
};
|
|
using BaseRefPtr = std::shared_ptr<BaseRef>;
|
|
|
|
struct BaseRefHash {
|
|
std::size_t operator()(const BaseRef& c) const { return c.hash(); }
|
|
};
|
|
|
|
struct BaseRefLess {
|
|
bool operator()(const BaseRef& a, const BaseRef& b) const { return a.hash() < b.hash(); }
|
|
};
|
|
|
|
namespace utils {
|
|
// judge isa relation
|
|
// examples: isa<Int32Imm>(handle), isa<FuncGraph>(handle)
|
|
template <typename T, typename std::enable_if<is_base<T>::value && !is_base_ref<T>::value, int>::type = 0>
|
|
bool isa(const BaseRef& handle) {
|
|
if (!handle.m_ptr) {
|
|
return false;
|
|
}
|
|
return handle.m_ptr->isa<T>();
|
|
}
|
|
|
|
// noderef isa ptr isa<AnfNodePtr>(x) or isa<SeqPtr>()
|
|
template <typename T, typename U = typename std::enable_if<is_shared_ptr<T>::value, typename T::element_type>::type,
|
|
typename std::enable_if<is_base<U>::value || is_base_ref<U>::value, int>::type = 0>
|
|
bool isa(const BaseRef& handle) {
|
|
if (handle.m_ptr == nullptr) {
|
|
return typeid(handle.m_ptr) == typeid(T);
|
|
}
|
|
|
|
if (handle.m_ptr->isa<U>()) {
|
|
return true;
|
|
}
|
|
|
|
// constptr isa<anfnodeptr> can be true
|
|
return std::dynamic_pointer_cast<U>(handle.m_ptr) != nullptr;
|
|
}
|
|
|
|
// isa<int32>(handle)
|
|
template <typename S, typename U = typename ImmTraits<S>::type::element_type>
|
|
bool isa(const BaseRef& handle) {
|
|
if (handle.m_ptr == nullptr) {
|
|
return false;
|
|
}
|
|
return handle.m_ptr->isa<U>();
|
|
}
|
|
|
|
// isa<BaseRef>(handle), judge reference or ptr
|
|
template <typename T, typename std::enable_if<is_base_ref<T>::value, int>::type = 0>
|
|
bool isa(const BaseRef& handle) {
|
|
static const uint32_t tid = Base::GetTypeId(typeid(T).name());
|
|
return handle.IsFromTypeId(tid) || (handle.m_ptr && handle.m_ptr->isa<T>());
|
|
}
|
|
|
|
// valueref -> C++ type
|
|
// cast<int>(handle)
|
|
template <typename T, typename std::enable_if<!is_base_ref<T>::value && !is_shared_ptr<T>::value, int>::type = 0>
|
|
T cast(const BaseRef& handle) {
|
|
T ret = GetValue<T>(std::static_pointer_cast<Value>(handle.m_ptr));
|
|
return std::move(ret);
|
|
}
|
|
|
|
// valueref -> valueref type
|
|
// cast<VectorRef>(handle)
|
|
template <typename T, typename std::enable_if<is_base_ref<T>::value, int>::type = 0>
|
|
const T& cast(const BaseRef& handle) {
|
|
if (handle.m_ptr) {
|
|
return static_cast<const T&>(*handle.m_ptr);
|
|
}
|
|
|
|
return std::move(static_cast<const T&>(handle));
|
|
}
|
|
|
|
// valueref -> nodeptr type
|
|
// cast<FuncGraphPtr>(handle)
|
|
template <typename T, typename U = typename std::enable_if<is_shared_ptr<T>::value, typename T::element_type>::type,
|
|
typename std::enable_if<is_shared_ptr<T>::value && std::is_base_of<Base, typename T::element_type>::value,
|
|
int>::type = 0>
|
|
T cast(const BaseRef& handle) {
|
|
if (!handle.m_ptr) {
|
|
MS_LOG(EXCEPTION) << "Can not cast to " << typeid(T).name() << ", pointer is null";
|
|
}
|
|
|
|
auto m = handle.m_ptr->cast<T>();
|
|
if (nullptr != m) {
|
|
return m;
|
|
}
|
|
return std::static_pointer_cast<U>(handle.m_ptr);
|
|
}
|
|
} // namespace utils
|
|
|
|
class VectorRef : public BaseRef {
|
|
public:
|
|
VectorRef() {}
|
|
explicit VectorRef(const std::vector<BaseRef>& elements) : elements_(elements) {}
|
|
VectorRef(const const_iterator& begin, const const_iterator& end) : elements_(begin, end) {}
|
|
|
|
// left reference
|
|
virtual VectorRef& operator=(const VectorRef& other);
|
|
|
|
~VectorRef() override = default;
|
|
|
|
std::shared_ptr<Base> copy() const override { return std::make_shared<VectorRef>(elements_); }
|
|
|
|
bool empty() const { return (elements_.size() == 0); }
|
|
|
|
std::size_t size() const { return elements_.size(); }
|
|
MS_DECLARE_PARENT(VectorRef, BaseRef)
|
|
|
|
const BaseRef& operator[](const std::size_t& dim) const {
|
|
if (dim >= size()) {
|
|
MS_LOG(EXCEPTION) << "Out of the size of the tuple.";
|
|
}
|
|
return elements_[dim];
|
|
}
|
|
|
|
uint32_t type() const override { return tid(); }
|
|
std::string ToString() const override;
|
|
std::vector<BaseRef>& elements() { return elements_; }
|
|
void clear() { elements_.clear(); }
|
|
|
|
bool operator==(const BaseRef& other) const override;
|
|
bool operator==(const VectorRef& other) const;
|
|
|
|
void push_back(const BaseRef& value) { elements_.push_back(value); }
|
|
void push_back(BaseRef&& value) { elements_.push_back(value); }
|
|
|
|
void emplace_back(const BaseRef& value) { elements_.emplace_back(value); }
|
|
void emplace_back(BaseRef&& value) { elements_.emplace_back(value); }
|
|
|
|
template <class InputIt>
|
|
void insert(const iterator pos, const InputIt first, const InputIt last) {
|
|
(void)elements_.insert(pos, first, last);
|
|
}
|
|
|
|
template <class InputIt>
|
|
void insert(const const_iterator cpos, const InputIt first, const InputIt last) {
|
|
auto pos = ConstIteratorCast(&elements_, cpos);
|
|
(void)elements_.insert(pos, first, last);
|
|
}
|
|
|
|
const_iterator begin() const { return elements_.begin(); }
|
|
const_iterator end() const { return elements_.end(); }
|
|
|
|
const_reverse_iterator rbegin() const { return elements_.rbegin(); }
|
|
const_reverse_iterator rend() const { return elements_.rend(); }
|
|
|
|
iterator erase(const const_iterator cpos) {
|
|
auto pos = ConstIteratorCast(&elements_, cpos);
|
|
return elements_.erase(pos);
|
|
}
|
|
|
|
iterator erase(const const_iterator cfirst, const const_iterator clast) {
|
|
auto first = ConstIteratorCast(&elements_, cfirst);
|
|
auto last = ConstIteratorCast(&elements_, clast);
|
|
return elements_.erase(first, last);
|
|
}
|
|
|
|
std::size_t hash() const override {
|
|
std::stringstream buffer;
|
|
buffer << ToString();
|
|
return std::hash<std::string>()(buffer.str());
|
|
}
|
|
|
|
std::vector<BaseRef> elements_;
|
|
};
|
|
|
|
using VectorRefPtr = std::shared_ptr<VectorRef>;
|
|
|
|
using set_iterator = std::set<BaseRef, BaseRefLess>::iterator;
|
|
using const_set_iterator = std::set<BaseRef, BaseRefLess>::const_iterator;
|
|
|
|
struct VectorRefHash {
|
|
std::size_t operator()(const VectorRef& c) const { return c.hash(); }
|
|
};
|
|
|
|
class SetRef : public BaseRef {
|
|
public:
|
|
SetRef() {}
|
|
explicit SetRef(const std::set<BaseRef, BaseRefLess>& elements) : elements_(elements) {}
|
|
SetRef(const std::initializer_list<BaseRef> elements) : elements_(elements.begin(), elements.end()) {}
|
|
SetRef(const const_set_iterator& begin, const const_set_iterator& end) : elements_(begin, end) {}
|
|
|
|
// left reference
|
|
virtual SetRef& operator=(const SetRef& other);
|
|
|
|
bool operator==(const BaseRef& other) const override;
|
|
bool operator==(const SetRef& other) const;
|
|
|
|
~SetRef() override = default;
|
|
|
|
std::shared_ptr<Base> copy() const override { return std::make_shared<SetRef>(elements_); }
|
|
|
|
bool empty() const { return (elements_.size() == 0); }
|
|
|
|
std::size_t size() const { return elements_.size(); }
|
|
MS_DECLARE_PARENT(SetRef, BaseRef)
|
|
|
|
uint32_t type() const override { return tid(); }
|
|
std::string ToString() const override;
|
|
std::set<BaseRef, BaseRefLess>& elements() { return elements_; }
|
|
void clear() { elements_.clear(); }
|
|
|
|
void insert(const BaseRef& elem) { (void)elements_.insert(elem); }
|
|
|
|
const_set_iterator begin() const { return elements_.begin(); }
|
|
const_set_iterator end() const { return elements_.end(); }
|
|
|
|
template <class InputIt>
|
|
void insert(const InputIt first, const InputIt last) {
|
|
(void)elements_.insert(first, last);
|
|
}
|
|
|
|
std::size_t count(const BaseRef& elem) const { return elements_.count(elem); }
|
|
const_set_iterator find(const BaseRef& elem) const { return elements_.find(elem); }
|
|
|
|
std::set<BaseRef, BaseRefLess> elements_;
|
|
};
|
|
|
|
using SetRefPtr = std::shared_ptr<SetRef>;
|
|
|
|
class PyObjectRef : public BaseRef {
|
|
public:
|
|
explicit PyObjectRef(const py::object& py_object) : object_(py_object) {}
|
|
explicit PyObjectRef(const py::tuple& tuple_obj) : object_(tuple_obj) {}
|
|
|
|
~PyObjectRef() override = default;
|
|
|
|
std::shared_ptr<Base> copy() const override { return std::make_shared<PyObjectRef>(object_); }
|
|
MS_DECLARE_PARENT(PyObjectRef, BaseRef)
|
|
|
|
uint32_t type() const override { return tid(); }
|
|
std::string ToString() const override { return py::str(object_); }
|
|
bool operator==(const BaseRef& other) const override;
|
|
bool operator==(const PyObjectRef& other) const;
|
|
|
|
py::object object_;
|
|
};
|
|
|
|
class RunFunctionRef : public BaseRef {
|
|
public:
|
|
RunFunctionRef() {}
|
|
explicit RunFunctionRef(const RunFuncPtr& ref_func) : func_(ref_func) {}
|
|
|
|
~RunFunctionRef() override = default;
|
|
MS_DECLARE_PARENT(RunFunctionRef, BaseRef)
|
|
|
|
uint32_t type() const override { return tid(); }
|
|
std::string ToString() const override { return std::string("RunFunctionRef"); }
|
|
bool operator==(const BaseRef& other) const override;
|
|
bool operator==(const RunFunctionRef& other) const;
|
|
|
|
RunFuncPtr func_;
|
|
};
|
|
} // namespace mindspore
|
|
|
|
#endif // MINDSPORE_CCSRC_UTILS_NODE_REF_H_
|