chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
paddle_test(type_test SRCS type_test.cc DEPS common)
|
||||
paddle_test(type_util_test SRCS type_util_test.cc DEPS pir common)
|
||||
paddle_test(ir_attribute_test SRCS ir_attribute_test.cc)
|
||||
paddle_test(ir_value_test SRCS ir_value_test.cc)
|
||||
paddle_test(ir_op_test SRCS ir_op_test.cc DEPS test_dialect)
|
||||
paddle_test(ir_region_test SRCS ir_region_test.cc)
|
||||
paddle_test(ir_builder_test SRCS ir_builder_test.cc)
|
||||
paddle_test(ir_program_test SRCS ir_program_test.cc)
|
||||
paddle_test(ir_infershape_test SRCS ir_infershape_test.cc)
|
||||
paddle_test(scalar_attribute_test SRCS scalar_attribute_test.cc)
|
||||
paddle_test(paddle_fatal_test SRCS paddle_fatal_test.cc)
|
||||
|
||||
file(
|
||||
DOWNLOAD https://paddle-ci.gz.bcebos.com/ir_translator_test/resnet50_main.prog
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resnet50_main.prog
|
||||
EXPECTED_MD5 b64c0ad3c96d99fc37d12094623ce1ad)
|
||||
|
||||
file(
|
||||
DOWNLOAD
|
||||
https://paddle-ci.gz.bcebos.com/ir_translator_test/resnet50_startup.prog
|
||||
${CMAKE_CURRENT_BINARY_DIR}/resnet50_startup.prog
|
||||
EXPECTED_MD5 6affc5f40f0f0bb84d956919b95eaf50)
|
||||
|
||||
file(
|
||||
DOWNLOAD
|
||||
https://paddle-ci.gz.bcebos.com/ir_translator_test/conditional_block_test.prog
|
||||
${CMAKE_CURRENT_BINARY_DIR}/conditional_block_test.prog
|
||||
EXPECTED_MD5 cf9dc869ca7f69e2d57b38dbf8427134)
|
||||
|
||||
file(
|
||||
DOWNLOAD https://paddle-ci.gz.bcebos.com/ir_translator_test/while_op_test.prog
|
||||
${CMAKE_CURRENT_BINARY_DIR}/while_op_test.prog
|
||||
EXPECTED_MD5 290164ae52a496332b0be5829fc93bcd)
|
||||
|
||||
paddle_test(program_translator_test SRCS program_translator_test.cc)
|
||||
|
||||
paddle_test(add_dialect_parser_test SRCS add_dialect_parser_test.cc DEPS gtest)
|
||||
|
||||
paddle_test(ir_op_info_test SRCS op_info_test.cc)
|
||||
paddle_test(ir_op_yaml_info_parser_test SRCS op_yaml_info_parser_test.cc)
|
||||
|
||||
paddle_test(ir_type_converter_test SRCS ir_type_converter_test.cc)
|
||||
|
||||
paddle_test(type_interface_test SRCS type_interface_test.cc DEPS test_dialect
|
||||
gtest)
|
||||
|
||||
paddle_test(block_operand_test SRCS block_operand_test.cc DEPS test_dialect
|
||||
gtest)
|
||||
|
||||
paddle_test(block_argument_test SRCS block_argument_test.cc DEPS test_dialect)
|
||||
|
||||
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(ir_op_test)
|
||||
endif()
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/fluid/framework/operator.h"
|
||||
#include "paddle/fluid/framework/program_desc.h"
|
||||
#include "paddle/fluid/ir_adaptor/translator/translate.h"
|
||||
#include "paddle/phi/core/framework/framework.pb.h"
|
||||
#include "paddle/pir/include/core/attribute.h"
|
||||
#include "paddle/pir/include/core/attribute_base.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute_storage.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/utils.h"
|
||||
#include "test/cpp/pir/tools/macros_utils.h"
|
||||
|
||||
using OperatorDialect = paddle::dialect::OperatorDialect;
|
||||
using AttributeStorage = pir::AttributeStorage;
|
||||
|
||||
class TestParserDialect : public pir::Dialect {
|
||||
public:
|
||||
explicit TestParserDialect(pir::IrContext* context);
|
||||
|
||||
static const char* name() { return "tp"; }
|
||||
|
||||
void PrintAttribute(pir::Attribute attr, std::ostream& os) const; // NOLINT
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
};
|
||||
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(TestParserDialect);
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(TestParserDialect);
|
||||
|
||||
DECLARE_BASE_TYPE_ATTRIBUTE_STORAGE(CharAttributeStorage, char);
|
||||
|
||||
class CharAttribute : public pir::Attribute {
|
||||
public:
|
||||
using Attribute::Attribute;
|
||||
|
||||
DECLARE_ATTRIBUTE_UTILITY_FUNCTOR(CharAttribute, CharAttributeStorage);
|
||||
|
||||
char data() const;
|
||||
};
|
||||
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(CharAttribute);
|
||||
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(CharAttribute);
|
||||
|
||||
void TestParserDialect::initialize() { RegisterAttributes<CharAttribute>(); }
|
||||
|
||||
char CharAttribute::data() const { return storage()->data(); }
|
||||
|
||||
TestParserDialect::TestParserDialect(pir::IrContext* context)
|
||||
: pir::Dialect(name(), context, pir::TypeId::get<TestParserDialect>()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void TestParserDialect::PrintAttribute(pir::Attribute attr,
|
||||
std::ostream& os) const {
|
||||
auto byte_attr = attr.dyn_cast<CharAttribute>();
|
||||
os << "(tp.char)" << byte_attr.data();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "test/cpp/pir/tools/test_dialect.h"
|
||||
#include "test/cpp/pir/tools/test_op.h"
|
||||
|
||||
TEST(block_argument_test, base) {
|
||||
pir::IrContext ctx;
|
||||
ctx.GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
pir::Program program(&ctx);
|
||||
pir::Block* block = program.block();
|
||||
pir::Builder builder(&ctx, block);
|
||||
|
||||
std::vector<pir::Type> types(3, builder.float32_type());
|
||||
block->AddArgs(types);
|
||||
|
||||
EXPECT_FALSE(block->args_empty());
|
||||
EXPECT_EQ(block->args_size(), types.size());
|
||||
|
||||
uint32_t index = 0;
|
||||
for (auto iter = block->args_begin(); iter != block->args_end(); ++iter) {
|
||||
EXPECT_EQ(iter->dyn_cast<pir::BlockArgument>().index(), index++);
|
||||
}
|
||||
|
||||
pir::Value value = block->arg(0);
|
||||
pir::BlockArgument argument = value.dyn_cast<pir::BlockArgument>();
|
||||
EXPECT_TRUE(argument);
|
||||
EXPECT_EQ(argument.owner(), block);
|
||||
EXPECT_EQ(block->arg_type(0), types[0]);
|
||||
pir::OpResult op_result = value.dyn_cast<pir::OpResult>();
|
||||
EXPECT_FALSE(op_result);
|
||||
|
||||
auto op = builder.Build<pir::ConstantOp>(builder.double_attr(1.0),
|
||||
builder.float64_type());
|
||||
value = op.result(0);
|
||||
argument = value.dyn_cast<pir::BlockArgument>();
|
||||
EXPECT_FALSE(argument);
|
||||
op_result = value.dyn_cast<pir::OpResult>();
|
||||
EXPECT_TRUE(op_result);
|
||||
block->AddArgs({builder.bool_type()});
|
||||
EXPECT_EQ(block->args_size(), 4u);
|
||||
|
||||
value = block->AddArg(builder.bool_type());
|
||||
EXPECT_EQ(value.type(), builder.bool_type());
|
||||
}
|
||||
|
||||
TEST(block_argument_test, kwargs) {
|
||||
pir::IrContext ctx;
|
||||
ctx.GetOrRegisterDialect<test::TestDialect>();
|
||||
|
||||
pir::Program program(&ctx);
|
||||
pir::Block* block = program.block();
|
||||
pir::Builder builder(&ctx, block);
|
||||
|
||||
std::unordered_map<std::string, pir::Type> types{
|
||||
{"a", builder.float32_type()},
|
||||
{"b", builder.float32_type()},
|
||||
{"c", builder.float32_type()}};
|
||||
block->AddKwargs(types);
|
||||
|
||||
EXPECT_FALSE(block->kwargs_empty());
|
||||
EXPECT_EQ(block->kwargs_size(), types.size());
|
||||
|
||||
for (auto iter = block->kwargs_begin(); iter != block->kwargs_end(); ++iter) {
|
||||
EXPECT_EQ(iter->second.dyn_cast<pir::BlockArgument>().type(),
|
||||
builder.float32_type());
|
||||
}
|
||||
|
||||
pir::Value value = block->kwarg("a");
|
||||
pir::BlockArgument argument = value.dyn_cast<pir::BlockArgument>();
|
||||
EXPECT_TRUE(argument);
|
||||
EXPECT_EQ(argument.owner(), block);
|
||||
EXPECT_EQ(block->kwarg_type("a"), types["a"]);
|
||||
pir::OpResult op_result = value.dyn_cast<pir::OpResult>();
|
||||
EXPECT_FALSE(op_result);
|
||||
|
||||
auto op = builder.Build<pir::ConstantOp>(builder.double_attr(1.0),
|
||||
builder.float64_type());
|
||||
value = op.result(0);
|
||||
argument = value.dyn_cast<pir::BlockArgument>();
|
||||
EXPECT_FALSE(argument);
|
||||
op_result = value.dyn_cast<pir::OpResult>();
|
||||
EXPECT_TRUE(op_result);
|
||||
value = block->AddKwarg("d", builder.bool_type());
|
||||
EXPECT_EQ(block->kwargs_size(), 4u);
|
||||
EXPECT_EQ(value.type(), builder.bool_type());
|
||||
}
|
||||
|
||||
TEST(block_argument_test, fatal) {
|
||||
auto block = new pir::Block();
|
||||
auto arg = block->AddArg(nullptr);
|
||||
auto op = pir::Operation::Create({arg}, {}, {}, nullptr);
|
||||
EXPECT_DEATH(delete block,
|
||||
"Destroyed a position block argument that is still in use.*");
|
||||
auto kwarg = block->AddKwarg("a", nullptr);
|
||||
arg.ReplaceAllUsesWith(kwarg);
|
||||
block->ClearArgs();
|
||||
EXPECT_DEATH(delete block,
|
||||
"Destroyed a keyword block argument that is still in use.*");
|
||||
|
||||
op->Destroy();
|
||||
op = pir::Operation::Create({}, {}, {}, nullptr, 0, {block});
|
||||
EXPECT_DEATH(delete block, "Destroyed a block that is still in use.*");
|
||||
op->Destroy();
|
||||
delete block;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
|
||||
#include "test/cpp/pir/tools/test_dialect.h"
|
||||
#include "test/cpp/pir/tools/test_op.h"
|
||||
TEST(block_operand_test, type_block) {
|
||||
pir::IrContext ctx;
|
||||
ctx.GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(&ctx);
|
||||
pir::Block* block = program.block();
|
||||
|
||||
pir::Builder builder(&ctx, block);
|
||||
test::RegionOp region_op = builder.Build<test::RegionOp>();
|
||||
|
||||
auto& region = region_op->region(0);
|
||||
|
||||
pir::Block* block_1 = new pir::Block();
|
||||
pir::Block* block_2 = new pir::Block();
|
||||
pir::Block* block_3 = new pir::Block();
|
||||
region.push_back(block_1);
|
||||
region.push_back(block_2);
|
||||
region.push_back(block_3);
|
||||
|
||||
builder.SetInsertionPointToBlockEnd(block_1);
|
||||
auto op1 = builder.Build<test::BranchOp>(std::vector<pir::Value>{}, block_2);
|
||||
EXPECT_TRUE(block_2->HasOneUse());
|
||||
EXPECT_FALSE(block_2->use_empty());
|
||||
|
||||
auto iter_begin = block_2->use_begin();
|
||||
auto iter_end = block_2->use_end();
|
||||
auto block_operand = op1->block_operand(0);
|
||||
auto iter_curr = iter_begin++;
|
||||
EXPECT_EQ(iter_begin, iter_end);
|
||||
EXPECT_EQ(*iter_curr, block_operand);
|
||||
EXPECT_EQ(block_2->first_use(), block_operand);
|
||||
EXPECT_EQ(iter_curr->owner(), op1);
|
||||
|
||||
builder.SetInsertionPointToBlockEnd(block_3);
|
||||
auto op3 = builder.Build<test::BranchOp>(std::vector<pir::Value>{}, block_1);
|
||||
block_operand = op3->block_operand(0);
|
||||
block_operand.set_source(block_2);
|
||||
EXPECT_EQ(block_2, block_operand.source());
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <map>
|
||||
|
||||
#include "paddle/pir/include/core/attribute.h"
|
||||
#include "paddle/pir/include/core/attribute_base.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "test/cpp/pir/tools/macros_utils.h"
|
||||
|
||||
class AttributeA {};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(AttributeA)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(AttributeA)
|
||||
|
||||
struct FakeDialect : pir::Dialect {
|
||||
explicit FakeDialect(pir::IrContext *context)
|
||||
: pir::Dialect(name(), context, pir::TypeId::get<FakeDialect>()) {}
|
||||
static const char *name() { return "fake"; }
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(FakeDialect)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(FakeDialect)
|
||||
|
||||
TEST(attribute_test, attribute_base) {
|
||||
// Test 1: Test the function of IrContext to register Dialect.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *fake_dialect = ctx->GetOrRegisterDialect<FakeDialect>();
|
||||
// Test 2: Test the get method of AbstractType.
|
||||
pir::TypeId a_id = pir::TypeId::get<AttributeA>();
|
||||
pir::AbstractAttribute abstract_attribute_a =
|
||||
pir::AbstractAttribute::get(a_id, *fake_dialect);
|
||||
EXPECT_EQ(abstract_attribute_a.type_id(), a_id);
|
||||
// Test 3: Test the constructor of AbstractStorage.
|
||||
pir::AttributeStorage storage_a(&abstract_attribute_a);
|
||||
EXPECT_EQ(storage_a.abstract_attribute().type_id(),
|
||||
abstract_attribute_a.type_id());
|
||||
}
|
||||
|
||||
TEST(attribute_test, built_in_attribute) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
// Test 1: Test the parametric built-in attribute of IrContext.
|
||||
std::string str_tmp = "string_a";
|
||||
pir::Attribute string_attr_1 = pir::StrAttribute::get(ctx, str_tmp);
|
||||
pir::Attribute string_attr_2 = pir::StrAttribute::get(ctx, str_tmp);
|
||||
EXPECT_EQ(string_attr_1, string_attr_2);
|
||||
EXPECT_EQ(pir::StrAttribute::classof(string_attr_1), 1);
|
||||
// Test 2: Test isa and dyn_cast.
|
||||
EXPECT_EQ(string_attr_1.isa<pir::StrAttribute>(), true);
|
||||
pir::StrAttribute string_attr_cast_1 =
|
||||
string_attr_1.dyn_cast<pir::StrAttribute>();
|
||||
EXPECT_EQ(string_attr_cast_1.isa<pir::StrAttribute>(), true);
|
||||
EXPECT_EQ(string_attr_cast_1.size() == 8, 1);
|
||||
|
||||
pir::Int32Type i32_type = pir::Int32Type::get(ctx);
|
||||
pir::Attribute type_attr = pir::TypeAttribute::get(ctx, i32_type);
|
||||
EXPECT_TRUE(type_attr.isa<pir::TypeAttribute>());
|
||||
EXPECT_EQ(type_attr.dyn_cast<pir::TypeAttribute>().data().type_id(),
|
||||
i32_type.type_id());
|
||||
}
|
||||
@@ -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 <gtest/gtest.h>
|
||||
#include <map>
|
||||
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
|
||||
TEST(builder_test, type_api) {
|
||||
pir::IrContext ctx;
|
||||
pir::Builder builder(&ctx);
|
||||
EXPECT_EQ(pir::UInt8Type::get(&ctx), builder.uint8_type());
|
||||
EXPECT_EQ(pir::Int8Type::get(&ctx), builder.int8_type());
|
||||
EXPECT_EQ(pir::VectorType::get(&ctx, std::vector<pir::Type>()),
|
||||
builder.vec_type({}));
|
||||
EXPECT_EQ(pir::BFloat16Type::get(&ctx), builder.bfloat16_type());
|
||||
EXPECT_EQ(pir::Float32Type::get(&ctx), builder.float32_type());
|
||||
EXPECT_EQ(pir::Float64Type::get(&ctx), builder.float64_type());
|
||||
EXPECT_EQ(pir::IndexType::get(&ctx), builder.index_type());
|
||||
EXPECT_EQ(pir::Int16Type::get(&ctx), builder.int16_type());
|
||||
EXPECT_EQ(pir::BoolType::get(&ctx), builder.bool_type());
|
||||
EXPECT_EQ(pir::Complex64Type::get(&ctx), builder.complex64_type());
|
||||
EXPECT_EQ(pir::Complex128Type::get(&ctx), builder.complex128_type());
|
||||
EXPECT_EQ(pir::Float8E4M3FNType::get(&ctx), builder.float8e4m3fn_type());
|
||||
EXPECT_EQ(pir::Float8E5M2Type::get(&ctx), builder.float8e5m2_type());
|
||||
}
|
||||
|
||||
TEST(builder_test, attribute_api) {
|
||||
pir::IrContext ctx;
|
||||
pir::Builder builder(&ctx);
|
||||
EXPECT_EQ(pir::StrAttribute::get(&ctx, "test"), builder.str_attr("test"));
|
||||
EXPECT_EQ(pir::BoolAttribute::get(&ctx, true), builder.bool_attr(true));
|
||||
EXPECT_EQ(pir::FloatAttribute::get(&ctx, 0.2f), builder.float_attr(0.2f));
|
||||
EXPECT_EQ(pir::DoubleAttribute::get(&ctx, 2.0), builder.double_attr(2.0));
|
||||
EXPECT_EQ(pir::Int32Attribute::get(&ctx, 2), builder.int32_attr(2));
|
||||
EXPECT_EQ(pir::Int64Attribute::get(&ctx, 2), builder.int64_attr(2));
|
||||
EXPECT_EQ(pir::IndexAttribute::get(&ctx, 2), builder.index_attr(2));
|
||||
EXPECT_EQ(pir::ArrayAttribute::get(&ctx, std::vector<pir::Attribute>()),
|
||||
builder.array_attr({}));
|
||||
EXPECT_EQ(pir::PointerAttribute::get(&ctx, nullptr),
|
||||
builder.pointer_attr(nullptr));
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/pir/include/core/block.h"
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/op_base.h"
|
||||
#include "paddle/pir/include/core/region.h"
|
||||
|
||||
#include "paddle/fluid/framework/scope.h"
|
||||
#include "paddle/fluid/framework/tensor.h"
|
||||
#include "paddle/fluid/framework/variable.h"
|
||||
#include "paddle/fluid/framework/variable_helper.h"
|
||||
|
||||
#include "paddle/phi/common/place.h"
|
||||
#include "paddle/phi/core/kernel_context.h"
|
||||
#include "paddle/phi/core/kernel_factory.h"
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/interface/infermeta.h"
|
||||
#include "paddle/fluid/platform/init.h"
|
||||
#include "paddle/phi/core/infermeta_utils.h"
|
||||
#include "paddle/phi/infermeta/nullary.h"
|
||||
|
||||
#include "test/cpp/pir/tools/macros_utils.h"
|
||||
|
||||
// Define op
|
||||
class OperationTest
|
||||
: public pir::Op<OperationTest, paddle::dialect::InferMetaInterface> {
|
||||
public:
|
||||
using Op::Op;
|
||||
static const char *name() { return "test.operation2"; }
|
||||
static constexpr uint32_t attributes_num = 2;
|
||||
static const char *attributes_name[attributes_num]; // NOLINT
|
||||
static void VerifySig() {}
|
||||
static void InferMeta(phi::InferMetaContext *infer_meta) {
|
||||
auto fn = PD_INFER_META(phi::CreateInferMeta);
|
||||
fn(infer_meta);
|
||||
}
|
||||
static std::vector<pir::Type> InferMeta(
|
||||
const std::vector<pir::Value> &input_values, pir::AttributeMap *) {
|
||||
VLOG(4) << "Start infermeta OperationTest";
|
||||
std::vector<pir::Type> argument_outputs;
|
||||
return argument_outputs;
|
||||
}
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(OperationTest)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(OperationTest)
|
||||
|
||||
const char *OperationTest::attributes_name[attributes_num] = { // NOLINT
|
||||
"op2_attr1",
|
||||
"op2_attr2"};
|
||||
|
||||
// Define a dialect, op1 and op2 will be registered by this dialect.
|
||||
class TestDialect : public pir::Dialect {
|
||||
public:
|
||||
explicit TestDialect(pir::IrContext *context)
|
||||
: pir::Dialect(name(), context, pir::TypeId::get<TestDialect>()) {
|
||||
initialize();
|
||||
}
|
||||
static const char *name() { return "test"; }
|
||||
|
||||
private:
|
||||
void initialize() { RegisterOps<OperationTest>(); }
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(TestDialect)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(TestDialect)
|
||||
|
||||
TEST(infershape_test, infershape_test) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *test_dialect = ctx->GetOrRegisterDialect<TestDialect>();
|
||||
EXPECT_EQ(test_dialect != nullptr, true);
|
||||
|
||||
// (2) Get registered operations.
|
||||
|
||||
std::string op_name = OperationTest::name();
|
||||
pir::OpInfo op_info = ctx->GetRegisteredOpInfo(op_name);
|
||||
|
||||
std::vector<pir::Value> op_inputs = {};
|
||||
std::vector<pir::Type> op_output_types = {pir::Float32Type::get(ctx)};
|
||||
pir::Operation *op =
|
||||
pir::Operation::Create(op_inputs, {}, op_output_types, op_info);
|
||||
|
||||
paddle::dialect::InferMetaInterface interface =
|
||||
op->dyn_cast<paddle::dialect::InferMetaInterface>();
|
||||
phi::InferMetaContext infer_meta_ctx;
|
||||
infer_meta_ctx.EmplaceBackAttr(phi::IntArray({5, 6}));
|
||||
infer_meta_ctx.EmplaceBackAttr(phi::DataType::FLOAT32);
|
||||
|
||||
phi::DenseTensor tensor;
|
||||
infer_meta_ctx.EmplaceBackOutput(phi::MetaTensor(&tensor));
|
||||
interface.InferMeta(&infer_meta_ctx);
|
||||
|
||||
EXPECT_EQ(tensor.dims().size(), 2);
|
||||
EXPECT_EQ(tensor.dims()[0], 5);
|
||||
EXPECT_EQ(tensor.dims()[1], 6);
|
||||
}
|
||||
@@ -0,0 +1,562 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "paddle/common/enforce.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/phi/core/tensor_meta.h"
|
||||
#include "paddle/pir/include/core/block.h"
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/ir_printer.h"
|
||||
#include "paddle/pir/include/core/op_base.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "paddle/pir/include/core/region.h"
|
||||
#include "test/cpp/pir/tools/test_dialect.h"
|
||||
#include "test/cpp/pir/tools/test_op.h"
|
||||
|
||||
#include "test/cpp/pir/tools/test_pir_utils.h"
|
||||
|
||||
TEST(op_test, region_test) {
|
||||
// (1) Register Dialect, Operation1, Operation2 into IrContext.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *test_dialect = ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
EXPECT_EQ(test_dialect != nullptr, true);
|
||||
|
||||
// (2) Get registered operations.
|
||||
pir::OpInfo op1_info = ctx->GetRegisteredOpInfo(test::Operation1::name());
|
||||
pir::OpInfo op2_info = ctx->GetRegisteredOpInfo(test::Operation2::name());
|
||||
|
||||
pir::Operation *op1 = pir::Operation::Create(
|
||||
{},
|
||||
test::CreateAttributeMap({"op1_attr1", "op1_attr2"},
|
||||
{"op1_attr1", "op1_attr2"}),
|
||||
{pir::Float32Type::get(ctx)},
|
||||
op1_info);
|
||||
pir::Operation *op_2 =
|
||||
pir::Operation::Create({}, {}, {pir::Float32Type::get(ctx)}, op2_info);
|
||||
|
||||
pir::OperationArgument argument(op2_info);
|
||||
argument.output_types = {pir::Float32Type::get(ctx)};
|
||||
argument.AddRegion(nullptr);
|
||||
|
||||
pir::Operation *op3 = pir::Operation::Create(std::move(argument));
|
||||
|
||||
pir::Region ®ion = op3->region(0);
|
||||
EXPECT_EQ(region.empty(), true);
|
||||
|
||||
// (3) Test custom operation printer
|
||||
std::stringstream ss;
|
||||
op1->Print(ss);
|
||||
EXPECT_EQ(ss.str(), "(%0) = \"test.operation1\" ()");
|
||||
|
||||
region.push_back(new pir::Block());
|
||||
region.push_front(new pir::Block());
|
||||
region.insert(region.begin(), new pir::Block());
|
||||
auto &block = region.front();
|
||||
block.push_front(op1);
|
||||
block.insert(block.begin(), op_2);
|
||||
op3->Destroy();
|
||||
}
|
||||
|
||||
TEST(op_test, module_op_death) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::OpInfo op_info = ctx->GetRegisteredOpInfo(pir::ModuleOp::name());
|
||||
|
||||
std::vector<pir::Value> inputs{pir::Value()};
|
||||
pir::AttributeMap attrs{{"program", pir::Int32Attribute::get(ctx, 1)}};
|
||||
std::vector<pir::Type> output_types = {pir::Float32Type::get(ctx)};
|
||||
|
||||
EXPECT_THROW(pir::Operation::Create(inputs, {}, {}, op_info),
|
||||
common::enforce::EnforceNotMet);
|
||||
EXPECT_THROW(pir::Operation::Create({}, attrs, {}, op_info),
|
||||
common::enforce::EnforceNotMet);
|
||||
EXPECT_THROW(pir::Operation::Create({}, {}, output_types, op_info),
|
||||
common::enforce::EnforceNotMet);
|
||||
|
||||
pir::Program program(ctx);
|
||||
|
||||
EXPECT_EQ(program.module_op().program(), &program);
|
||||
EXPECT_EQ(program.module_op().ir_context(), ctx);
|
||||
|
||||
program.module_op()->set_attribute("program",
|
||||
pir::PointerAttribute::get(ctx, &program));
|
||||
}
|
||||
|
||||
TEST(op_test, trait_and_interface) {
|
||||
pir::IrContext ctx;
|
||||
ctx.GetOrRegisterDialect<test::TestDialect>();
|
||||
pir::Program program(&ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(&ctx, block);
|
||||
auto op1 = builder.Build<test::Operation1>();
|
||||
auto op2 = builder.Build<test::Operation2>();
|
||||
|
||||
EXPECT_EQ(op1->HasTrait<test::ReadOnlyTrait>(), false);
|
||||
EXPECT_EQ(op1->HasInterface<test::InferShapeInterface>(), false);
|
||||
EXPECT_EQ(op2->HasTrait<test::ReadOnlyTrait>(), true);
|
||||
EXPECT_EQ(op2->HasInterface<test::InferShapeInterface>(), true);
|
||||
|
||||
pir::OperationArgument argument(&ctx, "test.region");
|
||||
EXPECT_THROW(builder.Build(std::move(argument)),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, op_traits_test) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims = {2, 2};
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype =
|
||||
pir::DenseTensorType::get(ctx, dtype, dims, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op1_temp"}, {"op1_attr"}, dtype);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op2_temp"}, {"op2_attr"}, dtype);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
auto op3 = builder.Build<test::TraitExampleOp>(
|
||||
op1->result(0), op2->result(0), dense_tensor_dtype);
|
||||
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameOperandsShapeTrait>(), true);
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameOperandsAndResultShapeTrait>(), true);
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameOperandsElementTypeTrait>(), true);
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameOperandsAndResultElementTypeTrait>(), true);
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameOperandsAndResultTypeTrait>(), true);
|
||||
EXPECT_EQ(op3->HasTrait<pir::SameTypeOperandsTrait>(), true);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_shape_trait_test1) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsShapeTraitOp1>(),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_shape_trait_test2) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype1 = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims1 = {2, 2};
|
||||
|
||||
pir::Type dtype2 = pir::Float64Type::get(ctx);
|
||||
phi::DDim dims2 = {2, 2, 2};
|
||||
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims1, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims1, {"op1_temp"}, {"op1_attr"}, dtype1);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims2, {"op2_temp"}, {"op2_attr"}, dtype2);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsShapeTraitOp2>(
|
||||
op1->result(0), op2->result(0), dense_tensor_dtype),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_shape_trait_test1) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultShapeTraitOp1>(),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_shape_trait_test2) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype = pir::Float64Type::get(ctx);
|
||||
phi::DDim dims = {2, 2, 2};
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op1_temp"}, {"op1_attr"}, dtype);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op2_temp"}, {"op2_attr"}, dtype);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultShapeTraitOp2>(
|
||||
op1->result(0), op2->result(0)),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_shape_trait_test3) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype1 = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims1 = {2, 2};
|
||||
|
||||
pir::Type dtype2 = pir::Float64Type::get(ctx);
|
||||
phi::DDim dims2 = {2, 2, 2};
|
||||
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims1, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims1, {"op1_temp"}, {"op1_attr"}, dtype1);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims2, {"op2_temp"}, {"op2_attr"}, dtype2);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultShapeTraitOp3>(
|
||||
op1->result(0), op2->result(0), dense_tensor_dtype),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_element_type_trait_test1) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsElementTypeTraitOp1>(),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_element_type_trait_test2) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype1 = pir::Float32Type::get(ctx);
|
||||
pir::Type dtype2 = pir::Float64Type::get(ctx);
|
||||
|
||||
phi::DDim dims = {2, 2};
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op1_temp"}, {"op1_attr"}, dtype1);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op2_temp"}, {"op2_attr"}, dtype2);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsElementTypeTraitOp2>(
|
||||
op1->result(0), op2->result(0), dense_tensor_dtype),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_element_type_trait_test1) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultElementTypeTraitOp1>(),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_element_type_trait_test2) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims = {2, 2};
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op1_temp"}, {"op1_attr"}, dtype);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op2_temp"}, {"op2_attr"}, dtype);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultElementTypeTraitOp2>(
|
||||
op1->result(0), op2->result(0)),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_element_type_trait_test3) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype1 = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims1 = {2, 2};
|
||||
|
||||
pir::Type dtype2 = pir::Float64Type::get(ctx);
|
||||
phi::DDim dims2 = {2, 2, 2};
|
||||
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype1 =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims1, data_layout, lod, offset);
|
||||
pir::DenseTensorType dense_tensor_dtype2 =
|
||||
pir::DenseTensorType::get(ctx, dtype2, dims2, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims1, {"op1_temp"}, {"op1_attr"}, dtype1);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims2, {"op2_temp"}, {"op2_attr"}, dtype2);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultElementTypeTraitOp3>(
|
||||
op1->result(0),
|
||||
op2->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype1),
|
||||
common::enforce::EnforceNotMet);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultElementTypeTraitOp3>(
|
||||
op1->result(0),
|
||||
op1->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype2),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_type_trait_test1) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp1>(),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_type_trait_test2) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims = {2, 2};
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op1_temp"}, {"op1_attr"}, dtype);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims, {"op2_temp"}, {"op2_attr"}, dtype);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp2>(
|
||||
op1->result(0), op2->result(0)),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(op_test, same_operands_and_result_type_trait_test3) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Program program(ctx);
|
||||
auto block = program.block();
|
||||
pir::Builder builder(ctx, block);
|
||||
|
||||
pir::Type dtype1 = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims1 = {2, 2};
|
||||
|
||||
pir::Type dtype2 = pir::Float64Type::get(ctx);
|
||||
phi::DDim dims2 = {2, 2, 2};
|
||||
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype1 =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims1, data_layout, lod, offset);
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype2 =
|
||||
pir::DenseTensorType::get(ctx, dtype2, dims2, data_layout, lod, offset);
|
||||
|
||||
pir::DenseTensorType dense_tensor_dtype3 =
|
||||
pir::DenseTensorType::get(ctx, dtype1, dims2, data_layout, lod, offset);
|
||||
|
||||
pir::Operation *op1 =
|
||||
test::CreateDenseTensorOp(ctx, dims1, {"op1_temp"}, {"op1_attr"}, dtype2);
|
||||
pir::Operation *op2 =
|
||||
test::CreateDenseTensorOp(ctx, dims2, {"op2_temp"}, {"op2_attr"}, dtype1);
|
||||
|
||||
block->push_back(op1);
|
||||
block->push_back(op2);
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp3>(
|
||||
op1->result(0),
|
||||
op2->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype2),
|
||||
common::enforce::EnforceNotMet);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp3>(
|
||||
op1->result(0),
|
||||
op2->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype3),
|
||||
common::enforce::EnforceNotMet);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp3>(
|
||||
op1->result(0),
|
||||
op2->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype1),
|
||||
common::enforce::EnforceNotMet);
|
||||
|
||||
EXPECT_THROW(builder.Build<test::SameOperandsAndResultTypeTraitOp3>(
|
||||
op2->result(0),
|
||||
op1->result(0),
|
||||
dense_tensor_dtype1,
|
||||
dense_tensor_dtype1),
|
||||
common::enforce::EnforceNotMet);
|
||||
}
|
||||
|
||||
TEST(printer_test, custom_hooks) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *test_dialect = ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
EXPECT_EQ(test_dialect != nullptr, true);
|
||||
|
||||
pir::OpInfo op1_info = ctx->GetRegisteredOpInfo(test::Operation1::name());
|
||||
pir::OpInfo op2_info = ctx->GetRegisteredOpInfo(test::Operation2::name());
|
||||
|
||||
pir::Operation *op1 = pir::Operation::Create(
|
||||
{},
|
||||
test::CreateAttributeMap({"op1_attr1", "op1_attr2"},
|
||||
{"op1_attr1", "op1_attr2"}),
|
||||
{pir::Float32Type::get(ctx)},
|
||||
op1_info);
|
||||
pir::Operation *op2 = pir::Operation::Create(
|
||||
{op1->result(0)}, {}, {pir::Float32Type::get(ctx)}, op2_info);
|
||||
|
||||
pir::Program program(ctx);
|
||||
program.block()->push_back(op1);
|
||||
program.block()->push_back(op2);
|
||||
|
||||
pir::PrintHooks hooks;
|
||||
// this one retains old printing and adds new info
|
||||
hooks.value_print_hook = [](pir::Value v, pir::IrPrinter &printer) {
|
||||
printer.IrPrinter::PrintValue(v);
|
||||
printer.os << " [extra info]";
|
||||
};
|
||||
// this one overrides old printing
|
||||
hooks.op_print_hook = [](const pir::Operation &op, pir::IrPrinter &printer) {
|
||||
printer.PrintOpResult(op);
|
||||
printer.os << " :=";
|
||||
|
||||
printer.os << " \"" << op.name() << "\"";
|
||||
printer.PrintOpOperands(op);
|
||||
printer.PrintAttributeMap(op);
|
||||
printer.os << " :";
|
||||
printer.PrintOpReturnType(op);
|
||||
};
|
||||
|
||||
hooks.attribute_print_hook = [](pir::Attribute attr,
|
||||
pir::IrPrinter &printer) {
|
||||
printer.os << "[PlaceHolder]";
|
||||
};
|
||||
hooks.type_print_hook = [](pir::Type type, pir::IrPrinter &printer) {
|
||||
printer.os << "[" << type << "]";
|
||||
};
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << pir::CustomPrintHelper{program, hooks};
|
||||
EXPECT_EQ(
|
||||
ss.str(),
|
||||
"{\n"
|
||||
"(%0 [extra info]) := \"test.operation1\" () "
|
||||
"{op1_attr1:[PlaceHolder],op1_attr2:[PlaceHolder]} :[f32]\n"
|
||||
"(%1 [extra info]) := \"test.operation2\" (%0 [extra info]) {} :[f32]\n"
|
||||
"}\n");
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/interface/op_yaml_info.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/utils/utils.h"
|
||||
#include "paddle/phi/core/meta_tensor.h"
|
||||
#include "paddle/phi/infermeta/binary.h"
|
||||
#include "paddle/phi/kernels/elementwise_add_kernel.h"
|
||||
#include "paddle/pir/include/core/block.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "paddle/pir/include/core/utils.h"
|
||||
// NOTE(zhangbo9674): File pd_op.h is generated by op_gen.py, see details in
|
||||
// paddle/fluid/pir/dialect/CMakeLists.txt.
|
||||
#include "paddle/common/errors.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/pd_op.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/transforms/param_to_variable.h"
|
||||
#include "paddle/phi/core/enforce.h"
|
||||
#include "test/cpp/pir/tools/macros_utils.h"
|
||||
class AddOp : public pir::Op<AddOp> {
|
||||
public:
|
||||
using Op::Op;
|
||||
static const char *name() { return "test.add"; }
|
||||
static constexpr const char **attributes_name = nullptr;
|
||||
static constexpr uint32_t attributes_num = 0;
|
||||
void VerifySig();
|
||||
static void Build(pir::Builder &builder, // NOLINT
|
||||
pir::OperationArgument &argument, // NOLINT
|
||||
pir::Value l_operand,
|
||||
pir::Value r_operand,
|
||||
pir::Type sum_type);
|
||||
};
|
||||
void AddOp::VerifySig() {
|
||||
if (num_operands() != 2) {
|
||||
PADDLE_THROW(
|
||||
common::errors::Fatal("The size of inputs must be equal to 2."));
|
||||
}
|
||||
if (num_results() != 1) {
|
||||
PADDLE_THROW(
|
||||
common::errors::Fatal("The size of outputs must be equal to 1."));
|
||||
}
|
||||
}
|
||||
void AddOp::Build(pir::Builder &,
|
||||
pir::OperationArgument &argument,
|
||||
pir::Value l_operand,
|
||||
pir::Value r_operand,
|
||||
pir::Type sum_type) {
|
||||
argument.AddInput(l_operand);
|
||||
argument.AddInput(r_operand);
|
||||
argument.AddOutput(sum_type);
|
||||
}
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(AddOp)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(AddOp)
|
||||
|
||||
TEST(program_test, slice_combine_test) {
|
||||
// (1) Init environment.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
|
||||
// (2) Create an empty program object
|
||||
pir::Program program(ctx);
|
||||
// pir::Program *program = new pir::Program();
|
||||
EXPECT_EQ(program.block()->empty(), true);
|
||||
|
||||
// (3) Create a float32 DenseTensor Parameter and save into Program
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
|
||||
// (4) Def a = ParameterOp("a")
|
||||
std::string op1_name = pir::ParameterOp::name();
|
||||
pir::OpInfo op1_info = ctx->GetRegisteredOpInfo(op1_name);
|
||||
std::unordered_map<std::string, pir::Attribute> op1_attribute{
|
||||
{"parameter_name", pir::StrAttribute::get(ctx, "a")}};
|
||||
pir::Operation *op1 =
|
||||
pir::Operation::Create({}, op1_attribute, {fp32_dtype}, op1_info);
|
||||
program.block()->push_back(op1);
|
||||
|
||||
// (5) Def b = Constant("b")
|
||||
std::string op2_name = std::string(pir::ConstantOp::name());
|
||||
pir::OpInfo op2_info = ctx->GetRegisteredOpInfo(op2_name);
|
||||
pir::AttributeMap attr_map;
|
||||
attr_map.insert(std::pair<std::string, pir::Attribute>(
|
||||
"value", pir::FloatAttribute::get(ctx, 2.0)));
|
||||
pir::Operation *op2 =
|
||||
pir::Operation::Create({}, attr_map, {fp32_dtype}, op2_info);
|
||||
program.block()->push_back(op2);
|
||||
|
||||
// (6) Def combine_op = CombineOp("a", "b")
|
||||
std::string combine_op_name = std::string(pir::CombineOp::name());
|
||||
pir::OpInfo combine_op_info = ctx->GetRegisteredOpInfo(combine_op_name);
|
||||
pir::Type output_type = pir::VectorType::get(
|
||||
ctx, std::vector<pir::Type>({fp32_dtype, fp32_dtype}));
|
||||
pir::Operation *combine_op = pir::Operation::Create(
|
||||
{op1->result(0), op2->result(0)}, {}, {output_type}, combine_op_info);
|
||||
pir::CombineOp combine_op_type = combine_op->dyn_cast<pir::CombineOp>();
|
||||
EXPECT_TRUE(combine_op_type.out());
|
||||
program.block()->push_back(combine_op);
|
||||
|
||||
// (7) Def slice_op = SliceOp(combine_op, 0)
|
||||
std::string slice_op_name = std::string(pir::SliceOp::name());
|
||||
pir::OpInfo slice_op_info = ctx->GetRegisteredOpInfo(slice_op_name);
|
||||
pir::Attribute index_attr = pir::Int32Attribute::get(ctx, 0);
|
||||
pir::Operation *slice_op = pir::Operation::Create({combine_op->result(0)},
|
||||
{{"index", index_attr}},
|
||||
{fp32_dtype},
|
||||
slice_op_info);
|
||||
program.block()->push_back(slice_op);
|
||||
|
||||
// (8) Traverse Program
|
||||
EXPECT_EQ(program.block()->size() == 4, true);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/pir/include/core/block.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/ir_mapping.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "paddle/pir/include/core/utils.h"
|
||||
|
||||
TEST(region, erase_op_test) {
|
||||
// (1) Init environment.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
|
||||
// (2) Create an empty program object
|
||||
pir::Program program(ctx);
|
||||
pir::Builder builder = pir::Builder(ctx, program.block());
|
||||
|
||||
// (3) Def a = ConstantOp("2.0"); b = ConstantOp("2.0");
|
||||
pir::FloatAttribute fp_attr = builder.float_attr(2.0f);
|
||||
pir::Float32Type fp32_type = builder.float32_type();
|
||||
pir::Value a = builder.Build<pir::ConstantOp>(fp_attr, fp32_type)->result(0);
|
||||
pir::Value b = builder.Build<pir::ConstantOp>(fp_attr, fp32_type)->result(0);
|
||||
|
||||
// (6) Def c = CombineOp(a, b)
|
||||
builder.Build<pir::CombineOp>(std::vector<pir::Value>{a, b});
|
||||
|
||||
// Test pir::Block::erase
|
||||
pir::Block *block = program.block();
|
||||
EXPECT_EQ(block->size(), 3u);
|
||||
block->erase(block->back());
|
||||
EXPECT_EQ(block->size(), 2u);
|
||||
|
||||
// Test pir::Region::erase
|
||||
pir::Region ®ion = program.module_op()->region(0);
|
||||
region.push_back(new pir::Block());
|
||||
EXPECT_EQ(region.size(), 2u);
|
||||
region.erase(region.begin());
|
||||
EXPECT_EQ(region.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(region, clone_op_test) {
|
||||
// (1) Init environment.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
|
||||
// (2) Create an empty program object
|
||||
pir::Program program(ctx);
|
||||
pir::Builder builder = pir::Builder(ctx, program.block());
|
||||
|
||||
// (3) Def a = ConstantOp("2.0"); b = ConstantOp("2.0");
|
||||
pir::FloatAttribute fp_attr = builder.float_attr(2.0f);
|
||||
pir::Float32Type fp32_type = builder.float32_type();
|
||||
pir::Value a = builder.Build<pir::ConstantOp>(fp_attr, fp32_type)->result(0);
|
||||
pir::Value b = builder.Build<pir::ConstantOp>(fp_attr, fp32_type)->result(0);
|
||||
|
||||
// (6) Def c = CombineOp(a, b)
|
||||
builder.Build<pir::CombineOp>(std::vector<pir::Value>{a, b});
|
||||
|
||||
// (7) Test clone module op
|
||||
pir::Operation &op = *program.module_op();
|
||||
pir::Block &block = op.region(0).front();
|
||||
pir::IrMapping mapper;
|
||||
pir::Operation &new_op = *op.Clone(mapper, pir::CloneOptions::All());
|
||||
|
||||
// (8) Check the cloned op recursively
|
||||
EXPECT_EQ(mapper.Lookup(&op), &new_op);
|
||||
EXPECT_EQ(new_op.num_regions(), 1u);
|
||||
pir::Region &new_region = new_op.region(0);
|
||||
EXPECT_EQ(new_region.size(), 1u);
|
||||
pir::Block &new_block = new_region.front();
|
||||
EXPECT_EQ(mapper.Lookup(&block), &new_block);
|
||||
EXPECT_EQ(new_block.size(), 3u);
|
||||
|
||||
for (auto op_iter = block.begin(), new_op_iter = new_block.begin();
|
||||
op_iter != block.end();
|
||||
++op_iter, ++new_op_iter) {
|
||||
pir::Operation &op = *op_iter;
|
||||
pir::Operation &new_op = *new_op_iter;
|
||||
EXPECT_EQ(mapper.Lookup(&op), &new_op);
|
||||
EXPECT_EQ(op.num_operands(), new_op.num_operands());
|
||||
for (uint32_t i = 0; i < op.num_operands(); ++i) {
|
||||
EXPECT_EQ(mapper.Lookup(op.operand_source(i)), new_op.operand_source(i));
|
||||
}
|
||||
EXPECT_EQ(op.num_results(), new_op.num_results());
|
||||
for (uint32_t i = 0; i < op.num_results(); ++i) {
|
||||
EXPECT_EQ(mapper.Lookup(op.result(i)), new_op.result(i));
|
||||
}
|
||||
EXPECT_TRUE(std::equal(op.attributes().begin(),
|
||||
op.attributes().end(),
|
||||
new_op.attributes().begin(),
|
||||
new_op.attributes().end()));
|
||||
EXPECT_EQ(op.info(), new_op.info());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "paddle/fluid/framework/convert_utils.h"
|
||||
#include "paddle/fluid/framework/data_type.h"
|
||||
#include "paddle/fluid/framework/var_desc.h"
|
||||
#include "paddle/fluid/ir_adaptor/translator/attribute_translator.h"
|
||||
#include "paddle/fluid/ir_adaptor/translator/type_translator.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/utils/utils.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/type.h"
|
||||
|
||||
template <typename IR_TYPE>
|
||||
void test_parameterless_type() {
|
||||
pir::IrContext* ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
|
||||
pir::Type type = IR_TYPE::get(ctx);
|
||||
std::stringstream ss;
|
||||
ss << type;
|
||||
EXPECT_GT(ss.str().size(), 0u);
|
||||
EXPECT_NE(ss.str(), "<<NULL TYPE>>");
|
||||
phi::DataType phi_type = paddle::dialect::TransToPhiDataType(type);
|
||||
EXPECT_EQ(type, paddle::dialect::TransToIrDataType(phi_type));
|
||||
|
||||
auto& type_translator = paddle::translator::TypeTranslator::instance();
|
||||
paddle::framework::VarDesc empty_var_desc("empty");
|
||||
auto proto_type = paddle::framework::TransToProtoVarType(phi_type);
|
||||
pir::Type final_type = type_translator[proto_type](ctx, empty_var_desc);
|
||||
EXPECT_EQ(type, final_type);
|
||||
}
|
||||
|
||||
template <typename... IR_TYPE>
|
||||
void test_parameterless_type_helper() {
|
||||
(void)std::initializer_list<int>{0,
|
||||
(test_parameterless_type<IR_TYPE>(), 0)...};
|
||||
}
|
||||
|
||||
TEST(TypeConverterTest, parameterless_type) {
|
||||
test_parameterless_type_helper<pir::UInt8Type,
|
||||
pir::Int8Type,
|
||||
pir::BFloat16Type,
|
||||
pir::Float16Type,
|
||||
pir::Float32Type,
|
||||
pir::Float64Type,
|
||||
pir::Int16Type,
|
||||
pir::Int32Type,
|
||||
pir::Int64Type,
|
||||
pir::BoolType,
|
||||
pir::Complex64Type,
|
||||
pir::Complex128Type,
|
||||
pir::Float8E4M3FNType,
|
||||
pir::Float8E5M2Type>();
|
||||
}
|
||||
|
||||
void test_index_type() {
|
||||
pir::IrContext* ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
|
||||
pir::Type type = pir::IndexType::get(ctx);
|
||||
std::stringstream ss;
|
||||
ss << type;
|
||||
EXPECT_GT(ss.str().size(), 0u);
|
||||
EXPECT_EQ(ss.str(), "index");
|
||||
EXPECT_NE(ss.str(), "<<NULL TYPE>>");
|
||||
phi::DataType phi_type = paddle::dialect::TransToPhiDataType(type);
|
||||
auto& type_translator = paddle::translator::TypeTranslator::instance();
|
||||
paddle::framework::VarDesc empty_var_desc("empty");
|
||||
auto proto_type = paddle::framework::TransToProtoVarType(phi_type);
|
||||
pir::Type final_type = type_translator[proto_type](ctx, empty_var_desc);
|
||||
EXPECT_EQ(paddle::dialect::TransToIrDataType(phi_type), final_type);
|
||||
}
|
||||
|
||||
TEST(IndexTypeConverterTest, index_type) { test_index_type(); }
|
||||
|
||||
TEST(AttributeConverterTest, int2bool) {
|
||||
pir::IrContext* ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
|
||||
auto& attr_translator = paddle::translator::AttributeTranslator::instance();
|
||||
int v = 0;
|
||||
paddle::framework::Attribute attr(v);
|
||||
pir::Attribute pir_attr = attr_translator("pir::BoolAttribute", attr);
|
||||
EXPECT_TRUE(pir_attr.isa<pir::BoolAttribute>());
|
||||
|
||||
int64_t v1 = 0;
|
||||
paddle::framework::Attribute attr1(v1);
|
||||
pir_attr = attr_translator("pir::BoolAttribute", attr1);
|
||||
EXPECT_TRUE(pir_attr.isa<pir::BoolAttribute>());
|
||||
|
||||
pir_attr =
|
||||
attr_translator("pir::BoolAttribute", paddle::framework::Attribute());
|
||||
EXPECT_TRUE(pir_attr.isa<pir::BoolAttribute>());
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/pir/include/core/attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/operation.h"
|
||||
#include "paddle/pir/include/dialect/shape/utils/shape_analysis.h"
|
||||
#include "paddle/pir/src/core/op_result_impl.h"
|
||||
|
||||
// This unittest is used to test the construction interfaces of value class and
|
||||
// operation. The constructed test scenario is: a = OP1(); b = OP2(); c = OP3(a,
|
||||
// b); d, e, f, g, h, i, j = OP4(a, c);
|
||||
namespace test {
|
||||
|
||||
pir::AttributeMap CreateAttributeMap(
|
||||
const std::vector<std::string> &attribute_names,
|
||||
const std::vector<std::string> &attributes) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::AttributeMap attr_map;
|
||||
for (size_t i = 0; i < attribute_names.size(); i++) {
|
||||
pir::Attribute attr_value = pir::StrAttribute::get(ctx, attributes[i]);
|
||||
attr_map.insert(
|
||||
std::pair<std::string, pir::Attribute>(attribute_names[i], attr_value));
|
||||
}
|
||||
return attr_map;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
TEST(value_test, value_test) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
// 1. Construct OP1: a = OP1()
|
||||
std::vector<pir::Value> op1_inputs = {};
|
||||
std::vector<pir::Type> op1_output_types = {pir::Float32Type::get(ctx)};
|
||||
pir::Operation *op1 = pir::Operation::Create(
|
||||
op1_inputs,
|
||||
test::CreateAttributeMap({"op1_name"}, {"op1_attr"}),
|
||||
op1_output_types,
|
||||
nullptr);
|
||||
op1->Print(std::cout);
|
||||
pir::Value a = op1->result(0);
|
||||
EXPECT_TRUE(a.use_empty());
|
||||
// 2. Construct OP2: b = OP2();
|
||||
std::vector<pir::Value> op2_inputs = {};
|
||||
std::vector<pir::Type> op2_output_types = {pir::Float32Type::get(ctx)};
|
||||
pir::Operation *op2 = pir::Operation::Create(
|
||||
op2_inputs,
|
||||
test::CreateAttributeMap({"op2_name"}, {"op2_attr"}),
|
||||
op2_output_types,
|
||||
nullptr);
|
||||
op2->Print(std::cout);
|
||||
pir::Value b = op2->result(0);
|
||||
EXPECT_TRUE(b.use_empty());
|
||||
// 3. Construct OP3: c = OP3(a, b);
|
||||
std::vector<pir::Value> op3_inputs{a, b};
|
||||
std::vector<pir::Type> op3_output_types = {pir::Float32Type::get(ctx)};
|
||||
pir::Operation *op3 = pir::Operation::Create(
|
||||
op3_inputs,
|
||||
test::CreateAttributeMap({"op3_name"}, {"op3_attr"}),
|
||||
op3_output_types,
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(op1->result(0).HasOneUse());
|
||||
EXPECT_TRUE(op2->result(0).HasOneUse());
|
||||
op3->Print(std::cout);
|
||||
pir::Value c = op3->result(0);
|
||||
// 4. Construct OP4: d, e, f, g, h, i, j = OP4(a, c);
|
||||
std::vector<pir::Value> op4_inputs = {a, c};
|
||||
std::vector<pir::Type> op4_output_types;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
op4_output_types.push_back(pir::Float32Type::get(ctx));
|
||||
}
|
||||
pir::Operation *op4 = pir::Operation::Create(
|
||||
op4_inputs,
|
||||
test::CreateAttributeMap({"op4_name"}, {"op4_attr"}),
|
||||
op4_output_types,
|
||||
nullptr);
|
||||
op4->Print(std::cout);
|
||||
|
||||
// Test 1:
|
||||
EXPECT_EQ(op1->result(0).defining_op(), op1);
|
||||
EXPECT_EQ(op2->result(0).defining_op(), op2);
|
||||
EXPECT_EQ(op3->result(0).defining_op(), op3);
|
||||
EXPECT_EQ(op4->result(6).defining_op(), op4);
|
||||
|
||||
// Test 2: op1_first_output -> op4_first_input
|
||||
pir::Value op1_first_output = op1->result(0);
|
||||
pir::OpOperand op4_first_input = op4->operand(0);
|
||||
|
||||
EXPECT_EQ(op1_first_output.first_use(), op4_first_input);
|
||||
pir::OpOperand op3_first_input = op3->operand(0);
|
||||
|
||||
EXPECT_EQ(op4_first_input.next_use(), op3_first_input);
|
||||
EXPECT_EQ(op3_first_input.next_use(), nullptr);
|
||||
|
||||
// Test 3: Value iterator
|
||||
using my_iterator = pir::Value::UseIterator;
|
||||
my_iterator iter = op1->result(0).use_begin();
|
||||
EXPECT_EQ(iter.owner(), op4);
|
||||
++iter;
|
||||
EXPECT_EQ(iter.owner(), op3);
|
||||
|
||||
// Test 4: Value Replace Use
|
||||
// a = OP1(); b = OP2(); c = OP3(a, b); d, e, f, g, h, i, j = OP4(a, c);
|
||||
//
|
||||
c.ReplaceUsesWithIf(b, [](pir::OpOperand) { return true; });
|
||||
EXPECT_EQ(op4->operand_source(1), b);
|
||||
EXPECT_TRUE(c.use_empty());
|
||||
|
||||
b.ReplaceAllUsesWith(a);
|
||||
EXPECT_EQ(op4->operand_source(1), a);
|
||||
EXPECT_TRUE(b.use_empty());
|
||||
|
||||
// destroy
|
||||
VLOG(0) << op1->result(0).PrintUdChain() << std::endl;
|
||||
op4->Destroy();
|
||||
VLOG(0) << op1->result(0).PrintUdChain() << std::endl;
|
||||
op3->Destroy();
|
||||
VLOG(0) << op1->result(0).PrintUdChain() << std::endl;
|
||||
op2->Destroy();
|
||||
VLOG(0) << op1->result(0).PrintUdChain() << std::endl;
|
||||
op1->Destroy();
|
||||
}
|
||||
|
||||
TEST(op_result_test, exception) {
|
||||
EXPECT_THROW(
|
||||
pir::detail::OpInlineResultImpl(nullptr, MAX_INLINE_RESULT_IDX + 1),
|
||||
common::enforce::EnforceNotMet);
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
auto op = pir::Operation::Create(
|
||||
{}, {{"test", pir::Int32Attribute::get(ctx, 1)}}, {nullptr}, nullptr);
|
||||
auto result = op->result(0);
|
||||
auto op2 = pir::Operation::Create({result}, {}, {}, nullptr);
|
||||
EXPECT_DEATH(op->Destroy(), "Destroyed a op_result that is still in use.*");
|
||||
EXPECT_THROW(result.set_attribute("test", nullptr),
|
||||
common::enforce::EnforceNotMet);
|
||||
EXPECT_THROW(op->result(1), common::enforce::EnforceNotMet);
|
||||
EXPECT_THROW(op->operand(1), common::enforce::EnforceNotMet);
|
||||
op2->Destroy();
|
||||
op->Destroy();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/pir/include/core/block.h"
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "paddle/pir/include/core/verify.h"
|
||||
|
||||
TEST(ir_op_info_test, op_op_info_test) {
|
||||
pir::IrContext* context = pir::IrContext::Instance();
|
||||
pir::Program program(context);
|
||||
|
||||
pir::Block* block = program.block();
|
||||
pir::Builder builder(context, block);
|
||||
builder.Build<pir::ConstantOp>(pir::Int32Attribute::get(context, 5),
|
||||
pir::Int32Type::get(context));
|
||||
|
||||
auto& op = block->back();
|
||||
|
||||
EXPECT_EQ(block->end(), ++pir::Block::Iterator(op));
|
||||
|
||||
auto& info_map = context->registered_op_info_map();
|
||||
EXPECT_FALSE(info_map.empty());
|
||||
|
||||
void* info_1 = op.info();
|
||||
auto info_2 = pir::OpInfo::RecoverFromVoidPointer(info_1);
|
||||
EXPECT_EQ(op.info(), info_2);
|
||||
pir::Verify(program.module_op());
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_attribute.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/utils/op_yaml_info_parser.h"
|
||||
#include "paddle/pir/include/core/builder.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/interface/op_yaml_info.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_op.h"
|
||||
|
||||
#include "paddle/pir/include/core/utils.h"
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/pd_op.h"
|
||||
|
||||
TEST(ir_op_info_test, op_op_info_test) {
|
||||
pir::IrContext* ctx = pir::IrContext::Instance();
|
||||
pir::Program program(ctx);
|
||||
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Builder builder(ctx, program.block());
|
||||
|
||||
auto uniform1 =
|
||||
builder.Build<paddle::dialect::UniformOp>(std::vector<int64_t>{2, 2},
|
||||
phi::DataType::FLOAT32,
|
||||
0.0,
|
||||
1.0,
|
||||
2,
|
||||
phi::CPUPlace());
|
||||
|
||||
uniform1->num_operands();
|
||||
paddle::dialect::OpYamlInfoInterface op_info_interface =
|
||||
uniform1->dyn_cast<paddle::dialect::OpYamlInfoInterface>();
|
||||
|
||||
auto op_info_res = op_info_interface.GetOpInfo();
|
||||
|
||||
paddle::dialect::OpYamlInfoParser op_yaml_info_parser(op_info_res);
|
||||
|
||||
EXPECT_EQ((op_yaml_info_parser.AttrTypeName("seed") == "pir::Int32Attribute"),
|
||||
true);
|
||||
EXPECT_EQ(op_yaml_info_parser.IsTensorAttribute(0), true);
|
||||
|
||||
EXPECT_EQ(op_yaml_info_parser.InputTensorNumber(), 0u);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2024 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/common/enforce.h"
|
||||
#include "paddle/phi/core/enforce.h"
|
||||
|
||||
class FatalClass {
|
||||
public:
|
||||
FatalClass() {}
|
||||
~FatalClass() { PADDLE_FATAL("fatal occurred in deconstructor!"); }
|
||||
};
|
||||
|
||||
void throw_exception_in_func() {
|
||||
FatalClass test_case;
|
||||
PADDLE_THROW(::common::errors::External("throw exception in func"));
|
||||
}
|
||||
|
||||
void terminate_in_func() { FatalClass test_case; }
|
||||
|
||||
TEST(paddle_fatal_test, base) {
|
||||
EXPECT_FALSE(::common::enforce::IsPaddleFatalSkip());
|
||||
EXPECT_DEATH(terminate_in_func(), "fatal occurred in deconstructor!.*");
|
||||
EXPECT_THROW(throw_exception_in_func(), common::enforce::EnforceNotMet);
|
||||
EXPECT_FALSE(::common::enforce::IsPaddleFatalSkip());
|
||||
::common::enforce::SkipPaddleFatal(true);
|
||||
// skip fatal.
|
||||
terminate_in_func();
|
||||
// unskip paddle fatal.
|
||||
::common::enforce::SkipPaddleFatal(false);
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "paddle/fluid/framework/block_desc.h"
|
||||
#include "paddle/fluid/framework/operator.h"
|
||||
#include "paddle/fluid/framework/program_desc.h"
|
||||
#include "paddle/fluid/ir_adaptor/translator/translate.h"
|
||||
#include "paddle/fluid/ir_adaptor/translator/utils.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/control_flow_op.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/manual_op.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/pd_op.h"
|
||||
#include "paddle/phi/core/framework/framework.pb.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/ir_printer.h"
|
||||
#include "paddle/pir/include/core/program.h"
|
||||
#include "paddle/pir/include/dialect/control_flow/ir/cf_op.h"
|
||||
|
||||
using OperatorDialect = paddle::dialect::OperatorDialect;
|
||||
using ProgramDesc = paddle::framework::ProgramDesc;
|
||||
using BlockDesc = paddle::framework::BlockDesc;
|
||||
using OpDesc = paddle::framework::OpDesc;
|
||||
using VarDesc = paddle::framework::VarDesc;
|
||||
using VarType = paddle::framework::proto::VarType;
|
||||
|
||||
ProgramDesc load_from_file(const std::string &file_name) {
|
||||
std::ifstream fin(file_name, std::ios::in | std::ios::binary);
|
||||
fin.seekg(0, std::ios::end);
|
||||
|
||||
std::string buffer(fin.tellg(), ' ');
|
||||
fin.seekg(0, std::ios::beg);
|
||||
fin.read(&buffer[0], buffer.size()); // NOLINT
|
||||
fin.close();
|
||||
return ProgramDesc(buffer);
|
||||
}
|
||||
|
||||
TEST(OperatorDialectTest, MainProgram) {
|
||||
auto p = load_from_file("resnet50_main.prog");
|
||||
EXPECT_EQ(p.Size(), 1u);
|
||||
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<OperatorDialect>();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
auto program = paddle::TranslateLegacyProgramToProgram(p);
|
||||
|
||||
std::stringstream ss;
|
||||
program->Print(ss);
|
||||
|
||||
// ops.size() = op size in BlockDesc + parameter_op + combine op + int
|
||||
// array op + full op (Note: p already has a full)
|
||||
EXPECT_EQ(program->block()->size(),
|
||||
p.Block(0).OpSize() + program->parameters_num() + 20 + 5 + 9 + 2);
|
||||
EXPECT_GT(ss.str().size(), 0u);
|
||||
}
|
||||
|
||||
TEST(OperatorDialectTest, ConditionBlock) {
|
||||
auto p = load_from_file("conditional_block_test.prog");
|
||||
EXPECT_EQ(p.Size(), 7u);
|
||||
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<OperatorDialect>();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
auto program = paddle::TranslateLegacyProgramToProgram(p);
|
||||
|
||||
EXPECT_EQ(program->block()->size(), 9u);
|
||||
size_t id = 0;
|
||||
for (auto &op : *program->block()) {
|
||||
if (id == 0 || id == 1) {
|
||||
EXPECT_EQ(op.isa<paddle::dialect::FullOp>(), true);
|
||||
}
|
||||
if (id == 2) {
|
||||
EXPECT_EQ(op.isa<paddle::dialect::LessThanOp>(), true);
|
||||
}
|
||||
if (id == 3) {
|
||||
EXPECT_EQ(op.isa<paddle::dialect::IfOp>(), true);
|
||||
EXPECT_EQ(op.num_regions(), 2u);
|
||||
// true block
|
||||
pir::Block &true_block =
|
||||
op.dyn_cast<paddle::dialect::IfOp>().true_block();
|
||||
size_t true_id = 0;
|
||||
for (auto &op1 : true_block) {
|
||||
if (true_id == 0 || true_id == 1) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::FullOp>(), true);
|
||||
}
|
||||
if (true_id == 2) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::LessThanOp>(), true);
|
||||
}
|
||||
if (true_id == 3) {
|
||||
auto &true_true_block =
|
||||
op1.dyn_cast<paddle::dialect::IfOp>().true_block();
|
||||
size_t true_true_id = 0;
|
||||
for (auto &op2 : true_true_block) {
|
||||
if (true_true_id == 0) {
|
||||
EXPECT_EQ(op2.isa<paddle::dialect::AddOp>(), true);
|
||||
}
|
||||
if (true_true_id == 1) {
|
||||
EXPECT_EQ(op2.isa<paddle::dialect::AssignOp>(), true);
|
||||
}
|
||||
if (true_true_id == 2) {
|
||||
EXPECT_EQ(op2.isa<pir::YieldOp>(), true);
|
||||
}
|
||||
true_true_id++;
|
||||
}
|
||||
}
|
||||
if (true_id == 4) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::LogicalNotOp>(), true);
|
||||
}
|
||||
if (true_id == 5) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::IfOp>(), true);
|
||||
}
|
||||
if (true_id == 6) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::CastOp>(), true);
|
||||
}
|
||||
if (true_id == 7) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::SelectInputOp>(), true);
|
||||
}
|
||||
if (true_id == 8) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::MultiplyOp>(), true);
|
||||
}
|
||||
if (true_id == 9 || true_id == 10) {
|
||||
EXPECT_EQ(op1.isa<paddle::dialect::AssignOp>(), true);
|
||||
}
|
||||
if (true_id == 11) {
|
||||
EXPECT_EQ(op1.isa<pir::YieldOp>(), true);
|
||||
}
|
||||
true_id++;
|
||||
}
|
||||
}
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OperatorDialectTest, StartupProgram) {
|
||||
auto p = load_from_file("resnet50_startup.prog");
|
||||
EXPECT_EQ(p.Size(), 1u);
|
||||
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<OperatorDialect>();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
auto program = paddle::TranslateLegacyProgramToProgram(p);
|
||||
|
||||
size_t op_size = program->block()->size();
|
||||
// ops.size() = op size in BlockDesc + parameter_op +
|
||||
// constant_op_for_uniform
|
||||
// + constant_op for gaussian
|
||||
EXPECT_EQ(op_size, p.Block(0).OpSize() + program->parameters_num() + 3 + 53);
|
||||
|
||||
std::stringstream ss;
|
||||
program->Print(ss);
|
||||
EXPECT_GT(ss.str().size(), 0u);
|
||||
}
|
||||
|
||||
TEST(RegisterInfoTest, MainProgram) {
|
||||
auto p = load_from_file("resnet50_startup.prog");
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
|
||||
auto unregistered_ops =
|
||||
paddle::translator::CheckUnregisteredOperation(ctx, p);
|
||||
EXPECT_EQ(unregistered_ops.size(), 0u);
|
||||
|
||||
auto new_op = std::unique_ptr<OpDesc>(
|
||||
new OpDesc("something must not be registered", {}, {}, {}));
|
||||
auto *block = p.MutableBlock(0);
|
||||
block->AppendAllocatedOp(std::move(new_op));
|
||||
|
||||
unregistered_ops = paddle::translator::CheckUnregisteredOperation(ctx, p);
|
||||
EXPECT_EQ(unregistered_ops.size(), 1u);
|
||||
EXPECT_EQ(unregistered_ops[0], "something must not be registered");
|
||||
}
|
||||
|
||||
TEST(OperatorDialectTest, WhileOpProgram) {
|
||||
auto p = load_from_file("while_op_test.prog");
|
||||
EXPECT_EQ(p.Size(), 3u);
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<OperatorDialect>();
|
||||
ctx->GetOrRegisterDialect<pir::BuiltinDialect>();
|
||||
auto program = paddle::TranslateLegacyProgramToProgram(p);
|
||||
|
||||
std::stringstream ss;
|
||||
program->Print(ss);
|
||||
|
||||
LOG(INFO) << ss.str();
|
||||
|
||||
EXPECT_EQ(program->block()->size(), 4u);
|
||||
size_t id = 0;
|
||||
for (auto &op : *program->block()) {
|
||||
if (id == 0 || id == 1) {
|
||||
EXPECT_TRUE(op.isa<paddle::dialect::FullOp>());
|
||||
}
|
||||
if (id == 2) {
|
||||
EXPECT_TRUE(op.isa<paddle::dialect::LessThanOp>());
|
||||
}
|
||||
if (id == 3) {
|
||||
EXPECT_TRUE(op.isa<paddle::dialect::WhileOp>());
|
||||
EXPECT_EQ(op.num_regions(), 1u);
|
||||
// body block
|
||||
pir::Block &body_block = op.dyn_cast<paddle::dialect::WhileOp>().body();
|
||||
size_t body_id = 0;
|
||||
for (auto &op1 : body_block) {
|
||||
if (body_id == 0) {
|
||||
EXPECT_TRUE(op1.isa<paddle::dialect::FullOp>());
|
||||
}
|
||||
if (body_id == 1) {
|
||||
EXPECT_TRUE(op1.isa<paddle::dialect::ScaleOp>());
|
||||
}
|
||||
if (body_id == 2) {
|
||||
EXPECT_TRUE(op1.isa<paddle::dialect::LessThanOp>());
|
||||
}
|
||||
if (body_id == 3) {
|
||||
pir::Block &body_body_block =
|
||||
op1.dyn_cast<paddle::dialect::WhileOp>().body();
|
||||
size_t body_body_id = 0;
|
||||
for (auto &op2 : body_body_block) {
|
||||
if (body_body_id == 0) {
|
||||
EXPECT_TRUE(op2.isa<paddle::dialect::FullOp>());
|
||||
}
|
||||
if (body_body_id == 1) {
|
||||
EXPECT_TRUE(op2.isa<paddle::dialect::ScaleOp>());
|
||||
}
|
||||
if (body_body_id == 2) {
|
||||
EXPECT_TRUE(op2.isa<paddle::dialect::LessThanOp>());
|
||||
}
|
||||
if (body_body_id == 3 || body_body_id == 4) {
|
||||
EXPECT_TRUE(op2.isa<paddle::dialect::AssignOut_Op>());
|
||||
}
|
||||
if (body_body_id == 5) {
|
||||
EXPECT_TRUE(op2.isa<pir::YieldOp>());
|
||||
}
|
||||
body_body_id++;
|
||||
}
|
||||
}
|
||||
if (body_id == 4) {
|
||||
EXPECT_TRUE(op1.isa<paddle::dialect::LessThanOp>());
|
||||
}
|
||||
if (body_id == 5 || body_id == 6) {
|
||||
EXPECT_TRUE(op1.isa<paddle::dialect::AssignOut_Op>());
|
||||
}
|
||||
if (body_id == 7) {
|
||||
EXPECT_TRUE(op1.isa<pir::YieldOp>());
|
||||
}
|
||||
body_id++;
|
||||
}
|
||||
}
|
||||
id++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_attribute.h"
|
||||
#include "paddle/pir/include/core/attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_attribute.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
|
||||
using ScalarAttribute = paddle::dialect::ScalarAttribute;
|
||||
|
||||
TEST(ScalarTest, base) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
|
||||
pir::Attribute bool_scalar = pir::BoolAttribute::get(ctx, false);
|
||||
EXPECT_TRUE(bool_scalar.isa<ScalarAttribute>());
|
||||
EXPECT_TRUE(bool_scalar.isa<pir::BoolAttribute>());
|
||||
pir::BoolAttribute pure_bool = bool_scalar.dyn_cast<pir::BoolAttribute>();
|
||||
EXPECT_TRUE(pure_bool.isa<ScalarAttribute>());
|
||||
ScalarAttribute scalar_from_bool = bool_scalar.dyn_cast<ScalarAttribute>();
|
||||
EXPECT_TRUE(scalar_from_bool.isa<pir::BoolAttribute>());
|
||||
EXPECT_NO_THROW(scalar_from_bool.dyn_cast<pir::BoolAttribute>());
|
||||
}
|
||||
|
||||
TEST(ScalarTest, test_classof) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Attribute bool_scalar = pir::BoolAttribute::get(ctx, false);
|
||||
EXPECT_TRUE(bool_scalar.isa<ScalarAttribute>());
|
||||
|
||||
pir::Attribute float_scalar = pir::FloatAttribute::get(ctx, 1.0f);
|
||||
EXPECT_TRUE(float_scalar.isa<ScalarAttribute>());
|
||||
|
||||
pir::Attribute double_scalar = pir::DoubleAttribute::get(ctx, 1.0);
|
||||
EXPECT_TRUE(double_scalar.isa<ScalarAttribute>());
|
||||
|
||||
pir::Attribute int32_scalar = pir::Int32Attribute::get(ctx, 1);
|
||||
EXPECT_TRUE(int32_scalar.isa<ScalarAttribute>());
|
||||
|
||||
pir::Attribute index_scalar = pir::IndexAttribute::get(ctx, 1l);
|
||||
EXPECT_TRUE(index_scalar.isa<ScalarAttribute>());
|
||||
|
||||
pir::Attribute int64_scalar = pir::Int64Attribute::get(ctx, 1l);
|
||||
EXPECT_TRUE(int64_scalar.isa<ScalarAttribute>());
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/type.h"
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "test/cpp/pir/tools/test_dialect.h"
|
||||
#include "test/cpp/pir/tools/test_op.h"
|
||||
|
||||
TEST(shape_dtype_test, shape_dtype_test) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *test_dialect = ctx->GetOrRegisterDialect<test::TestDialect>();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
EXPECT_EQ(test_dialect != nullptr, true);
|
||||
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims = {2, 2};
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
pir::DenseTensorType dense_tensor_type = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
|
||||
EXPECT_EQ(dense_tensor_type.dtype().isa<pir::Float32Type>(), true);
|
||||
EXPECT_EQ(dense_tensor_type.dims(), dims);
|
||||
EXPECT_EQ(dense_tensor_type.data_layout(), data_layout);
|
||||
EXPECT_EQ(dense_tensor_type.lod(), lod);
|
||||
EXPECT_EQ(dense_tensor_type.offset(), offset);
|
||||
|
||||
pir::ShapedTypeInterface dense_tensor_type_interface =
|
||||
dense_tensor_type.dyn_cast<pir::ShapedTypeInterface>();
|
||||
|
||||
EXPECT_TRUE(dense_tensor_type_interface);
|
||||
EXPECT_EQ(
|
||||
dense_tensor_type_interface.GetElementType().isa<pir::Float32Type>(),
|
||||
true);
|
||||
EXPECT_EQ(dense_tensor_type_interface.GetShape(), dims);
|
||||
EXPECT_EQ(dense_tensor_type_interface.kDynamic, std::int64_t(-1));
|
||||
EXPECT_EQ(dense_tensor_type_interface.GetRank(), 2);
|
||||
EXPECT_EQ(dense_tensor_type_interface.IsDynamic(2), false);
|
||||
EXPECT_EQ(dense_tensor_type_interface.IsDynamicShape(), false);
|
||||
EXPECT_EQ(dense_tensor_type_interface.IsDynamicDim(1), false);
|
||||
EXPECT_EQ(dense_tensor_type_interface.GetNumDynamicDims(), 0);
|
||||
EXPECT_EQ(dense_tensor_type_interface.GetDimSize(0), 2);
|
||||
|
||||
pir::Type fp32_type = pir::Float32Type::get(ctx);
|
||||
pir::ShapedTypeInterface fp32_type_interface =
|
||||
fp32_type.dyn_cast<pir::ShapedTypeInterface>();
|
||||
|
||||
EXPECT_FALSE(fp32_type_interface);
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
|
||||
#include "paddle/fluid/pir/dialect/operator/ir/op_type.h"
|
||||
#include "paddle/pir/include/core/builtin_dialect.h"
|
||||
#include "paddle/pir/include/core/builtin_type.h"
|
||||
#include "paddle/pir/include/core/dialect.h"
|
||||
#include "paddle/pir/include/core/ir_context.h"
|
||||
#include "paddle/pir/include/core/type.h"
|
||||
#include "paddle/pir/include/core/type_base.h"
|
||||
#include "paddle/pir/include/core/type_name.h"
|
||||
#include "paddle/pir/include/core/type_utils.h"
|
||||
#include "paddle/pir/include/core/utils.h"
|
||||
#include "test/cpp/pir/tools/macros_utils.h"
|
||||
|
||||
class TypeA {};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(TypeA)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(TypeA)
|
||||
|
||||
class TypeB {};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(TypeB)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(TypeB)
|
||||
|
||||
std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
|
||||
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
TEST(type_test, type_id) {
|
||||
// Test 1: Test construct TypeId by TypeId::get<T>() and overloaded operator==
|
||||
// method.
|
||||
pir::TypeId a_id = pir::TypeId::get<TypeA>();
|
||||
pir::TypeId a_other_id = pir::TypeId::get<TypeA>();
|
||||
pir::TypeId b_id = pir::TypeId::get<TypeB>();
|
||||
EXPECT_EQ(a_id, a_other_id);
|
||||
EXPECT_NE(a_id, b_id);
|
||||
|
||||
// Test 2: Test the hash function of TypeId.
|
||||
std::unordered_map<pir::TypeId, pir::TypeId *> 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Define a FakeDialect without registering any types.
|
||||
struct FakeDialect : pir::Dialect {
|
||||
explicit FakeDialect(pir::IrContext *context)
|
||||
: pir::Dialect(name(), context, pir::TypeId::get<FakeDialect>()) {}
|
||||
static const char *name() { return "fake"; }
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(FakeDialect)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(FakeDialect)
|
||||
|
||||
TEST(type_test, type_base) {
|
||||
// Test 1: Test the function of IrContext to register Dialect.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
pir::Dialect *fake_dialect = ctx->GetOrRegisterDialect<FakeDialect>();
|
||||
|
||||
// Test 2: Test the get method of AbstractType.
|
||||
pir::TypeId a_id = pir::TypeId::get<TypeA>();
|
||||
pir::AbstractType abstract_type_a =
|
||||
pir::AbstractType::get(a_id, *fake_dialect, {});
|
||||
EXPECT_EQ(abstract_type_a.type_id(), a_id);
|
||||
|
||||
// Test 3: Test the constructor of TypeStorage.
|
||||
pir::TypeStorage storage_a(&abstract_type_a);
|
||||
EXPECT_EQ(storage_a.abstract_type().type_id(), abstract_type_a.type_id());
|
||||
}
|
||||
|
||||
TEST(type_test, built_in_type) {
|
||||
// Test the interfaces of class Type: judgment, type_id, abstract_type,
|
||||
// classof.
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
|
||||
// Test 1: Test the parameterless built-in type of IrContext.
|
||||
pir::Type bfp16_1 = pir::BFloat16Type::get(ctx);
|
||||
pir::Type bfp16_2 = pir::BFloat16Type::get(ctx);
|
||||
EXPECT_EQ(bfp16_1, bfp16_2);
|
||||
EXPECT_EQ(bfp16_1.type_id(), bfp16_2.type_id());
|
||||
EXPECT_EQ(&bfp16_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(bfp16_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::BFloat16Type::classof(bfp16_1), 1);
|
||||
|
||||
pir::Type index_1 = pir::IndexType::get(ctx);
|
||||
pir::Type index_2 = pir::IndexType::get(ctx);
|
||||
EXPECT_TRUE(index_1.IsIndex());
|
||||
EXPECT_EQ(index_1, index_2);
|
||||
EXPECT_EQ(index_1.type_id(), index_2.type_id());
|
||||
EXPECT_EQ(&index_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(index_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::IndexType::classof(index_1), 1);
|
||||
|
||||
pir::Type fp16_1 = pir::Float16Type::get(ctx);
|
||||
pir::Type fp16_2 = pir::Float16Type::get(ctx);
|
||||
EXPECT_EQ(fp16_1, fp16_2);
|
||||
EXPECT_EQ(fp16_1.type_id(), fp16_2.type_id());
|
||||
EXPECT_EQ(&fp16_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(fp16_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Float16Type::classof(fp16_1), 1);
|
||||
|
||||
pir::Type fp32_1 = pir::Float32Type::get(ctx);
|
||||
pir::Type fp32_2 = pir::Float32Type::get(ctx);
|
||||
EXPECT_EQ(fp32_1, fp32_2);
|
||||
EXPECT_EQ(fp32_1.type_id(), fp32_2.type_id());
|
||||
EXPECT_EQ(&fp32_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(fp32_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Float32Type::classof(fp32_1), 1);
|
||||
|
||||
pir::Type fp64_1 = pir::Float64Type::get(ctx);
|
||||
pir::Type fp64_2 = pir::Float64Type::get(ctx);
|
||||
EXPECT_EQ(fp64_1, fp64_2);
|
||||
EXPECT_EQ(fp64_1.type_id(), fp64_2.type_id());
|
||||
EXPECT_EQ(&fp64_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(fp64_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Float64Type::classof(fp64_1), 1);
|
||||
|
||||
pir::Type int16_1 = pir::Int16Type::get(ctx);
|
||||
pir::Type int16_2 = pir::Int16Type::get(ctx);
|
||||
EXPECT_EQ(int16_1, int16_2);
|
||||
EXPECT_EQ(int16_1.type_id(), int16_2.type_id());
|
||||
EXPECT_EQ(&int16_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(int16_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Int16Type::classof(int16_1), 1);
|
||||
|
||||
pir::Type int32_1 = pir::Int32Type::get(ctx);
|
||||
pir::Type int32_2 = pir::Int32Type::get(ctx);
|
||||
EXPECT_EQ(int32_1, int32_2);
|
||||
EXPECT_EQ(int32_1.type_id(), int32_2.type_id());
|
||||
EXPECT_EQ(&int32_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(int32_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Int32Type::classof(int32_1), 1);
|
||||
|
||||
pir::Type int64_1 = pir::Int64Type::get(ctx);
|
||||
pir::Type int64_2 = pir::Int64Type::get(ctx);
|
||||
EXPECT_EQ(int64_1, int64_2);
|
||||
EXPECT_EQ(int64_1.type_id(), int64_2.type_id());
|
||||
EXPECT_EQ(&int64_1.abstract_type(),
|
||||
&pir::AbstractType::lookup(int64_1.type_id(), ctx));
|
||||
EXPECT_EQ(pir::Int64Type::classof(int64_1), 1);
|
||||
|
||||
// Test 2: Test isa and dyn_cast.
|
||||
EXPECT_EQ(fp16_1.isa<pir::Float16Type>(), true);
|
||||
EXPECT_EQ(fp16_1.isa<pir::Float32Type>(), false);
|
||||
EXPECT_EQ(fp16_1.isa<pir::Type>(), true);
|
||||
|
||||
// Test 3: Test VectorType
|
||||
std::vector<pir::Type> vec_type = {int32_1, int64_1};
|
||||
pir::Type vector_type = pir::VectorType::get(ctx, vec_type);
|
||||
EXPECT_EQ(vector_type.isa<pir::VectorType>(), true);
|
||||
EXPECT_EQ(vector_type.dyn_cast<pir::VectorType>().size() == 2, true);
|
||||
EXPECT_EQ(vector_type.dyn_cast<pir::VectorType>()[0].isa<pir::Int32Type>(),
|
||||
true);
|
||||
EXPECT_EQ(vector_type.dyn_cast<pir::VectorType>()[1].isa<pir::Int64Type>(),
|
||||
true);
|
||||
}
|
||||
|
||||
// Customize a parameterized TypeStorage IntegerTypeStorage.
|
||||
struct IntegerTypeStorage : public pir::TypeStorage {
|
||||
IntegerTypeStorage(unsigned width, unsigned signedness)
|
||||
: width_(width), signedness_(signedness) {}
|
||||
using ParamKey = std::pair<unsigned, unsigned>;
|
||||
|
||||
static std::size_t HashValue(const ParamKey &key) {
|
||||
return hash_combine(std::hash<unsigned>()(std::get<0>(key)),
|
||||
std::hash<unsigned>()(std::get<1>(key)));
|
||||
}
|
||||
|
||||
bool operator==(const ParamKey &key) const {
|
||||
return ParamKey(width_, signedness_) == key;
|
||||
}
|
||||
|
||||
static IntegerTypeStorage *Construct(const ParamKey &key) {
|
||||
return new IntegerTypeStorage(key.first, key.second);
|
||||
}
|
||||
|
||||
ParamKey GetAsKey() const { return ParamKey(width_, signedness_); }
|
||||
|
||||
unsigned width_ : 30;
|
||||
unsigned signedness_ : 2;
|
||||
};
|
||||
|
||||
// Customize a parameterized type: IntegerType, storage type is
|
||||
// IntegerTypeStorage.
|
||||
class IntegerType
|
||||
: public pir::Type::TypeBase<IntegerType, pir::Type, IntegerTypeStorage> {
|
||||
public:
|
||||
using Base::Base;
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(IntegerType)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(IntegerType)
|
||||
|
||||
// Customize a Dialect IntegerDialect, registration type of IntegerType.
|
||||
struct IntegerDialect : pir::Dialect {
|
||||
explicit IntegerDialect(pir::IrContext *context)
|
||||
: pir::Dialect(name(), context, pir::TypeId::get<IntegerDialect>()) {
|
||||
RegisterType<IntegerType>();
|
||||
}
|
||||
static const char *name() { return "integer"; }
|
||||
};
|
||||
IR_DECLARE_EXPLICIT_TEST_TYPE_ID(IntegerDialect)
|
||||
IR_DEFINE_EXPLICIT_TYPE_ID(IntegerDialect)
|
||||
|
||||
TEST(type_test, custom_type_dialect) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
// Test 1: Test the function of IrContext to register Dialect.
|
||||
ctx->GetOrRegisterDialect<IntegerDialect>();
|
||||
|
||||
pir::Type int1_1 = IntegerType::get(ctx, 1, 0);
|
||||
pir::Type int1_2 = IntegerType::get(ctx, 1, 0);
|
||||
EXPECT_EQ(int1_1, int1_2);
|
||||
|
||||
pir::Type int8 = IntegerType::get(ctx, 8, 0);
|
||||
EXPECT_NE(int8, int1_2);
|
||||
|
||||
// Test 2: Test Dialect interfaces
|
||||
EXPECT_EQ(ctx, int8.ir_context());
|
||||
|
||||
EXPECT_EQ(int8.dialect().id(), pir::TypeId::get<IntegerDialect>());
|
||||
|
||||
std::vector<pir::Dialect *> dialect_list = ctx->GetRegisteredDialects();
|
||||
EXPECT_EQ(dialect_list.size() == 5, 1); // integer, builtin, fake
|
||||
|
||||
pir::Dialect *dialect_builtin1 = ctx->GetRegisteredDialect("builtin");
|
||||
pir::Dialect *dialect_builtin2 =
|
||||
ctx->GetRegisteredDialect<pir::BuiltinDialect>();
|
||||
EXPECT_EQ(dialect_builtin1, dialect_builtin2);
|
||||
|
||||
pir::Dialect *dialect_integer1 = ctx->GetRegisteredDialect("integer");
|
||||
pir::Dialect *dialect_integer2 = ctx->GetRegisteredDialect<IntegerDialect>();
|
||||
EXPECT_EQ(dialect_integer1, dialect_integer2);
|
||||
}
|
||||
|
||||
TEST(type_test, sparse_coo) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
common::DDim dims = {4, 4};
|
||||
common::DDim non_zero_dims = {4, 1};
|
||||
common::DataLayout data_layout = common::DataLayout::NCHW;
|
||||
pir::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
pir::DenseTensorType none_zero_indices = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
pir::DenseTensorType none_zero_elements = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
bool coalesced = false;
|
||||
paddle::dialect::SparseCooTensorTypeStorage storage1(fp32_dtype,
|
||||
dims,
|
||||
non_zero_dims,
|
||||
data_layout,
|
||||
none_zero_indices,
|
||||
none_zero_elements,
|
||||
coalesced);
|
||||
auto storage2 = std::make_tuple(fp32_dtype,
|
||||
dims,
|
||||
non_zero_dims,
|
||||
data_layout,
|
||||
none_zero_indices,
|
||||
none_zero_elements,
|
||||
coalesced);
|
||||
pir::Type pir_type =
|
||||
paddle::dialect::SparseCooTensorType::get(ctx,
|
||||
fp32_dtype,
|
||||
dims,
|
||||
non_zero_dims,
|
||||
data_layout,
|
||||
none_zero_indices,
|
||||
none_zero_elements,
|
||||
coalesced);
|
||||
EXPECT_TRUE(storage1 == storage2);
|
||||
EXPECT_EQ(pir_type.isa<paddle::dialect::SparseCooTensorType>(), true);
|
||||
paddle::dialect::SparseCooTensorType sparse_coo_tensor_type =
|
||||
pir_type.dyn_cast<paddle::dialect::SparseCooTensorType>();
|
||||
EXPECT_EQ(sparse_coo_tensor_type.dims(), dims);
|
||||
EXPECT_EQ(sparse_coo_tensor_type.non_zero_dims(), non_zero_dims);
|
||||
EXPECT_EQ(sparse_coo_tensor_type.data_layout(), data_layout);
|
||||
EXPECT_EQ(sparse_coo_tensor_type.non_zero_indices(), none_zero_indices);
|
||||
EXPECT_EQ(sparse_coo_tensor_type.non_zero_elements(), none_zero_elements);
|
||||
EXPECT_EQ(sparse_coo_tensor_type.coalesced(), coalesced);
|
||||
}
|
||||
|
||||
TEST(type_test, pd_op_dialect) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims = {2, 2};
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
paddle::dialect::SelectedRowsType select_rows_dtype =
|
||||
paddle::dialect::SelectedRowsType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
EXPECT_EQ(select_rows_dtype.dtype().isa<pir::Float32Type>(), true);
|
||||
EXPECT_EQ(select_rows_dtype.dims(), dims);
|
||||
EXPECT_EQ(select_rows_dtype.data_layout(), data_layout);
|
||||
EXPECT_EQ(select_rows_dtype.lod(), lod);
|
||||
EXPECT_EQ(select_rows_dtype.offset(), offset);
|
||||
}
|
||||
|
||||
TEST(type_test, sparse_csr) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
common::DDim dims = {4, 4};
|
||||
common::DataLayout data_layout = common::DataLayout::NCHW;
|
||||
pir::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
pir::DenseTensorType non_zero_crows = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
pir::DenseTensorType non_zero_cols = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
pir::DenseTensorType non_zero_elements = pir::DenseTensorType::get(
|
||||
ctx, fp32_dtype, dims, data_layout, lod, offset);
|
||||
paddle::dialect::SparseCsrTensorTypeStorage storage1(fp32_dtype,
|
||||
dims,
|
||||
data_layout,
|
||||
non_zero_crows,
|
||||
non_zero_cols,
|
||||
non_zero_elements);
|
||||
auto storage2 = std::make_tuple(fp32_dtype,
|
||||
dims,
|
||||
data_layout,
|
||||
non_zero_crows,
|
||||
non_zero_cols,
|
||||
non_zero_elements);
|
||||
pir::Type pir_type =
|
||||
paddle::dialect::SparseCsrTensorType::get(ctx,
|
||||
fp32_dtype,
|
||||
dims,
|
||||
data_layout,
|
||||
non_zero_crows,
|
||||
non_zero_cols,
|
||||
non_zero_elements);
|
||||
EXPECT_TRUE(storage1 == storage2);
|
||||
EXPECT_EQ(pir_type.isa<paddle::dialect::SparseCsrTensorType>(), true);
|
||||
paddle::dialect::SparseCsrTensorType sparse_csr_tensor_type =
|
||||
pir_type.dyn_cast<paddle::dialect::SparseCsrTensorType>();
|
||||
EXPECT_EQ(sparse_csr_tensor_type.dims(), dims);
|
||||
EXPECT_EQ(sparse_csr_tensor_type.data_layout(), data_layout);
|
||||
EXPECT_EQ(sparse_csr_tensor_type.non_zero_crows(), non_zero_crows);
|
||||
EXPECT_EQ(sparse_csr_tensor_type.non_zero_cols(), non_zero_cols);
|
||||
EXPECT_EQ(sparse_csr_tensor_type.non_zero_elements(), non_zero_elements);
|
||||
}
|
||||
|
||||
TEST(type_test, type_util) {
|
||||
pir::IrContext *ctx = pir::IrContext::Instance();
|
||||
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
|
||||
|
||||
pir::Type fp32_dtype = pir::Float32Type::get(ctx);
|
||||
phi::DDim dims1 = {2, 2};
|
||||
phi::DDim dims2 = {2, 2, 3};
|
||||
phi::DataLayout data_layout = phi::DataLayout::NCHW;
|
||||
phi::LegacyLoD lod = {{0, 1, 2}};
|
||||
size_t offset = 0;
|
||||
|
||||
paddle::dialect::SelectedRowsType select_rows_dtype1 =
|
||||
paddle::dialect::SelectedRowsType::get(
|
||||
ctx, fp32_dtype, dims1, data_layout, lod, offset);
|
||||
|
||||
paddle::dialect::SelectedRowsType select_rows_dtype2 =
|
||||
paddle::dialect::SelectedRowsType::get(
|
||||
ctx, fp32_dtype, dims2, data_layout, lod, offset);
|
||||
|
||||
std::vector<pir::Type> types1 = {
|
||||
select_rows_dtype1, select_rows_dtype1, select_rows_dtype1};
|
||||
std::vector<pir::Type> types2 = {
|
||||
select_rows_dtype1, select_rows_dtype1, select_rows_dtype1};
|
||||
std::vector<pir::Type> types3 = {
|
||||
select_rows_dtype2, select_rows_dtype2, select_rows_dtype2};
|
||||
|
||||
EXPECT_TRUE(pir::VerifyCompatibleShapes(types1, types2));
|
||||
EXPECT_FALSE(pir::VerifyCompatibleShapes(types1, types3));
|
||||
}
|
||||
|
||||
namespace TestNamespace {
|
||||
class TestClass {};
|
||||
} // namespace TestNamespace
|
||||
|
||||
TEST(type_test, get_type_name) {
|
||||
auto name = pir::get_type_name<TestNamespace::TestClass>();
|
||||
EXPECT_EQ(name, "TestNamespace::TestClass");
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include "paddle/pir/include/core/builtin_type_interfaces.h"
|
||||
#include "paddle/pir/include/core/type_utils.h"
|
||||
|
||||
TEST(type_util_test, verify_compatible_dims) {
|
||||
EXPECT_TRUE(
|
||||
pir::VerifyCompatibleDims({pir::ShapedTypeInterface::kDynamic, 2, 2}));
|
||||
EXPECT_FALSE(pir::VerifyCompatibleDims({2, 3}));
|
||||
}
|
||||
Reference in New Issue
Block a user