chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+56
View File
@@ -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();
}
+125
View File
@@ -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;
}
+62
View File
@@ -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());
}
+74
View File
@@ -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());
}
+57
View File
@@ -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));
}
+112
View File
@@ -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);
}
+562
View File
@@ -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 &region = 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");
}
+130
View File
@@ -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);
}
+110
View File
@@ -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 &region = 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());
}
}
+110
View File
@@ -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>());
}
+156
View File
@@ -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();
}
+46
View File
@@ -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);
}
+43
View File
@@ -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>());
}
+68
View File
@@ -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);
}
+401
View File
@@ -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");
}
+24
View File
@@ -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}));
}