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

181 lines
7.4 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/codegen_cuda_host.h"
#include <algorithm>
#include <string>
#include <unordered_map>
#include "paddle/cinn/backends/codegen_device_util.h"
#include "paddle/cinn/backends/extern_func_emitter_builtin.h"
#include "paddle/cinn/backends/extern_func_jit_register.h"
#include "paddle/cinn/backends/llvm/llvm_util.h"
#include "paddle/cinn/runtime/intrinsic.h"
#include "paddle/common/enforce.h"
namespace cinn {
namespace backends {
using cinn::common::bfloat16;
using cinn::common::float16;
llvm::Value* CodeGenGpuHost::LowerGPUKernelCall(const ir::Call* call_ir) {
std::vector<llvm::Value*> ll_function_args;
std::transform(f_->arg_begin(),
f_->arg_end(),
std::back_inserter(ll_function_args),
[](auto& arg) { return std::addressof(arg); });
auto* kernel_args = ll_function_args[0];
auto* kernel_args_count = ll_function_args[1];
llvm::Value* kernel_stream = nullptr;
if (ll_function_args.size() == 3) {
kernel_stream = ll_function_args[2];
PADDLE_ENFORCE_EQ(
kernel_stream->getType(),
ll_void_p_ty(),
::common::errors::InvalidArgument(
"The type of kernel_stream should be void*")); // void* stream
}
PADDLE_ENFORCE_EQ(
kernel_args->getType(),
ll_void_p_ty(),
::common::errors::InvalidArgument(
"The type of kernel_args should be void*")); // void* args
PADDLE_ENFORCE_EQ(
kernel_args_count->getType(),
ll_int32_ty(),
::common::errors::InvalidArgument(
"The type of kernel_args_count should be int32")); // int32
std::unordered_map<std::string, llvm::Value*> global_args = {
{KERNEL_ARGS, kernel_args},
{KERNEL_ARGS_NUM, kernel_args_count},
{KERNEL_STREAM, kernel_stream}};
auto ret_type = CinnTypeToLLVMType(Void(), m_);
std::vector<llvm::Type*> args_type;
for (auto r_arg : call_ir->read_args) {
if (r_arg.is_var()) {
if (r_arg.as_var()->type().is_cpp_handle() ||
r_arg.as_var()->type().is_string()) {
args_type.push_back(CinnTypeToLLVMType(type_of<void*>(), m_));
} else if (r_arg.as_var()->type().is_int(32)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int32_t>(), m_));
} else if (r_arg.as_var()->type().is_int(64)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int64_t>(), m_));
} else {
CINN_NOT_IMPLEMENTED;
}
} else {
if (r_arg.type().is_bool()) {
args_type.push_back(CinnTypeToLLVMType(type_of<bool>(), m_));
} else if (r_arg.type().is_uint(8)) {
args_type.push_back(CinnTypeToLLVMType(type_of<uint8_t>(), m_));
} else if (r_arg.type().is_uint(16)) {
args_type.push_back(CinnTypeToLLVMType(type_of<uint16_t>(), m_));
} else if (r_arg.type().is_uint(32)) {
args_type.push_back(CinnTypeToLLVMType(type_of<uint32_t>(), m_));
} else if (r_arg.type().is_uint(64)) {
args_type.push_back(CinnTypeToLLVMType(type_of<uint64_t>(), m_));
} else if (r_arg.type().is_int(8)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int8_t>(), m_));
} else if (r_arg.type().is_int(16)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int16_t>(), m_));
} else if (r_arg.type().is_int(32)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int32_t>(), m_));
} else if (r_arg.type().is_int(64)) {
args_type.push_back(CinnTypeToLLVMType(type_of<int64_t>(), m_));
} else if (r_arg.type().is_float(32)) {
args_type.push_back(CinnTypeToLLVMType(type_of<float>(), m_));
} else if (r_arg.type().is_float(64)) {
args_type.push_back(CinnTypeToLLVMType(type_of<double>(), m_));
} else if (r_arg.type().is_bfloat16()) {
args_type.push_back(CinnTypeToLLVMType(type_of<bfloat16>(), m_));
} else if (r_arg.type().is_float16()) {
args_type.push_back(CinnTypeToLLVMType(type_of<float16>(), m_));
} else {
CINN_NOT_IMPLEMENTED;
}
}
}
auto func_type = llvm::FunctionType::get(ret_type, args_type, false);
auto call_func = m_->getOrInsertFunction(call_ir->name, func_type);
std::vector<llvm::Value*> call_args;
for (auto& r_arg : call_ir->read_args) {
if (r_arg.is_var()) {
if (r_arg.as_var()->type().is_string()) {
auto kvalue = m_->getOrInsertGlobal(r_arg.as_var()->name + "_ptr_",
b_->getInt8PtrTy());
call_args.push_back(b_->CreateLoad(
b_->getInt8PtrTy(), kvalue, r_arg.as_var()->name + "_ptr_load"));
} else if (r_arg.as_var()->type().is_cpp_handle()) {
PADDLE_ENFORCE_EQ(
global_args.count(r_arg.as_var()->name),
1,
::common::errors::InvalidArgument(
"The argument '%s' must be present in global_args.",
r_arg.as_var()->name.c_str()));
call_args.push_back(global_args[r_arg.as_var()->name]);
} else if (r_arg.as_var()->type().is_int()) {
call_args.push_back(GetVar(r_arg.as_var()->name, false));
} else {
CINN_NOT_IMPLEMENTED;
}
} else {
if (r_arg.type().is_bool()) {
call_args.push_back(b_->getInt1(r_arg.as_bool()));
} else if (r_arg.type().is_int(8)) {
call_args.push_back(b_->getInt8(r_arg.as_int8()));
} else if (r_arg.type().is_int(16)) {
call_args.push_back(b_->getInt16(r_arg.as_int16()));
} else if (r_arg.type().is_int(32)) {
call_args.push_back(CodeGenLLVM::Visit(&r_arg));
} else if (r_arg.type().is_int(64)) {
call_args.push_back(CodeGenLLVM::Visit(&r_arg));
} else if (r_arg.type().is_uint(8)) {
call_args.push_back(b_->getInt8(r_arg.as_uint8()));
} else if (r_arg.type().is_uint(16)) {
call_args.push_back(b_->getInt16(r_arg.as_uint16()));
} else if (r_arg.type().is_uint(32)) {
call_args.push_back(b_->getInt32(r_arg.as_uint32()));
} else if (r_arg.type().is_uint(64)) {
call_args.push_back(b_->getInt64(r_arg.as_uint64()));
} else if (r_arg.type().is_float(32)) {
call_args.push_back(llvm::ConstantFP::get(
b_->getFloatTy(), llvm::APFloat(r_arg.as_float())));
} else if (r_arg.type().is_float(64)) {
call_args.push_back(llvm::ConstantFP::get(
b_->getDoubleTy(), llvm::APFloat(r_arg.as_double())));
} else if (r_arg.type().is_bfloat16()) {
call_args.push_back(llvm::ConstantFP::get(
b_->getBFloatTy(),
llvm::APFloat(static_cast<float>(r_arg.as_bfloat16()))));
} else if (r_arg.type().is_float16()) {
call_args.push_back(llvm::ConstantFP::get(
b_->getHalfTy(),
llvm::APFloat(static_cast<float>(r_arg.as_float16()))));
} else {
CINN_NOT_IMPLEMENTED;
}
}
}
b_->CreateCall(call_func, call_args);
return nullptr;
}
} // namespace backends
} // namespace cinn