Skip to content

Commit

Permalink
Lower private global variables in functions
Browse files Browse the repository at this point in the history
Usually the functions are inlined into one entry functions before the
SpirvLowerGlobal Pass, However in one case,
llpc-raytracing-mode=continuations, the module does not inline library
functions to entry function. the private global variables are used in
multi functions. These private global variables are coming from
gpurt hlsl module, usually are enum values hence, these global
variables are loaded, but not stored. So we are probably safe lower
these variables in there used functions.

wer
  • Loading branch information
jiaolu committed Nov 28, 2023
1 parent 8d38dd6 commit f214abd
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
54 changes: 34 additions & 20 deletions llpc/lower/llpcSpirvLowerGlobal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,27 +590,44 @@ void SpirvLowerGlobal::mapGlobalVariableToProxy(GlobalVariable *globalVar) {
const auto &dataLayout = m_module->getDataLayout();
Type *globalVarTy = globalVar->getValueType();

m_builder->SetInsertPointPastAllocas(m_entryPoint);

Value *proxy = nullptr;

removeConstantExpr(m_context, globalVar);
// Handle special globals, regular allocas will be removed by SROA pass.
if (globalVar->getName().startswith(RtName::HitAttribute))
if (globalVar->getName().startswith(RtName::HitAttribute)) {
proxy = m_entryPoint->getArg(1);
else if (globalVar->getName().startswith(RtName::IncomingRayPayLoad))
globalVar->replaceAllUsesWith(proxy);
} else if (globalVar->getName().startswith(RtName::IncomingRayPayLoad)) {
proxy = m_entryPoint->getArg(0);
else if (globalVar->getName().startswith(RtName::IncomingCallableData))
globalVar->replaceAllUsesWith(proxy);
} else if (globalVar->getName().startswith(RtName::IncomingCallableData)) {
proxy = m_entryPoint->getArg(0);
else
proxy = m_builder->CreateAlloca(globalVarTy, dataLayout.getAllocaAddrSpace(), nullptr,
Twine(LlpcName::GlobalProxyPrefix) + globalVar->getName());
globalVar->replaceAllUsesWith(proxy);
} else {
// Collect used functions
SmallSet<Function *, 4> funcs;
for (User *user : globalVar->users()) {
auto inst = cast<Instruction>(user);
funcs.insert(inst->getFunction());
}
for (Function *func : funcs) {
assert(m_entryPoint);
m_builder->SetInsertPointPastAllocas(func);
proxy = m_builder->CreateAlloca(globalVarTy, dataLayout.getAllocaAddrSpace(), nullptr,
Twine(LlpcName::GlobalProxyPrefix) + globalVar->getName());

if (globalVar->hasInitializer()) {
auto initializer = globalVar->getInitializer();
m_builder->CreateStore(initializer, proxy);
if (globalVar->hasInitializer()) {
auto initializer = globalVar->getInitializer();
m_builder->CreateStore(initializer, proxy);
}
globalVar->mutateType(proxy->getType());
globalVar->replaceUsesWithIf(proxy, [func](Use &U) {
Instruction *userInst = cast<Instruction>(U.getUser());
return userInst->getFunction() == func;
});
}
}

m_globalVarProxyMap[globalVar] = proxy;
m_globalVarProxy.insert(globalVar);
}

// =====================================================================================================================
Expand Down Expand Up @@ -687,20 +704,17 @@ void SpirvLowerGlobal::mapOutputToProxy(GlobalVariable *output) {
// =====================================================================================================================
// Does lowering operations for SPIR-V global variables, replaces global variables with proxy variables.
void SpirvLowerGlobal::lowerGlobalVar() {
if (m_globalVarProxyMap.empty()) {
if (m_globalVarProxy.empty()) {
// Skip lowering if there is no global variable
return;
}

// Replace global variable with proxy variable
for (auto globalVarMap : m_globalVarProxyMap) {
auto globalVar = cast<GlobalVariable>(globalVarMap.first);
auto proxy = globalVarMap.second;
globalVar->mutateType(proxy->getType()); // To clear address space for pointer to make replacement valid
globalVar->replaceAllUsesWith(proxy);
// remove global variables
for (auto globalVar : m_globalVarProxy) {
globalVar->dropAllReferences();
globalVar->eraseFromParent();
}
m_globalVarProxy.clear();
}

// =====================================================================================================================
Expand Down
4 changes: 2 additions & 2 deletions llpc/lower/llpcSpirvLowerGlobal.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ class SpirvLowerGlobal : public SpirvLower, public llvm::PassInfoMixin<SpirvLowe
void addCallInstForXfbOutput(const ShaderInOutMetadata &outputMeta, Value *outputValue, unsigned xfbBufferAdjust,
unsigned xfbOffsetAdjust, unsigned locOffset, lgc::InOutInfo outputInfo);

std::unordered_map<llvm::Value *, llvm::Value *> m_globalVarProxyMap; // Proxy map for lowering global variables
std::unordered_map<llvm::Value *, llvm::Value *> m_inputProxyMap; // Proxy map for lowering inputs
std::unordered_set<llvm::GlobalVariable *> m_globalVarProxy; // The unordered_set for lowering global variables
std::unordered_map<llvm::Value *, llvm::Value *> m_inputProxyMap; // Proxy map for lowering inputs

// NOTE: Here we use list to store pairs of output proxy mappings. This is because we want output patching to be
// "ordered" (resulting LLVM IR for the patching always be consistent).
Expand Down

0 comments on commit f214abd

Please sign in to comment.