/
redgpu
/
clspv
Обзор
Документация
Войти
/
redgpu
/
clspv
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
lib/ClusterConstants.cpp
148 строк
5 KB
Kévin Petit
A few fixes to SPIR-V 1.4 support (#748)
03 авг 2021, 20:21
Не верифицирован
03 авг 2021, 20:21
85bcee0
Код
Авторство
О чём код?
// Copyright 2018 The Clspv 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. // Cluster module-scope __constant variables. But only if option // ModuleScopeConstantsInUniformBuffer is true. #include <cassert> #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/UniqueVector.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" #include "clspv/AddressSpace.h" #include "clspv/Option.h" #include "ArgKind.h" #include "Constants.h" #include "NormalizeGlobalVariable.h" #include "Passes.h" using namespace llvm; #define DEBUG_TYPE "clusterconstants" namespace { struct ClusterModuleScopeConstantVars : public ModulePass { static char ID; ClusterModuleScopeConstantVars() : ModulePass(ID) {} bool runOnModule(Module &M) override; }; } // namespace char ClusterModuleScopeConstantVars::ID = 0; INITIALIZE_PASS(ClusterModuleScopeConstantVars, "ClusterModuleScopeConstantVars", "Cluster module-scope __constant variables", false, false) namespace clspv { llvm::ModulePass *createClusterModuleScopeConstantVars() { return new ClusterModuleScopeConstantVars(); } } // namespace clspv bool ClusterModuleScopeConstantVars::runOnModule(Module &M) { bool Changed = false; LLVMContext &Context = M.getContext(); clspv::NormalizeGlobalVariables(M); SmallVector<GlobalVariable *, 8> global_constants; UniqueVector<Constant *> initializers; SmallVector<GlobalVariable *, 8> dead_global_constants; for (GlobalVariable &GV : M.globals()) { if (GV.hasInitializer() && GV.getType()->getPointerAddressSpace() == clspv::AddressSpace::Constant) { // Only keep live __constant variables. if (GV.use_empty()) { dead_global_constants.push_back(&GV); } else { global_constants.push_back(&GV); initializers.insert(GV.getInitializer()); } } } for (GlobalVariable *GV : dead_global_constants) { Changed = true; GV->eraseFromParent(); } if (global_constants.size() > 1 || (global_constants.size() == 1 && !global_constants[0]->getType()->isStructTy())) { Changed = true; // Make the struct type. SmallVector<Type *, 8> types; types.reserve(initializers.size()); for (Value *init : initializers) { Type *ty = init->getType(); types.push_back(ty); } StructType *type = StructType::get(Context, types); // Make the global variable. SmallVector<Constant *, 8> initializers_as_vec(initializers.begin(), initializers.end()); Constant *clustered_initializer = ConstantStruct::get(type, initializers_as_vec); GlobalVariable *clustered_gv = new GlobalVariable( M, type, true, GlobalValue::InternalLinkage, clustered_initializer, clspv::ClusteredConstantsVariableName(), nullptr, GlobalValue::ThreadLocalMode::NotThreadLocal, clspv::AddressSpace::Constant); assert(clustered_gv); // Replace uses of the other globals with references to the members of the // clustered constant. IRBuilder<> Builder(Context); Value *zero = Builder.getInt32(0); for (GlobalVariable *GV : global_constants) { SmallVector<User *, 8> users(GV->users()); for (User *user : users) { if (GV == user) { // This is the original global variable declaration. Skip it. } else if (auto *inst = dyn_cast<Instruction>(user)) { unsigned index = initializers.idFor(GV->getInitializer()) - 1; Instruction *gep = GetElementPtrInst::CreateInBounds( clustered_gv, {zero, Builder.getInt32(index)}, "", inst); user->replaceUsesOfWith(GV, gep); } else { errs() << "Don't know how to handle updating user of __constant: " << *user << "\n"; llvm_unreachable("Unhandled case replacing a user of __constant"); } } } // Remove the old constants. for (GlobalVariable *GV : global_constants) { GV->eraseFromParent(); } } return Changed; }