CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
125 lines
4.0 KiB
C++
125 lines
4.0 KiB
C++
//===-- NVPTXMarkKernelPtrsGlobal.cpp - Mark kernel pointers as global ----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// For CUDA kernels, pointers loaded from byval parameters are known to be in
|
|
// global address space. This pass inserts addrspacecast pairs to make that
|
|
// explicit, enabling later address-space inference to propagate the global AS.
|
|
// It also handles the pattern where a pointer is loaded as an integer and then
|
|
// converted via inttoptr.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "NVPTX.h"
|
|
#include "NVVMProperties.h"
|
|
#include "llvm/Analysis/ValueTracking.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/NVPTXAddrSpace.h"
|
|
|
|
using namespace llvm;
|
|
using namespace NVPTXAS;
|
|
|
|
static void markPointerAsAS(Value *Ptr, unsigned AS) {
|
|
if (Ptr->getType()->getPointerAddressSpace() != ADDRESS_SPACE_GENERIC)
|
|
return;
|
|
|
|
BasicBlock::iterator InsertPt;
|
|
if (auto *Arg = dyn_cast<Argument>(Ptr)) {
|
|
InsertPt = Arg->getParent()->getEntryBlock().begin();
|
|
} else {
|
|
InsertPt = ++cast<Instruction>(Ptr)->getIterator();
|
|
assert(InsertPt != InsertPt->getParent()->end() &&
|
|
"We don't call this function with Ptr being a terminator.");
|
|
}
|
|
|
|
Instruction *PtrInGlobal = new AddrSpaceCastInst(
|
|
Ptr, PointerType::get(Ptr->getContext(), AS), Ptr->getName(), InsertPt);
|
|
Value *PtrInGeneric = new AddrSpaceCastInst(PtrInGlobal, Ptr->getType(),
|
|
Ptr->getName(), InsertPt);
|
|
Ptr->replaceAllUsesWith(PtrInGeneric);
|
|
PtrInGlobal->setOperand(0, Ptr);
|
|
}
|
|
|
|
static void markPointerAsGlobal(Value *Ptr) {
|
|
markPointerAsAS(Ptr, ADDRESS_SPACE_GLOBAL);
|
|
}
|
|
|
|
static void handleIntToPtr(Value &V) {
|
|
if (!all_of(V.users(), [](User *U) { return isa<IntToPtrInst>(U); }))
|
|
return;
|
|
|
|
SmallVector<User *, 16> UsersToUpdate(V.users());
|
|
for (User *U : UsersToUpdate)
|
|
markPointerAsGlobal(U);
|
|
}
|
|
|
|
static bool markKernelPtrsGlobal(Function &F) {
|
|
if (!isKernelFunction(F))
|
|
return false;
|
|
|
|
// Copying of byval aggregates + SROA may result in pointers being loaded as
|
|
// integers, followed by inttoptr. We mark those as global too, but only if
|
|
// the loaded integer is used exclusively for conversion to a pointer.
|
|
for (auto &I : instructions(F)) {
|
|
auto *LI = dyn_cast<LoadInst>(&I);
|
|
if (!LI)
|
|
continue;
|
|
|
|
if (LI->getType()->isPointerTy() || LI->getType()->isIntegerTy()) {
|
|
Value *UO = getUnderlyingObject(LI->getPointerOperand());
|
|
if (auto *Arg = dyn_cast<Argument>(UO)) {
|
|
if (Arg->hasByValAttr()) {
|
|
if (LI->getType()->isPointerTy())
|
|
markPointerAsGlobal(LI);
|
|
else
|
|
handleIntToPtr(*LI);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (Argument &Arg : F.args())
|
|
if (Arg.getType()->isIntegerTy())
|
|
handleIntToPtr(Arg);
|
|
|
|
return true;
|
|
}
|
|
|
|
namespace {
|
|
|
|
class NVPTXMarkKernelPtrsGlobalLegacyPass : public FunctionPass {
|
|
public:
|
|
static char ID;
|
|
NVPTXMarkKernelPtrsGlobalLegacyPass() : FunctionPass(ID) {}
|
|
bool runOnFunction(Function &F) override;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
INITIALIZE_PASS(NVPTXMarkKernelPtrsGlobalLegacyPass,
|
|
"nvptx-mark-kernel-ptrs-global",
|
|
"NVPTX Mark Kernel Pointers Global", false, false)
|
|
|
|
bool NVPTXMarkKernelPtrsGlobalLegacyPass::runOnFunction(Function &F) {
|
|
return markKernelPtrsGlobal(F);
|
|
}
|
|
|
|
char NVPTXMarkKernelPtrsGlobalLegacyPass::ID = 0;
|
|
|
|
FunctionPass *llvm::createNVPTXMarkKernelPtrsGlobalPass() {
|
|
return new NVPTXMarkKernelPtrsGlobalLegacyPass();
|
|
}
|
|
|
|
PreservedAnalyses
|
|
NVPTXMarkKernelPtrsGlobalPass::run(Function &F, FunctionAnalysisManager &) {
|
|
return markKernelPtrsGlobal(F) ? PreservedAnalyses::none()
|
|
: PreservedAnalyses::all();
|
|
}
|