Path: blob/main/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXLowerAlloca.cpp
35271 views
//===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// For all alloca instructions, and add a pair of cast to local address for9// each of them. For example,10//11// %A = alloca i3212// store i32 0, i32* %A ; emits st.u3213//14// will be transformed to15//16// %A = alloca i3217// %Local = addrspacecast i32* %A to i32 addrspace(5)*18// %Generic = addrspacecast i32 addrspace(5)* %A to i32*19// store i32 0, i32 addrspace(5)* %Generic ; emits st.local.u3220//21// And we will rely on NVPTXInferAddressSpaces to combine the last two22// instructions.23//24//===----------------------------------------------------------------------===//2526#include "NVPTX.h"27#include "NVPTXUtilities.h"28#include "MCTargetDesc/NVPTXBaseInfo.h"29#include "llvm/IR/Function.h"30#include "llvm/IR/Instructions.h"31#include "llvm/IR/IntrinsicInst.h"32#include "llvm/IR/Module.h"33#include "llvm/IR/Type.h"34#include "llvm/Pass.h"3536using namespace llvm;3738namespace llvm {39void initializeNVPTXLowerAllocaPass(PassRegistry &);40}4142namespace {43class NVPTXLowerAlloca : public FunctionPass {44bool runOnFunction(Function &F) override;4546public:47static char ID; // Pass identification, replacement for typeid48NVPTXLowerAlloca() : FunctionPass(ID) {}49StringRef getPassName() const override {50return "convert address space of alloca'ed memory to local";51}52};53} // namespace5455char NVPTXLowerAlloca::ID = 1;5657INITIALIZE_PASS(NVPTXLowerAlloca, "nvptx-lower-alloca",58"Lower Alloca", false, false)5960// =============================================================================61// Main function for this pass.62// =============================================================================63bool NVPTXLowerAlloca::runOnFunction(Function &F) {64if (skipFunction(F))65return false;6667bool Changed = false;68for (auto &BB : F)69for (auto &I : BB) {70if (auto allocaInst = dyn_cast<AllocaInst>(&I)) {71Changed = true;72auto ETy = allocaInst->getAllocatedType();73auto LocalAddrTy = PointerType::get(ETy, ADDRESS_SPACE_LOCAL);74auto NewASCToLocal = new AddrSpaceCastInst(allocaInst, LocalAddrTy, "");75auto GenericAddrTy = PointerType::get(ETy, ADDRESS_SPACE_GENERIC);76auto NewASCToGeneric =77new AddrSpaceCastInst(NewASCToLocal, GenericAddrTy, "");78NewASCToLocal->insertAfter(allocaInst);79NewASCToGeneric->insertAfter(NewASCToLocal);80for (Use &AllocaUse : llvm::make_early_inc_range(allocaInst->uses())) {81// Check Load, Store, GEP, and BitCast Uses on alloca and make them82// use the converted generic address, in order to expose non-generic83// addrspacecast to NVPTXInferAddressSpaces. For other types84// of instructions this is unnecessary and may introduce redundant85// address cast.86auto LI = dyn_cast<LoadInst>(AllocaUse.getUser());87if (LI && LI->getPointerOperand() == allocaInst &&88!LI->isVolatile()) {89LI->setOperand(LI->getPointerOperandIndex(), NewASCToGeneric);90continue;91}92auto SI = dyn_cast<StoreInst>(AllocaUse.getUser());93if (SI && SI->getPointerOperand() == allocaInst &&94!SI->isVolatile()) {95SI->setOperand(SI->getPointerOperandIndex(), NewASCToGeneric);96continue;97}98auto GI = dyn_cast<GetElementPtrInst>(AllocaUse.getUser());99if (GI && GI->getPointerOperand() == allocaInst) {100GI->setOperand(GI->getPointerOperandIndex(), NewASCToGeneric);101continue;102}103auto BI = dyn_cast<BitCastInst>(AllocaUse.getUser());104if (BI && BI->getOperand(0) == allocaInst) {105BI->setOperand(0, NewASCToGeneric);106continue;107}108}109}110}111return Changed;112}113114FunctionPass *llvm::createNVPTXLowerAllocaPass() {115return new NVPTXLowerAlloca();116}117118119