// Copyright (c) 2021 CINN 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 #include #include #include #include #include "paddle/cinn/common/type.h" #include "paddle/cinn/ir/ir.h" //! This file defines some intrinsic IR nodes, this is similar to the MLIR operations, we try to expose some underlying //! opaque operations to IR system to helpe more intuitive codegen. namespace cinn::ir { // clang-format off #define INTRINSIC_KIND_FOR_EACH(macro__) \ macro__(BufferGetDataHandle) \ macro__(BufferGetDataConstHandle) \ macro__(PodValueToX) \ macro__(BufferCreate) \ macro__(GetAddr) \ macro__(ArgsConstruct) \ macro__(BuiltinIntrin) // clang-format on enum class IntrinsicKind { // All the intrinsics should registered here. #define __(x__) k##x__, INTRINSIC_KIND_FOR_EACH(__) #undef __ }; class IntrinsicOp : public IrNode { public: IntrinsicOp(IntrinsicKind kind, llvm::ArrayRef input_types, llvm::ArrayRef output_types) : kind_(kind), input_types_(input_types.begin(), input_types.end()), output_types_(output_types.begin(), output_types.end()) {} const Type& GetInputType(int offset) const; const Type& GetOutputType(int offset) const; void AddInputType(const Type& type) { input_types_.push_back(type); } void AddOutputType(const Type& type) { output_types_.push_back(type); } const llvm::SmallVectorImpl& input_types() const { return input_types_; } const llvm::SmallVectorImpl& output_types() const { return input_types_; } //! Verify the \p input_types and \p output_types matches the signature of this operation. void Verify(llvm::ArrayRef input_types, llvm::ArrayRef output_types) const; void Verify(llvm::ArrayRef inputs, llvm::ArrayRef outputs) const; void Verify(llvm::ArrayRef inputs) const; void Verify() const override {} const char* type_info() const override; IntrinsicKind getKind() const { return kind_; } IrNodeTy node_type() const override { return _node_type_; } static constexpr IrNodeTy _node_type_{IrNodeTy::IntrinsicOp}; protected: llvm::SmallVector input_types_; llvm::SmallVector output_types_; const IntrinsicKind kind_; }; namespace intrinsics { /** * The operation to get the memory address from cinn_buffer_t. */ struct BufferGetDataHandle : public IntrinsicOp { // signature: (cinn_buffer_t*) -> (void*) BufferGetDataHandle() : IntrinsicOp(IntrinsicKind::kBufferGetDataHandle, {type_of()}, {type_of()}) {} static Expr Make(Expr buffer); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kBufferGetDataHandle; } Expr buffer; }; /** * The operation to get the memory address from cinn_buffer_t. */ struct BufferGetDataConstHandle : public IntrinsicOp { // signature: (cinn_buffer_t*) -> (const void*) BufferGetDataConstHandle() : IntrinsicOp(IntrinsicKind::kBufferGetDataConstHandle, {type_of()}, {type_of()}) {} static Expr Make(Expr buffer); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kBufferGetDataConstHandle; } Expr buffer; }; /** * The operation to represent the helper methods: * - cinn_pod_value_to_float * - cinn_pod_value_to_duoble * - cinn_pod_value_to_int64 * - cinn_pod_value_to_int32 * - cinn_pod_value_to_void_p * - cinn_pod_value_to_buffer_p */ struct PodValueToX : public IntrinsicOp { // signature: (cinn_pod_value_t*) -> (X), X is some pod type. PodValueToX() : IntrinsicOp(IntrinsicKind::kPodValueToX, {type_of()}, {}) {} static Expr Make(Expr pod_value_ptr, const Type& type); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kPodValueToX; } Expr pod_value_ptr; }; /** * The operation to create a buffer. */ struct BufferCreate : public IntrinsicOp { // signature: (cinn_buffer_t*) -> void BufferCreate() : IntrinsicOp(IntrinsicKind::kBufferCreate, {type_of()}, {}) {} static Expr Make(Expr buffer); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kBufferCreate; } Expr buffer; }; /** * The operation to get the address of a data. */ struct GetAddr : public IntrinsicOp { // signature: (X) -> (X*) GetAddr() : IntrinsicOp(IntrinsicKind::kGetAddr, {}, {}) {} static Expr Make(Expr data); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kGetAddr; } Expr data; }; /** * The operation to construct a cinn_pod_value_t* */ struct ArgsConstruct : public IntrinsicOp { ArgsConstruct() : IntrinsicOp(IntrinsicKind::kArgsConstruct, {}, {}) {} static Expr Make(Var var, llvm::ArrayRef args); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kArgsConstruct; } Var var; llvm::SmallVector args; }; /** * The llvm intrinsic op */ struct BuiltinIntrin : public IntrinsicOp { BuiltinIntrin() : IntrinsicOp(IntrinsicKind::kBuiltinIntrin, {}, {}) {} static Expr Make( const std::string& name, llvm::ArrayRef args, llvm::Intrinsic::ID id, int64_t arg_nums, const Type& type); static bool classof(const IntrinsicOp* s) { return s->getKind() == IntrinsicKind::kBuiltinIntrin; } std::string name; llvm::SmallVector args; llvm::Intrinsic::ID id; int64_t arg_nums; }; } // namespace intrinsics } // namespace cinn::ir