Home | History | Annotate | Line # | Download | only in NVPTX
      1 //===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // For all alloca instructions, and add a pair of cast to local address for
     10 // each of them. For example,
     11 //
     12 //   %A = alloca i32
     13 //   store i32 0, i32* %A ; emits st.u32
     14 //
     15 // will be transformed to
     16 //
     17 //   %A = alloca i32
     18 //   %Local = addrspacecast i32* %A to i32 addrspace(5)*
     19 //   %Generic = addrspacecast i32 addrspace(5)* %A to i32*
     20 //   store i32 0, i32 addrspace(5)* %Generic ; emits st.local.u32
     21 //
     22 // And we will rely on NVPTXInferAddressSpaces to combine the last two
     23 // instructions.
     24 //
     25 //===----------------------------------------------------------------------===//
     26 
     27 #include "NVPTX.h"
     28 #include "NVPTXUtilities.h"
     29 #include "MCTargetDesc/NVPTXBaseInfo.h"
     30 #include "llvm/IR/Function.h"
     31 #include "llvm/IR/Instructions.h"
     32 #include "llvm/IR/IntrinsicInst.h"
     33 #include "llvm/IR/Module.h"
     34 #include "llvm/IR/Type.h"
     35 #include "llvm/Pass.h"
     36 
     37 using namespace llvm;
     38 
     39 namespace llvm {
     40 void initializeNVPTXLowerAllocaPass(PassRegistry &);
     41 }
     42 
     43 namespace {
     44 class NVPTXLowerAlloca : public FunctionPass {
     45   bool runOnFunction(Function &F) override;
     46 
     47 public:
     48   static char ID; // Pass identification, replacement for typeid
     49   NVPTXLowerAlloca() : FunctionPass(ID) {}
     50   StringRef getPassName() const override {
     51     return "convert address space of alloca'ed memory to local";
     52   }
     53 };
     54 } // namespace
     55 
     56 char NVPTXLowerAlloca::ID = 1;
     57 
     58 INITIALIZE_PASS(NVPTXLowerAlloca, "nvptx-lower-alloca",
     59                 "Lower Alloca", false, false)
     60 
     61 // =============================================================================
     62 // Main function for this pass.
     63 // =============================================================================
     64 bool NVPTXLowerAlloca::runOnFunction(Function &F) {
     65   if (skipFunction(F))
     66     return false;
     67 
     68   bool Changed = false;
     69   for (auto &BB : F)
     70     for (auto &I : BB) {
     71       if (auto allocaInst = dyn_cast<AllocaInst>(&I)) {
     72         Changed = true;
     73         auto ETy = cast<PointerType>(allocaInst->getType())->getElementType();
     74         auto LocalAddrTy = PointerType::get(ETy, ADDRESS_SPACE_LOCAL);
     75         auto NewASCToLocal = new AddrSpaceCastInst(allocaInst, LocalAddrTy, "");
     76         auto GenericAddrTy = PointerType::get(ETy, ADDRESS_SPACE_GENERIC);
     77         auto NewASCToGeneric =
     78             new AddrSpaceCastInst(NewASCToLocal, GenericAddrTy, "");
     79         NewASCToLocal->insertAfter(allocaInst);
     80         NewASCToGeneric->insertAfter(NewASCToLocal);
     81         for (Value::use_iterator UI = allocaInst->use_begin(),
     82                                  UE = allocaInst->use_end();
     83              UI != UE;) {
     84           // Check Load, Store, GEP, and BitCast Uses on alloca and make them
     85           // use the converted generic address, in order to expose non-generic
     86           // addrspacecast to NVPTXInferAddressSpaces. For other types
     87           // of instructions this is unnecessary and may introduce redundant
     88           // address cast.
     89           const auto &AllocaUse = *UI++;
     90           auto LI = dyn_cast<LoadInst>(AllocaUse.getUser());
     91           if (LI && LI->getPointerOperand() == allocaInst &&
     92               !LI->isVolatile()) {
     93             LI->setOperand(LI->getPointerOperandIndex(), NewASCToGeneric);
     94             continue;
     95           }
     96           auto SI = dyn_cast<StoreInst>(AllocaUse.getUser());
     97           if (SI && SI->getPointerOperand() == allocaInst &&
     98               !SI->isVolatile()) {
     99             SI->setOperand(SI->getPointerOperandIndex(), NewASCToGeneric);
    100             continue;
    101           }
    102           auto GI = dyn_cast<GetElementPtrInst>(AllocaUse.getUser());
    103           if (GI && GI->getPointerOperand() == allocaInst) {
    104             GI->setOperand(GI->getPointerOperandIndex(), NewASCToGeneric);
    105             continue;
    106           }
    107           auto BI = dyn_cast<BitCastInst>(AllocaUse.getUser());
    108           if (BI && BI->getOperand(0) == allocaInst) {
    109             BI->setOperand(0, NewASCToGeneric);
    110             continue;
    111           }
    112         }
    113       }
    114     }
    115   return Changed;
    116 }
    117 
    118 FunctionPass *llvm::createNVPTXLowerAllocaPass() {
    119   return new NVPTXLowerAlloca();
    120 }
    121