Home | History | Annotate | Download | only in NVPTX
      1 //===-- NVPTXLowerAlloca.cpp - Make alloca to use local memory =====--===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // For all alloca instructions, and add a pair of cast to local address for
     11 // each of them. For example,
     12 //
     13 //   %A = alloca i32
     14 //   store i32 0, i32* %A ; emits st.u32
     15 //
     16 // will be transformed to
     17 //
     18 //   %A = alloca i32
     19 //   %Local = addrspacecast i32* %A to i32 addrspace(5)*
     20 //   %Generic = addrspacecast i32 addrspace(5)* %A to i32*
     21 //   store i32 0, i32 addrspace(5)* %Generic ; emits st.local.u32
     22 //
     23 // And we will rely on NVPTXFavorNonGenericAddrSpace to combine the last
     24 // two instructions.
     25 //
     26 //===----------------------------------------------------------------------===//
     27 
     28 #include "NVPTX.h"
     29 #include "NVPTXUtilities.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 BasicBlockPass {
     45   bool runOnBasicBlock(BasicBlock &BB) override;
     46 
     47 public:
     48   static char ID; // Pass identification, replacement for typeid
     49   NVPTXLowerAlloca() : BasicBlockPass(ID) {}
     50   const char *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::runOnBasicBlock(BasicBlock &BB) {
     65   if (skipBasicBlock(BB))
     66     return false;
     67 
     68   bool Changed = false;
     69   for (auto &I : BB) {
     70     if (auto allocaInst = dyn_cast<AllocaInst>(&I)) {
     71       Changed = true;
     72       auto PTy = dyn_cast<PointerType>(allocaInst->getType());
     73       auto ETy = PTy->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 = new AddrSpaceCastInst(NewASCToLocal,
     78                                                     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 NVPTXFavorNonGenericAddrSpace. 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 && !LI->isVolatile()) {
     92           LI->setOperand(LI->getPointerOperandIndex(), NewASCToGeneric);
     93           continue;
     94         }
     95         auto SI = dyn_cast<StoreInst>(AllocaUse.getUser());
     96         if (SI && SI->getPointerOperand() == allocaInst && !SI->isVolatile()) {
     97           SI->setOperand(SI->getPointerOperandIndex(), NewASCToGeneric);
     98           continue;
     99         }
    100         auto GI = dyn_cast<GetElementPtrInst>(AllocaUse.getUser());
    101         if (GI && GI->getPointerOperand() == allocaInst) {
    102           GI->setOperand(GI->getPointerOperandIndex(), NewASCToGeneric);
    103           continue;
    104         }
    105         auto BI = dyn_cast<BitCastInst>(AllocaUse.getUser());
    106         if (BI && BI->getOperand(0) == allocaInst) {
    107           BI->setOperand(0, NewASCToGeneric);
    108           continue;
    109         }
    110       }
    111     }
    112   }
    113   return Changed;
    114 }
    115 
    116 BasicBlockPass *llvm::createNVPTXLowerAllocaPass() {
    117   return new NVPTXLowerAlloca();
    118 }
    119