Files
paddlepaddle--paddle/paddle/cinn/backends/llvm/simple_jit.cc
T
2026-07-13 12:40:42 +08:00

142 lines
5.5 KiB
C++

// Copyright (c) 2021 CINN Authors. All Rights Reserved.
//
// 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 "paddle/cinn/backends/llvm/simple_jit.h"
#include <llvm/AsmParser/Parser.h>
#include <llvm/ExecutionEngine/JITSymbol.h>
#include <llvm/ExecutionEngine/Orc/Core.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/Scalar/GVN.h>
#include <llvm/Transforms/Scalar/Reassociate.h>
#include <llvm/Transforms/Scalar/SimplifyCFG.h>
#include <string>
#include <utility>
#include "paddle/cinn/backends/codegen_cuda_host.h"
#include "paddle/cinn/backends/llvm/cinn_runtime_llvm_ir.h"
#include "paddle/cinn/backends/llvm/codegen_llvm.h"
#include "paddle/cinn/backends/llvm/llvm_util.h"
#include "paddle/cinn/backends/llvm/runtime_symbol_registry.h"
#include "paddle/cinn/ir/ir_printer.h"
#include "paddle/cinn/runtime/intrinsic.h"
namespace cinn {
namespace backends {
void SimpleJIT::AddModule(std::unique_ptr<llvm::Module> module, bool optimize) {
/*
for (auto &fn : module->functions()) {
LOG(INFO) << "fn:\n" << DumpToString(fn);
}
*/
PADDLE_ENFORCE_EQ(
!llvm::verifyModule(*module, &llvm::errs()),
true,
::common::errors::InvalidArgument(
"Transformation resulted in an invalid module\n\nmodule:\n"));
if (optimize) {
llvm::PassBuilder pass_builder;
llvm::LoopAnalysisManager loop_analysis_manager;
llvm::FunctionAnalysisManager function_analysis_manager;
llvm::CGSCCAnalysisManager cgscc_analysis_manager;
llvm::ModuleAnalysisManager module_analysis_manager;
pass_builder.registerModuleAnalyses(module_analysis_manager);
pass_builder.registerCGSCCAnalyses(cgscc_analysis_manager);
pass_builder.registerFunctionAnalyses(function_analysis_manager);
pass_builder.registerLoopAnalyses(loop_analysis_manager);
pass_builder.crossRegisterProxies(loop_analysis_manager,
function_analysis_manager,
cgscc_analysis_manager,
module_analysis_manager);
llvm::ModulePassManager module_pass_manager =
pass_builder.buildPerModuleDefaultPipeline(
llvm::PassBuilder::OptimizationLevel::O3);
module_pass_manager.run(*module, module_analysis_manager);
}
VLOG(3) << "jit target: " << jit_->getDataLayout().getStringRepresentation();
VLOG(3) << "module target: "
<< module->getDataLayout().getStringRepresentation();
llvm::orc::ThreadSafeModule tsm(std::move(module), context_);
llvm::cantFail(jit_->addIRModule(std::move(tsm)));
}
SimpleJIT::SimpleJIT() : context_(std::make_unique<llvm::LLVMContext>()) {
// Keep this aligned with cmake/cinn/llvm.cmake: CINN JIT links only the
// native target. InitializeAll* references every configured target in LLVM's
// TargetSelect.h and needs the matching all-target libraries.
// https://github.com/llvm/llvm-project/blob/llvmorg-13.0.1/llvm/include/llvm/Support/TargetSelect.h
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
jit_ = llvm::cantFail(llvm::orc::LLJITBuilder().create());
PADDLE_ENFORCE_NOT_NULL(
jit_, ::common::errors::InvalidArgument("JIT creation failed."));
auto proc_symbols_generator = llvm::cantFail(
llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
jit_->getDataLayout().getGlobalPrefix()));
jit_->getMainJITDylib().addGenerator(std::move(proc_symbols_generator));
llvm::orc::MangleAndInterner mangle(jit_->getExecutionSession(),
jit_->getDataLayout());
for (auto &item : GlobalSymbolRegistry::Global().All()) {
VLOG(2) << "Insert [" << item.first << "] to SimpleJIT";
llvm::cantFail(jit_->getMainJITDylib().define(llvm::orc::absoluteSymbols(
{{mangle(item.first),
{llvm::pointerToJITTargetAddress(item.second),
llvm::JITSymbolFlags::None}}})));
}
}
template <typename CodeGenT>
void SimpleJIT::Link(ir::Module module, bool optimize) {
std::string runtime_ir(backends::kRuntimeLlvmIr);
llvm::SMDiagnostic error;
auto m = llvm::parseAssemblyString(runtime_ir, error, context());
m->setDataLayout(jit_->getDataLayout());
auto b = std::make_unique<llvm::IRBuilder<>>(context());
auto ir_emitter = std::make_unique<CodeGenT>(m.get(), b.get());
ir_emitter->Compile(module);
PADDLE_ENFORCE_EQ(!llvm::verifyModule(*m, &llvm::errs()),
true,
::common::errors::InvalidArgument("Invalid module found."));
AddModule(std::move(m), optimize);
}
template void SimpleJIT::Link<CodeGenLLVM>(ir::Module module, bool optimize);
template void SimpleJIT::Link<CodeGenGpuHost>(ir::Module module, bool optimize);
} // namespace backends
} // namespace cinn