From 5b5a60b8da1ff16b3abc8ff77bc9734c813587e1 Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 13:43:02 +0800 Subject: [PATCH 01/11] [llvm] Avoid creating new LLVM contexts when updating struct module --- taichi/codegen/llvm/codegen_llvm.cpp | 5 ++- taichi/codegen/llvm/llvm_codegen_utils.cpp | 43 +++++++++++++++++++++- taichi/codegen/llvm/llvm_codegen_utils.h | 12 +++--- taichi/runtime/llvm/llvm_context.cpp | 6 --- taichi/runtime/llvm/llvm_context.h | 3 -- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/taichi/codegen/llvm/codegen_llvm.cpp b/taichi/codegen/llvm/codegen_llvm.cpp index 720d7b84fd2fe..6966c81f44d84 100644 --- a/taichi/codegen/llvm/codegen_llvm.cpp +++ b/taichi/codegen/llvm/codegen_llvm.cpp @@ -925,8 +925,9 @@ void CodeGenLLVM::emit_gc(OffloadedStmt *stmt) { } llvm::Value *CodeGenLLVM::create_call(llvm::Value *func, - llvm::ArrayRef args) { - check_func_call_signature(func, args); + llvm::ArrayRef args_arr) { + std::vector args = args_arr; + check_func_call_signature(func, args, builder.get()); #ifdef TI_LLVM_15 llvm::FunctionType *func_ty = nullptr; if (auto *fn = llvm::dyn_cast(func)) { diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index a7aed880b230b..bbea8ba347d50 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -10,8 +10,24 @@ std::string type_name(llvm::Type *type) { return type_name_str; } + +/* + * Determine whether two types are the same + * (a type is a renamed version of the other one) based on the type name + */ +bool is_same_type(llvm::Type *a, llvm::Type *b) { + if (a == b) { + return true; + } + auto a_name = type_name(a); + auto b_name = type_name(b); + int min_len = std::min(a_name.size(), b_name.size()) - 1; + return a_name.substr(0, min_len) == b_name.substr(0, min_len); +} + void check_func_call_signature(llvm::Value *func, - std::vector arglist) { + std::vector &arglist, + llvm::IRBuilder<> *builder) { llvm::FunctionType *func_type = nullptr; if (llvm::Function *fn = llvm::dyn_cast(func)) { func_type = fn->getFunctionType(); @@ -31,7 +47,32 @@ void check_func_call_signature(llvm::Value *func, for (int i = 0; i < num_params; i++) { auto required = func_type->getFunctionParamType(i); auto provided = arglist[i]->getType(); + /* + * Types in modules imported from files which are not the first appearances + * are renamed "original_type.xxx", so we have to create a pointer cast to the + * type in the function parameter list when the types in the function parameter + * are renamed. + */ if (required != provided) { + bool is_same = true; + if (required->isPointerTy() && required->getPointerElementType()->isFunctionTy()) { + auto req_func = llvm::dyn_cast(required->getPointerElementType()); + auto prov_func = llvm::dyn_cast(provided->getPointerElementType()); + if (req_func->getNumParams() != prov_func->getNumParams()) { + is_same = false; + } + for (int j = 0; is_same && j < req_func->getNumParams(); j++) { + if (!is_same_type(req_func->getParamType(j), prov_func->getParamType(j))) { + is_same = false; + } + } + } else { + is_same = is_same_type(required, provided); + } + if (is_same) { + arglist[i] = builder->CreatePointerCast(arglist[i], required); + continue; + } TI_INFO("Function : {}", std::string(func->getName())); TI_INFO(" Type : {}", type_name(func->getType())); if (&required->getContext() != &provided->getContext()) { diff --git a/taichi/codegen/llvm/llvm_codegen_utils.h b/taichi/codegen/llvm/llvm_codegen_utils.h index 324f585449a1d..3784f4ebf6e36 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.h +++ b/taichi/codegen/llvm/llvm_codegen_utils.h @@ -44,7 +44,8 @@ inline constexpr char kLLVMPhysicalCoordinatesName[] = "PhysicalCoordinates"; std::string type_name(llvm::Type *type); void check_func_call_signature(llvm::Value *func, - std::vector arglist); + std::vector &arglist, + llvm::IRBuilder<> *builder); class LLVMModuleBuilder { public: @@ -121,8 +122,9 @@ class LLVMModuleBuilder { const std::string &func_name, const std::vector &arglist) { auto func = get_runtime_function(func_name); - check_func_call_signature(func, arglist); - return builder->CreateCall(func, arglist); + std::vector args = arglist; + check_func_call_signature(func, args, builder); + return builder->CreateCall(func, args); } template @@ -131,7 +133,7 @@ class LLVMModuleBuilder { Args &&...args) { auto func = get_runtime_function(func_name); auto arglist = std::vector({args...}); - check_func_call_signature(func, arglist); + check_func_call_signature(func, arglist, builder); return builder->CreateCall(func, arglist); } @@ -186,7 +188,7 @@ class RuntimeObject { llvm::Value *call(const std::string &func_name, Args &&...args) { auto func = get_func(func_name); auto arglist = std::vector({ptr, args...}); - check_func_call_signature(func, arglist); + check_func_call_signature(func, arglist, builder); return builder->CreateCall(func, arglist); } diff --git a/taichi/runtime/llvm/llvm_context.cpp b/taichi/runtime/llvm/llvm_context.cpp index c0cffdd253a3c..69df639057ed5 100644 --- a/taichi/runtime/llvm/llvm_context.cpp +++ b/taichi/runtime/llvm/llvm_context.cpp @@ -529,12 +529,6 @@ void TaichiLLVMContext::set_struct_module( continue; } TI_ASSERT(!data->runtime_module); - data->struct_module.reset(); - old_contexts_.push_back(std::move(data->thread_safe_llvm_context)); - data->thread_safe_llvm_context = - std::make_unique( - std::make_unique()); - data->llvm_context = data->thread_safe_llvm_context->getContext(); data->struct_module = clone_module_to_context( this_thread_data->struct_module.get(), data->llvm_context); } diff --git a/taichi/runtime/llvm/llvm_context.h b/taichi/runtime/llvm/llvm_context.h index 09f602559db77..24c69445abd13 100644 --- a/taichi/runtime/llvm/llvm_context.h +++ b/taichi/runtime/llvm/llvm_context.h @@ -163,9 +163,6 @@ class TaichiLLVMContext { std::mutex thread_map_mut_; std::unordered_map> snode_tree_funcs_; - std::vector> - old_contexts_; // Contains old contexts that have modules stored inside - // the offline cache. }; class LlvmModuleBitcodeLoader { From 3834653598e361ccd6782f13937525fe8ea82d9c Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 13:59:42 +0800 Subject: [PATCH 02/11] fix --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index bbea8ba347d50..4e7be7f6b504b 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -19,9 +19,16 @@ bool is_same_type(llvm::Type *a, llvm::Type *b) { if (a == b) { return true; } + if (a->isPointerTy() != b->isPointerTy()) { + return false; + } + if (a->isPointerTy()) { + a = a->getPointerElementType(); + b = b->getPointerElementType(); + } auto a_name = type_name(a); auto b_name = type_name(b); - int min_len = std::min(a_name.size(), b_name.size()) - 1; + int min_len = std::min(a_name.size(), b_name.size()); return a_name.substr(0, min_len) == b_name.substr(0, min_len); } From fa1441c4c9529f3ebffb509cd6d9be8fe8a2c0c9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Jul 2022 05:46:02 +0000 Subject: [PATCH 03/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 4e7be7f6b504b..23a04384114aa 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -10,7 +10,6 @@ std::string type_name(llvm::Type *type) { return type_name_str; } - /* * Determine whether two types are the same * (a type is a renamed version of the other one) based on the type name @@ -56,20 +55,24 @@ void check_func_call_signature(llvm::Value *func, auto provided = arglist[i]->getType(); /* * Types in modules imported from files which are not the first appearances - * are renamed "original_type.xxx", so we have to create a pointer cast to the - * type in the function parameter list when the types in the function parameter - * are renamed. + * are renamed "original_type.xxx", so we have to create a pointer cast to + * the type in the function parameter list when the types in the function + * parameter are renamed. */ if (required != provided) { bool is_same = true; - if (required->isPointerTy() && required->getPointerElementType()->isFunctionTy()) { - auto req_func = llvm::dyn_cast(required->getPointerElementType()); - auto prov_func = llvm::dyn_cast(provided->getPointerElementType()); + if (required->isPointerTy() && + required->getPointerElementType()->isFunctionTy()) { + auto req_func = llvm::dyn_cast( + required->getPointerElementType()); + auto prov_func = llvm::dyn_cast( + provided->getPointerElementType()); if (req_func->getNumParams() != prov_func->getNumParams()) { is_same = false; } for (int j = 0; is_same && j < req_func->getNumParams(); j++) { - if (!is_same_type(req_func->getParamType(j), prov_func->getParamType(j))) { + if (!is_same_type(req_func->getParamType(j), + prov_func->getParamType(j))) { is_same = false; } } From d6a5ded96a97f051b90b06943f20a85156b14b51 Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 14:07:05 +0800 Subject: [PATCH 04/11] fix --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 62 ++++++++++++---------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 23a04384114aa..fb14a5f88bfc7 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -12,21 +12,44 @@ std::string type_name(llvm::Type *type) { /* * Determine whether two types are the same - * (a type is a renamed version of the other one) based on the type name + * (required type is required renamed version of the other one) based on the type name. + * Check recursively if the types are function types. */ -bool is_same_type(llvm::Type *a, llvm::Type *b) { - if (a == b) { +bool is_same_type(llvm::Type *required, llvm::Type *provided) { + if (required == provided) { return true; } - if (a->isPointerTy() != b->isPointerTy()) { + if (required->isPointerTy() != provided->isPointerTy()) { return false; } - if (a->isPointerTy()) { - a = a->getPointerElementType(); - b = b->getPointerElementType(); + if (required->isPointerTy()) { + required = required->getPointerElementType(); + provided = provided->getPointerElementType(); } - auto a_name = type_name(a); - auto b_name = type_name(b); + if (required->isFunctionTy() != provided->isFunctionTy()) { + return false; + } + if (required->isFunctionTy()) { + auto req_func = llvm::dyn_cast( + required); + auto prov_func = llvm::dyn_cast( + provided); + if (!is_same_type(req_func->getReturnType(), prov_func->getReturnType())) { + return false; + } + if (req_func->getNumParams() != prov_func->getNumParams()) { + return false; + } + for (int j = 0; j < req_func->getNumParams(); j++) { + if (!is_same_type(req_func->getParamType(j), + prov_func->getParamType(j))) { + return false; + } + } + return true; + } + auto a_name = type_name(required); + auto b_name = type_name(provided); int min_len = std::min(a_name.size(), b_name.size()); return a_name.substr(0, min_len) == b_name.substr(0, min_len); } @@ -60,26 +83,7 @@ void check_func_call_signature(llvm::Value *func, * parameter are renamed. */ if (required != provided) { - bool is_same = true; - if (required->isPointerTy() && - required->getPointerElementType()->isFunctionTy()) { - auto req_func = llvm::dyn_cast( - required->getPointerElementType()); - auto prov_func = llvm::dyn_cast( - provided->getPointerElementType()); - if (req_func->getNumParams() != prov_func->getNumParams()) { - is_same = false; - } - for (int j = 0; is_same && j < req_func->getNumParams(); j++) { - if (!is_same_type(req_func->getParamType(j), - prov_func->getParamType(j))) { - is_same = false; - } - } - } else { - is_same = is_same_type(required, provided); - } - if (is_same) { + if (is_same_type(required, provided)) { arglist[i] = builder->CreatePointerCast(arglist[i], required); continue; } From e704533b0cae36b832f85301337d1b66a3a7ef39 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Jul 2022 06:08:55 +0000 Subject: [PATCH 05/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index fb14a5f88bfc7..fe9c6f587305b 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -12,8 +12,8 @@ std::string type_name(llvm::Type *type) { /* * Determine whether two types are the same - * (required type is required renamed version of the other one) based on the type name. - * Check recursively if the types are function types. + * (required type is required renamed version of the other one) based on the + * type name. Check recursively if the types are function types. */ bool is_same_type(llvm::Type *required, llvm::Type *provided) { if (required == provided) { @@ -30,10 +30,8 @@ bool is_same_type(llvm::Type *required, llvm::Type *provided) { return false; } if (required->isFunctionTy()) { - auto req_func = llvm::dyn_cast( - required); - auto prov_func = llvm::dyn_cast( - provided); + auto req_func = llvm::dyn_cast(required); + auto prov_func = llvm::dyn_cast(provided); if (!is_same_type(req_func->getReturnType(), prov_func->getReturnType())) { return false; } From d019bb3ad1d9025f3036d14a10c440dfb9bf12a4 Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 14:09:38 +0800 Subject: [PATCH 06/11] fix --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index fe9c6f587305b..0e4da8df0f765 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -46,10 +46,10 @@ bool is_same_type(llvm::Type *required, llvm::Type *provided) { } return true; } - auto a_name = type_name(required); - auto b_name = type_name(provided); - int min_len = std::min(a_name.size(), b_name.size()); - return a_name.substr(0, min_len) == b_name.substr(0, min_len); + auto req_name = type_name(required); + auto prov_name = type_name(provided); + int min_len = std::min(req_name.size(), prov_name.size()); + return req_name.substr(0, min_len) == prov_name.substr(0, min_len); } void check_func_call_signature(llvm::Value *func, From 5231c19ae106756241a432703dc1ad60a12d0f5f Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 14:41:05 +0800 Subject: [PATCH 07/11] fix --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 0e4da8df0f765..9c926df0809c9 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -6,7 +6,7 @@ namespace lang { std::string type_name(llvm::Type *type) { std::string type_name_str; llvm::raw_string_ostream rso(type_name_str); - type->print(rso); + type->print(rso, false, true); return type_name_str; } From 256ba9b4a6f7d72781d0c581b9f8cb8d6fd1a58a Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Tue, 12 Jul 2022 14:42:42 +0800 Subject: [PATCH 08/11] add comment --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 9c926df0809c9..2b6e5ea4266b3 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -6,7 +6,7 @@ namespace lang { std::string type_name(llvm::Type *type) { std::string type_name_str; llvm::raw_string_ostream rso(type_name_str); - type->print(rso, false, true); + type->print(rso, /*IsForDebug=*/false, /*NoDetails=*/true); return type_name_str; } From 9cdf4fb1f8cc9b720fde1b58c33d10d53cc32530 Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Wed, 13 Jul 2022 15:13:44 +0800 Subject: [PATCH 09/11] add comments on renaming --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 2b6e5ea4266b3..5659fd6cfdca2 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -12,8 +12,12 @@ std::string type_name(llvm::Type *type) { /* * Determine whether two types are the same - * (required type is required renamed version of the other one) based on the + * (a type is a renamed version of the other one) based on the * type name. Check recursively if the types are function types. + * + * The name of a type imported multiple times is added a suffix starting with a "." + * following by a number. For example, "RuntimeContext" may be renamed to names + * like "RuntimeContext.0" and "RuntimeContext.8". */ bool is_same_type(llvm::Type *required, llvm::Type *provided) { if (required == provided) { From 80b8e5ecab81c2d8a4392e8161f94a1b2afac257 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 13 Jul 2022 07:15:29 +0000 Subject: [PATCH 10/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index 5659fd6cfdca2..e75c0b256cdfa 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -15,9 +15,9 @@ std::string type_name(llvm::Type *type) { * (a type is a renamed version of the other one) based on the * type name. Check recursively if the types are function types. * - * The name of a type imported multiple times is added a suffix starting with a "." - * following by a number. For example, "RuntimeContext" may be renamed to names - * like "RuntimeContext.0" and "RuntimeContext.8". + * The name of a type imported multiple times is added a suffix starting with a + * "." following by a number. For example, "RuntimeContext" may be renamed to + * names like "RuntimeContext.0" and "RuntimeContext.8". */ bool is_same_type(llvm::Type *required, llvm::Type *provided) { if (required == provided) { From 8757c13b8279c0fde83cf8a1bb27480476cbd407 Mon Sep 17 00:00:00 2001 From: lin-hitonami Date: Wed, 13 Jul 2022 15:29:21 +0800 Subject: [PATCH 11/11] add comments --- taichi/codegen/llvm/llvm_codegen_utils.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/taichi/codegen/llvm/llvm_codegen_utils.cpp b/taichi/codegen/llvm/llvm_codegen_utils.cpp index e75c0b256cdfa..6645fa3c91e6f 100644 --- a/taichi/codegen/llvm/llvm_codegen_utils.cpp +++ b/taichi/codegen/llvm/llvm_codegen_utils.cpp @@ -79,10 +79,12 @@ void check_func_call_signature(llvm::Value *func, auto required = func_type->getFunctionParamType(i); auto provided = arglist[i]->getType(); /* - * Types in modules imported from files which are not the first appearances - * are renamed "original_type.xxx", so we have to create a pointer cast to - * the type in the function parameter list when the types in the function - * parameter are renamed. + * When importing a module from file, the imported `llvm::Type`s can get + * conflict with the same type in the llvm::Context. In such scenario, + * the imported types will be renamed from "original_type" to + * "original_type.xxx", making them separate types in essence. + * To make the types of the argument and parameter the same, + * a pointer cast must be performed. */ if (required != provided) { if (is_same_type(required, provided)) {