From 859917f77ca4c7765e6951d6bd33bf1dd5e632c6 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Tue, 29 Oct 2024 19:10:29 +0300 Subject: [PATCH 01/21] README.md adjustment --- static_core/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/static_core/README.md b/static_core/README.md index 9ec244042..26247e675 100644 --- a/static_core/README.md +++ b/static_core/README.md @@ -1,3 +1,9 @@ +# Experimental LLVM-Ark integration repository + +Panda version with experimental LLVM AOT / LLVM IRTOC changes. + +# Original Ark Runtime README + # Bootstrapping Currently an officially supported host OS for development, building and testing is Ubuntu 18.04 and Ubuntu 20.04. -- Gitee From 388b30639a7bc652ab40b3ad861877cdf388d80a Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Wed, 16 Oct 2024 10:11:12 +0300 Subject: [PATCH 02/21] Adjust LLVM build script and readme --- static_core/scripts/llvm/README.md | 17 ++++++------ static_core/scripts/llvm/build_llvm.sh | 37 +++++++++++--------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/static_core/scripts/llvm/README.md b/static_core/scripts/llvm/README.md index 0faea9145..64d134804 100644 --- a/static_core/scripts/llvm/README.md +++ b/static_core/scripts/llvm/README.md @@ -15,6 +15,7 @@ Some variables are mandatory, others are optional. ```bash ### Required variables BUILD_DIR= +INSTALL_DIR= (default: "/opt", installing there usually requires root privileges) LLVM_SOURCES=/llvm VERSION=(default: "main") PACKAGE_VERSION=(default: $VERSION) # must match REQUIRED_LLVM_VERSION in libllvmbackend/CMakeLists.txt @@ -28,10 +29,9 @@ BUILD_OHOS_RELEASE=(default: BUILD_OHOS_RELEASE_GN=(default: false) ### Optional variables -INSTALL_DIR= (default: "") -DO_STRIPPING=(default: true) -DO_TAR=(default: true) +DO_STRIPPING=(default: true) +DO_TAR=(default: true) OHOS_SDK=, required for any OHOS build. @@ -59,21 +59,22 @@ LLVM_SOURCES="/home/user/src/llvm-for-ark/llvm" \ VERSION="15.0.4-ark99-beta9" \ PACKAGE_VERSION="15.0.4-ark99" \ OPTIMIZE_DEBUG=false \ +DO_STRIPPING=false \ BUILD_X86_DEBUG=true \ BUILD_AARCH64_DEBUG=true \ bash -x ./build_llvm.sh ``` In this example, only `x86_64` and `arm64` debug versions are built. Then, they can be specified for Ark build, like: -* host build: `-DLLVM_TARGET_PATH=/home/user/build/llvm-15.0.4-ark99-beta9-debug-x86_64` +* host build: `-DLLVM_TARGET_PATH=/home/user/inst/llvm-15.0.4-ark99-beta9-debug-x86_64` * cross-arm64 build: - * `-DLLVM_TARGET_PATH=/home/user/build/llvm-15.0.4-ark99-beta9-debug-aarch64` - * `-DLLVM_HOST_PATH=/home/user/build/llvm-15.0.4-ark99-beta9-debug-x86_64` + * `-DLLVM_TARGET_PATH=/home/user/inst/llvm-15.0.4-ark99-beta9-debug-aarch64` + * `-DLLVM_HOST_PATH=/home/user/inst/llvm-15.0.4-ark99-beta9-debug-x86_64` ## Example with packaging all necessary versions ```bash -INSTALL_DIR="/mnt/scratch/install" \ +INSTALL_DIR="/opt" \ BUILD_DIR="/mnt/scratch/build" \ LLVM_SOURCES="/mnt/scratch/src/llvm-for-ark/llvm" \ VERSION="15.0.4-ark99-beta9" \ @@ -86,5 +87,5 @@ BUILD_AARCH64_DEBUG=true \ BUILD_AARCH64_RELEASE=true \ BUILD_OHOS_RELEASE=true \ BUILD_OHOS_RELEASE_GN=true \ -bash -x ./build_llvm.sh +sudo bash -x ./build_llvm.sh ``` diff --git a/static_core/scripts/llvm/build_llvm.sh b/static_core/scripts/llvm/build_llvm.sh index df835fe12..f34c4055f 100755 --- a/static_core/scripts/llvm/build_llvm.sh +++ b/static_core/scripts/llvm/build_llvm.sh @@ -16,15 +16,17 @@ set -euo pipefail # Required variables BUILD_DIR=${BUILD_DIR:-""} +INSTALL_DIR=${INSTALL_DIR:-"/opt"} LLVM_SOURCES=${LLVM_SOURCES:-""} + # Optional variables -INSTALL_DIR=${INSTALL_DIR:-""} # empty -- do not install VERSION=${VERSION:-"main"} # Specifies build and install directory names: PACKAGE_VERSION=${PACKAGE_VERSION:-${VERSION}} BUILD_SUFFIX=${BUILD_SUFFIX:-""} # llvm--{debug,release}-{aarch64,x86} OPTIMIZE_DEBUG=${OPTIMIZE_DEBUG:-true} # Compile debug versions with -O2 -DO_STRIPPING=${DO_STRIPPING:-true} # checked only if install -DO_TARS=${DO_TARS:-true} # checked only if install +DO_STRIPPING=${DO_STRIPPING:-true} +DO_TARS=${DO_TARS:-true} + # Select a target to build BUILD_X86_DEBUG=${BUILD_X86_DEBUG:-false} BUILD_X86_RELEASE=${BUILD_X86_RELEASE:-false} @@ -52,6 +54,11 @@ if [[ -z "${BUILD_DIR}" ]]; then exit 1 fi +if [[ -z "${INSTALL_DIR}" ]]; then + echo "Please, specify install directory with INSTALL_DIR variable" + exit 1 +fi + if [[ -z "${LLVM_SOURCES}" ]]; then echo "Please, specify llvm sources directory with LLVM_SOURCES variable" exit 1 @@ -152,9 +159,7 @@ if [[ "x${BUILD_X86_DEBUG}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" AUTO_LLVM_TABLEGEN="${BUILD_PREFIX}/bin/llvm-tblgen" if [[ ! -f "${AUTO_LLVM_TABLEGEN}" ]]; then @@ -195,9 +200,7 @@ if [[ "x${BUILD_X86_RELEASE}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" AUTO_LLVM_TABLEGEN="${BUILD_PREFIX}/bin/llvm-tblgen" if [[ ! -f "${AUTO_LLVM_TABLEGEN}" ]]; then @@ -248,9 +251,7 @@ if [[ "x${BUILD_AARCH64_DEBUG}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" fi if [[ "x${BUILD_AARCH64_RELEASE}" == "xtrue" ]]; then @@ -293,9 +294,7 @@ if [[ "x${BUILD_AARCH64_RELEASE}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" fi if [[ "x${BUILD_OHOS_RELEASE}" == "xtrue" ]]; then @@ -332,9 +331,7 @@ if [[ "x${BUILD_OHOS_RELEASE}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" fi if [[ "x${BUILD_OHOS_RELEASE_GN}" == "xtrue" ]]; then @@ -380,7 +377,5 @@ if [[ "x${BUILD_OHOS_RELEASE_GN}" == "xtrue" ]]; then "${LLVM_SOURCES}" ninja distribution - if [[ -n "${INSTALL_DIR}" ]]; then - install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" - fi + install "${INSTALL_PREFIX}" "${DO_STRIPPING}" "${DO_TARS}" fi -- Gitee From 6a16e8510739400faf0c3172433cd3699a027c6e Mon Sep 17 00:00:00 2001 From: Leonid Skvortsov Date: Fri, 4 Oct 2024 18:22:56 +0300 Subject: [PATCH 03/21] Fix entrypoints in GN build --- static_core/libllvmbackend/BUILD.gn | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/static_core/libllvmbackend/BUILD.gn b/static_core/libllvmbackend/BUILD.gn index 59356034f..395a68e96 100644 --- a/static_core/libllvmbackend/BUILD.gn +++ b/static_core/libllvmbackend/BUILD.gn @@ -195,12 +195,13 @@ if (is_llvmbackend) { extra_dependencies = [ "$ark_root/runtime:arkruntime_gen_intrinsics_yaml" ] } - entrypoints_yaml = "$ark_root/runtime/entrypoints/entrypoints.yaml" + entrypoints_yaml = rebase_path("$target_gen_dir/../runtime/entrypoints.yaml") ark_gen_file("libllvmbackend_entrypoints_gen_inl") { template_file = "$llvmbackend_templates_dir/entrypoints_gen.inl.erb" data = [ entrypoints_yaml ] api = [ "$llvmbackend_templates_dir/entrypoints.rb" ] output_file = "$target_gen_dir/entrypoints_gen.inl" + extra_dependencies = [ "$ark_root:concat_entrypoints_yamls" ] } ark_gen_file("libllvmbackend_entrypoints_llvm_ark_interface_gen_inl") { @@ -209,6 +210,7 @@ if (is_llvmbackend) { data = [ entrypoints_yaml ] api = [ "$llvmbackend_templates_dir/entrypoints.rb" ] output_file = "$target_gen_dir/entrypoints_llvm_ark_interface_gen.inl" + extra_dependencies = [ "$ark_root:concat_entrypoints_yamls" ] } ark_gen_file("libllvmbackend_llvm_passes_inl") { -- Gitee From 5dd6add337b0c97a7cf0a683bae99e0ba3d454ff Mon Sep 17 00:00:00 2001 From: Leonid Skvortsov Date: Tue, 8 Oct 2024 18:09:30 +0300 Subject: [PATCH 04/21] Follow NonNull attribute to intrinsic calls --- static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index 4c976f6c0..1bbfe73b9 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -4414,12 +4414,18 @@ void LLVMIrConstructor::VisitIntrinsic(GraphVisitor *v, Inst *inst) if (g_options.IsCompilerEncodeIntrinsics()) { bool lowered = ctor->TryEmitIntrinsic(inst, entryId); if (lowered) { + ASSERT(!inst->NoNullPtr()); return; } } // Create call otherwise auto result = ctor->CreateIntrinsicCall(inst); if (inst->GetType() != DataType::VOID) { + if (inst->NoNullPtr()) { + ASSERT(inst->GetType() == DataType::REFERENCE); + ASSERT(result->getType()->isPointerTy()); + result->addRetAttr(llvm::Attribute::NonNull); + } ctor->ValueMapAdd(inst, result); } } -- Gitee From 01656f959e88e2c3adacaeb0a908fe29af3424f0 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Fri, 18 Oct 2024 10:17:32 +0300 Subject: [PATCH 05/21] Refactor 'EmitStringGetBytesTlab' Signed-off-by: Denis Zavedeev --- .../ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl b/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl index 009d72857..4d9a8a750 100644 --- a/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl +++ b/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl @@ -358,10 +358,8 @@ bool LLVMIrConstructor::EmitStringGetBytesTlab(Inst *inst) auto offset = GetGraph()->GetRuntime()->GetArrayU8ClassPointerTlsOffset(GetGraph()->GetArch()); auto klass = llvmbackend::runtime_calls::LoadTLSValue(&builder_, arkInterface_, offset, builder_.getPtrTy()); auto eid = RuntimeInterface::EntrypointId::STRING_GET_BYTES_TLAB; - auto result = CreateEntrypointCall(eid, inst, - {GetInputValue(inst, 0), GetInputValue(inst, 1), GetInputValue(inst, 2), klass}); - ASSERT(result->getCallingConv() == llvm::CallingConv::C); - result->setCallingConv(llvm::CallingConv::ArkFast4); + auto result = + CreateFastPathCall(inst, eid, {GetInputValue(inst, 0), GetInputValue(inst, 1), GetInputValue(inst, 2), klass}); result->addRetAttr(llvm::Attribute::NonNull); result->addRetAttr(llvm::Attribute::NoAlias); ValueMapAdd(inst, result); -- Gitee From d9a7bd297fc1cebbf0e77e9ec968b4f789be3628 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Fri, 18 Oct 2024 10:41:33 +0300 Subject: [PATCH 06/21] Drop numArgs parameter in EmitFastPath Signed-off-by: Denis Zavedeev --- .../lowering/llvm_ir_constructor.cpp | 26 ++++++++++--------- .../lowering/llvm_ir_constructor.h | 2 +- .../ets_llvm_ir_constructor_gen.inl | 12 ++++----- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index 1bbfe73b9..1f97b9f7a 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -423,11 +423,13 @@ bool LLVMIrConstructor::TryEmitIntrinsic(Inst *inst, RuntimeInterface::Intrinsic // Specific intrinsic Emitters -bool LLVMIrConstructor::EmitFastPath(Inst *inst, RuntimeInterface::EntrypointId eid, uint32_t numArgs) +bool LLVMIrConstructor::EmitFastPath(Inst *inst, RuntimeInterface::EntrypointId eid) { - ArenaVector args(GetGraph()->GetLocalAllocator()->Adapter()); - for (uint32_t i = 0; i < numArgs; i++) { - args.push_back(GetInputValue(inst, i)); + llvm::SmallVector args; + for (uint32_t i = 0; i < inst->GetInputsCount(); i++) { + if (!inst->GetInput(i).GetInst()->IsSaveState()) { + args.push_back(GetInputValue(inst, i)); + } } auto call = CreateFastPathCall(inst, eid, args); @@ -440,42 +442,42 @@ bool LLVMIrConstructor::EmitFastPath(Inst *inst, RuntimeInterface::EntrypointId bool LLVMIrConstructor::EmitStringEquals(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_EQUALS_COMPRESSED, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_EQUALS_COMPRESSED); } bool LLVMIrConstructor::EmitStringBuilderBool(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_BOOL, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_BOOL); } bool LLVMIrConstructor::EmitStringBuilderChar(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_CHAR, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_CHAR); } bool LLVMIrConstructor::EmitStringBuilderString(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_STRING_COMPRESSED, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_BUILDER_STRING_COMPRESSED); } bool LLVMIrConstructor::EmitStringConcat2(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT2_TLAB, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT2_TLAB); } bool LLVMIrConstructor::EmitStringConcat3(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT3_TLAB, 3U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT3_TLAB); } bool LLVMIrConstructor::EmitStringConcat4(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT4_TLAB, 4U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_CONCAT4_TLAB); } bool LLVMIrConstructor::EmitStringCompareTo(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_COMPARE_TO, 2U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_COMPARE_TO); } bool LLVMIrConstructor::EmitIsInf(Inst *inst) diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.h b/static_core/libllvmbackend/lowering/llvm_ir_constructor.h index ab8fb64a2..3d99476d2 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.h +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.h @@ -34,7 +34,7 @@ class LLVMIrConstructor : public GraphVisitor { private: // Specific intrinsic Emitters - bool EmitFastPath(Inst *inst, RuntimeInterface::EntrypointId eid, uint32_t numArgs); + bool EmitFastPath(Inst *inst, RuntimeInterface::EntrypointId eid); bool EmitStringEquals(Inst *inst); bool EmitStringBuilderBool(Inst *inst); bool EmitStringBuilderChar(Inst *inst); diff --git a/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl b/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl index 4d9a8a750..39af1d2fc 100644 --- a/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl +++ b/static_core/plugins/ets/libllvmbackend/ets_llvm_ir_constructor_gen.inl @@ -48,7 +48,7 @@ bool LLVMIrConstructor::EmitArrayCopyTo(Inst *inst) bool LLVMIrConstructor::EmitStdStringSubstring(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::SUB_STRING_FROM_STRING_TLAB_COMPRESSED, 3U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::SUB_STRING_FROM_STRING_TLAB_COMPRESSED); } bool LLVMIrConstructor::EmitStringBuilderAppendBool(Inst *inst) @@ -160,7 +160,7 @@ bool LLVMIrConstructor::EmitStringBuilderAppendStrings(Inst *inst) default: UNREACHABLE(); } - return EmitFastPath(inst, eid, inst->GetInputsCount() - 1U); // -1 to skip save state + return EmitFastPath(inst, eid); } bool LLVMIrConstructor::EmitStringBuilderToString(Inst *inst) @@ -311,7 +311,7 @@ void LLVMIrConstructor::StringBuilderAppendStringMain(Inst *inst, llvm::Value *s bool LLVMIrConstructor::EmitDoubleToStringDecimal(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::DOUBLE_TO_STRING_DECIMAL, 3U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::DOUBLE_TO_STRING_DECIMAL); } bool LLVMIrConstructor::EmitStringTrimLeft(Inst *inst) @@ -340,17 +340,17 @@ bool LLVMIrConstructor::EmitStringTrim(Inst *inst) bool LLVMIrConstructor::EmitCharIsWhiteSpace(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::CHAR_IS_WHITE_SPACE, 1U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::CHAR_IS_WHITE_SPACE); } bool LLVMIrConstructor::EmitStringStartsWith(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_STARTS_WITH, 3U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_STARTS_WITH); } bool LLVMIrConstructor::EmitStringEndsWith(Inst *inst) { - return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_ENDS_WITH, 3U); + return EmitFastPath(inst, RuntimeInterface::EntrypointId::STRING_ENDS_WITH); } bool LLVMIrConstructor::EmitStringGetBytesTlab(Inst *inst) -- Gitee From 4069e2579231963c528365f9a98e47a483e7d9d1 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Wed, 16 Oct 2024 09:46:15 +0300 Subject: [PATCH 07/21] Bump llvm version to ark19 --- static_core/libllvmbackend/CMakeLists.txt | 2 +- static_core/libllvmbackend/llvm.gni | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static_core/libllvmbackend/CMakeLists.txt b/static_core/libllvmbackend/CMakeLists.txt index d5f009d58..30c6db24d 100644 --- a/static_core/libllvmbackend/CMakeLists.txt +++ b/static_core/libllvmbackend/CMakeLists.txt @@ -228,7 +228,7 @@ endif() panda_target_compile_options(llvmbackend PUBLIC "-Wno-unused-parameter") -panda_target_compile_definitions(llvmbackend PUBLIC REQUIRED_LLVM_VERSION=15.0.4-ark18) +panda_target_compile_definitions(llvmbackend PUBLIC REQUIRED_LLVM_VERSION=15.0.4-ark19) if (PANDA_LLVM_AOT AND PANDA_TARGET_AMD64 AND PANDA_COMPILER_TARGET_AARCH64 AND PANDA_WITH_TESTS) set(PANDA_LLVM_AOT_TESTS_SOURCES diff --git a/static_core/libllvmbackend/llvm.gni b/static_core/libllvmbackend/llvm.gni index 227919178..b47bf0dbd 100644 --- a/static_core/libllvmbackend/llvm.gni +++ b/static_core/libllvmbackend/llvm.gni @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -llvm_version = "15.0.4-ark18" +llvm_version = "15.0.4-ark19" llvm_lib_file_suffix = "lib/libLLVM-15.so" declare_args() { -- Gitee From 6763cf01178996144b81d3395dc7b61ae5cb3e93 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Fri, 18 Oct 2024 16:21:34 +0300 Subject: [PATCH 08/21] Use Tck_MustTail Signed-off-by: Denis Zavedeev --- static_core/libllvmbackend/llvm_irtoc_compiler.cpp | 1 + static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp | 5 +++-- static_core/tests/checked/checker.rb | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/static_core/libllvmbackend/llvm_irtoc_compiler.cpp b/static_core/libllvmbackend/llvm_irtoc_compiler.cpp index 7d5e20f75..46b13c37e 100644 --- a/static_core/libllvmbackend/llvm_irtoc_compiler.cpp +++ b/static_core/libllvmbackend/llvm_irtoc_compiler.cpp @@ -165,6 +165,7 @@ void LLVMIrtocCompiler::InitializeSpecificLLVMOptions(Arch arch) SetLLVMOption("aarch64-enable-ptr32", "true"); } SetLLVMOption("inline-remark-attribute", "true"); + SetLLVMOption("verify-musttail-calls", "false"); LLVMCompiler::InitializeLLVMOptions(); } diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index 1f97b9f7a..f5282dc3f 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -573,7 +573,7 @@ bool LLVMIrConstructor::EmitSlowPathEntry(Inst *inst) auto call = builder_.CreateCall(callee->getFunctionType(), callee, args); call->setCallingConv(callee->getCallingConv()); - call->setTailCallKind(llvm::CallInst::TailCallKind::TCK_Tail); + call->setTailCallKind(llvm::CallInst::TailCallKind::TCK_MustTail); call->addFnAttr(llvm::Attribute::get(call->getContext(), "ark-tail-call")); CreateReturn(call); return true; @@ -691,7 +691,7 @@ bool LLVMIrConstructor::EmitTailCall(Inst *inst) } else { UNREACHABLE(); } - call->setTailCallKind(llvm::CallInst::TailCallKind::TCK_Tail); + call->setTailCallKind(llvm::CallInst::TailCallKind::TCK_MustTail); call->addFnAttr(llvm::Attribute::get(call->getContext(), "ark-tail-call")); CreateReturn(call); std::fill(ccValues_.begin(), ccValues_.end(), nullptr); @@ -2258,6 +2258,7 @@ llvm::CallInst *LLVMIrConstructor::CreateTailCallFastPath(Inst *inst) auto ftype = llvm::FunctionType::get(GetType(inst->GetType()), argTypes, false); callee = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, externalName, func_->getParent()); cc = func_->getCallingConv(); + callee->setCallingConv(cc); } else { size_t size = func_->arg_size(); ASSERT(callee->arg_size() <= size); diff --git a/static_core/tests/checked/checker.rb b/static_core/tests/checked/checker.rb index 5aaec8ac3..7f061f2a0 100755 --- a/static_core/tests/checked/checker.rb +++ b/static_core/tests/checked/checker.rb @@ -189,7 +189,7 @@ class Checker # Current search scope @disasm_scope = nil - Dir.mkdir(@cwd) unless File.exists?(@cwd) + Dir.mkdir(@cwd) unless File.exist?(@cwd) clear_data end -- Gitee From 654a487d752d43d4417174283db3d39e08353c3e Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Thu, 24 Oct 2024 12:02:29 +0300 Subject: [PATCH 09/21] [VMB] Support LLVMAOT and selecting interpreter --- static_core/tests/vm-benchmarks/src/vmb/cli.py | 14 +++++++++++++- .../src/vmb/plugins/platforms/arkts_device.py | 6 ++++-- .../src/vmb/plugins/platforms/arkts_host.py | 6 ++++-- .../vm-benchmarks/src/vmb/plugins/tools/ark.py | 6 ++++++ .../vm-benchmarks/src/vmb/plugins/tools/paoc.py | 6 +++++- static_core/tests/vm-benchmarks/src/vmb/tool.py | 9 ++++++++- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/static_core/tests/vm-benchmarks/src/vmb/cli.py b/static_core/tests/vm-benchmarks/src/vmb/cli.py index 1aa21f7cb..010470e7c 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/cli.py +++ b/static_core/tests/vm-benchmarks/src/vmb/cli.py @@ -61,7 +61,11 @@ def add_measurement_opts(parser: argparse.ArgumentParser) -> None: help='If >= 0 invoke GC twice ' 'and wait ms before iteration') parser.add_argument("-aot-co", "--aot-compiler-options", default=[], - type=str, action="append", help="aot-compiler options") + type=str, action="append", + help="Sets ahead-of-time compiler options") + parser.add_argument("-aot-lib-co", "--aot-lib-compiler-options", default=[], + type=str, action="append", + help="Sets ahead-of-time compiler options for libraries") parser.add_argument("-c", "--concurrency-level", default=None, type=str, help="Concurrency level (DEPRECATED)") @@ -272,8 +276,16 @@ class Args(argparse.Namespace): mode = ToolMode(self.get('mode')) if ToolMode.AOT == mode: flags |= OptFlags.AOT + elif ToolMode.LLVMAOT == mode: + flags |= OptFlags.AOT | OptFlags.LLVMAOT elif ToolMode.INT == mode: flags |= OptFlags.INT + elif ToolMode.INT_CPP == mode: + flags |= OptFlags.INT | OptFlags.INT_CPP + elif ToolMode.INT_IRTOC == mode: + flags |= OptFlags.INT | OptFlags.INT_IRTOC + elif ToolMode.INT_LLVM == mode: + flags |= OptFlags.INT | OptFlags.INT_LLVM elif ToolMode.JIT == mode: flags |= OptFlags.JIT if self.get('dry_run', False): diff --git a/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_device.py b/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_device.py index 268f2d8a5..9e354d09d 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_device.py +++ b/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_device.py @@ -41,9 +41,11 @@ class Platform(PlatformBase): log.info('Skipping aot compilation of libs') else: an = Path(self.ark.etsstdlib).with_suffix('.an') - log.info('AOT-Compiling %s. This may took a long time...', + aot_lib_opts = ' '.join(args.aot_lib_compiler_options) + log.info('AOT-Compiling %s. This may take a long time...', self.ark.etsstdlib) - res = self.paoc.run_paoc(self.ark.etsstdlib, an, timeout=1800) + res = self.paoc.run_paoc(self.ark.etsstdlib, an, + opts=aot_lib_opts, timeout=1800) if not self.ext_info.get('etsstdlib', {}): self.ext_info['etsstdlib'] = {} self.ext_info['etsstdlib']['etsstdlib.an'] = \ diff --git a/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_host.py b/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_host.py index e6e9e419e..5b3120d5d 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_host.py +++ b/static_core/tests/vm-benchmarks/src/vmb/plugins/platforms/arkts_host.py @@ -43,9 +43,11 @@ class Platform(PlatformBase): else: an = ToolBase.libs.joinpath( Path(self.ark.etsstdlib).with_suffix('.an').name) - log.info('AOT-Compiling %s. This may took a long time...', + aot_lib_opts = ' '.join(args.aot_lib_compiler_options) + log.info('AOT-Compiling %s. This may take a long time...', self.ark.etsstdlib) - res = self.paoc.run_paoc(self.ark.etsstdlib, an, timeout=1800) + res = self.paoc.run_paoc(self.ark.etsstdlib, an, + opts=aot_lib_opts, timeout=1800) if not self.ext_info.get('etsstdlib', {}): self.ext_info['etsstdlib'] = {} self.ext_info['etsstdlib']['etsstdlib.an'] = \ diff --git a/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/ark.py b/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/ark.py index 3f4084b05..536e0bbf6 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/ark.py +++ b/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/ark.py @@ -50,6 +50,12 @@ class Tool(ToolBase): an_files.append(stdlib) if OptFlags.INT in self.flags: opts += '--compiler-enable-jit=false ' + if OptFlags.INT_CPP in self.flags: + opts += '--interpreter-type=cpp ' + if OptFlags.INT_IRTOC in self.flags: + opts += '--interpreter-type=irtoc ' + if OptFlags.INT_LLVM in self.flags: + opts += '--interpreter-type=llvm ' if OptFlags.GC_STATS in self.flags: opts += '--print-gc-statistics --log-components=gc ' \ '--log-level=info --log-stream=file ' \ diff --git a/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/paoc.py b/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/paoc.py index 43bc2b616..b8b87ec72 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/paoc.py +++ b/static_core/tests/vm-benchmarks/src/vmb/plugins/tools/paoc.py @@ -50,8 +50,12 @@ class Tool(ToolBase): aot_stats = '--compiler-dump-stats-csv={an}.dump.csv ' else: aot_stats = '' + if OptFlags.LLVMAOT in self.flags: + aot_mode = '--paoc-mode=llvm ' + else: + aot_mode = '--paoc-mode=aot ' self.cmd = f'LD_LIBRARY_PATH={self.ark_lib} {self.paoc} ' \ - f'--boot-panda-files={self.etsstdlib} ' \ + f'--boot-panda-files={self.etsstdlib} {aot_mode} ' \ '--load-runtimes=ets {opts} ' \ f'{self.custom} {aot_stats}' \ '--paoc-panda-files={abc} ' \ diff --git a/static_core/tests/vm-benchmarks/src/vmb/tool.py b/static_core/tests/vm-benchmarks/src/vmb/tool.py index dad6d25e8..e814add66 100644 --- a/static_core/tests/vm-benchmarks/src/vmb/tool.py +++ b/static_core/tests/vm-benchmarks/src/vmb/tool.py @@ -47,6 +47,10 @@ class ToolMode(StringEnum): AOT = 'aot' INT = 'int' JIT = 'jit' + INT_CPP = 'int-cpp' + INT_IRTOC = 'int-irtoc' + INT_LLVM = 'int-llvm' + LLVMAOT = 'llvmaot' DEFAULT = 'default' @@ -58,10 +62,13 @@ class OptFlags(Flag): AOT_SKIP_LIBS = auto() DRY_RUN = auto() DISABLE_INLINING = auto() - # these 3 flags are mutually exclusive (this is guarantied by ToolMode) AOT = auto() INT = auto() JIT = auto() + INT_CPP = auto() + INT_IRTOC = auto() + INT_LLVM = auto() + LLVMAOT = auto() class ToolBase(CrossShell, ABC): -- Gitee From e5a737229da16af8d0ad6b2a422c32e01c52fe40 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Fri, 27 Sep 2024 16:18:09 +0300 Subject: [PATCH 10/21] [CI] Clang-tidy/clang-format scripts adjustments --- static_core/CMakeLists.txt | 2 +- static_core/cmake/ClangTidy.cmake | 6 +++ .../clang-tidy/clang-tidy_llvm_config.json | 10 ++++ .../scripts/clang-tidy/clang_tidy_check.py | 54 ++++++++++++++----- .../scripts/code_style/code_style_check.py | 21 +++++--- 5 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 static_core/scripts/clang-tidy/clang-tidy_llvm_config.json diff --git a/static_core/CMakeLists.txt b/static_core/CMakeLists.txt index ddc400a3f..63d72c8c4 100644 --- a/static_core/CMakeLists.txt +++ b/static_core/CMakeLists.txt @@ -347,7 +347,7 @@ if(PANDA_WITH_TESTS) ) if (NOT PANDA_TARGET_MACOS) - add_dependencies(tests_full code-style-check) + add_dependencies(tests_full code-style-check doxygen-style-check clang-tidy-llvmbackend) endif() add_subdirectory(scripts) diff --git a/static_core/cmake/ClangTidy.cmake b/static_core/cmake/ClangTidy.cmake index 1d6bf74d8..444bf268b 100644 --- a/static_core/cmake/ClangTidy.cmake +++ b/static_core/cmake/ClangTidy.cmake @@ -40,3 +40,9 @@ add_custom_target(test-cmake-checker COMMAND ${PANDA_ROOT}/scripts/cmake-checker/cmake_checker.py ${PANDA_ROOT} TEST USES_TERMINAL ) + +add_custom_target(clang-tidy-llvmbackend + COMMAND ${PANDA_ROOT}/scripts/clang-tidy/clang_tidy_check.py ${PANDA_ROOT} ${PANDA_BINARY_ROOT} "--cfg-filter=${PANDA_ROOT}/scripts/clang-tidy/clang-tidy_llvm_config.json" + USES_TERMINAL + DEPENDS panda_gen_files +) diff --git a/static_core/scripts/clang-tidy/clang-tidy_llvm_config.json b/static_core/scripts/clang-tidy/clang-tidy_llvm_config.json new file mode 100644 index 000000000..ebf474cc2 --- /dev/null +++ b/static_core/scripts/clang-tidy/clang-tidy_llvm_config.json @@ -0,0 +1,10 @@ +[ + "libllvmbackend", + "irtoc/backend/", + "compiler/aot/aot_builder/aot_builder.cpp", + "compiler/aot/aot_builder/llvm_aot_builder.cpp", + "compiler/aot/aot_file.cpp", + "compiler/optimizer/ir/aot_data.cpp", + "compiler/tools/paoc/paoc.cpp", + "compiler/tools/paoc/paoc_llvm.cpp" +] diff --git a/static_core/scripts/clang-tidy/clang_tidy_check.py b/static_core/scripts/clang-tidy/clang_tidy_check.py index c6e5b3492..97a5d4753 100755 --- a/static_core/scripts/clang-tidy/clang_tidy_check.py +++ b/static_core/scripts/clang-tidy/clang_tidy_check.py @@ -29,9 +29,13 @@ def get_args(): 'panda_dir', help='panda sources directory.', type=str) parser.add_argument( 'build_dir', help='panda build directory.', type=str) + parser.add_argument( + '--cfg-filter', type=str, action='store', dest='cfg_filter', + required=False, + help='Path to config with filenames to be checked. If missed all source files will be checked.') parser.add_argument( '--filename-filter', type=str, action='store', dest='filename_filter', - required=False, default="*", + required=False, help='Regexp for filename with path to it. If missed all source files will be checked.') parser.add_argument( '--full', action="store_true", help='Check all files with all compile keys.') @@ -213,7 +217,7 @@ default_disabled_checks = [ ] -def run_clang_tidy(src_path: str, config_file_path: str, build_dir: str, header_filter: str, compile_args: str) -> bool: +def run_clang_tidy(src_path: str, config_file_path: str, build_dir: str, header_filter: str, compile_args: str, delayed_stderr: list, job_num: int) -> bool: # Used by ctcache to provide a wrapper for real clang-tidy that will check the cache # before launching clang-tidy and save the result to ctcache server cmd_path = os.getenv('CLANG_TIDY_PATH') @@ -240,10 +244,14 @@ def run_clang_tidy(src_path: str, config_file_path: str, build_dir: str, header_ print("Note: bad output for ", src_path) return True - print('Failed: ' + ' '.join(cmd) + '\n' + out_msg) + failed_output = f'Failed: ' + ' '.join(cmd) + failed_output += f'\n{out_msg}\n' if e.stderr: - print(e.stderr.decode()) + failed_output += e.stderr.decode() + + delayed_stderr[job_num] = failed_output + print(failed_output) return False @@ -260,12 +268,15 @@ def get_full_path(relative_path: str, location_base: str, panda_dir: str, build_ def check_file_list(file_list: list, panda_dir: str, build_dir: str, header_filter: str, proc_count: int) -> bool: pool = multiprocessing.Pool(proc_count) jobs = [] - for src, args in file_list: + manager = multiprocessing.Manager() + delayed_stderr = manager.list([None] * len(file_list)) + for i in range(len(file_list)): + src, args = file_list[i] msg = "Done clang-tidy: %s" % (src) proc = pool.apply_async(func=run_clang_tidy, args=( - src, panda_dir, build_dir, header_filter, args)) + src, panda_dir, build_dir, header_filter, args, delayed_stderr, i)) jobs.append((proc, msg)) # Wait for jobs to complete before exiting @@ -289,6 +300,7 @@ def check_file_list(file_list: list, panda_dir: str, build_dir: str, header_filt # Safely terminate the pool pool.close() pool.join() + print('\n'.join([ds for ds in delayed_stderr if ds])) return main_ret_val @@ -409,10 +421,13 @@ def verify_uniq_element_list(uniq_element_list: list) -> bool: return len(uniq_element_list) == len(set(uniq_element_list)) -def verify_args(panda_dir: str, build_dir: str) -> str: +def verify_args(panda_dir: str, build_dir: str, filename_filter: str, cfg_filter: str): if not verify_uniq_element_list(default_disabled_checks): return "Error: Dupclicated defauls disabled checks" + if filename_filter and cfg_filter: + return "Error: --filename-filter and --cfg-filter cannot be used together, please remove one." + return "" @@ -458,6 +473,13 @@ def get_proc_count(cmd_ard : int) -> int: return multiprocessing.cpu_count() +def parse_config(cfg_filter): + cfg_data = None + with open(cfg_filter) as cfg: + cfg_data = json.load(cfg) + return f"({'|'.join(cfg_data)})" + + if __name__ == "__main__": arguments = get_args() files_list = [] @@ -470,17 +492,25 @@ if __name__ == "__main__": default_disabled_checks.append("-fuchsia-statically-constructed-objects") default_disabled_checks.append("-cert-err58-cpp") - err_msg = verify_args(arguments.panda_dir, arguments.build_dir) + err_msg = verify_args( + arguments.panda_dir, arguments.build_dir, arguments.filename_filter, arguments.cfg_filter) if err_msg: sys.exit(err_msg) - files_list = get_file_list( - arguments.panda_dir, arguments.build_dir, arguments.filename_filter) + filename_filter = "*" + + if arguments.filename_filter: + filename_filter = arguments.filename_filter + elif arguments.cfg_filter: + filename_filter = parse_config(arguments.cfg_filter) + + files_list = get_file_list(arguments.panda_dir, arguments.build_dir, filename_filter) if not files_list: sys.exit("Can't be prepaired source list." - "Please check availble in build `dir compile_commands.json`" - "and correcting of parameter `--filename-filter` if you use it.") + "Please check available in build `dir compile_commands.json`" + "and correcting of parameter `--filename-filter`" + " or `--cfg-filter` if you use it.") if not arguments.check_libabckit: check_headers_in_es2panda_sources(arguments.panda_dir) diff --git a/static_core/scripts/code_style/code_style_check.py b/static_core/scripts/code_style/code_style_check.py index b3a8ad6c5..f8735d1e9 100755 --- a/static_core/scripts/code_style/code_style_check.py +++ b/static_core/scripts/code_style/code_style_check.py @@ -39,7 +39,7 @@ def get_args(): return parser.parse_args() -def run_clang_format(src_path, panda_dir, reformat, msg): +def run_clang_format(src_path, panda_dir, reformat, msg, delayed_stderr, job_num): check_cmd = [str(os.path.join(panda_dir, 'scripts', 'code_style', 'run_code_style_tools.sh'))] reformat_cmd = [CLANG_FORMAT, '-i'] @@ -56,11 +56,14 @@ def run_clang_format(src_path, panda_dir, reformat, msg): print("Note: missed output for ", src_path) return True - print('Failed: ', ' '.join(cmd)) - print(e.stdout.decode()) + failed_output = f'Failed: ' + ' '.join(cmd) + failed_output += f'\n{e.stdout.decode()}\n' if e.stderr: - print(e.stderr.decode()) + failed_output += e.stderr.decode() + + delayed_stderr[job_num] = failed_output + print(failed_output) return False @@ -84,16 +87,19 @@ def check_file_list(file_list : list, panda_dir : str, reformat : bool, proc_cou main_ret_val = True total_count = str(len(file_list)) idx = 0 - for src in file_list: + manager = multiprocessing.Manager() + delayed_stderr = manager.list([None] * len(file_list)) + for i in range(len(file_list)): + src = file_list[i] idx += 1 msg = "[%s/%s] Running clang-format: %s" % (str(idx), total_count, src) proc = pool.apply_async(func=run_clang_format, args=( - src, panda_dir, reformat, msg)) + src, panda_dir, reformat, msg, delayed_stderr, i)) jobs.append(proc) # Wait for jobs to complete before exiting while(not all([p.ready() for p in jobs])): - time.sleep(5) + time.sleep(1) for job in jobs: if not job.get(): @@ -103,6 +109,7 @@ def check_file_list(file_list : list, panda_dir : str, reformat : bool, proc_cou # Safely terminate the pool pool.close() pool.join() + print('\n'.join([ds for ds in delayed_stderr if ds])) return main_ret_val -- Gitee From 40150b96e4270db81277f8ffe820d0f01b67052f Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Thu, 26 Sep 2024 18:42:07 +0300 Subject: [PATCH 11/21] [CI] Tweak llvmaot options for etsstdlib --- static_core/plugins/ets/CMakeLists.txt | 13 +++- static_core/plugins/ets/tests/CMakeLists.txt | 73 ++++++-------------- 2 files changed, 33 insertions(+), 53 deletions(-) diff --git a/static_core/plugins/ets/CMakeLists.txt b/static_core/plugins/ets/CMakeLists.txt index aa939c5aa..40530c4a8 100644 --- a/static_core/plugins/ets/CMakeLists.txt +++ b/static_core/plugins/ets/CMakeLists.txt @@ -126,10 +126,19 @@ endif() if(PANDA_WITH_COMPILER) add_subdirectory(compiler) - set (COMPILER_OPTIONS "--compiler-check-final=true") + if(PANDA_LLVM_AOT) + set(STDLIB_PAOC_MODE "llvm") + set(COMPILER_OPTIONS "--compiler-check-final=true" "--llvm-gc-check=true" "--llvm-pre-opt=2") + if (NOT PANDA_ENABLE_THREAD_SANITIZER) + set(COMPILER_OPTIONS ${COMPILER_OPTIONS} "--llvmaot-threads=4" "--llvmaot-methods-per-module=512") + endif() + else() + set(STDLIB_PAOC_MODE "aot") + set(COMPILER_OPTIONS "--compiler-check-final=true") + endif() add_custom_target(ets-compile-stdlib-default COMMENT "Running ark_aot compilation for etsstdlib with default options" - COMMAND ${CMAKE_SOURCE_DIR}/plugins/ets/compiler/tools/paoc_compile_stdlib.sh --prefix="${PANDA_RUN_PREFIX}" --binary-dir=${CMAKE_BINARY_DIR} -compiler-options="${COMPILER_OPTIONS}" -paoc-output=${CMAKE_CURRENT_BINARY_DIR}/etsstdlib.an + COMMAND ${CMAKE_SOURCE_DIR}/plugins/ets/compiler/tools/paoc_compile_stdlib.sh --prefix="${PANDA_RUN_PREFIX}" --binary-dir=${CMAKE_BINARY_DIR} -compiler-options="${COMPILER_OPTIONS}" --paoc-mode=${STDLIB_PAOC_MODE} -paoc-output=${CMAKE_CURRENT_BINARY_DIR}/etsstdlib.an DEPENDS ark_aot etsstdlib ) endif() diff --git a/static_core/plugins/ets/tests/CMakeLists.txt b/static_core/plugins/ets/tests/CMakeLists.txt index e5e1ddaa8..a738b060b 100644 --- a/static_core/plugins/ets/tests/CMakeLists.txt +++ b/static_core/plugins/ets/tests/CMakeLists.txt @@ -432,51 +432,32 @@ endfunction() set (COMPILER_OPTIONS_OSR "--compiler-ignore-failures=true" ${COMPILER_OPTIONS}) function(compile_stdlib TARGET_ARCH) - add_custom_target(ets-compile-stdlib-aot-${TARGET_ARCH} - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with default options" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=aot -compiler-options="${COMPILER_OPTIONS}" -paoc-output=etsstdlib_aot_${TARGET_ARCH}.an - DEPENDS ark_aot etsstdlib - ) - add_custom_target(ets-compile-stdlib-jit-${TARGET_ARCH} - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with jit mode" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=jit -compiler-options="${COMPILER_OPTIONS}" -paoc-output=etsstdlib_jit_${TARGET_ARCH}.an - DEPENDS ark_aot etsstdlib - ) - add_custom_target(ets-compile-stdlib-aot-${TARGET_ARCH}-no-inline - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} without inlining" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=aot -compiler-options="${COMPILER_OPTIONS_NO_INLINE}" -paoc-output=etsstdlib_aot_${TARGET_ARCH}_no_inline.an - DEPENDS ark_aot etsstdlib - ) - add_custom_target(ets-compile-stdlib-aot-${TARGET_ARCH}-stw - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with gc stw" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=aot -compiler-options="${COMPILER_OPTIONS_GC_STW}" -paoc-output=etsstdlib_aot_${TARGET_ARCH}_stw.an - DEPENDS ark_aot etsstdlib - ) - add_dependencies(ets-compile-stdlib ets-compile-stdlib-aot-${TARGET_ARCH} ets-compile-stdlib-jit-${TARGET_ARCH} ets-compile-stdlib-aot-${TARGET_ARCH}-no-inline ets-compile-stdlib-aot-${TARGET_ARCH}-stw) if (PANDA_LLVM_AOT) - add_custom_target(ets-compile-stdlib-llvm-${TARGET_ARCH} - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with llvm" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS_LLVM}" -paoc-output=etsstdlib_llvmaot_${TARGET_ARCH}.an + add_custom_target(ets-compile-stdlib-llvmaot-${TARGET_ARCH} + COMMENT "Running LLVMAOT compilation for etsstdlib for ${TARGET_ARCH}" + COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS}" -paoc-output=etsstdlib_llvmaot_${TARGET_ARCH}.an DEPENDS ark_aot etsstdlib ) - add_custom_target(ets-compile-stdlib-llvm-pre-opt-2-${TARGET_ARCH} - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with llvm pre-opt" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS_LLVM_PRE_OPT}" -paoc-output=etsstdlib_llvmaot_pre_opt_2_${TARGET_ARCH}.an + add_custom_target(ets-compile-stdlib-llvmaot-${TARGET_ARCH}-no-inline + COMMENT "Running LLVMAOT compilation for etsstdlib for ${TARGET_ARCH} without inlining" + COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS_NO_INLINE}" -paoc-output=etsstdlib_llvmaot_${TARGET_ARCH}_no_inline.an DEPENDS ark_aot etsstdlib ) - add_dependencies( - ets-compile-stdlib - ets-compile-stdlib-llvm-${TARGET_ARCH} - ets-compile-stdlib-llvm-pre-opt-2-${TARGET_ARCH} + add_custom_target(ets-compile-stdlib-llvmaot-${TARGET_ARCH}-no-pre-opt + COMMENT "Running LLVMAOT compilation for etsstdlib for ${TARGET_ARCH} with llvm without pre-opt" + COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS_NO_PRE_OPT}" -paoc-output=etsstdlib_llvmaot_${TARGET_ARCH}_no_pre_opt.an + DEPENDS ark_aot etsstdlib ) - endif() - if (TARGET_ARCH STREQUAL "arm64") - add_custom_target(ets-compile-stdlib-osr-${TARGET_ARCH} - COMMENT "Running ark_aot compilation for etsstdlib for ${TARGET_ARCH} with osr mode" - COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=osr -compiler-options="${COMPILER_OPTIONS_OSR}" -paoc-output=etsstdlib_osr_${TARGET_ARCH}.an + add_custom_target(ets-compile-stdlib-llvmaot-${TARGET_ARCH}-stw + COMMENT "Running LLVMAOT compilation for etsstdlib for ${TARGET_ARCH} with gc stw" + COMMAND ${ARK_AOT_RUNNER} --binary-dir=${CMAKE_BINARY_DIR} --target-arch=${TARGET_ARCH} --paoc-mode=llvm -compiler-options="${COMPILER_OPTIONS_GC_STW}" -paoc-output=etsstdlib_llvmaot_${TARGET_ARCH}_stw.an DEPENDS ark_aot etsstdlib ) - add_dependencies(ets-compile-stdlib ets-compile-stdlib-osr-${TARGET_ARCH}) + add_dependencies(ets-compile-stdlib + ets-compile-stdlib-llvmaot-${TARGET_ARCH} + ets-compile-stdlib-llvmaot-${TARGET_ARCH}-no-inline + ets-compile-stdlib-llvmaot-${TARGET_ARCH}-no-pre-opt + ets-compile-stdlib-llvmaot-${TARGET_ARCH}-stw) endif() endfunction() @@ -495,23 +476,13 @@ endif() if(PANDA_TEST_COMPILE_STDLIB) set (ARK_AOT_RUNNER ${CMAKE_SOURCE_DIR}/plugins/ets/compiler/tools/paoc_compile_stdlib.sh) - if (NOT PANDA_CI_TESTING_MODE STREQUAL "Nightly") - set (COMPILER_OPTIONS "--compiler-check-final=true") - if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set (COMPILER_OPTIONS ${COMPILER_OPTIONS} "--compiler-inst-graph-coloring-limit=2000") - endif() + set (COMPILER_OPTIONS "--compiler-check-final=true" "--llvm-gc-check=true" "--llvm-pre-opt=2") + if (NOT PANDA_ENABLE_THREAD_SANITIZER) + set (COMPILER_OPTIONS ${COMPILER_OPTIONS} "--llvmaot-threads=4" "--llvmaot-methods-per-module=512") endif() set (COMPILER_OPTIONS_NO_INLINE "--compiler-inlining=false" ${COMPILER_OPTIONS}) set (COMPILER_OPTIONS_GC_STW "--gc-type=stw" ${COMPILER_OPTIONS}) - if (PANDA_LLVM_AOT) - set (COMPILER_OPTIONS_LLVM ${COMPILER_OPTIONS}) - set (COMPILER_OPTIONS_LLVM_PRE_OPT "--llvm-pre-opt=2" ${COMPILER_OPTIONS}) - # NOTE(zdenis): False positives come from libLLVM.so - if (NOT PANDA_ENABLE_THREAD_SANITIZER) - set (COMPILER_OPTIONS_LLVM "--llvmaot-threads=4" "--llvmaot-methods-per-module=512" ${COMPILER_OPTIONS_LLVM}) - set (COMPILER_OPTIONS_LLVM_PRE_OPT "--llvmaot-threads=4" "--llvmaot-methods-per-module=512" ${COMPILER_OPTIONS_LLVM_PRE_OPT}) - endif() - endif () + set (COMPILER_OPTIONS_NO_PRE_OPT ${COMPILER_OPTIONS} "--llvm-pre-opt=0") add_custom_target(ets-compile-stdlib) if (PANDA_COMPILER_TARGET_X86_64) compile_stdlib(x86_64) -- Gitee From 42a65922949d66d283b19ea702680469024bb0bd Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Thu, 26 Sep 2024 18:43:07 +0300 Subject: [PATCH 12/21] [CI] Enable libllvmbackend in "Panda SDK" builds --- static_core/scripts/sdk/build_sdk_lib | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/static_core/scripts/sdk/build_sdk_lib b/static_core/scripts/sdk/build_sdk_lib index b6589851a..f207fed2a 100644 --- a/static_core/scripts/sdk/build_sdk_lib +++ b/static_core/scripts/sdk/build_sdk_lib @@ -26,7 +26,7 @@ function build_panda() { COMMONS_CMAKE_ARGS="\ -GNinja \ -S$ARK_ROOT \ - -DCMAKE_BUILD_TYPE=$PANDA_SDK_BUILD_TYPE \ + -DCMAKE_BUILD_TYPE=${PANDA_SDK_BUILD_TYPE} \ -DPANDA_PRODUCT_BUILD=$product_build \ -DPANDA_WITH_ECMASCRIPT=ON \ -DPANDA_WITH_ETS=ON \ @@ -77,7 +77,10 @@ function linux_tools() { -DPANDA_CROSS_AARCH64_TOOLCHAIN_FILE=cmake/toolchain/cross-ohos-musl-aarch64.cmake \ -DTOOLCHAIN_SYSROOT=$OHOS_SDK_NATIVE/sysroot \ -DTOOLCHAIN_CLANG_ROOT=$OHOS_SDK_NATIVE/llvm \ - -DPANDA_WITH_ECMASCRIPT=ON" + -DPANDA_WITH_ECMASCRIPT=ON \ + -DPANDA_LLVM_BACKEND=ON \ + -DLLVM_TARGET_PATH=/opt/llvm-15-${PANDA_SDK_BUILD_TYPE,,}-x86_64" + local linux_build_targets="ark ark_aot ark_disasm ark_link es2panda e2p_test_plugin etsnative" build_panda "$linux_build_dir" "$linux_cmake_args" "$linux_build_targets" copy_into_sdk "$linux_build_dir" "$PANDA_SDK_PATH/linux_host_tools" "$SCRIPT_DIR"/linux_host_tools.txt @@ -101,7 +104,11 @@ function ohos() { -DTOOLCHAIN_SYSROOT=$OHOS_SDK_NATIVE/sysroot \ -DTOOLCHAIN_CLANG_ROOT=$OHOS_SDK_NATIVE/llvm \ -DPANDA_ETS_INTEROP_JS=ON \ - -DPANDA_WITH_ECMASCRIPT=ON" + -DPANDA_WITH_ECMASCRIPT=ON \ + -DPANDA_LLVM_BACKEND=ON \ + -DLLVM_HOST_PATH=/opt/llvm-15-${PANDA_SDK_BUILD_TYPE,,}-x86_64 \ + -DLLVM_TARGET_PATH=/opt/llvm-15-release-ohos" + local ohos_build_targets="ark ark_aot arkruntime arkassembler ets_interop_js_napi e2p_test_plugin etsnative" build_panda "$ohos_build_dir" "$target_cmake_args" "$ohos_build_targets" copy_into_sdk "$ohos_build_dir" "$taget_sdk_dir" "$SCRIPT_DIR"/ohos_arm64.txt -- Gitee From 765ec9d4ffdf11ce9e506b1566840b52f623f5f1 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Fri, 27 Sep 2024 13:53:48 +0300 Subject: [PATCH 13/21] [CI] cts-generator: add arm64-host and llvm-irtoc runs --- static_core/tests/CMakeLists.txt | 3 ++ .../tests/cts-generator/CMakeLists.txt | 29 +------------------ 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/static_core/tests/CMakeLists.txt b/static_core/tests/CMakeLists.txt index aa236767b..697a203d1 100644 --- a/static_core/tests/CMakeLists.txt +++ b/static_core/tests/CMakeLists.txt @@ -31,6 +31,9 @@ add_dependencies(irtoc-interpreter-tests irtoc-opcode-suite) if(NOT PANDA_TARGET_AMD64 OR PANDA_TARGET_WINDOWS) add_dependencies(core_tests cts-assembly regression) add_subdirectory(cts-coverage-tool) + if(PANDA_TARGET_ARM64 AND NOT CMAKE_CROSSCOMPILING) + add_subdirectory(cts-generator) + endif() else() add_custom_target(verifier-tests COMMENT "Regression tests for verifier") add_dependencies(core_tests cts-assembly regression verifier-tests) diff --git a/static_core/tests/cts-generator/CMakeLists.txt b/static_core/tests/cts-generator/CMakeLists.txt index 92b74363c..aba30003c 100644 --- a/static_core/tests/cts-generator/CMakeLists.txt +++ b/static_core/tests/cts-generator/CMakeLists.txt @@ -157,19 +157,7 @@ if(NOT CMAKE_CROSSCOMPILING) -p "${PROJECT_BINARY_DIR}/../../" -x "${CTS_TEMP_DIR}" -v 1 - ${QUICKENER_ARGLAUNCH} - --global-timeout ${PANDA_CTS_TESTING_TIMEOUT} - --timeout ${PANDA_CTS_TEST_TIMEOUT} - -j ${PANDA_CTS_JOBS_NUMBER} - --verifier-config "${PROJECT_BINARY_DIR}/verifier.config" - ${CTS_TEST_PRLIMIT_OPTIONS} - ${CTS_TEST_SELECT_OPTION_ARGS} VERBATIM - COMMAND ${CTS_TEST_RUNNER} - -t "${CTS_GENERATED_DIR}" - -p "${PROJECT_BINARY_DIR}/../../" - -x "${CTS_TEMP_DIR}" - -v 1 - -o "--interpreter-type=cpp" + -o "--compiler-enable-jit=false" ${QUICKENER_ARGLAUNCH} --global-timeout ${PANDA_CTS_TESTING_TIMEOUT} --timeout ${PANDA_CTS_TEST_TIMEOUT} @@ -178,21 +166,6 @@ if(NOT CMAKE_CROSSCOMPILING) ${CTS_TEST_PRLIMIT_OPTIONS} --exclude-tag verifier ${CTS_TEST_SELECT_OPTION_ARGS} VERBATIM - COMMAND ${CTS_TEST_RUNNER} - -t "${CTS_GENERATED_DIR}" - -p "${PROJECT_BINARY_DIR}/../../" - -x "${CTS_TEMP_DIR}" - -v 1 - ${QUICKENER_ARGLAUNCH} - --global-timeout ${PANDA_CTS_TESTING_TIMEOUT} - --timeout ${PANDA_CTS_TEST_TIMEOUT} - -j ${PANDA_CTS_JOBS_NUMBER} - --verifier-config "${PROJECT_BINARY_DIR}/verifier.config" - -o "--compiler-hotness-threshold=0" - -o "--no-async-jit" - ${CTS_TEST_PRLIMIT_OPTIONS} - --exclude-tag verifier - ${CTS_TEST_SELECT_OPTION_JIT_ARGS} VERBATIM DEPENDS "$" "$" "${TARGETFILE_ARKQUICK}" "$" "${OUTPUT_FILES}" ) -- Gitee From 86092b90c7208c269a5e6c45a0b2cfb0181cf2f3 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Fri, 27 Sep 2024 16:17:32 +0300 Subject: [PATCH 14/21] [CI] Add 'expr_5.sts' to AOT ignore lists --- .../test-lists/ets-cts/ets-cts-ignored-AMD64-AOT.txt | 3 +++ .../test-lists/ets-cts/ets-cts-ignored-ARM64-AOT.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-AMD64-AOT.txt b/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-AMD64-AOT.txt index 4874bc64f..138b0a14b 100644 --- a/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-AMD64-AOT.txt +++ b/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-AMD64-AOT.txt @@ -1,3 +1,6 @@ +# LLVM AOT removes unused allocation +17.experimental_features/02.array_creation_expressions/01.runtime_evaluation_of_array_creation_expressions/expr_5.sts + # 17881 Skip these, because the run fails if multiple files are connected. The connection is necessary, because of the export tests. 13.compilation_units_packages_and_modules/04.import_directives/05.type_import_binding/type_binding_class.sts 13.compilation_units_packages_and_modules/04.import_directives/05.type_import_binding/type_binding_class_alias.sts diff --git a/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-ARM64-AOT.txt b/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-ARM64-AOT.txt index 4874bc64f..138b0a14b 100644 --- a/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-ARM64-AOT.txt +++ b/static_core/tests/tests-u-runner/test-lists/ets-cts/ets-cts-ignored-ARM64-AOT.txt @@ -1,3 +1,6 @@ +# LLVM AOT removes unused allocation +17.experimental_features/02.array_creation_expressions/01.runtime_evaluation_of_array_creation_expressions/expr_5.sts + # 17881 Skip these, because the run fails if multiple files are connected. The connection is necessary, because of the export tests. 13.compilation_units_packages_and_modules/04.import_directives/05.type_import_binding/type_binding_class.sts 13.compilation_units_packages_and_modules/04.import_directives/05.type_import_binding/type_binding_class_alias.sts -- Gitee From 2d9454afb14a48a78f4ae6026e19b4cc2a25e7dc Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Tue, 24 Sep 2024 18:55:49 +0300 Subject: [PATCH 15/21] Dump method name with signature --- static_core/compiler/tools/paoc/paoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static_core/compiler/tools/paoc/paoc.cpp b/static_core/compiler/tools/paoc/paoc.cpp index e1b025265..57b0a4aef 100644 --- a/static_core/compiler/tools/paoc/paoc.cpp +++ b/static_core/compiler/tools/paoc/paoc.cpp @@ -64,7 +64,7 @@ void Paoc::CompilingContext::DumpStatistics() const { ASSERT(stats); char sep = ','; - *stats << method->GetFullName() << sep; + *stats << '"' << method->GetFullName(true) << '"' << sep; *stats << "paoc-summary" << sep; *stats << allocator.GetAllocatedSize() << sep; *stats << graphLocalAllocator.GetAllocatedSize() << '\n'; -- Gitee From a4e8bbc5dc35f8f374c4c8fddf25ea6c0226cb49 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Tue, 24 Sep 2024 18:14:18 +0300 Subject: [PATCH 16/21] Detect missing llvm_codegen_func --- static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index f5282dc3f..987655aeb 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -4421,6 +4421,7 @@ void LLVMIrConstructor::VisitIntrinsic(GraphVisitor *v, Inst *inst) return; } } + ASSERT(!EncodesBuiltin(ctor->GetGraph()->GetRuntime(), entryId, ctor->GetGraph()->GetArch())); // Create call otherwise auto result = ctor->CreateIntrinsicCall(inst); if (inst->GetType() != DataType::VOID) { -- Gitee From 790ba66b3bd66431205eb1a7ce13b245b692b2ac Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Fri, 11 Oct 2024 20:02:04 +0300 Subject: [PATCH 17/21] Passes headers --- .../transforms/passes/aarch64_fixup_sdiv.h | 5 ++--- .../passes/ark_frame_lowering/frame_builder.h | 2 +- .../passes/ark_frame_lowering/frame_lowering.h | 2 +- .../libllvmbackend/transforms/passes/ark_gvn.h | 4 ++-- .../libllvmbackend/transforms/passes/ark_inlining.h | 6 +++--- .../transforms/passes/ark_speculation.h | 2 +- .../libllvmbackend/transforms/passes/check_external.h | 2 +- .../transforms/passes/check_tail_calls.h | 2 +- static_core/libllvmbackend/transforms/passes/devirt.h | 4 ++-- .../libllvmbackend/transforms/passes/expand_atomics.h | 2 +- .../libllvmbackend/transforms/passes/fixup_poisons.h | 2 +- .../libllvmbackend/transforms/passes/gc_intrusion.h | 4 ++-- .../transforms/passes/gc_intrusion_check.h | 4 ++-- .../transforms/passes/gep_propagation.h | 4 ++-- .../libllvmbackend/transforms/passes/infer_flags.cpp | 5 ----- .../libllvmbackend/transforms/passes/infer_flags.h | 11 +++++------ .../libllvmbackend/transforms/passes/inline_devirt.h | 8 ++++---- .../passes/inline_ir/cleanup_inline_module.h | 2 +- .../passes/inline_ir/discard_inline_module.cpp | 5 ----- .../passes/inline_ir/discard_inline_module.h | 7 +++++-- .../transforms/passes/inline_ir/mark_always_inline.h | 2 +- .../transforms/passes/inline_ir/mark_inline_module.h | 2 +- .../passes/inline_ir/remove_unused_functions.h | 2 +- .../transforms/passes/insert_safepoints.h | 8 ++------ .../transforms/passes/intrinsics_lowering.h | 5 ++--- .../libllvmbackend/transforms/passes/loop_peeling.cpp | 4 ---- .../libllvmbackend/transforms/passes/loop_peeling.h | 7 +++++-- .../libllvmbackend/transforms/passes/mem_barriers.cpp | 3 +-- .../libllvmbackend/transforms/passes/mem_barriers.h | 4 ++-- .../transforms/passes/panda_runtime_lowering.h | 7 +++---- .../transforms/passes/propagate_lenarray.cpp | 5 ----- .../transforms/passes/propagate_lenarray.h | 5 ++++- .../libllvmbackend/transforms/passes/prune_deopt.h | 4 ++-- 33 files changed, 61 insertions(+), 80 deletions(-) diff --git a/static_core/libllvmbackend/transforms/passes/aarch64_fixup_sdiv.h b/static_core/libllvmbackend/transforms/passes/aarch64_fixup_sdiv.h index 9f0624444..8587375bb 100644 --- a/static_core/libllvmbackend/transforms/passes/aarch64_fixup_sdiv.h +++ b/static_core/libllvmbackend/transforms/passes/aarch64_fixup_sdiv.h @@ -31,10 +31,9 @@ public: explicit AArch64FixupSDiv(LLVMArkInterface *arkInterface = nullptr); - static AArch64FixupSDiv Create(LLVMArkInterface *arkInterface, - const ark::llvmbackend::LLVMCompilerOptions *options); + static AArch64FixupSDiv Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } diff --git a/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_builder.h b/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_builder.h index db60c0223..57a98faca 100644 --- a/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_builder.h +++ b/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_builder.h @@ -115,4 +115,4 @@ private: std::string_view asmPairRegs, ssize_t calleeOffset); }; -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_FRAME_LOWERING_FRAME_BUILDER_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_FRAME_LOWERING_FRAME_BUILDER_H diff --git a/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_lowering.h b/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_lowering.h index 196315037..091af4d2c 100644 --- a/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_lowering.h +++ b/static_core/libllvmbackend/transforms/passes/ark_frame_lowering/frame_lowering.h @@ -27,4 +27,4 @@ class LLVMArkInterface; llvm::MachineFunctionPass *CreateFrameLoweringPass(LLVMArkInterface *arkInterface); } // namespace ark::llvmbackend -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_FRAME_LOWERING_FRAME_LOWERING_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_FRAME_LOWERING_FRAME_LOWERING_H diff --git a/static_core/libllvmbackend/transforms/passes/ark_gvn.h b/static_core/libllvmbackend/transforms/passes/ark_gvn.h index 6cd42904a..a2516a416 100644 --- a/static_core/libllvmbackend/transforms/passes/ark_gvn.h +++ b/static_core/libllvmbackend/transforms/passes/ark_gvn.h @@ -36,11 +36,11 @@ class ArkGVN : public llvm::PassInfoMixin { public: explicit ArkGVN(LLVMArkInterface *arkInterface = nullptr); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } - static ArkGVN Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + static ArkGVN Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); diff --git a/static_core/libllvmbackend/transforms/passes/ark_inlining.h b/static_core/libllvmbackend/transforms/passes/ark_inlining.h index c67ebd57f..0391498f6 100644 --- a/static_core/libllvmbackend/transforms/passes/ark_inlining.h +++ b/static_core/libllvmbackend/transforms/passes/ark_inlining.h @@ -34,7 +34,7 @@ class IrtocInlineChecker : public llvm::PassInfoMixin { public: static constexpr llvm::StringRef ARG_NAME = "irtoc-inline-check"; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); void CheckShouldInline(llvm::CallBase *callBase); // NOLINTNEXTLINE(readability-identifier-naming) @@ -49,8 +49,8 @@ public: static constexpr llvm::StringRef ARG_NAME = "inline-prepare"; explicit InlinePrepare(llvm::InlineParams inlineParams) : inlineParams_ {inlineParams} {} - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); - static InlinePrepare Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); + static InlinePrepare Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &moduleAm); diff --git a/static_core/libllvmbackend/transforms/passes/ark_speculation.h b/static_core/libllvmbackend/transforms/passes/ark_speculation.h index 112f9104c..e7d06dd21 100644 --- a/static_core/libllvmbackend/transforms/passes/ark_speculation.h +++ b/static_core/libllvmbackend/transforms/passes/ark_speculation.h @@ -32,7 +32,7 @@ public: static constexpr llvm::StringRef ARG_NAME = "wrap-speculative-execution"; explicit ArkSpeculativeExecution() : llvm::SpeculativeExecutionPass(ONLY_IF_DIVERGENT_TARGET) {} - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } diff --git a/static_core/libllvmbackend/transforms/passes/check_external.h b/static_core/libllvmbackend/transforms/passes/check_external.h index c599cf8e8..4706ec9e8 100644 --- a/static_core/libllvmbackend/transforms/passes/check_external.h +++ b/static_core/libllvmbackend/transforms/passes/check_external.h @@ -33,7 +33,7 @@ class CheckExternal : public llvm::PassInfoMixin { public: explicit CheckExternal() = default; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); static CheckExternal Create(); diff --git a/static_core/libllvmbackend/transforms/passes/check_tail_calls.h b/static_core/libllvmbackend/transforms/passes/check_tail_calls.h index 9262ab3dd..c949f8371 100644 --- a/static_core/libllvmbackend/transforms/passes/check_tail_calls.h +++ b/static_core/libllvmbackend/transforms/passes/check_tail_calls.h @@ -26,4 +26,4 @@ namespace ark::llvmbackend { llvm::MachineFunctionPass *CreateCheckTailCallsPass(); } // namespace ark::llvmbackend -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_CHECK_TAIL_CALLS_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_CHECK_TAIL_CALLS_H diff --git a/static_core/libllvmbackend/transforms/passes/devirt.h b/static_core/libllvmbackend/transforms/passes/devirt.h index daabdfb69..d1db36422 100644 --- a/static_core/libllvmbackend/transforms/passes/devirt.h +++ b/static_core/libllvmbackend/transforms/passes/devirt.h @@ -38,9 +38,9 @@ class Devirt : public llvm::PassInfoMixin { public: explicit Devirt(LLVMArkInterface *arkInterface = nullptr); - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); - static Devirt Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + static Devirt Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); diff --git a/static_core/libllvmbackend/transforms/passes/expand_atomics.h b/static_core/libllvmbackend/transforms/passes/expand_atomics.h index b217ed558..92c27c71d 100644 --- a/static_core/libllvmbackend/transforms/passes/expand_atomics.h +++ b/static_core/libllvmbackend/transforms/passes/expand_atomics.h @@ -30,7 +30,7 @@ public: explicit ExpandAtomics(); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } diff --git a/static_core/libllvmbackend/transforms/passes/fixup_poisons.h b/static_core/libllvmbackend/transforms/passes/fixup_poisons.h index f5d7adb2b..63ae3ef7e 100644 --- a/static_core/libllvmbackend/transforms/passes/fixup_poisons.h +++ b/static_core/libllvmbackend/transforms/passes/fixup_poisons.h @@ -31,7 +31,7 @@ public: explicit FixupPoisons(); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } diff --git a/static_core/libllvmbackend/transforms/passes/gc_intrusion.h b/static_core/libllvmbackend/transforms/passes/gc_intrusion.h index e49795d03..ab5b0a566 100644 --- a/static_core/libllvmbackend/transforms/passes/gc_intrusion.h +++ b/static_core/libllvmbackend/transforms/passes/gc_intrusion.h @@ -30,7 +30,7 @@ class GcRefLiveness; class GcIntrusion : public llvm::PassInfoMixin { public: - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } @@ -96,4 +96,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_H diff --git a/static_core/libllvmbackend/transforms/passes/gc_intrusion_check.h b/static_core/libllvmbackend/transforms/passes/gc_intrusion_check.h index a01a1554e..f0e023eb7 100644 --- a/static_core/libllvmbackend/transforms/passes/gc_intrusion_check.h +++ b/static_core/libllvmbackend/transforms/passes/gc_intrusion_check.h @@ -33,7 +33,7 @@ class GcIntrusionCheck : public llvm::PassInfoMixin { public: static constexpr llvm::StringRef ARG_NAME = "gc-intrusion-check"; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); @@ -57,4 +57,4 @@ private: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_CHECK_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_CHECK_H diff --git a/static_core/libllvmbackend/transforms/passes/gep_propagation.h b/static_core/libllvmbackend/transforms/passes/gep_propagation.h index 1fa0421fd..ca3b9b162 100644 --- a/static_core/libllvmbackend/transforms/passes/gep_propagation.h +++ b/static_core/libllvmbackend/transforms/passes/gep_propagation.h @@ -31,7 +31,7 @@ namespace ark::llvmbackend::passes { class GepPropagation : public llvm::PassInfoMixin { public: - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } @@ -77,4 +77,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GEP_PROPAGATION_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GEP_PROPAGATION_H diff --git a/static_core/libllvmbackend/transforms/passes/infer_flags.cpp b/static_core/libllvmbackend/transforms/passes/infer_flags.cpp index 233642e57..99679c640 100644 --- a/static_core/libllvmbackend/transforms/passes/infer_flags.cpp +++ b/static_core/libllvmbackend/transforms/passes/infer_flags.cpp @@ -58,11 +58,6 @@ bool CanOverflow(const llvm::KnownBits &start, const llvm::KnownBits &step, uint namespace ark::llvmbackend::passes { -bool InferFlags::ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) -{ - return true; -} - llvm::PreservedAnalyses InferFlags::run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager) { LLVM_DEBUG(llvm::dbgs() << "Running on '" << function.getName() << "'\n"); diff --git a/static_core/libllvmbackend/transforms/passes/infer_flags.h b/static_core/libllvmbackend/transforms/passes/infer_flags.h index cee7c3784..3c196a808 100644 --- a/static_core/libllvmbackend/transforms/passes/infer_flags.h +++ b/static_core/libllvmbackend/transforms/passes/infer_flags.h @@ -24,10 +24,6 @@ namespace ark::llvmbackend { struct LLVMCompilerOptions; } // namespace ark::llvmbackend -namespace ark::llvmbackend { -class LLVMArkInterface; -} // namespace ark::llvmbackend - namespace ark::llvmbackend::passes { /// Simple pass, that infers "nsw" flag (no signed wrap) to help llvm perform optimizations @@ -35,7 +31,10 @@ class InferFlags : public llvm::PassInfoMixin { public: explicit InferFlags() = default; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) + { + return true; + } // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); @@ -51,4 +50,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INFER_FLAGS_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INFER_FLAGS_H diff --git a/static_core/libllvmbackend/transforms/passes/inline_devirt.h b/static_core/libllvmbackend/transforms/passes/inline_devirt.h index 74286c674..221efc544 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_devirt.h +++ b/static_core/libllvmbackend/transforms/passes/inline_devirt.h @@ -28,9 +28,9 @@ class InlineDevirt : public llvm::PassInfoMixin { public: explicit InlineDevirt(LLVMArkInterface *arkInterface = nullptr, bool doVirtualInline = true); - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); - static InlineDevirt Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + static InlineDevirt Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::LazyCallGraph::SCC &initialSCC, llvm::CGSCCAnalysisManager &analysisManager, @@ -52,8 +52,8 @@ public: private: bool RunInlining(llvm::InlinerPass &inlinePass, llvm::SmallPtrSetImpl &changedFunctions); - bool RunDevirt(ark::llvmbackend::passes::Devirt &devirtPass); - void RunCheckExternal(ark::llvmbackend::passes::CheckExternal &externalPass); + bool RunDevirt(Devirt &devirtPass); + void RunCheckExternal(CheckExternal &externalPass); }; } // namespace ark::llvmbackend::passes diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/cleanup_inline_module.h b/static_core/libllvmbackend/transforms/passes/inline_ir/cleanup_inline_module.h index 6a24a6210..90ac3d272 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/cleanup_inline_module.h +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/cleanup_inline_module.h @@ -38,7 +38,7 @@ public: ~CleanupInlineModule(); - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &analysis_manager); diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.cpp b/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.cpp index 92e84884b..0da26fc01 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.cpp +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.cpp @@ -31,11 +31,6 @@ using llvm::convertToDeclaration; namespace ark::llvmbackend::passes { -bool DiscardInlineModule::ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) -{ - return true; -} - /// Discard all functions and global variables from inline module llvm::PreservedAnalyses DiscardInlineModule::run(llvm::Module &module, llvm::ModuleAnalysisManager & /*AM*/) { diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.h b/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.h index b2b836ca2..9067f0dd1 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.h +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/discard_inline_module.h @@ -30,7 +30,10 @@ namespace ark::llvmbackend::passes { class DiscardInlineModule : public llvm::PassInfoMixin { public: - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) + { + return true; + } // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &analysis_manager); @@ -46,4 +49,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INLINE_IR_DISCARD_INLINE_MODULE_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INLINE_IR_DISCARD_INLINE_MODULE_H diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/mark_always_inline.h b/static_core/libllvmbackend/transforms/passes/inline_ir/mark_always_inline.h index 215263cf1..bb83a4087 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/mark_always_inline.h +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/mark_always_inline.h @@ -31,7 +31,7 @@ namespace ark::llvmbackend::passes { */ class MarkAlwaysInline : public llvm::PassInfoMixin { public: - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysis_manager); diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/mark_inline_module.h b/static_core/libllvmbackend/transforms/passes/inline_ir/mark_inline_module.h index 491ea8047..6c0c52f6a 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/mark_inline_module.h +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/mark_inline_module.h @@ -30,7 +30,7 @@ namespace ark::llvmbackend::passes { class MarkInlineModule : public llvm::PassInfoMixin { public: - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &analysis_manager); diff --git a/static_core/libllvmbackend/transforms/passes/inline_ir/remove_unused_functions.h b/static_core/libllvmbackend/transforms/passes/inline_ir/remove_unused_functions.h index 4ff01bbd8..9b4f42b3a 100644 --- a/static_core/libllvmbackend/transforms/passes/inline_ir/remove_unused_functions.h +++ b/static_core/libllvmbackend/transforms/passes/inline_ir/remove_unused_functions.h @@ -39,7 +39,7 @@ namespace ark::llvmbackend::passes { */ class RemoveUnusedFunctions : public llvm::PassInfoMixin { public: - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Module &module, llvm::ModuleAnalysisManager &analysis_manager); diff --git a/static_core/libllvmbackend/transforms/passes/insert_safepoints.h b/static_core/libllvmbackend/transforms/passes/insert_safepoints.h index 59e9c801d..7e45db00f 100644 --- a/static_core/libllvmbackend/transforms/passes/insert_safepoints.h +++ b/static_core/libllvmbackend/transforms/passes/insert_safepoints.h @@ -22,17 +22,13 @@ namespace ark::llvmbackend { struct LLVMCompilerOptions; } // namespace ark::llvmbackend -namespace ark::llvmbackend { -class LLVMArkInterface; -} // namespace ark::llvmbackend - namespace ark::llvmbackend::passes { class InsertSafepoints : public llvm::PassInfoMixin { public: explicit InsertSafepoints() = default; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert(const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); @@ -43,4 +39,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INSERT_SAFEPOINTS_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_INSERT_SAFEPOINTS_H diff --git a/static_core/libllvmbackend/transforms/passes/intrinsics_lowering.h b/static_core/libllvmbackend/transforms/passes/intrinsics_lowering.h index 4ea00f59b..4a64f8d6c 100644 --- a/static_core/libllvmbackend/transforms/passes/intrinsics_lowering.h +++ b/static_core/libllvmbackend/transforms/passes/intrinsics_lowering.h @@ -38,13 +38,12 @@ class IntrinsicsLowering : public llvm::PassInfoMixin { public: explicit IntrinsicsLowering(LLVMArkInterface *arkInterface = nullptr); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } - static IntrinsicsLowering Create(LLVMArkInterface *arkInterface, - const ark::llvmbackend::LLVMCompilerOptions *options); + static IntrinsicsLowering Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); diff --git a/static_core/libllvmbackend/transforms/passes/loop_peeling.cpp b/static_core/libllvmbackend/transforms/passes/loop_peeling.cpp index 433ed2e9c..f617fab11 100644 --- a/static_core/libllvmbackend/transforms/passes/loop_peeling.cpp +++ b/static_core/libllvmbackend/transforms/passes/loop_peeling.cpp @@ -68,8 +68,4 @@ bool ArkLoopPeeling::ContainsDeoptimize(llvm::Loop *loop) return false; } -bool ArkLoopPeeling::ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) -{ - return true; -} } // namespace ark::llvmbackend::passes diff --git a/static_core/libllvmbackend/transforms/passes/loop_peeling.h b/static_core/libllvmbackend/transforms/passes/loop_peeling.h index 1f12c37e9..9254a5cfb 100644 --- a/static_core/libllvmbackend/transforms/passes/loop_peeling.h +++ b/static_core/libllvmbackend/transforms/passes/loop_peeling.h @@ -39,7 +39,10 @@ public: explicit ArkLoopPeeling() = default; - static bool ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) + { + return true; + } private: bool ContainsDeoptimize(llvm::Loop *loop); @@ -50,4 +53,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_LOOP_PEELING_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_LOOP_PEELING_H diff --git a/static_core/libllvmbackend/transforms/passes/mem_barriers.cpp b/static_core/libllvmbackend/transforms/passes/mem_barriers.cpp index 765111a44..2e6996feb 100644 --- a/static_core/libllvmbackend/transforms/passes/mem_barriers.cpp +++ b/static_core/libllvmbackend/transforms/passes/mem_barriers.cpp @@ -29,8 +29,7 @@ using llvm::Instruction; namespace ark::llvmbackend::passes { -MemBarriers MemBarriers::Create([[maybe_unused]] LLVMArkInterface *arkInterface, - const ark::llvmbackend::LLVMCompilerOptions *options) +MemBarriers MemBarriers::Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options) { return MemBarriers(arkInterface, options->optimize); } diff --git a/static_core/libllvmbackend/transforms/passes/mem_barriers.h b/static_core/libllvmbackend/transforms/passes/mem_barriers.h index 2f25c88b6..29285d7d7 100644 --- a/static_core/libllvmbackend/transforms/passes/mem_barriers.h +++ b/static_core/libllvmbackend/transforms/passes/mem_barriers.h @@ -30,12 +30,12 @@ class MemBarriers : public llvm::PassInfoMixin { public: explicit MemBarriers(LLVMArkInterface *arkInterface, bool optimize); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } - static MemBarriers Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + static MemBarriers Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); diff --git a/static_core/libllvmbackend/transforms/passes/panda_runtime_lowering.h b/static_core/libllvmbackend/transforms/passes/panda_runtime_lowering.h index 26c7bebbd..51270d2f7 100644 --- a/static_core/libllvmbackend/transforms/passes/panda_runtime_lowering.h +++ b/static_core/libllvmbackend/transforms/passes/panda_runtime_lowering.h @@ -35,13 +35,12 @@ class PandaRuntimeLowering : public llvm::PassInfoMixin { public: explicit PandaRuntimeLowering(LLVMArkInterface *arkInterface = nullptr); - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } - static PandaRuntimeLowering Create(LLVMArkInterface *arkInterface, - const ark::llvmbackend::LLVMCompilerOptions *options); + static PandaRuntimeLowering Create(LLVMArkInterface *arkInterface, const LLVMCompilerOptions *options); // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &am); @@ -63,4 +62,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_PANDA_RUNTIME_LOWERING_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_PANDA_RUNTIME_LOWERING_H diff --git a/static_core/libllvmbackend/transforms/passes/propagate_lenarray.cpp b/static_core/libllvmbackend/transforms/passes/propagate_lenarray.cpp index 6bc06f189..5c1f907ed 100644 --- a/static_core/libllvmbackend/transforms/passes/propagate_lenarray.cpp +++ b/static_core/libllvmbackend/transforms/passes/propagate_lenarray.cpp @@ -33,11 +33,6 @@ namespace ark::llvmbackend::passes { -bool PropagateLenArray::ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) -{ - return true; -} - llvm::PreservedAnalyses PropagateLenArray::run(llvm::Function &function, [[maybe_unused]] llvm::FunctionAnalysisManager &analysisManager) { diff --git a/static_core/libllvmbackend/transforms/passes/propagate_lenarray.h b/static_core/libllvmbackend/transforms/passes/propagate_lenarray.h index 96635803c..4559aed61 100644 --- a/static_core/libllvmbackend/transforms/passes/propagate_lenarray.h +++ b/static_core/libllvmbackend/transforms/passes/propagate_lenarray.h @@ -31,7 +31,10 @@ public: explicit PropagateLenArray() = default; - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options); + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) + { + return true; + } // NOLINTNEXTLINE(readability-identifier-naming) llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); diff --git a/static_core/libllvmbackend/transforms/passes/prune_deopt.h b/static_core/libllvmbackend/transforms/passes/prune_deopt.h index 99b94278d..1692e6ba0 100644 --- a/static_core/libllvmbackend/transforms/passes/prune_deopt.h +++ b/static_core/libllvmbackend/transforms/passes/prune_deopt.h @@ -30,7 +30,7 @@ namespace ark::llvmbackend::passes { class PruneDeopt : public llvm::PassInfoMixin { public: - static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + static bool ShouldInsert([[maybe_unused]] const LLVMCompilerOptions *options) { return true; } @@ -59,4 +59,4 @@ public: } // namespace ark::llvmbackend::passes -#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_PRUNE_DEOPT_H +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_PRUNE_DEOPT_H -- Gitee From 7581473a90356759a92546d9119a6b3fc61f1812 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Sat, 2 Nov 2024 17:59:26 +0300 Subject: [PATCH 18/21] Fix 'CreateLaunchArgsArray' in LLVM AOT Make sure that llvm aot stores pointer to reference with zeroed high part of 64-bit args slot Signed-off-by: Denis Zavedeev --- static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index 987655aeb..08dd07812 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -1910,8 +1910,9 @@ llvm::Value *LLVMIrConstructor::CreateLaunchArgsArray(CallInst *callInst, uint32 auto typeSize = DataType::GetTypeSize(type, GetGraph()->GetArch()); if (typeSize < DataType::GetTypeSize(DataType::INT32, GetGraph()->GetArch())) { arg = CoerceValue(arg, type, DataType::INT32); + } else if (type == DataType::REFERENCE) { + arg = builder_.CreatePtrToInt(arg, builder_.getInt64Ty()); } - auto gep = builder_.CreateConstInBoundsGEP1_32(builder_.getInt64Ty(), callArgs, i); builder_.CreateStore(arg, gep); } -- Gitee From 5e7f984a393742e75652cd71fa53eb30438c3228 Mon Sep 17 00:00:00 2001 From: Denis Zavedeev Date: Thu, 31 Oct 2024 12:48:12 +0300 Subject: [PATCH 19/21] Introduce PreWrb FastPath wrapper Signed-off-by: Denis Zavedeev --- static_core/irtoc/scripts/gc.irt | 13 ++++ .../libllvmbackend/lowering/gc_barriers.cpp | 66 +++++++++++++++++-- .../libllvmbackend/lowering/gc_barriers.h | 2 +- .../lowering/llvm_ir_constructor.cpp | 6 +- .../templates/llvm_passes.inl.erb | 6 +- .../libllvmbackend/transforms/builtins.cpp | 3 +- static_core/libllvmbackend/utils.cpp | 16 +++++ static_core/libllvmbackend/utils.h | 1 + .../runtime/entrypoints/entrypoints.yaml | 8 +++ 9 files changed, 109 insertions(+), 12 deletions(-) diff --git a/static_core/irtoc/scripts/gc.irt b/static_core/irtoc/scripts/gc.irt index 36e010a1f..c748098b1 100644 --- a/static_core/irtoc/scripts/gc.irt +++ b/static_core/irtoc/scripts/gc.irt @@ -27,6 +27,19 @@ function(:EmptyPostWriteBarrier, ReturnVoid().void } +# wrapper over the PreWrb function to avoid +# the prologue bloating in the caller +function(:PreWrbInterposer, + params: {mem: 'ref'}, + mode: [:FastPath]) { + if Options.arch == :arm32 + Intrinsic(:UNREACHABLE).Terminator.void + next + end + Call(mem).Method("PreWrbFuncEntrypoint").void + ReturnVoid().void +} + def PostInterGenerationalBarrier(obj_num) if obj_num == 0 params = {mem: 'ref_uint'} diff --git a/static_core/libllvmbackend/lowering/gc_barriers.cpp b/static_core/libllvmbackend/lowering/gc_barriers.cpp index bab5986e7..c2c5c9387 100644 --- a/static_core/libllvmbackend/lowering/gc_barriers.cpp +++ b/static_core/libllvmbackend/lowering/gc_barriers.cpp @@ -19,6 +19,7 @@ #include "metadata.h" #include "transforms/builtins.h" #include "transforms/runtime_calls.h" +#include "utils.h" #include "compiler/optimizer/ir/basicblock.h" @@ -27,9 +28,66 @@ #include namespace ark::llvmbackend::gc_barriers { +namespace { +inline llvm::Function *GetOrDeclarePreWrbinterposer(llvm::FunctionType *functionType, llvm::Module *module) +{ + ASSERT(functionType != nullptr); + ASSERT(module != nullptr); + constexpr llvm::StringRef NAME = "PreWrbInterposer"; + + auto function = module->getFunction(NAME); + if (function != nullptr) { + ASSERT(function->doesNotThrow()); + ASSERT(function->getVisibility() == llvm::GlobalValue::ProtectedVisibility); + ASSERT(function->getCallingConv() == llvm::CallingConv::ArkFast1); + return function; + } + + function = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, NAME, module); + function->setDoesNotThrow(); + function->setVisibility(llvm::GlobalValue::ProtectedVisibility); + function->setSectionPrefix(NAME); + function->setCallingConv(llvm::CallingConv::ArkFast1); + + return function; +} + +void CreatePreWrbCall(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface, llvm::Value *threadRegValue, + llvm::Value *frameRegValue, llvm::LoadInst *entrypoint, llvm::Value *load) +{ + constexpr auto VAR_ARGS = true; + auto *func = builder->GetInsertBlock()->getParent(); + auto *module = func->getParent(); + auto *ptrType = builder->getPtrTy(); + auto *ptrGcType = builder->getPtrTy(LLVMArkInterface::GC_ADDR_SPACE); + auto *voidType = builder->getVoidTy(); + + if (!arkInterface->IsIrtocMode()) { + // AoT mode, call PreWrbEntrypoint + ASSERT(frameRegValue == nullptr); + auto *functionType = llvm::FunctionType::get(voidType, {ptrGcType}, !VAR_ARGS); + [[maybe_unused]] auto *call = builder->CreateCall(functionType, entrypoint, {load}); + ASSERT(call->getCallingConv() == llvm::CallingConv::C); + return; + } + if (frameRegValue != nullptr) { + ASSERT(utils::IsFastPath(func) || !arkInterface->IsArm64()); + auto *functionType = llvm::FunctionType::get(voidType, {ptrGcType, ptrType, ptrType}, !VAR_ARGS); + auto *callee = GetOrDeclarePreWrbinterposer(functionType, module); + auto *call = builder->CreateCall(callee, {load, threadRegValue, frameRegValue}); + call->setCallingConv(llvm::CallingConv::ArkFast1); + return; + } + ASSERT(arkInterface->IsArm64()); + auto *functionType = llvm::FunctionType::get(voidType, {ptrGcType, ptrType}, !VAR_ARGS); + auto *callee = GetOrDeclarePreWrbinterposer(functionType, module); + auto *call = builder->CreateCall(callee, {load, threadRegValue}); + call->setCallingConv(llvm::CallingConv::ArkFast1); +} +} // namespace void EmitPreWRB(llvm::IRBuilder<> *builder, llvm::Value *mem, bool isVolatileMem, llvm::BasicBlock *outBb, - LLVMArkInterface *arkInterface, llvm::Value *threadRegValue) + LLVMArkInterface *arkInterface, llvm::Value *threadRegValue, llvm::Value *frameRegValue) { auto func = builder->GetInsertBlock()->getParent(); auto module = func->getParent(); @@ -70,12 +128,8 @@ void EmitPreWRB(llvm::IRBuilder<> *builder, llvm::Value *mem, bool isVolatileMem // Call Runtime builder->SetInsertPoint(callRuntimeBb); - static constexpr auto VAR_ARGS = true; - auto functionType = - llvm::FunctionType::get(builder->getVoidTy(), {builder->getPtrTy(LLVMArkInterface::GC_ADDR_SPACE)}, !VAR_ARGS); - builder->CreateCall(functionType, entrypoint, {load}); + CreatePreWrbCall(builder, arkInterface, threadRegValue, frameRegValue, entrypoint, load); builder->CreateBr(outBb); - builder->SetInsertPoint(outBb); } diff --git a/static_core/libllvmbackend/lowering/gc_barriers.h b/static_core/libllvmbackend/lowering/gc_barriers.h index 5d8c70d65..639384831 100644 --- a/static_core/libllvmbackend/lowering/gc_barriers.h +++ b/static_core/libllvmbackend/lowering/gc_barriers.h @@ -24,7 +24,7 @@ class LLVMArkInterface; namespace ark::llvmbackend::gc_barriers { void EmitPreWRB(llvm::IRBuilder<> *builder, llvm::Value *mem, bool isVolatileMem, llvm::BasicBlock *outBb, - LLVMArkInterface *arkInterface, llvm::Value *threadRegValue); + LLVMArkInterface *arkInterface, llvm::Value *threadRegValue, llvm::Value *frameRegValue); void EmitPostWRB(llvm::IRBuilder<> *builder, llvm::Value *mem, llvm::Value *offset, llvm::Value *value, LLVMArkInterface *arkInterface, llvm::Value *threadRegValue, llvm::Value *frameRegValue); diff --git a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp index 08dd07812..a48930efd 100644 --- a/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp +++ b/static_core/libllvmbackend/lowering/llvm_ir_constructor.cpp @@ -2157,7 +2157,11 @@ void LLVMIrConstructor::CreatePreWRB(Inst *inst, llvm::Value *mem) } auto &ctx = func_->getContext(); auto outBb = llvm::BasicBlock::Create(ctx, CreateBasicBlockName(inst, "pre_wrb_out"), func_); - llvmbackend::gc_barriers::EmitPreWRB(&builder_, mem, isVolatile, outBb, arkInterface_, GetThreadRegValue()); + + bool needFrame = + arkInterface_->IsIrtocMode() && (GetGraph()->GetArch() == Arch::X86_64 || GetGraph()->GetMode().IsFastPath()); + auto frame = needFrame ? GetRealFrameRegValue() : nullptr; + llvmbackend::gc_barriers::EmitPreWRB(&builder_, mem, isVolatile, outBb, arkInterface_, GetThreadRegValue(), frame); } void LLVMIrConstructor::CreatePostWRB(Inst *inst, llvm::Value *mem, llvm::Value *offset, llvm::Value *value) diff --git a/static_core/libllvmbackend/templates/llvm_passes.inl.erb b/static_core/libllvmbackend/templates/llvm_passes.inl.erb index 75b0dba4b..6dbfc7969 100644 --- a/static_core/libllvmbackend/templates/llvm_passes.inl.erb +++ b/static_core/libllvmbackend/templates/llvm_passes.inl.erb @@ -40,7 +40,7 @@ public: bool ParseModulePasses(StringRef name, llvm::ModulePassManager &modulePm, const LLVMCompilerOptions &options); bool ParseFunctionPasses(StringRef name, llvm::FunctionPassManager &functionPm, const LLVMCompilerOptions &options); bool ParseSCCPasses(StringRef name, llvm::CGSCCPassManager &sccPm, const LLVMCompilerOptions &options); - bool ParseLoopPasses(StringRef name, llvm::LoopPassManager &sccPm, const LLVMCompilerOptions &options); + bool ParseLoopPasses(StringRef name, llvm::LoopPassManager &loopPm, const LLVMCompilerOptions &options); void RegisterParserCallbacks(llvm::PassBuilder &builder, const ark::llvmbackend::LLVMCompilerOptions &options) { @@ -57,8 +57,8 @@ public: return ParseSCCPasses(name, sccPm, options); }); builder.registerPipelineParsingCallback( - [&](StringRef name, llvm::LoopPassManager &sccPm, PipelineElements /*unused*/) -> bool { - return ParseLoopPasses(name, sccPm, options); + [&](StringRef name, llvm::LoopPassManager &loopPm, PipelineElements /*unused*/) -> bool { + return ParseLoopPasses(name, loopPm, options); }); } private: diff --git a/static_core/libllvmbackend/transforms/builtins.cpp b/static_core/libllvmbackend/transforms/builtins.cpp index ca1633a05..649170a48 100644 --- a/static_core/libllvmbackend/transforms/builtins.cpp +++ b/static_core/libllvmbackend/transforms/builtins.cpp @@ -177,7 +177,8 @@ llvm::Value *PreWRBHelper(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVM initialBb->back().eraseFromParent(); builder->SetInsertPoint(initialBb); auto threadRegValue = GetThreadRegValue(builder, arkInterface); - ark::llvmbackend::gc_barriers::EmitPreWRB(builder, mem, isVolatileMem, continuation, arkInterface, threadRegValue); + ark::llvmbackend::gc_barriers::EmitPreWRB(builder, mem, isVolatileMem, continuation, arkInterface, threadRegValue, + nullptr); return nullptr; } } // namespace diff --git a/static_core/libllvmbackend/utils.cpp b/static_core/libllvmbackend/utils.cpp index dc58a6314..6a52bdeb9 100644 --- a/static_core/libllvmbackend/utils.cpp +++ b/static_core/libllvmbackend/utils.cpp @@ -89,4 +89,20 @@ llvm::Value *CreateLoadMethodUsingVTable(llvm::Value *thiz, llvm::Function *call return builder->CreateLoad(builder->getPtrTy(), methodPtr); } +bool IsFastPath(llvm::Function *func) +{ + switch (func->getCallingConv()) { + case llvm::CallingConv::ArkFast0: + case llvm::CallingConv::ArkFast1: + case llvm::CallingConv::ArkFast2: + case llvm::CallingConv::ArkFast3: + case llvm::CallingConv::ArkFast4: + case llvm::CallingConv::ArkFast5: + case llvm::CallingConv::ArkFast6: + return true; + default: + return false; + } +} + } // namespace ark::llvmbackend::utils diff --git a/static_core/libllvmbackend/utils.h b/static_core/libllvmbackend/utils.h index f63ce60c4..0192e8f45 100644 --- a/static_core/libllvmbackend/utils.h +++ b/static_core/libllvmbackend/utils.h @@ -30,6 +30,7 @@ llvm::Value *CreateLoadClassFromObject(llvm::Value *object, llvm::IRBuilder<> *b ark::llvmbackend::LLVMArkInterface *arkInterface); llvm::Value *CreateLoadMethodUsingVTable(llvm::Value *thiz, llvm::Function *caller, size_t methodId, llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface); +bool IsFastPath(llvm::Function *func); } // namespace ark::llvmbackend::utils diff --git a/static_core/runtime/entrypoints/entrypoints.yaml b/static_core/runtime/entrypoints/entrypoints.yaml index f1d3c551f..67000f3b9 100644 --- a/static_core/runtime/entrypoints/entrypoints.yaml +++ b/static_core/runtime/entrypoints/entrypoints.yaml @@ -705,6 +705,14 @@ entrypoints: - void - ark::ObjectHeader* +- name: PreWrbInterposer # "bridge" to avoid generating the excessive prologue + entrypoint: PreWrbInterposer + bridge: none + properties: [irtoc] + signature: + - void + - ark::ObjectHeader* + - name: MonitorEnterOddSaved entrypoint: LockObjectSlowPathEntrypoint bridge: odd_saved -- Gitee From e2ac456cc8c1fdf60d6db7f6fe581ecaeec04d78 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Wed, 6 Nov 2024 11:49:23 +0300 Subject: [PATCH 20/21] Fix for check-tail-calls pass --- .../libllvmbackend/transforms/passes/check_tail_calls.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/static_core/libllvmbackend/transforms/passes/check_tail_calls.cpp b/static_core/libllvmbackend/transforms/passes/check_tail_calls.cpp index d5ac10ac3..ecac9d21c 100644 --- a/static_core/libllvmbackend/transforms/passes/check_tail_calls.cpp +++ b/static_core/libllvmbackend/transforms/passes/check_tail_calls.cpp @@ -117,6 +117,9 @@ public: [&instInfo](llvm::MachineInstr &term) { return instInfo->isTailCall(term); })) { return true; } + if (basicBlock->succ_empty()) { + return false; + } if (visitedBasicBlocks->contains(basicBlock)) { llvm::report_fatal_error("Cycle in CFG in '" + basicBlock->getParent()->getName() + "' prevents tail call check"); -- Gitee From 84da09b80a6022634c4b3794dfd0e681829959e3 Mon Sep 17 00:00:00 2001 From: Leonid Skvortsov Date: Thu, 7 Nov 2024 18:51:56 +0300 Subject: [PATCH 21/21] Sink alloc --- static_core/libllvmbackend/BUILD.gn | 1 + static_core/libllvmbackend/CMakeLists.txt | 1 + .../transforms/llvm_optimizer.cpp | 1 + .../transforms/passes/heap_alloc_sink.cpp | 600 ++++++++++++++++++ .../transforms/passes/heap_alloc_sink.h | 171 +++++ .../transforms/passes/passes.yaml | 6 + .../libllvmbackend/transforms/pipeline.cfg | 2 + .../plugins/ets/tests/checked/CMakeLists.txt | 2 + .../checked/ets_llvmaot_heap_alloc_sink.sts | 39 ++ .../ets_llvmaot_heap_alloc_sink_two.sts | 38 ++ 10 files changed, 861 insertions(+) create mode 100644 static_core/libllvmbackend/transforms/passes/heap_alloc_sink.cpp create mode 100644 static_core/libllvmbackend/transforms/passes/heap_alloc_sink.h create mode 100644 static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink.sts create mode 100644 static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink_two.sts diff --git a/static_core/libllvmbackend/BUILD.gn b/static_core/libllvmbackend/BUILD.gn index 395a68e96..1e1298c64 100644 --- a/static_core/libllvmbackend/BUILD.gn +++ b/static_core/libllvmbackend/BUILD.gn @@ -85,6 +85,7 @@ if (is_llvmbackend) { "transforms/passes/gep_propagation.cpp", "transforms/passes/infer_flags.cpp", "transforms/passes/inline_devirt.cpp", + "transforms/passes/heap_alloc_sink.cpp", "transforms/passes/inline_ir/cleanup_inline_module.cpp", "transforms/passes/inline_ir/discard_inline_module.cpp", "transforms/passes/inline_ir/inline_ir_utils.cpp", diff --git a/static_core/libllvmbackend/CMakeLists.txt b/static_core/libllvmbackend/CMakeLists.txt index 30c6db24d..f96f28f3f 100644 --- a/static_core/libllvmbackend/CMakeLists.txt +++ b/static_core/libllvmbackend/CMakeLists.txt @@ -74,6 +74,7 @@ set(SOURCES transforms/passes/panda_runtime_lowering.cpp transforms/passes/propagate_lenarray.cpp transforms/passes/prune_deopt.cpp + transforms/passes/heap_alloc_sink.cpp transforms/runtime_calls.cpp utils.cpp ) diff --git a/static_core/libllvmbackend/transforms/llvm_optimizer.cpp b/static_core/libllvmbackend/transforms/llvm_optimizer.cpp index 4bfdcc3f4..9ef729219 100644 --- a/static_core/libllvmbackend/transforms/llvm_optimizer.cpp +++ b/static_core/libllvmbackend/transforms/llvm_optimizer.cpp @@ -35,6 +35,7 @@ #include "passes/loop_peeling.h" #include "passes/propagate_lenarray.h" #include "passes/check_external.h" +#include "passes/heap_alloc_sink.h" #include "passes/inline_ir/cleanup_inline_module.h" #include "passes/inline_ir/discard_inline_module.h" diff --git a/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.cpp b/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.cpp new file mode 100644 index 000000000..f1f436bcd --- /dev/null +++ b/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.cpp @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "heap_alloc_sink.h" + +using llvm::AllocFnKind; +using llvm::Attribute; +using llvm::AttributeList; +using llvm::BasicBlock; +using llvm::CallBase; +using llvm::CallInst; +using llvm::DominatorTree; +using llvm::dyn_cast; +using llvm::Function; +using llvm::Instruction; +using llvm::isa; +using llvm::LLVMContext; +using llvm::Loop; +using llvm::LoopInfo; +using llvm::OperandBundleDef; +using llvm::OperandBundleUse; +using llvm::PHINode; +using llvm::Use; +using llvm::Value; + +namespace ark::llvmbackend::passes { +HeapAllocSink::HeapAllocSink(LLVMArkInterface *arkInterface) : arkInterface_ {arkInterface} {} + +HeapAllocSink HeapAllocSink::Create(LLVMArkInterface *arkInterface, + [[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) +{ + return HeapAllocSink(arkInterface); +} + +void HeapAllocSink::MoveAllocInsideBlock(CallInst *alloc, BasicBlock *blockForOpt) +{ + auto insertionPt = blockForOpt->getFirstInsertionPt(); + alloc->moveBefore(*blockForOpt, insertionPt); +} + +bool HeapAllocSink::IsLegalToMove(CallInst *alloc, BasicBlock *basicBlock, DominatorTree &dominatorTree) +{ + std::vector blocksToCheck; + for (const auto &user : alloc->users()) { + auto userInst = dyn_cast(user); + if (userInst != nullptr) { + if (isa(userInst)) { + auto phiNode = dyn_cast(userInst); + std::vector phiBlocksAccessAlloc = FindBasicBlocksAccessingAllocInPHINode(phiNode, alloc); + blocksToCheck.insert(blocksToCheck.end(), phiBlocksAccessAlloc.begin(), phiBlocksAccessAlloc.end()); + } else { + blocksToCheck.emplace_back(userInst->getParent()); + } + } + } + + if (basicBlock != alloc->getParent()) { + if (dominatorTree.dominates(basicBlock, alloc->getParent())) { + return false; + } + } + + for (const auto &basicBlockToCheck : blocksToCheck) { + if (not dominatorTree.dominates(basicBlock, basicBlockToCheck)) { + return false; + } + } + + for (const auto &operand : alloc->operands()) { + auto operandInst = dyn_cast(operand); + if (operandInst != nullptr) { + if (not dominatorTree.dominates(operandInst->getParent(), basicBlock)) { + return false; + } + } + } + + return true; +} + +std::vector HeapAllocSink::GetCallsWithHeapKind(Function &func, const AllocFnKind &allocFnKind) +{ + std::vector allocs; + for (BasicBlock &block : func) { + for (Instruction &inst : block) { + auto *callInst = dyn_cast(&inst); + if (callInst == nullptr) { + continue; + } + if (IsAllocKind(callInst, allocFnKind)) { + allocs.push_back(callInst); + } + } + } + + return allocs; +} + +bool HeapAllocSink::AttributesContainAllocKind(bool hasAllocKind, const AttributeList &attributes, + const AllocFnKind &allocFnKind) +{ + bool correctKind = false; + if (hasAllocKind) { + Attribute allocAttribute = attributes.getFnAttr(Attribute::AllocKind); + AllocFnKind kind = allocAttribute.getAllocKind(); + correctKind = ((static_cast(kind) & static_cast(allocFnKind)) != 0U); + } + + return correctKind; +} + +bool HeapAllocSink::IsAllocKind(const CallInst *callInst, const AllocFnKind &allocFnKind) +{ + Function *calledFunc = callInst->getCalledFunction(); + AttributeList funcAttributes = AttributeList(); + bool funcHasAllocKind = false; + if (calledFunc != nullptr) { + funcAttributes = calledFunc->getAttributes(); + funcHasAllocKind = funcAttributes.hasFnAttr(Attribute::AllocKind); + } + + AttributeList callInstAttributes = callInst->getAttributes(); + bool callInsthasAllocKind = callInstAttributes.hasFnAttr(Attribute::AllocKind); + + bool callInstIsAllocKind = AttributesContainAllocKind(callInsthasAllocKind, callInstAttributes, allocFnKind); + bool calledFuncIsAllocKind = AttributesContainAllocKind(funcHasAllocKind, funcAttributes, allocFnKind); + + return callInstIsAllocKind or calledFuncIsAllocKind; +} + +bool HeapAllocSink::BlockAccessAllocMemory(BasicBlock *block, CallInst *alloc) +{ + if (block == nullptr or alloc == nullptr) { + return false; + } + + for (const Instruction &inst : *block) { + for (size_t i = 0; i < inst.getNumOperands(); ++i) { + const Value *operandValue = inst.getOperand(i); + + if (operandValue == alloc) { + return true; + } + } + } + + return false; +} + +BasicBlock *HeapAllocSink::GetBasicBlockForOptForAlloc( + CallInst *alloc, LoopInfo &loopInfo, DominatorTree &dominatorTree, + const std::set &basicBlocksNotInLoop, + const std::set> &basicBlocksAndTheirLoopHeaders) +{ + BasicBlock *needOptBlock; + Loop *loopOfAlloc = loopInfo.getLoopFor(alloc->getParent()); + std::set availableBlocksForOpt = basicBlocksNotInLoop; + if (loopOfAlloc != nullptr) { + UpdateAvailableBlocksForOpt(loopOfAlloc, availableBlocksForOpt, basicBlocksAndTheirLoopHeaders); + } + needOptBlock = NeedOptimization(availableBlocksForOpt, alloc, dominatorTree); + + return needOptBlock; +} + +std::set> HeapAllocSink::GetAllocsAndBasicBlocksForOpt( + Function &func, const std::vector &allocs, LoopInfo &loopInfo, DominatorTree &dominatorTree) +{ + std::set basicBlocksNotInLoop; + std::set> basicBlocksAndTheirLoopHeaders; + + ClassifyBasicBlocks(func, basicBlocksNotInLoop, basicBlocksAndTheirLoopHeaders, loopInfo); + + std::set> canBeOptimizedSet; + + for (auto &alloc : allocs) { + BasicBlock *needOptBlock = GetBasicBlockForOptForAlloc(alloc, loopInfo, dominatorTree, basicBlocksNotInLoop, + basicBlocksAndTheirLoopHeaders); + if (needOptBlock != nullptr) { + auto pair = std::make_pair(alloc, needOptBlock); + canBeOptimizedSet.insert(pair); + } + } + + return canBeOptimizedSet; +} + +void HeapAllocSink::ClassifyBasicBlocks(Function &func, std::set &basicBlocksNotInLoop, + std::set> &basicBlocksAndTheirLoopHeaders, + LoopInfo &loopInfo) +{ + for (auto &basicBlock : func) { + auto *loop = loopInfo.getLoopFor(&basicBlock); + if (loop == nullptr) { + basicBlocksNotInLoop.insert(&basicBlock); + } else { + BasicBlock *headerOfLoop = loop->getHeader(); + basicBlocksAndTheirLoopHeaders.insert(std::make_pair(&basicBlock, headerOfLoop)); + } + } +} + +void HeapAllocSink::UpdateAvailableBlocksForOpt( + const Loop *loopOfAlloc, std::set &availableBlocksForOpt, + const std::set> &basicBlocksAndTheirLoopHeaders) +{ + BasicBlock *headerOfInitialLoop = loopOfAlloc->getHeader(); + for (const auto &basicBlockAndLoopHeader : basicBlocksAndTheirLoopHeaders) { + if (headerOfInitialLoop == basicBlockAndLoopHeader.second) { + availableBlocksForOpt.insert(basicBlockAndLoopHeader.first); + } + } +} + +BasicBlock *HeapAllocSink::NeedOptimization(const std::set &availableBlocksForOpt, CallInst *alloc, + DominatorTree &dominatorTree) +{ + BasicBlock *blockForOptimization = nullptr; + auto allocBasicBlock = alloc->getParent(); + + BasicBlock *potentialBlockForOpt = FindPotentialBlockForOpt(alloc, dominatorTree); + + bool dominatedByBlockForOpt = dominatorTree.dominates(alloc, potentialBlockForOpt); + + bool blockInAvailableBlocksForOpt = availableBlocksForOpt.find(potentialBlockForOpt) != availableBlocksForOpt.end(); + if ((potentialBlockForOpt != nullptr) and potentialBlockForOpt != allocBasicBlock and + blockInAvailableBlocksForOpt and dominatedByBlockForOpt) { + blockForOptimization = potentialBlockForOpt; + } + + return blockForOptimization; +} + +bool HeapAllocSink::TryToOptimize(const std::set> &canBeOptimizedSet, + DominatorTree &dominatorTree) +{ + bool changed = false; + for (const auto &[alloc, blockForOpt] : canBeOptimizedSet) { + if (IsLegalToMove(alloc, blockForOpt, dominatorTree)) { + MoveAllocInsideBlock(alloc, blockForOpt); + changed = true; + } + } + + return changed; +} + +BasicBlock *HeapAllocSink::FindPotentialBlockForOpt(CallInst *alloc, const DominatorTree &dominatorTree) +{ + BasicBlock *dominatingBasicBlock = nullptr; + for (const auto &user : alloc->users()) { + auto *currentUserInst = dyn_cast(user); + BasicBlock *currentUserBlock; + + if (isa(currentUserInst)) { + auto phiNode = dyn_cast(currentUserInst); + currentUserBlock = GetBasicBlockForOptForPHINode(phiNode, alloc, dominatorTree); + } else { + currentUserBlock = currentUserInst->getParent(); + } + + dominatingBasicBlock = LowestCommonAncestor(currentUserBlock, dominatingBasicBlock, dominatorTree); + } + + return dominatingBasicBlock; +} + +std::vector HeapAllocSink::FindBasicBlocksAccessingAllocInPHINode(PHINode *phiNode, CallInst *alloc) +{ + std::vector basicBlocksAllocAccess; + unsigned int numOfValues = phiNode->getNumIncomingValues(); + for (size_t i = 0; i < numOfValues; ++i) { + if (phiNode->getIncomingValue(i) == alloc) { + basicBlocksAllocAccess.emplace_back(phiNode->getIncomingBlock(i)); + } + } + + return basicBlocksAllocAccess; +} + +bool HeapAllocSink::DeoptBundleContainsValue(const OperandBundleDef &deoptBundle, const Value *allocValue) +{ + for (const Value *value : deoptBundle.inputs()) { + if (value == allocValue) { + return true; + } + } + + return false; +} + +BasicBlock *HeapAllocSink::GetBasicBlockForOptForPHINode(PHINode *phiNode, CallInst *alloc, + const DominatorTree &dominatorTree) +{ + BasicBlock *lowestCommonAncestor = nullptr; + std::vector basicBlocksAllocAccess = FindBasicBlocksAccessingAllocInPHINode(phiNode, alloc); + for (const auto &basicBlock : basicBlocksAllocAccess) { + lowestCommonAncestor = LowestCommonAncestor(basicBlock, lowestCommonAncestor, dominatorTree); + } + + return lowestCommonAncestor; +} + +BasicBlock *HeapAllocSink::LowestCommonAncestor(BasicBlock *newBasicBlock, BasicBlock *lowestCommonAncestor, + const DominatorTree &dominatorTree) +{ + if (lowestCommonAncestor == nullptr) { + lowestCommonAncestor = newBasicBlock; + } + BasicBlock *dominatingBasicBlock = dominatorTree.findNearestCommonDominator(newBasicBlock, lowestCommonAncestor); + + return dominatingBasicBlock; +} + +std::map> HeapAllocSink::GetCallsWithAllocInDeoptBundle( + const std::vector &allocs) +{ + std::map> bundlesWithAllocsMap; + + for (size_t i = 0; i < allocs.size(); ++i) { + auto alloc = allocs[i]; + for (const auto &user : alloc->users()) { + if (not isa(user)) { + continue; + } + auto currentUserCallInst = dyn_cast(user); + auto deoptBundle = currentUserCallInst->getOperandBundle(LLVMContext::OB_deopt); + if (not deoptBundle) { + continue; + } + + OperandBundleUse deoptBundleUse = deoptBundle.value(); + + OperandBundleDef deoptBundleDef = GetOperandBundleDefFromUse(deoptBundleUse); + if (DeoptBundleContainsValue(deoptBundleDef, alloc)) { + if (bundlesWithAllocsMap.find(currentUserCallInst) != bundlesWithAllocsMap.end()) { + bundlesWithAllocsMap[currentUserCallInst].emplace_back(i); + } else { + bundlesWithAllocsMap[currentUserCallInst] = {i}; + } + } + } + } + + return bundlesWithAllocsMap; +} + +void HeapAllocSink::RemoveAllocFromDeoptBundleForAllCalls( + std::map> &deoptBundlesToAllocMap, std::vector &allocs, + std::vector &oldDeoptBundles) +{ + for (auto &deoptBundleToAllocMap : deoptBundlesToAllocMap) { + std::set allocValues = GetAllocValuesFromIdxs(allocs, deoptBundleToAllocMap.second); + RemoveHeapAllocFromDeoptBundle(deoptBundleToAllocMap.first, allocValues, allocs, oldDeoptBundles); + } +} + +std::set HeapAllocSink::GetAllocValuesFromIdxs(const std::vector &allocs, + const std::vector &allocIdxs) +{ + std::set allocValues; + for (const auto &idx : allocIdxs) { + allocValues.insert((allocs[idx])); + } + + return allocValues; +} + +OperandBundleDef HeapAllocSink::GetNewDeoptBundleWithoutAllocs(const std::vector &deoptBundle, + const std::set &allocValues) +{ + std::vector bundleValuesWithoutAlloc; + + // NOTE: In deopt, bundle allocation is always at the VREG_VALUE index, + // there are three other indexes associated with this index in deopt bundle, + // VREG_IDX, VREG_TYPE, VREG_VALUE + // they need to be removed + constexpr size_t VREG_BUNDLE_SIZE = 3; + for (int i = deoptBundle.size() - 1; i >= 0; i--) { + Value *value = deoptBundle[i]; + if (allocValues.find(value) != allocValues.end()) { + i -= VREG_BUNDLE_SIZE - 1; + } else { + bundleValuesWithoutAlloc.push_back(value); + } + } + + std::reverse(bundleValuesWithoutAlloc.begin(), bundleValuesWithoutAlloc.end()); + OperandBundleDef newDeoptBundle("deopt", bundleValuesWithoutAlloc); + + return newDeoptBundle; +} + +CallBase *HeapAllocSink::ChangeDeoptBundle(CallInst *callInstWithDeoptBundle, const OperandBundleDef &newDeoptBundle) +{ + CallBase *tmpCall = + CallBase::removeOperandBundle(callInstWithDeoptBundle, LLVMContext::OB_deopt, callInstWithDeoptBundle); + + CallBase *newCall = + CallBase::addOperandBundle(tmpCall, LLVMContext::OB_deopt, newDeoptBundle, callInstWithDeoptBundle); + + newCall->copyMetadata(*callInstWithDeoptBundle); + + tmpCall->eraseFromParent(); + + return newCall; +} + +OperandBundleDef HeapAllocSink::GetOperandBundleDefFromUse(const OperandBundleUse &operandBundleUse) +{ + std::vector bundleValuesWithoutAlloc = GetDeoptVec(operandBundleUse); + for (Value *value : operandBundleUse.Inputs) { + bundleValuesWithoutAlloc.push_back(value); + } + OperandBundleDef newDeoptBundle("deopt", bundleValuesWithoutAlloc); + + return newDeoptBundle; +} + +void HeapAllocSink::UpdateVectorOfAllocs(std::vector &allAllocs, CallInst *oldCallNoLongerValid, + CallBase *newCallValid) +{ + auto oldCallInAllocsFound = std::find(allAllocs.begin(), allAllocs.end(), oldCallNoLongerValid); + if (oldCallInAllocsFound != allAllocs.end()) { + *oldCallInAllocsFound = dyn_cast(newCallValid); + } +} + +void HeapAllocSink::UpdateOldDeoptBundles(std::vector &oldDeoptBundles, + CallInst *oldCallNoLongerValid, CallBase *newCallValid) +{ + for (auto &callWithDeopt : oldDeoptBundles) { + auto newCall = dyn_cast(newCallValid); + if (callWithDeopt.callInst == oldCallNoLongerValid) { + callWithDeopt.callInst = newCall; + } + + for (auto &value : callWithDeopt.oldDeoptBundle) { + if (not isa(value)) { + continue; + } + + if (value == oldCallNoLongerValid) { + value = newCall; + } + } + } +} + +std::vector HeapAllocSink::GetDeoptVec(const OperandBundleUse &deoptBundle) +{ + std::vector bundleValues; + for (Value *value : deoptBundle.Inputs) { + bundleValues.push_back(value); + } + + return bundleValues; +} + +void HeapAllocSink::AddOldDeoptBundle(std::vector &oldDeoptBundles, + CallInst *oldInstWithDeoptBundle) +{ + bool found = false; + for (auto &callWithDeopt : oldDeoptBundles) { + if (callWithDeopt.callInst == oldInstWithDeoptBundle) { + found = true; + } + } + + if (not found) { + OperandBundleUse operandUse = oldInstWithDeoptBundle->getOperandBundle(LLVMContext::OB_deopt).value(); + std::vector deoptBundleVec = GetDeoptVec(operandUse); + + oldDeoptBundles.emplace_back(CallWithDeoptBundleWithAlocs(oldInstWithDeoptBundle, deoptBundleVec)); + } +} + +void HeapAllocSink::ReplaceOldCallWithNewOne(CallInst *oldCallNoLongerValid, CallBase *newCall) +{ + oldCallNoLongerValid->replaceAllUsesWith(newCall); + oldCallNoLongerValid->eraseFromParent(); +} + +void HeapAllocSink::RemoveHeapAllocFromDeoptBundle(CallInst *callInstWithDeoptBundle, + const std::set &allocValues, + std::vector &allAllocs, + std::vector &oldDeoptBundles) +{ + auto deoptBundleUse = callInstWithDeoptBundle->getOperandBundle(LLVMContext::OB_deopt).value(); + std::vector deoptBundle = GetDeoptVec(deoptBundleUse); + OperandBundleDef newDeoptBundle = GetNewDeoptBundleWithoutAllocs(deoptBundle, allocValues); + AddOldDeoptBundle(oldDeoptBundles, callInstWithDeoptBundle); + + auto newCall = ChangeDeoptBundle(callInstWithDeoptBundle, newDeoptBundle); + UpdateVectorOfAllocs(allAllocs, callInstWithDeoptBundle, newCall); + UpdateOldDeoptBundles(oldDeoptBundles, callInstWithDeoptBundle, newCall); + + ReplaceOldCallWithNewOne(callInstWithDeoptBundle, newCall); +} + +void HeapAllocSink::ReturnDeopts(std::vector &oldDeoptBundles, + DominatorTree &dominatorTree) +{ + for (size_t i = 0; i < oldDeoptBundles.size(); ++i) { + bool callInstAfterOrBeforeIllegal = false; + bool deoptsToBeChanged = false; + std::set illegals; + + auto el = oldDeoptBundles[i]; + bool legalToReturnOldDeopt = true; + for (const auto &deoptEl : el.oldDeoptBundle) { + if (not isa(deoptEl)) { + continue; + } + auto currentCallInst = dyn_cast(deoptEl); + bool legalToMove = dominatorTree.dominates(currentCallInst, el.callInst); + if (not legalToMove) { + illegals.insert(currentCallInst); + legalToReturnOldDeopt = false; + continue; + } + callInstAfterOrBeforeIllegal = true; + } + if (callInstAfterOrBeforeIllegal and not legalToReturnOldDeopt) { + deoptsToBeChanged = true; + } + if (not legalToReturnOldDeopt and not deoptsToBeChanged) { + continue; + } + + CallBase *newCall; + if (deoptsToBeChanged) { + OperandBundleDef nonOldNewDeoptBundle = GetNewDeoptBundleWithoutAllocs(el.oldDeoptBundle, illegals); + newCall = ChangeDeoptBundle(el.callInst, nonOldNewDeoptBundle); + } else { + OperandBundleDef oldDeoptBundle("deopt", el.oldDeoptBundle); + newCall = ChangeDeoptBundle(el.callInst, oldDeoptBundle); + } + + UpdateOldDeoptBundles(oldDeoptBundles, el.callInst, newCall); + ReplaceOldCallWithNewOne(el.callInst, newCall); + } +} + +llvm::PreservedAnalyses HeapAllocSink::run(Function &func, llvm::FunctionAnalysisManager &analysisManager) +{ + std::vector oldDeoptBundles; + + LoopInfo &loopInfo = analysisManager.getResult(func); + + bool changed = false; + + std::vector allocs = GetCallsWithHeapKind(func, AllocFnKind::Alloc); + + auto callsWithAllocInDeoptBundle = GetCallsWithAllocInDeoptBundle(allocs); + RemoveAllocFromDeoptBundleForAllCalls(callsWithAllocInDeoptBundle, allocs, oldDeoptBundles); + + DominatorTree dominatorTree = DominatorTree(func); + + auto canBeOptimizedSet = GetAllocsAndBasicBlocksForOpt(func, allocs, loopInfo, dominatorTree); + + changed += static_cast(TryToOptimize(canBeOptimizedSet, dominatorTree)); + + ReturnDeopts(oldDeoptBundles, dominatorTree); + + return changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); +} +} // namespace ark::llvmbackend::passes diff --git a/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.h b/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.h new file mode 100644 index 000000000..2e1ede116 --- /dev/null +++ b/static_core/libllvmbackend/transforms/passes/heap_alloc_sink.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef LIBLLVMBACKEND_TRANSFORMS_PASSES_HEAP_ALLOC_SINK_H +#define LIBLLVMBACKEND_TRANSFORMS_PASSES_HEAP_ALLOC_SINK_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Passes/PassBuilder.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "llvm_ark_interface.h" + +namespace ark::llvmbackend { +struct LLVMCompilerOptions; +} // namespace ark::llvmbackend + +namespace ark::llvmbackend::passes { +class HeapAllocSink : public llvm::PassInfoMixin { +public: + explicit HeapAllocSink(LLVMArkInterface *arkInterface = nullptr); + + // NOLINTNEXTLINE(readability-identifier-naming) + llvm::PreservedAnalyses run(llvm::Function &func, llvm::FunctionAnalysisManager &analysisManager); + + static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) + { + return true; + } + + static HeapAllocSink Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); + + class CallWithDeoptBundleWithAlocs { + public: + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + llvm::CallInst *callInst; + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + std::vector oldDeoptBundle; + + CallWithDeoptBundleWithAlocs(llvm::CallInst *call, std::vector oldDeopts) + : callInst(call), oldDeoptBundle(std::move(oldDeopts)) + { + } + }; + +private: + bool IsLegalToMove(llvm::CallInst *alloc, llvm::BasicBlock *basicBlock, llvm::DominatorTree &dominatorTree); + + void MoveAllocInsideBlock(llvm::CallInst *alloc, llvm::BasicBlock *blockForOpt); + + std::vector GetCallsWithHeapKind(llvm::Function &func, const llvm::AllocFnKind &allocFnKind); + + bool IsAllocKind(const llvm::CallInst *callInst, const llvm::AllocFnKind &allocFnKind); + + bool AttributeHasAllocKind(bool hasAllocKind, const llvm::AttributeList &attributes); + + bool AttributesContainAllocKind(bool hasAllocKind, const llvm::AttributeList &attributes, + const llvm::AllocFnKind &allocFnKind); + + llvm::BasicBlock *GetBasicBlockForOptForAlloc( + llvm::CallInst *alloc, llvm::LoopInfo &loopInfo, llvm::DominatorTree &dominatorTree, + const std::set &basicBlocksNotInLoop, + const std::set> &basicBlocksAndTheirLoopHeaders); + + std::set> GetAllocsAndBasicBlocksForOpt( + llvm::Function &func, const std::vector &allocs, llvm::LoopInfo &loopInfo, + llvm::DominatorTree &dominatorTree); + + void ClassifyBasicBlocks( + llvm::Function &func, std::set &basicBlocksNotInLoop, + std::set> &basicBlocksAndTheirLoopHeaders, + llvm::LoopInfo &loopInfo); + + void UpdateAvailableBlocksForOpt( + const llvm::Loop *loopOfAlloc, std::set &availableBlocksForOpt, + const std::set> &basicBlocksAndTheirLoopHeaders); + + llvm::BasicBlock *NeedOptimization(const std::set &availableBlocksForOpt, llvm::CallInst *alloc, + llvm::DominatorTree &dominatorTree); + + bool TryToOptimize(const std::set> &canBeOptimizedSet, + llvm::DominatorTree &dominatorTree); + + llvm::BasicBlock *FindPotentialBlockForOpt(llvm::CallInst *alloc, const llvm::DominatorTree &dominatorTree); + + llvm::BasicBlock *LowestCommonAncestor(llvm::BasicBlock *newBasicBlock, llvm::BasicBlock *lowestCommonAncestor, + const llvm::DominatorTree &dominatorTree); + + llvm::BasicBlock *GetBasicBlockForOptForPHINode(llvm::PHINode *phiNode, llvm::CallInst *alloc, + const llvm::DominatorTree &dominatorTree); + + std::vector FindBasicBlocksAccessingAllocInPHINode(llvm::PHINode *phiNode, + llvm::CallInst *alloc); + + bool BlockAccessAllocMemory(llvm::BasicBlock *block, llvm::CallInst *alloc); + + void RemoveHeapAllocFromDeoptBundle(llvm::CallInst *callInstWithDeoptBundle, + const std::set &allocValues, + std::vector &allocs, + std::vector &oldDeoptBundles); + + bool DeoptBundleContainsValue(const llvm::OperandBundleDef &deoptBundle, const llvm::Value *allocValue); + + std::map> GetCallsWithAllocInDeoptBundle( + const std::vector &allocs); + + void RemoveAllocFromDeoptBundleForAllCalls(std::map> &deoptBundlesToAllocMap, + std::vector &allocs, + std::vector &oldDeoptBundles); + + std::set GetUsersOfAlloc(llvm::Value *alloc); + + llvm::OperandBundleDef GetNewDeoptBundleWithoutAllocs(const std::vector &deoptBundle, + const std::set &allocValues); + + std::set GetAllocValuesFromIdxs(const std::vector &allocs, + const std::vector &allocIdxs); + void AddOldDeoptBundle(std::vector &oldDeoptBundles, + llvm::CallInst *oldInstWithDeoptBundle); + + llvm::CallBase *ChangeDeoptBundle(llvm::CallInst *callInstWithDeoptBundle, + const llvm::OperandBundleDef &newDeoptBundle); + + void UpdateVectorOfAllocs(std::vector &allAllocs, llvm::CallInst *oldCallNoLongerValid, + llvm::CallBase *newCallValid); + + void UpdateOldDeoptBundles(std::vector &oldDeoptBundles, + llvm::CallInst *oldCallNoLongerValid, llvm::CallBase *newCallValid); + + void ReplaceOldCallWithNewOne(llvm::CallInst *oldCallNoLongerValid, llvm::CallBase *newCall); + + llvm::OperandBundleDef GetOperandBundleDefFromUse(const llvm::OperandBundleUse &operandBundleUse); + + std::vector GetDeoptVec(const llvm::OperandBundleUse &deoptBundle); + + void ReturnDeopts(std::vector &oldDeoptBundles, llvm::DominatorTree &dominatorTree); + +private: + LLVMArkInterface *arkInterface_; + +public: + static constexpr llvm::StringRef ARG_NAME = "heap-alloc-sink"; +}; +} // namespace ark::llvmbackend::passes + +#endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_HEAP_ALLOC_SINK_H diff --git a/static_core/libllvmbackend/transforms/passes/passes.yaml b/static_core/libllvmbackend/transforms/passes/passes.yaml index 5a1c5f684..091cfda5b 100644 --- a/static_core/libllvmbackend/transforms/passes/passes.yaml +++ b/static_core/libllvmbackend/transforms/passes/passes.yaml @@ -178,3 +178,9 @@ llvm_passes: Replace builtin for LenArray with size type: [function] setup: default + +- name: HeapAllocSink + description: > + Pass sinks heap allocation in place of use if possible + type: [function] + setup: default diff --git a/static_core/libllvmbackend/transforms/pipeline.cfg b/static_core/libllvmbackend/transforms/pipeline.cfg index 7503bc6ab..a2fa9f1c7 100644 --- a/static_core/libllvmbackend/transforms/pipeline.cfg +++ b/static_core/libllvmbackend/transforms/pipeline.cfg @@ -14,6 +14,7 @@ module( function( lower-expect, # Lower expect intrinsic + heap-alloc-sink, # Optimistically try to unswitch early before simplifycfg makes a lot of Selects out of branches loop-mssa( licm, @@ -117,6 +118,7 @@ module( discard-inline-module, # Discard inline module function( + heap-alloc-sink, loop-simplify, # Canonicalize natural loops lcssa, # Loop-Closed SSA Form Pass loop-rotate, # Rotate Loops diff --git a/static_core/plugins/ets/tests/checked/CMakeLists.txt b/static_core/plugins/ets/tests/checked/CMakeLists.txt index 61bc3e2b1..562f06661 100644 --- a/static_core/plugins/ets/tests/checked/CMakeLists.txt +++ b/static_core/plugins/ets/tests/checked/CMakeLists.txt @@ -257,3 +257,5 @@ panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/escape_analysis_cast panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/load_array.sts) panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/optimize_negation.sts) panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/llvm_infer_flags.sts) +panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ets_llvmaot_heap_alloc_sink.sts) +panda_add_checked_test_ets(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ets_llvmaot_heap_alloc_sink_two.sts) diff --git a/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink.sts b/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink.sts new file mode 100644 index 000000000..ce88888f3 --- /dev/null +++ b/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink.sts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +//! CHECKER Check that heap-alloc-sink pass moved heap allocation +//! RUN_LLVM options: "--llvm-dump-after --compiler-regex='.*foo'" +//! READ_FILE "console.out" +//! LLVM_METHOD /define.*\"std.core.Object ETSGLOBAL::foo.*\d+\"/ +//! INST /%v[0-9]*.not = icmp eq i64 %a[0-9]*, 42.*/ +//! INST_NEXT_NOT /%v[0-9]* = select i1.*/ +//! RUN entry: "ETSGLOBAL::main" + +function foo(rand: long): Object { + let obj: Object = new Object; + + let tmpObj: Object = new Object; + if (rand == 42) { + obj = tmpObj; + } + + return obj; +} + + +function main() { + let rand = 33; + let obj: Object = foo(rand); +} diff --git a/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink_two.sts b/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink_two.sts new file mode 100644 index 000000000..7b3fe9248 --- /dev/null +++ b/static_core/plugins/ets/tests/checked/ets_llvmaot_heap_alloc_sink_two.sts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +//! CHECKER Check that heap-alloc-sink pass moved heap allocation +//! RUN_LLVM options: "--llvm-options=--print-after=heap-alloc-sink --compiler-regex='.*foo'" +//! READ_FILE "console.out" +//! LLVM_METHOD /define.*\"std.core.Object ETSGLOBAL::foo.*\d+\"/ +//! INST /%v[0-9]* = icmp ne i64 42, %a[0-9]*.*/ +//! INST_NEXT_NOT /%[a-z]*.[a-z]* = select i1.*/ + +function consume(obj: Object): Object { + let localObj = obj; + return localObj; +} + +function foo(rand: long): Object { + let diffObject = new Object(); + let obj = new Object(); + + if (rand == 42) { + let localObj = consume(obj); + return localObj; + } + + return diffObject; +} -- Gitee