From 24f793d03ce868d8f22abc10f0b18b0b57a3a8c3 Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Thu, 10 Mar 2022 11:46:22 -0800 Subject: [PATCH 1/8] Add function ordering to C Codegen --- src/runtime/aot_executor/aot_executor.cc | 1 + .../aot_executor/aot_executor_factory.cc | 1 + src/runtime/hexagon/hexagon_module.cc | 2 +- src/runtime/pipeline/pipeline_executor.cc | 1 - src/runtime/vm/executable.cc | 2 +- src/target/source/codegen_c_host.cc | 31 ++++++++-- src/target/source/codegen_c_host.h | 8 ++- src/target/source/interface_c.cc | 3 +- src/target/source/source_module.cc | 4 +- tests/cpp/c_codegen_test.cc | 61 +++++++++++++++++++ 10 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 tests/cpp/c_codegen_test.cc diff --git a/src/runtime/aot_executor/aot_executor.cc b/src/runtime/aot_executor/aot_executor.cc index 732da14695eb..273213ac177b 100644 --- a/src/runtime/aot_executor/aot_executor.cc +++ b/src/runtime/aot_executor/aot_executor.cc @@ -132,6 +132,7 @@ PackedFunc AotExecutor::GetFunction(const std::string& name, *rv = this->GetInputIndex(args[0].operator String()); }); } else { + LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(); } } diff --git a/src/runtime/aot_executor/aot_executor_factory.cc b/src/runtime/aot_executor/aot_executor_factory.cc index 7760f0fe6c4d..fb4dfcd33cbf 100644 --- a/src/runtime/aot_executor/aot_executor_factory.cc +++ b/src/runtime/aot_executor/aot_executor_factory.cc @@ -60,6 +60,7 @@ PackedFunc AotExecutorFactory::GetFunction( *rv = Module(exec); }); } else { + LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(); } } diff --git a/src/runtime/hexagon/hexagon_module.cc b/src/runtime/hexagon/hexagon_module.cc index 7292b996e4a5..46881d998404 100644 --- a/src/runtime/hexagon/hexagon_module.cc +++ b/src/runtime/hexagon/hexagon_module.cc @@ -53,7 +53,7 @@ HexagonHostModuleNode::HexagonHostModuleNode(std::string data, std::string fmt, PackedFunc HexagonHostModuleNode::GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) { LOG(FATAL) << "HexagonHostModuleNode::GetFunction is not implemented."; - return nullptr; + return PackedFunc(); } std::string HexagonHostModuleNode::GetSource(const std::string& format) { diff --git a/src/runtime/pipeline/pipeline_executor.cc b/src/runtime/pipeline/pipeline_executor.cc index ccf5e09ebcf1..85eab912024f 100644 --- a/src/runtime/pipeline/pipeline_executor.cc +++ b/src/runtime/pipeline/pipeline_executor.cc @@ -86,7 +86,6 @@ PackedFunc PipelineExecutor::GetFunction(const std::string& name, LOG(FATAL) << "Unknown packed function: " << name; return PackedFunc(); } - return nullptr; } /*! diff --git a/src/runtime/vm/executable.cc b/src/runtime/vm/executable.cc index a003367c3724..85dad2839a8a 100644 --- a/src/runtime/vm/executable.cc +++ b/src/runtime/vm/executable.cc @@ -105,7 +105,7 @@ PackedFunc Executable::GetFunction(const std::string& name, const ObjectPtr #include +#include #include +#include #include #include "../../support/str_escape.h" @@ -78,6 +80,23 @@ void CodeGenCHost::AddFunction(const PrimFunc& f) { } } +void CodeGenCHost::AddFunctionsOrdered( + std::vector> functions) { + std::sort(functions.begin(), functions.end(), + [](std::pair kv_a, + std::pair kv_b) { + std::string name_hint_a = kv_a.first->name_hint; + std::string name_hint_b = kv_b.first->name_hint; + return name_hint_a < name_hint_b; + }); + + for (auto& kv : functions) { + ICHECK(kv.second->IsInstance()) << "CodegenCHost: Can only take PrimFunc"; + auto f = Downcast(kv.second); + AddFunction(f); + } +} + void CodeGenCHost::PrintFuncPrefix() { // NOLINT(*) stream << "#ifdef __cplusplus\n" << "extern \"C\"\n" @@ -351,9 +370,10 @@ runtime::Module BuildCHost(IRModule mod, Target target) { Map linked_params; PrimFunc aot_executor_fn; + std::vector> funcs; for (auto kv : mod->functions) { // Make sure that the executor function is the last one to be code generated so that all the - // symbols are available to tvm_run_func + // symbols are available to __tvm_main__ auto fun_name = std::string(kv.first->name_hint); bool is_aot_executor_fn = kv.second->GetAttr("runner_function", Bool(false)).value(); @@ -361,12 +381,13 @@ runtime::Module BuildCHost(IRModule mod, Target target) { aot_executor_fn = Downcast(kv.second); continue; } - - ICHECK(kv.second->IsInstance()) << "CodegenCHost: Can only take PrimFunc"; - auto f = Downcast(kv.second); - cg.AddFunction(f); + funcs.push_back(kv); } + // Add all functions except __tvm_main__ + cg.AddFunctionsOrdered(funcs); + + // Add __tvm_main__ if (aot_executor_fn.defined()) { cg.AddFunction(aot_executor_fn); } diff --git a/src/target/source/codegen_c_host.h b/src/target/source/codegen_c_host.h index c0e4ee9a263c..b674c7d68d9f 100644 --- a/src/target/source/codegen_c_host.h +++ b/src/target/source/codegen_c_host.h @@ -26,6 +26,7 @@ #include #include +#include #include #include "codegen_c.h" @@ -42,7 +43,12 @@ class CodeGenCHost : public CodeGenC { void InitGlobalContext(); void AddFunction(const PrimFunc& f); - + /*! + * \brief Add functions from the (unordered) range to the current module in a deterministic order. + * + * \param functions A vector of unordered range of current module. + */ + void AddFunctionsOrdered(std::vector> functions); void DefineModuleName(); void PrintType(DataType t, std::ostream& os) final; // NOLINT(*) diff --git a/src/target/source/interface_c.cc b/src/target/source/interface_c.cc index f4cef74e8af9..60380f42d0df 100644 --- a/src/target/source/interface_c.cc +++ b/src/target/source/interface_c.cc @@ -90,7 +90,8 @@ class InterfaceCNode : public runtime::ModuleNode { } PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { - return PackedFunc(nullptr); + LOG(INFO) << "GetFunction is not implemented in InterfaceCNode"; + return PackedFunc(); } private: diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 7db5d8c83a84..850bb9de306b 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -103,6 +103,7 @@ class CSourceModuleNode : public runtime::ModuleNode { return PackedFunc( [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->func_names_; }); } else { + LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(nullptr); } } @@ -171,7 +172,8 @@ class CSourceCrtMetadataModuleNode : public runtime::ModuleNode { std::string GetFormat() { return fmt_; } PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { - return PackedFunc(nullptr); + LOG(INFO) << "GetFunction is not implemented in CSourceCrtMetadataModuleNode"; + return PackedFunc(); } void SaveToFile(const std::string& file_name, const std::string& format) final { diff --git a/tests/cpp/c_codegen_test.cc b/tests/cpp/c_codegen_test.cc new file mode 100644 index 000000000000..46e1461873e0 --- /dev/null +++ b/tests/cpp/c_codegen_test.cc @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include +#include +#include +#include +#include +#include +#include + +TEST(CCodegen, FunctionOrder) { + using namespace tvm; + using namespace tvm::te; + + std::string tvm_module_main = std::string(runtime::symbol::tvm_module_main); + + tvm::Target target_c = tvm::Target("c -keys=cpu -link-params=0"); + + const int n = 4; + Array shape{n}; + + auto A = placeholder(shape, DataType::Float(32), "A"); + auto B = placeholder(shape, DataType::Float(32), "B"); + + auto elemwise_add = compute( + A->shape, [&A, &B](PrimExpr i) { return A[i] + B[i]; }, "elemwise_add"); + + auto fcreate = [=]() { + With llvm_scope(target_c); + return create_schedule({elemwise_add->op}); + }; + + auto args = Array({A, B, elemwise_add}); + + std::unordered_map binds; + auto lowered = LowerSchedule(fcreate(), args, "elemwise_add", binds); + Map inputs = {{target_c, lowered}}; + runtime::Module module = build(inputs, Target()); + Array functions = module->GetFunction("get_func_names", false)(); + + ICHECK(functions.back().compare(tvm_module_main) == 0); +} From 795237aaf8adc15cbc16557427b3f8e67bd3046f Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Mon, 14 Mar 2022 08:44:09 -0700 Subject: [PATCH 2/8] trigger From d0e33a28664fa82375646b6a6cb7524407189042 Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Mon, 14 Mar 2022 15:02:27 -0700 Subject: [PATCH 3/8] fix comment --- src/target/source/codegen_c_host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/source/codegen_c_host.h b/src/target/source/codegen_c_host.h index b674c7d68d9f..05bb83179365 100644 --- a/src/target/source/codegen_c_host.h +++ b/src/target/source/codegen_c_host.h @@ -44,7 +44,8 @@ class CodeGenCHost : public CodeGenC { void InitGlobalContext(); void AddFunction(const PrimFunc& f); /*! - * \brief Add functions from the (unordered) range to the current module in a deterministic order. + * \brief Add functions from the (unordered) range to the current module in a deterministic + * order. This helps with debugging. * * \param functions A vector of unordered range of current module. */ From 60de0b7affb0009e69703a6833c5f0e4827abdb2 Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Wed, 16 Mar 2022 11:51:29 -0700 Subject: [PATCH 4/8] address comments --- include/tvm/runtime/module.h | 8 +++++ src/runtime/aot_executor/aot_executor.cc | 1 - .../aot_executor/aot_executor_factory.cc | 1 - src/target/source/codegen_c_host.cc | 32 ++++++++----------- src/target/source/interface_c.cc | 1 - src/target/source/source_module.cc | 2 -- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/tvm/runtime/module.h b/include/tvm/runtime/module.h index a93f1c66c395..076172a8b5f7 100644 --- a/include/tvm/runtime/module.h +++ b/include/tvm/runtime/module.h @@ -251,6 +251,14 @@ inline const ModuleNode* Module::operator->() const { return static_cast(get()); } +inline std::ostream& operator<<(std::ostream& out, const Module& module) { + out << "Module(type_key= "; + out << module->type_key(); + out << ")"; + + return out; +} + } // namespace runtime } // namespace tvm diff --git a/src/runtime/aot_executor/aot_executor.cc b/src/runtime/aot_executor/aot_executor.cc index 273213ac177b..732da14695eb 100644 --- a/src/runtime/aot_executor/aot_executor.cc +++ b/src/runtime/aot_executor/aot_executor.cc @@ -132,7 +132,6 @@ PackedFunc AotExecutor::GetFunction(const std::string& name, *rv = this->GetInputIndex(args[0].operator String()); }); } else { - LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(); } } diff --git a/src/runtime/aot_executor/aot_executor_factory.cc b/src/runtime/aot_executor/aot_executor_factory.cc index fb4dfcd33cbf..7760f0fe6c4d 100644 --- a/src/runtime/aot_executor/aot_executor_factory.cc +++ b/src/runtime/aot_executor/aot_executor_factory.cc @@ -60,7 +60,6 @@ PackedFunc AotExecutorFactory::GetFunction( *rv = Module(exec); }); } else { - LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(); } } diff --git a/src/target/source/codegen_c_host.cc b/src/target/source/codegen_c_host.cc index 212460b3987b..94e22da1d58b 100644 --- a/src/target/source/codegen_c_host.cc +++ b/src/target/source/codegen_c_host.cc @@ -80,23 +80,6 @@ void CodeGenCHost::AddFunction(const PrimFunc& f) { } } -void CodeGenCHost::AddFunctionsOrdered( - std::vector> functions) { - std::sort(functions.begin(), functions.end(), - [](std::pair kv_a, - std::pair kv_b) { - std::string name_hint_a = kv_a.first->name_hint; - std::string name_hint_b = kv_b.first->name_hint; - return name_hint_a < name_hint_b; - }); - - for (auto& kv : functions) { - ICHECK(kv.second->IsInstance()) << "CodegenCHost: Can only take PrimFunc"; - auto f = Downcast(kv.second); - AddFunction(f); - } -} - void CodeGenCHost::PrintFuncPrefix() { // NOLINT(*) stream << "#ifdef __cplusplus\n" << "extern \"C\"\n" @@ -388,8 +371,21 @@ runtime::Module BuildCHost(IRModule mod, Target target) { funcs.push_back(kv); } + // Sort functions + std::sort(funcs.begin(), funcs.end(), + [](std::pair kv_a, + std::pair kv_b) { + std::string name_hint_a = kv_a.first->name_hint; + std::string name_hint_b = kv_b.first->name_hint; + return name_hint_a < name_hint_b; + }); + // Add all functions except __tvm_main__ - cg.AddFunctionsOrdered(funcs); + for (auto& kv : funcs) { + ICHECK(kv.second->IsInstance()) << "CodegenCHost: Can only take PrimFunc"; + auto f = Downcast(kv.second); + cg.AddFunction(f); + } // Add __tvm_main__ if (aot_executor_fn.defined()) { diff --git a/src/target/source/interface_c.cc b/src/target/source/interface_c.cc index 60380f42d0df..9f10fd2881e7 100644 --- a/src/target/source/interface_c.cc +++ b/src/target/source/interface_c.cc @@ -90,7 +90,6 @@ class InterfaceCNode : public runtime::ModuleNode { } PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { - LOG(INFO) << "GetFunction is not implemented in InterfaceCNode"; return PackedFunc(); } diff --git a/src/target/source/source_module.cc b/src/target/source/source_module.cc index 850bb9de306b..80b4f1b970f3 100644 --- a/src/target/source/source_module.cc +++ b/src/target/source/source_module.cc @@ -103,7 +103,6 @@ class CSourceModuleNode : public runtime::ModuleNode { return PackedFunc( [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->func_names_; }); } else { - LOG(INFO) << "Unknown packed function: " << name; return PackedFunc(nullptr); } } @@ -172,7 +171,6 @@ class CSourceCrtMetadataModuleNode : public runtime::ModuleNode { std::string GetFormat() { return fmt_; } PackedFunc GetFunction(const std::string& name, const ObjectPtr& sptr_to_self) final { - LOG(INFO) << "GetFunction is not implemented in CSourceCrtMetadataModuleNode"; return PackedFunc(); } From f97c4056fe95fd3fe660d0cf7e9e0e6338389f1a Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Wed, 16 Mar 2022 13:38:28 -0700 Subject: [PATCH 5/8] add test --- tests/cpp/c_codegen_test.cc | 49 ++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/cpp/c_codegen_test.cc b/tests/cpp/c_codegen_test.cc index 46e1461873e0..e6e8e3e77493 100644 --- a/tests/cpp/c_codegen_test.cc +++ b/tests/cpp/c_codegen_test.cc @@ -27,7 +27,7 @@ #include #include -TEST(CCodegen, FunctionOrder) { +TEST(CCodegen, MainFunctionOrder) { using namespace tvm; using namespace tvm::te; @@ -59,3 +59,50 @@ TEST(CCodegen, FunctionOrder) { ICHECK(functions.back().compare(tvm_module_main) == 0); } + +TEST(CCodegen, FunctionOrder) { + using testing::_; + using testing::ElementsAre; + using testing::StrEq; + using namespace tvm; + using namespace tvm::te; + + auto target = Target("c -keys=cpu -link-params=0"); + + // The shape of input tensors. + const int n = 4; + Array shape{n}; + + auto A = placeholder(shape, DataType::Float(32), "A"); + auto B = placeholder(shape, DataType::Float(32), "B"); + + auto op_1 = compute( + A->shape, [&A, &B](PrimExpr i) { return A[i] + B[i]; }, "op_1"); + + auto op_2 = compute( + A->shape, [&A, &B](PrimExpr i) { return A[i] - B[i]; }, "op_2"); + + auto fcreate_s1 = [=]() { + With llvm_scope(target); + return create_schedule({op_1->op}); + }; + + auto fcreate_s2 = [=]() { + With llvm_scope(target); + return create_schedule({op_2->op}); + }; + + auto args1 = Array({A, B, op_1}); + auto args2 = Array({A, B, op_2}); + + std::unordered_map binds; + auto lowered_s1 = LowerSchedule(fcreate_s1(), args1, "op_1", binds); + auto lowered_s2 = LowerSchedule(fcreate_s2(), args2, "op_2", binds); + + // add schedules in reverse order + Map inputs = {{target, lowered_s2}, {target, lowered_s1}}; + auto module = build(inputs, Target()); + Array func_array = module->GetFunction("get_func_names", false)(); + std::vector functions{func_array.begin(), func_array.end()}; + EXPECT_THAT(functions, ElementsAre(StrEq("op_1"), _, StrEq("op_2"), _)); +} From 25ae9398756d054952712db29ff8ab59de989866 Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Wed, 16 Mar 2022 19:35:27 -0700 Subject: [PATCH 6/8] add unorder check --- tests/cpp/c_codegen_test.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/cpp/c_codegen_test.cc b/tests/cpp/c_codegen_test.cc index e6e8e3e77493..c5b807a9d077 100644 --- a/tests/cpp/c_codegen_test.cc +++ b/tests/cpp/c_codegen_test.cc @@ -101,6 +101,14 @@ TEST(CCodegen, FunctionOrder) { // add schedules in reverse order Map inputs = {{target, lowered_s2}, {target, lowered_s1}}; + std::vector schedule_names; + for (auto const& module : inputs) { + for (auto const& func : module.second->functions) { + schedule_names.push_back(func.first->name_hint); + } + } + EXPECT_THAT(schedule_names, ElementsAre(StrEq("op_2"), StrEq("op_1"))); + auto module = build(inputs, Target()); Array func_array = module->GetFunction("get_func_names", false)(); std::vector functions{func_array.begin(), func_array.end()}; From fea6594dfeb90450836dda09e5ef7b09a170f30b Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Thu, 17 Mar 2022 17:23:15 -0700 Subject: [PATCH 7/8] fix test --- tests/cpp/c_codegen_test.cc | 63 ++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/tests/cpp/c_codegen_test.cc b/tests/cpp/c_codegen_test.cc index c5b807a9d077..9c496408e358 100644 --- a/tests/cpp/c_codegen_test.cc +++ b/tests/cpp/c_codegen_test.cc @@ -60,15 +60,10 @@ TEST(CCodegen, MainFunctionOrder) { ICHECK(functions.back().compare(tvm_module_main) == 0); } -TEST(CCodegen, FunctionOrder) { - using testing::_; - using testing::ElementsAre; - using testing::StrEq; +auto BuildLowered(std::string op_name, tvm::Target target) { using namespace tvm; using namespace tvm::te; - auto target = Target("c -keys=cpu -link-params=0"); - // The shape of input tensors. const int n = 4; Array shape{n}; @@ -76,38 +71,54 @@ TEST(CCodegen, FunctionOrder) { auto A = placeholder(shape, DataType::Float(32), "A"); auto B = placeholder(shape, DataType::Float(32), "B"); - auto op_1 = compute( - A->shape, [&A, &B](PrimExpr i) { return A[i] + B[i]; }, "op_1"); - - auto op_2 = compute( - A->shape, [&A, &B](PrimExpr i) { return A[i] - B[i]; }, "op_2"); + auto op = compute( + A->shape, [&A, &B](PrimExpr i) { return A[i] + B[i]; }, op_name); - auto fcreate_s1 = [=]() { + auto fcreate_s = [=]() { With llvm_scope(target); - return create_schedule({op_1->op}); + return create_schedule({op->op}); }; - auto fcreate_s2 = [=]() { - With llvm_scope(target); - return create_schedule({op_2->op}); - }; - - auto args1 = Array({A, B, op_1}); - auto args2 = Array({A, B, op_2}); - + auto args = Array({A, B, op}); std::unordered_map binds; - auto lowered_s1 = LowerSchedule(fcreate_s1(), args1, "op_1", binds); - auto lowered_s2 = LowerSchedule(fcreate_s2(), args2, "op_2", binds); + auto lowered_s = LowerSchedule(fcreate_s(), args, op_name, binds); + return lowered_s; +} - // add schedules in reverse order - Map inputs = {{target, lowered_s2}, {target, lowered_s1}}; +bool IsSorted(tvm::Map inputs) { std::vector schedule_names; for (auto const& module : inputs) { for (auto const& func : module.second->functions) { schedule_names.push_back(func.first->name_hint); } } - EXPECT_THAT(schedule_names, ElementsAre(StrEq("op_2"), StrEq("op_1"))); + return std::is_sorted(schedule_names.begin(), schedule_names.end()); +} + +TEST(CCodegen, FunctionOrder) { + using testing::_; + using testing::ElementsAre; + using testing::StrEq; + using namespace tvm; + using namespace tvm::te; + + Target target = Target("c -keys=cpu -link-params=0"); + + // add schedules in reverse order + Map inputs; + inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered("op_2", target)); + inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered("op_1", target)); + + uint32_t counter = 9; + while (IsSorted(inputs)) { + std::string op_name = "op_" + std::to_string(counter); + inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered(op_name, target)); + + counter -= 1; + if (counter == 0) { + counter = 9; + } + } auto module = build(inputs, Target()); Array func_array = module->GetFunction("get_func_names", false)(); From ddbe737e8021fa2509a4c45142fe80bcf05cc98e Mon Sep 17 00:00:00 2001 From: Mehrdad Hessar Date: Thu, 17 Mar 2022 17:41:04 -0700 Subject: [PATCH 8/8] address comments --- tests/cpp/c_codegen_test.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/cpp/c_codegen_test.cc b/tests/cpp/c_codegen_test.cc index 9c496408e358..097de862a926 100644 --- a/tests/cpp/c_codegen_test.cc +++ b/tests/cpp/c_codegen_test.cc @@ -109,17 +109,13 @@ TEST(CCodegen, FunctionOrder) { inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered("op_2", target)); inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered("op_1", target)); - uint32_t counter = 9; - while (IsSorted(inputs)) { + for (uint32_t counter = 99; IsSorted(inputs) && counter > 0; counter--) { std::string op_name = "op_" + std::to_string(counter); inputs.Set(Target("c -keys=cpu -link-params=0"), BuildLowered(op_name, target)); - - counter -= 1; - if (counter == 0) { - counter = 9; - } } + EXPECT_FALSE(IsSorted(inputs)); + auto module = build(inputs, Target()); Array func_array = module->GetFunction("get_func_names", false)(); std::vector functions{func_array.begin(), func_array.end()};