未验证 提交 9a8e9417 编写于 作者: W winter-wang 提交者: GitHub

[IR] standardize the use of new IR api. (#54289)

上级 f1c9c505
...@@ -613,7 +613,7 @@ def GenBuildInputArgsStr( ...@@ -613,7 +613,7 @@ def GenBuildInputArgsStr(
def GenBuildInputs(op_input_name_list): def GenBuildInputs(op_input_name_list):
BUILD_INPUT_TEMPLATE = """ std::vector<ir::OpResult> argument_inputs = {{{inputs_args}}}; BUILD_INPUT_TEMPLATE = """ std::vector<ir::OpResult> argument_inputs = {{{inputs_args}}};
argument.addOperands(argument_inputs.begin(), argument_inputs.end()); argument.AddOperands(argument_inputs.begin(), argument_inputs.end());
""" """
build_input_str = "" build_input_str = ""
if len(op_input_name_list) > 0: if len(op_input_name_list) > 0:
...@@ -693,7 +693,7 @@ def GenBuildAttributes(op_attribute_name_list, op_attribute_type_list): ...@@ -693,7 +693,7 @@ def GenBuildAttributes(op_attribute_name_list, op_attribute_type_list):
op_attribute_type=op_attribute_type_list[idx], op_attribute_type=op_attribute_type_list[idx],
attr=op_attribute_name_list[idx], attr=op_attribute_name_list[idx],
) )
attr_str += """ argument.addAttribute("{attr_name}", attr_{attr_name});\n""".format( attr_str += """ argument.AddAttribute("{attr_name}", attr_{attr_name});\n""".format(
attr_name=op_attribute_name_list[idx] attr_name=op_attribute_name_list[idx]
) )
...@@ -847,7 +847,7 @@ def GenBuildOutputs( ...@@ -847,7 +847,7 @@ def GenBuildOutputs(
name=op_output_name_list[idx] name=op_output_name_list[idx]
) )
build_output_str += " argument.addTypes(argument_outputs.begin(), argument_outputs.end());\n" build_output_str += " argument.AddTypes(argument_outputs.begin(), argument_outputs.end());\n"
return build_output_str return build_output_str
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "paddle/fluid/translator/op_translator.h" #include "paddle/fluid/translator/op_translator.h"
#include "paddle/fluid/translator/type_translator.h" #include "paddle/fluid/translator/type_translator.h"
#include "paddle/ir/core/attribute.h" #include "paddle/ir/core/attribute.h"
#include "paddle/ir/core/block.h"
#include "paddle/ir/core/builtin_op.h" #include "paddle/ir/core/builtin_op.h"
#include "paddle/ir/core/builtin_type.h" #include "paddle/ir/core/builtin_type.h"
#include "paddle/ir/core/operation.h" #include "paddle/ir/core/operation.h"
......
...@@ -28,7 +28,7 @@ using Program = ::ir::Program; ...@@ -28,7 +28,7 @@ using Program = ::ir::Program;
std::unique_ptr<Program> TranslateLegacyProgramToProgram( std::unique_ptr<Program> TranslateLegacyProgramToProgram(
const LegacyProgramDesc& legacy_program) { const LegacyProgramDesc& legacy_program) {
auto program = std::make_unique<Program>(); auto program = std::make_unique<Program>(ir::IrContext::Instance());
translator::ProgramTranslator program_translator(&legacy_program, translator::ProgramTranslator program_translator(&legacy_program,
program.get()); program.get());
......
...@@ -263,20 +263,4 @@ struct AttributeManager { ...@@ -263,20 +263,4 @@ struct AttributeManager {
return ir::AttributeManager::template get<concrete_attribute>(ctx, \ return ir::AttributeManager::template get<concrete_attribute>(ctx, \
args...); \ args...); \
} }
///
/// \brief This macro definition is used to register custom Attribute class.
///
#define REGISTER_ATTRIBUTE_2_IRCONTEXT(concrete_attribute, dialect) \
ir::AbstractAttribute *abstract_attribute_##concrete_attribute = \
new ir::AbstractAttribute(std::move( \
ir::AbstractAttribute::get<concrete_attribute>(*dialect))); \
\
dialect->ir_context()->RegisterAbstractAttribute( \
ir::TypeId::get<concrete_attribute>(), \
abstract_attribute_##concrete_attribute); \
\
ir::AttributeManager::RegisterAttribute<concrete_attribute>( \
dialect->ir_context());
} // namespace ir } // namespace ir
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "paddle/ir/core/builder.h" #include "paddle/ir/core/builder.h"
#include "paddle/ir/core/region.h" #include "paddle/ir/core/region.h"
#include "paddle/ir/core/value.h"
namespace ir { namespace ir {
Operation *Builder::insert(Operation *op) { Operation *Builder::insert(Operation *op) {
...@@ -31,10 +32,10 @@ Operation *Builder::create(OperationArgument &&argument) { ...@@ -31,10 +32,10 @@ Operation *Builder::create(OperationArgument &&argument) {
} }
/// Creates an operation with the given fields. /// Creates an operation with the given fields.
Operation *Builder::create(const std::vector<ir::OpResult> &inputs, Operation *Builder::create(const std::vector<OpResult> &inputs,
const AttributeMap &attribute, const AttributeMap &attribute,
const std::vector<ir::Type> &output_types, const std::vector<Type> &output_types,
ir::OpInfo op_info) { OpInfo op_info) {
return create(OperationArgument(inputs, attribute, output_types, op_info)); return create(OperationArgument(inputs, attribute, output_types, op_info));
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "paddle/ir/core/block.h" #include "paddle/ir/core/block.h"
#include "paddle/ir/core/operation.h" #include "paddle/ir/core/operation.h"
#include "paddle/ir/core/program.h"
namespace ir { namespace ir {
/// ///
......
...@@ -41,7 +41,7 @@ ModuleOp ModuleOp::create(IrContext *context, Program *pointer) { ...@@ -41,7 +41,7 @@ ModuleOp ModuleOp::create(IrContext *context, Program *pointer) {
ir::OpInfo info = context->GetRegisteredOpInfo(name()); ir::OpInfo info = context->GetRegisteredOpInfo(name());
OperationArgument argument(info); OperationArgument argument(info);
argument.AddRegion()->emplace_back(); argument.AddRegion()->emplace_back();
argument.addAttribute("program", PointerAttribute::get(context, pointer)); argument.AddAttribute("program", PointerAttribute::get(context, pointer));
return ModuleOp(Operation::create(std::move(argument))); return ModuleOp(Operation::create(std::move(argument)));
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "paddle/ir/core/program.h" #include "paddle/ir/core/program.h"
#include "paddle/ir/core/region.h" #include "paddle/ir/core/region.h"
#include "paddle/ir/core/utils.h" #include "paddle/ir/core/utils.h"
#include "paddle/ir/core/value_impl.h"
namespace ir { namespace ir {
Operation *Operation::create(OperationArgument &&argument) { Operation *Operation::create(OperationArgument &&argument) {
......
...@@ -18,12 +18,13 @@ ...@@ -18,12 +18,13 @@
#include "paddle/ir/core/op_info.h" #include "paddle/ir/core/op_info.h"
#include "paddle/ir/core/operation_utils.h" #include "paddle/ir/core/operation_utils.h"
#include "paddle/ir/core/type.h" #include "paddle/ir/core/type.h"
#include "paddle/ir/core/value_impl.h"
namespace ir { namespace ir {
class OpBase; class OpBase;
class Program; class Program;
class Block; class Block;
class OpOperand;
class OpResult;
class alignas(8) Operation final { class alignas(8) Operation final {
public: public:
...@@ -47,9 +48,9 @@ class alignas(8) Operation final { ...@@ -47,9 +48,9 @@ class alignas(8) Operation final {
IrContext *ir_context() const; IrContext *ir_context() const;
ir::OpResult GetResultByIndex(uint32_t index) const; OpResult GetResultByIndex(uint32_t index) const;
ir::OpOperand GetOperandByIndex(uint32_t index) const; OpOperand GetOperandByIndex(uint32_t index) const;
std::string print(); std::string print();
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
#pragma once #pragma once
#include "paddle/ir/core/builtin_attribute.h" #include "paddle/ir/core/attribute.h"
#include "paddle/ir/core/op_info.h" #include "paddle/ir/core/op_info.h"
#include "paddle/ir/core/region.h" #include "paddle/ir/core/region.h"
#include "paddle/ir/core/type.h" #include "paddle/ir/core/type.h"
#include "paddle/ir/core/value_impl.h" #include "paddle/ir/core/value.h"
namespace ir { namespace ir {
...@@ -52,18 +52,18 @@ struct OperationArgument { ...@@ -52,18 +52,18 @@ struct OperationArgument {
regions(std::move(regions)) {} regions(std::move(regions)) {}
template <class InputIt> template <class InputIt>
void addOperands(InputIt first, InputIt last); void AddOperands(InputIt first, InputIt last);
template <class InputIt> template <class InputIt>
void addTypes(InputIt first, InputIt last); void AddTypes(InputIt first, InputIt last);
/// Add an attribute with the specified name. /// Add an attribute with the specified name.
void addAttribute(const std::string& name, Attribute attr) { void AddAttribute(const std::string& name, Attribute attr) {
attributes[name] = attr; attributes[name] = attr;
} }
/// Add an array of named attributes. /// Add an array of named attributes.
template <class InputIt> template <class InputIt>
void addAttributes(InputIt first, InputIt last); void AddAttributes(InputIt first, InputIt last);
/// Get the context held by this operation state. /// Get the context held by this operation state.
IrContext* getContext() const { return info.ir_context(); } IrContext* getContext() const { return info.ir_context(); }
...@@ -74,19 +74,19 @@ struct OperationArgument { ...@@ -74,19 +74,19 @@ struct OperationArgument {
}; };
template <class InputIt> template <class InputIt>
void OperationArgument::addOperands(InputIt first, InputIt last) { void OperationArgument::AddOperands(InputIt first, InputIt last) {
while (first != last) { while (first != last) {
inputs.emplace_back(*first++); inputs.emplace_back(*first++);
} }
} }
template <class InputIt> template <class InputIt>
void OperationArgument::addTypes(InputIt first, InputIt last) { void OperationArgument::AddTypes(InputIt first, InputIt last) {
while (first != last) { while (first != last) {
output_types.emplace_back(*first++); output_types.emplace_back(*first++);
} }
} }
template <class InputIt> template <class InputIt>
void OperationArgument::addAttributes(InputIt first, InputIt last) { void OperationArgument::AddAttributes(InputIt first, InputIt last) {
while (first != last) { while (first != last) {
attributes[first->first] = first->second; attributes[first->first] = first->second;
++first; ++first;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "paddle/ir/core/block.h"
#include "paddle/ir/core/builtin_attribute.h" #include "paddle/ir/core/builtin_attribute.h"
#include "paddle/ir/core/builtin_type.h" #include "paddle/ir/core/builtin_type.h"
#include "paddle/ir/core/dialect.h" #include "paddle/ir/core/dialect.h"
...@@ -160,7 +161,7 @@ class ProgramPrinter : public Printer { ...@@ -160,7 +161,7 @@ class ProgramPrinter : public Printer {
std::vector<ir::Value> op_operands; std::vector<ir::Value> op_operands;
op_operands.reserve(num_op_operands); op_operands.reserve(num_op_operands);
for (size_t idx = 0; idx < num_op_operands; idx++) { for (size_t idx = 0; idx < num_op_operands; idx++) {
op_operands.push_back(op->GetOperandByIndex(idx).impl()->source()); op_operands.push_back(op->GetOperandByIndex(idx).source());
} }
PrintInterleave( PrintInterleave(
op_operands.begin(), op_operands.begin(),
...@@ -175,8 +176,7 @@ class ProgramPrinter : public Printer { ...@@ -175,8 +176,7 @@ class ProgramPrinter : public Printer {
std::vector<ir::Type> op_operand_types; std::vector<ir::Type> op_operand_types;
op_operand_types.reserve(num_op_operands); op_operand_types.reserve(num_op_operands);
for (size_t idx = 0; idx < num_op_operands; idx++) { for (size_t idx = 0; idx < num_op_operands; idx++) {
op_operand_types.push_back( op_operand_types.push_back(op->GetOperandByIndex(idx).source().type());
op->GetOperandByIndex(idx).impl()->source().type());
} }
PrintInterleave( PrintInterleave(
op_operand_types.begin(), op_operand_types.begin(),
......
...@@ -21,8 +21,6 @@ Program::Program(IrContext* context) { ...@@ -21,8 +21,6 @@ Program::Program(IrContext* context) {
module_ = ModuleOp::create(context, this); module_ = ModuleOp::create(context, this);
} }
Program::Program() : Program(IrContext::Instance()) {}
Program::~Program() { Program::~Program() {
if (module_) { if (module_) {
module_.destroy(); module_.destroy();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include "paddle/ir/core/attribute.h"
#include "paddle/ir/core/block.h" #include "paddle/ir/core/block.h"
#include "paddle/ir/core/builtin_attribute.h" #include "paddle/ir/core/builtin_attribute.h"
#include "paddle/ir/core/builtin_op.h" #include "paddle/ir/core/builtin_op.h"
...@@ -39,7 +40,6 @@ class Program { ...@@ -39,7 +40,6 @@ class Program {
using ParameterMap = using ParameterMap =
std::unordered_map<std::string, std::unique_ptr<Parameter>>; std::unordered_map<std::string, std::unique_ptr<Parameter>>;
explicit Program(IrContext* context); explicit Program(IrContext* context);
Program();
Program(Program&&) = delete; Program(Program&&) = delete;
Program(const Program& program) = delete; Program(const Program& program) = delete;
Program& operator=(const Program&) = delete; Program& operator=(const Program&) = delete;
......
...@@ -259,17 +259,4 @@ struct TypeManager { ...@@ -259,17 +259,4 @@ struct TypeManager {
static concrete_type get(ir::IrContext *ctx, Args... args) { \ static concrete_type get(ir::IrContext *ctx, Args... args) { \
return ir::TypeManager::template get<concrete_type>(ctx, args...); \ return ir::TypeManager::template get<concrete_type>(ctx, args...); \
} }
///
/// \brief This macro definition is used to register custom Type class.
///
#define REGISTER_TYPE_2_IRCONTEXT(concrete_type, dialect) \
ir::AbstractType *abstract_type_##concrete_type = new ir::AbstractType( \
std::move(ir::AbstractType::get<concrete_type>(*dialect))); \
\
dialect->ir_context()->RegisterAbstractType( \
ir::TypeId::get<concrete_type>(), abstract_type_##concrete_type); \
\
ir::TypeManager::RegisterType<concrete_type>(dialect->ir_context());
} // namespace ir } // namespace ir
...@@ -32,19 +32,13 @@ OpOperand &OpOperand::operator=(const detail::OpOperandImpl *impl) { ...@@ -32,19 +32,13 @@ OpOperand &OpOperand::operator=(const detail::OpOperandImpl *impl) {
return *this; return *this;
} }
bool OpOperand::operator==(OpOperand other) const { OpOperand OpOperand::next_use() const { return impl_->next_use(); }
return impl_ == other.impl_;
}
bool OpOperand::operator!=(OpOperand other) const {
return impl_ != other.impl_;
}
bool OpOperand::operator!() const { return impl_ == nullptr; } Value OpOperand::source() const { return impl_->source(); }
OpOperand::operator bool() const { return impl_; } Operation *OpOperand::owner() const { return impl_->owner(); }
detail::OpOperandImpl *OpOperand::impl() const { return impl_; } // detail::OpOperandImpl *OpOperand::impl() const { return impl_; }
// Value // Value
Value::Value(const detail::ValueImpl *impl) Value::Value(const detail::ValueImpl *impl)
...@@ -81,6 +75,8 @@ Value::use_iterator Value::begin() const { ...@@ -81,6 +75,8 @@ Value::use_iterator Value::begin() const {
Value::use_iterator Value::end() const { return Value::use_iterator(); } Value::use_iterator Value::end() const { return Value::use_iterator(); }
OpOperand Value::first_use() const { return impl()->first_use(); }
// OpResult // OpResult
bool OpResult::classof(Value value) { bool OpResult::classof(Value value) {
return ir::isa<detail::OpResultImpl>(value.impl()); return ir::isa<detail::OpResultImpl>(value.impl());
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
namespace ir { namespace ir {
class Operation; class Operation;
class Value;
namespace detail { namespace detail {
class OpOperandImpl; class OpOperandImpl;
...@@ -42,15 +43,21 @@ class OpOperand { ...@@ -42,15 +43,21 @@ class OpOperand {
OpOperand &operator=(const detail::OpOperandImpl *impl); OpOperand &operator=(const detail::OpOperandImpl *impl);
bool operator==(OpOperand other) const; bool operator==(const OpOperand &other) const { return impl_ == other.impl_; }
bool operator!=(OpOperand other) const; bool operator!=(const OpOperand &other) const { return !operator==(other); }
bool operator!() const; bool operator!() const { return impl_ == nullptr; }
explicit operator bool() const; operator bool() const { return impl_; }
detail::OpOperandImpl *impl() const; OpOperand next_use() const;
Value source() const;
Operation *owner() const;
// detail::OpOperandImpl *impl() const { return impl_;}
private: private:
detail::OpOperandImpl *impl_{nullptr}; detail::OpOperandImpl *impl_{nullptr};
...@@ -71,14 +78,14 @@ class ValueUseIterator { ...@@ -71,14 +78,14 @@ class ValueUseIterator {
return !(*this == rhs); return !(*this == rhs);
} }
ir::Operation *owner() const { return current_.impl()->owner(); } ir::Operation *owner() const { return current_.owner(); }
OperandType get() const { return current_; } OperandType get() const { return current_; }
OperandType operator*() const { return get(); } OperandType operator*() const { return get(); }
ValueUseIterator<OperandType> &operator++() { ValueUseIterator<OperandType> &operator++() {
current_ = current_.impl()->next_use(); current_ = current_.next_use();
return *this; return *this;
} }
...@@ -141,6 +148,8 @@ class Value { ...@@ -141,6 +148,8 @@ class Value {
use_iterator end() const; use_iterator end() const;
OpOperand first_use() const;
friend struct std::hash<Value>; friend struct std::hash<Value>;
protected: protected:
......
...@@ -103,11 +103,11 @@ class Operation1 : public ir::Op<Operation1> { ...@@ -103,11 +103,11 @@ class Operation1 : public ir::Op<Operation1> {
std::unordered_map<std::string, ir::Attribute> attributes = std::unordered_map<std::string, ir::Attribute> attributes =
CreateAttributeMap({"op1_attr1", "op1_attr2"}, CreateAttributeMap({"op1_attr1", "op1_attr2"},
{"op1_attr1", "op1_attr2"}); {"op1_attr1", "op1_attr2"});
argument.addOperands<std::vector<ir::OpResult>::iterator>(inputs.begin(), argument.AddOperands<std::vector<ir::OpResult>::iterator>(inputs.begin(),
inputs.end()); inputs.end());
argument.addTypes<std::vector<ir::Type>::iterator>(output_types.begin(), argument.AddTypes<std::vector<ir::Type>::iterator>(output_types.begin(),
output_types.end()); output_types.end());
argument.addAttributes< argument.AddAttributes<
std::unordered_map<std::string, ir::Attribute>::iterator>( std::unordered_map<std::string, ir::Attribute>::iterator>(
attributes.begin(), attributes.end()); attributes.begin(), attributes.end());
} }
......
...@@ -188,9 +188,9 @@ TEST(program_test, program) { ...@@ -188,9 +188,9 @@ TEST(program_test, program) {
std::unordered_map<std::string, ir::Attribute> abs_op_attribute; std::unordered_map<std::string, ir::Attribute> abs_op_attribute;
std::vector<ir::Type> output_types = {dense_tensor_dtype}; std::vector<ir::Type> output_types = {dense_tensor_dtype};
ir::OperationArgument abs_argument(abs_info); ir::OperationArgument abs_argument(abs_info);
abs_argument.addOperands(operands.begin(), operands.end()); abs_argument.AddOperands(operands.begin(), operands.end());
abs_argument.addAttributes(abs_op_attribute.begin(), abs_op_attribute.end()); abs_argument.AddAttributes(abs_op_attribute.begin(), abs_op_attribute.end());
abs_argument.addTypes(output_types.begin(), output_types.end()); abs_argument.AddTypes(output_types.begin(), output_types.end());
ir::Operation *abs_op = ir::Operation::create(std::move(abs_argument)); ir::Operation *abs_op = ir::Operation::create(std::move(abs_argument));
paddle::dialect::GetOpInfoInterface interface = paddle::dialect::GetOpInfoInterface interface =
abs_op->dyn_cast<paddle::dialect::GetOpInfoInterface>(); abs_op->dyn_cast<paddle::dialect::GetOpInfoInterface>();
...@@ -205,15 +205,14 @@ TEST(program_test, program) { ...@@ -205,15 +205,14 @@ TEST(program_test, program) {
ir::OperationArgument op4_argument( ir::OperationArgument op4_argument(
{op3->GetResultByIndex(0)}, {}, {}, op4_info); {op3->GetResultByIndex(0)}, {}, {}, op4_info);
op4_argument.addAttributes(op4_attribute.begin(), op4_attribute.end()); op4_argument.AddAttributes(op4_attribute.begin(), op4_attribute.end());
ir::Operation *op4 = ir::Operation::create(std::move(op4_argument)); ir::Operation *op4 = ir::Operation::create(std::move(op4_argument));
block->push_back(op4); block->push_back(op4);
EXPECT_EQ(op4->GetOperandByIndex(0).impl()->source().type().dialect().id(), EXPECT_EQ(op4->GetOperandByIndex(0).source().type().dialect().id(),
paddle_dialect->id()); paddle_dialect->id());
Interface *c_interface = op4->GetOperandByIndex(0) Interface *c_interface = op4->GetOperandByIndex(0)
.impl() .source()
->source()
.type() .type()
.dialect() .dialect()
.GetRegisteredInterface<Interface>(); .GetRegisteredInterface<Interface>();
...@@ -239,7 +238,7 @@ TEST(program_test, slice_combine_test) { ...@@ -239,7 +238,7 @@ TEST(program_test, slice_combine_test) {
ctx->GetOrRegisterDialect<ir::BuiltinDialect>(); ctx->GetOrRegisterDialect<ir::BuiltinDialect>();
// (2) Create an empty program object // (2) Create an empty program object
ir::Program program; ir::Program program(ctx);
// ir::Program *program = new ir::Program(); // ir::Program *program = new ir::Program();
EXPECT_EQ(program.block()->size() == 0, true); EXPECT_EQ(program.block()->size() == 0, true);
......
...@@ -85,16 +85,13 @@ TEST(value_test, value_test) { ...@@ -85,16 +85,13 @@ TEST(value_test, value_test) {
// Test 2: op1_first_output -> op4_first_input // Test 2: op1_first_output -> op4_first_input
ir::OpResult op1_first_output = op1->GetResultByIndex(0); ir::OpResult op1_first_output = op1->GetResultByIndex(0);
ir::detail::OpOperandImpl *op4_first_input = ir::OpOperand op4_first_input = op4->GetOperandByIndex(0);
reinterpret_cast<ir::detail::OpOperandImpl *>(
reinterpret_cast<uintptr_t>(op4) + sizeof(ir::Operation)); EXPECT_EQ(op1_first_output.first_use(), op4_first_input);
EXPECT_EQ(static_cast<ir::Value>(op1_first_output).impl()->first_use(), ir::OpOperand op3_first_input = op3->GetOperandByIndex(0);
op4_first_input);
ir::detail::OpOperandImpl *op3_first_input = EXPECT_EQ(op4_first_input.next_use(), op3_first_input);
reinterpret_cast<ir::detail::OpOperandImpl *>( EXPECT_EQ(op3_first_input.next_use(), nullptr);
reinterpret_cast<uintptr_t>(op3) + sizeof(ir::Operation));
EXPECT_EQ(op4_first_input->next_use(), op3_first_input);
EXPECT_EQ(op3_first_input->next_use(), nullptr);
// Test 3: Value iterator // Test 3: Value iterator
ir::Value::use_iterator iter = op1->GetResultByIndex(0).begin(); ir::Value::use_iterator iter = op1->GetResultByIndex(0).begin();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册