/
redgpu
/
clspv
Обзор
Документация
Войти
/
redgpu
/
clspv
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
lib/UndoByvalPass.cpp
177 строк
6 KB
alan-baker
Update LLVM (#711)
17 фев 2021, 16:28
Не верифицирован
17 фев 2021, 16:28
b41cfd3
Код
Авторство
О чём код?
// Copyright 2017 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. #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Cloning.h" #include "Passes.h" using namespace llvm; #define DEBUG_TYPE "undobyval" namespace { struct UndoByvalPass : public ModulePass { static char ID; UndoByvalPass() : ModulePass(ID) {} bool runOnModule(Module &M) override; }; } // namespace char UndoByvalPass::ID = 0; INITIALIZE_PASS(UndoByvalPass, "UndoByval", "Undo Byval Pass", false, false) namespace clspv { llvm::ModulePass *createUndoByvalPass() { return new UndoByvalPass(); } } // namespace clspv bool UndoByvalPass::runOnModule(Module &M) { bool Changed = false; SmallVector<Function *, 8> WorkList; for (Function &F : M) { if (F.isDeclaration()) { continue; } SmallVector<Type *, 8> NewFuncParamTys; SmallVector<Argument *, 8> ByValList; for (Argument &Arg : F.args()) { // Check byval attribute and build new function's parameter type. if (Arg.hasByValAttr()) { WorkList.push_back(&F); Changed = true; break; } } } for (Function *F : WorkList) { SmallVector<Type *, 8> NewFuncParamTys; SmallVector<Argument *, 8> ByValList; for (Argument &Arg : F->args()) { // Check byval attribute and build new function's parameter type. if (Arg.hasByValAttr()) { PointerType *PTy = cast<PointerType>(Arg.getType()); Type *ArgTy = PTy->getElementType(); NewFuncParamTys.push_back(ArgTy); ByValList.push_back(&Arg); } else { NewFuncParamTys.push_back(Arg.getType()); } } if (!ByValList.empty()) { FunctionType *NewFuncTy = FunctionType::get(F->getReturnType(), NewFuncParamTys, false); // Create new function. Function *NewFunc = Function::Create(NewFuncTy, F->getLinkage()); NewFunc->takeName(F); // Insert the function just after the original to preserve the ordering of // the functions within the module. auto &FunctionList = M.getFunctionList(); for (auto Iter = FunctionList.begin(), IterEnd = FunctionList.end(); Iter != IterEnd; ++Iter) { // If we find our functions place in the iterator. if (&*Iter == F) { FunctionList.insertAfter(Iter, NewFunc); break; } } // Create alloca instruction for byval argument on function's entry block. auto InsertPoint = F->getEntryBlock().getFirstNonPHIOrDbg(); ValueToValueMapTy ArgVMap; for (Argument *Arg : ByValList) { PointerType *PTy = cast<PointerType>(Arg->getType()); Type *ArgTy = PTy->getElementType(); AllocaInst *ArgAddr = new AllocaInst( ArgTy, 0, nullptr, Arg->getName() + ".addr", InsertPoint); // Change arg's users with ArgAddr. Arg->replaceAllUsesWith(ArgAddr); ArgVMap[Arg] = ArgAddr; } // Map original function's arguments to new function's arguments. ValueToValueMapTy VMap; auto NewArg = NewFunc->arg_begin(); for (auto &Arg : F->args()) { NewArg->setName(Arg.getName()); VMap[&Arg] = &*(NewArg++); } // Clone original function into new function. SmallVector<ReturnInst *, 4> RetInsts; CloneFunctionInto(NewFunc, F, VMap, CloneFunctionChangeType::LocalChangesOnly, RetInsts); // Store new arguments to their alloca space. for (Argument *Arg : ByValList) { Instruction *Alloca = cast<Instruction>(ArgVMap[Arg]); Instruction *NewAlloca = cast<Instruction>(VMap[Alloca]); Argument *NewArg = cast<Argument>(VMap[Arg]); new StoreInst(NewArg, NewAlloca, &*std::next(BasicBlock::iterator(*NewAlloca))); // Remove byval and align attributes. NewArg->removeAttr(Attribute::ByVal); NewArg->removeAttr(Attribute::Alignment); NewArg->takeName(Arg); } SmallVector<User *, 8> Users(F->user_begin(), F->user_end()); // Update caller site. for (auto User : Users) { // Create new call instruction for new function without byval. CallInst *Call = cast<CallInst>(User); auto Callee = Call->getCalledFunction(); SmallVector<Value *, 8> Args; for (unsigned i = 0; i < Callee->arg_size(); i++) { auto Arg = Callee->getArg(i); auto param = Call->getArgOperand(i); if (Arg->hasByValAttr()) { Args.push_back(new LoadInst(Arg->getType()->getPointerElementType(), param, "", Call)); } else { Args.push_back(param); } } CallInst *NewCall = CallInst::Create(NewFunc, Args, "", Call); NewCall->setCallingConv(NewFunc->getCallingConv()); Call->replaceAllUsesWith(NewCall); Call->eraseFromParent(); } F->eraseFromParent(); } } return Changed; }