[Kotlin/Native] Avoid jni overhead when optimizing bitcode.
The phase to eliminate redundant function prologue safepoints was written in Kotlin which meant that it was performing a lot of jni calls. Moving the simple optimization to C code speeds things up dramatically. On a large project this reduces the time for this phase from 11.8 seconds to 1.4 seconds.
This commit is contained in:
@@ -57,4 +57,4 @@ int LLVMInlineCall(LLVMValueRef call) {
|
||||
|
||||
void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createThreadSanitizerLegacyPassPass());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <CAPIExtensions.h>
|
||||
#include <RemoveRedundantSafepoints.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static constexpr const char* functionPrologueSafepointName = "Kotlin_mm_safePointFunctionPrologue";
|
||||
|
||||
static constexpr size_t functionPrologueSafepointNameLength =
|
||||
std::char_traits<char>::length(functionPrologueSafepointName);
|
||||
|
||||
static bool InstructionIsPrologueSafepoint(LLVMValueRef instruction) {
|
||||
if (LLVMIsACallInst(instruction) || LLVMIsAInvokeInst(instruction)) {
|
||||
size_t calledNameLength = 0;
|
||||
const char* calledName = LLVMGetValueName2(LLVMGetCalledValue(instruction), &calledNameLength);
|
||||
return functionPrologueSafepointNameLength == calledNameLength &&
|
||||
strncmp(calledName, functionPrologueSafepointName, calledNameLength) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool BlockHasSafepointInstruction(LLVMBasicBlockRef block) {
|
||||
LLVMValueRef current = LLVMGetFirstInstruction(block);
|
||||
while (current) {
|
||||
if (InstructionIsPrologueSafepoint(current)) {
|
||||
return true;
|
||||
}
|
||||
current = LLVMGetNextInstruction(current);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void RemoveOrInlinePrologueSafepointInstructions(
|
||||
LLVMBasicBlockRef block, bool removeFirst, bool isSafepointInliningAllowed) {
|
||||
// Collect safepoint calls to erase and inline.
|
||||
LLVMValueRef toInline = nullptr;
|
||||
std::vector<LLVMValueRef> toErase;
|
||||
bool first = true;
|
||||
LLVMValueRef current = LLVMGetFirstInstruction(block);
|
||||
while (current) {
|
||||
if (InstructionIsPrologueSafepoint(current)) {
|
||||
if (!first || removeFirst) {
|
||||
toErase.push_back(current);
|
||||
} else if (isSafepointInliningAllowed && !LLVMIsDeclaration(LLVMGetCalledValue(current))) {
|
||||
toInline = current;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
current = LLVMGetNextInstruction(current);
|
||||
}
|
||||
// Perform actual modifications after iteration.
|
||||
for (auto it = toErase.cbegin(); it != toErase.cend(); ++it) {
|
||||
LLVMInstructionEraseFromParent(*it);
|
||||
}
|
||||
if (toInline) {
|
||||
LLVMInlineCall(toInline);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVMKotlinRemoveRedundantSafepoints(LLVMModuleRef module, int isSafepointInliningAllowed) {
|
||||
bool inliningAllowed = isSafepointInliningAllowed != 0;
|
||||
LLVMValueRef currentFunction = LLVMGetFirstFunction(module);
|
||||
while (currentFunction) {
|
||||
if (!LLVMIsDeclaration(currentFunction)) {
|
||||
LLVMBasicBlockRef firstBlock = LLVMGetFirstBasicBlock(currentFunction);
|
||||
if (firstBlock) {
|
||||
bool firstBlockHasSafepoint = BlockHasSafepointInstruction(firstBlock);
|
||||
RemoveOrInlinePrologueSafepointInstructions(firstBlock, false, inliningAllowed);
|
||||
LLVMBasicBlockRef currentBlock = LLVMGetNextBasicBlock(firstBlock);
|
||||
while (currentBlock) {
|
||||
RemoveOrInlinePrologueSafepointInstructions(currentBlock, firstBlockHasSafepoint, inliningAllowed);
|
||||
currentBlock = LLVMGetNextBasicBlock(currentBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
currentFunction = LLVMGetNextFunction(currentFunction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef LIBLLVMEXT_REMOVE_REDUNDANT_SAFEPOINTS_H
|
||||
#define LIBLLVMEXT_REMOVE_REDUNDANT_SAFEPOINTS_H
|
||||
|
||||
#endif // LIBLLVMEXT_REMOVE_REDUNDANT_SAFEPOINTS_H
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/Target.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
void LLVMKotlinRemoveRedundantSafepoints(LLVMModuleRef module, int isSafePointInliningAllowed);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
Reference in New Issue
Block a user