149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===- NVPTXLowerAggrCopies.cpp - ------------------------------*- C++ -*--===//
249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//                     The LLVM Compiler Infrastructure
449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// This file is distributed under the University of Illinois Open Source
649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// License. See LICENSE.TXT for details.
749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===----------------------------------------------------------------------===//
949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// Lower aggregate copies, memset, memcpy, memmov intrinsics into loops when
1049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// the size is large or is not a compile-time constant.
1149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
1249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===----------------------------------------------------------------------===//
1349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1406cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "NVPTXLowerAggrCopies.h"
150b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
160b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h"
170b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h"
190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h"
200b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IntrinsicInst.h"
210b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Intrinsics.h"
220b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h"
230b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
2449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/Support/InstIterator.h"
2549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
2649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiusing namespace llvm;
2749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
283639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinskinamespace llvm { FunctionPass *createLowerAggrCopies(); }
2949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
3049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskichar NVPTXLowerAggrCopies::ID = 0;
3149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
3249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// Lower MemTransferInst or load-store pair to loop
333639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinskistatic void convertTransferToLoop(
343639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski    Instruction *splitAt, Value *srcAddr, Value *dstAddr, Value *len,
353639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski    //unsigned numLoads,
363639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski    bool srcVolatile, bool dstVolatile, LLVMContext &Context, Function &F) {
3749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  Type *indType = len->getType();
3849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
3949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *origBB = splitAt->getParent();
4049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *newBB = splitAt->getParent()->splitBasicBlock(splitAt, "split");
4149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *loopBB = BasicBlock::Create(Context, "loadstoreloop", &F, newBB);
4249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
4349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  origBB->getTerminator()->setSuccessor(0, loopBB);
4449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  IRBuilder<> builder(origBB, origBB->getTerminator());
4549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
4649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // srcAddr and dstAddr are expected to be pointer types,
4749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // so no check is made here.
483639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  unsigned srcAS = dyn_cast<PointerType>(srcAddr->getType())->getAddressSpace();
493639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  unsigned dstAS = dyn_cast<PointerType>(dstAddr->getType())->getAddressSpace();
5049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
5149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Cast pointers to (char *)
5249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  srcAddr = builder.CreateBitCast(srcAddr, Type::getInt8PtrTy(Context, srcAS));
5349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  dstAddr = builder.CreateBitCast(dstAddr, Type::getInt8PtrTy(Context, dstAS));
5449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
5549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  IRBuilder<> loop(loopBB);
5649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // The loop index (ind) is a phi node.
5749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  PHINode *ind = loop.CreatePHI(indType, 0);
5849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Incoming value for ind is 0
5949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  ind->addIncoming(ConstantInt::get(indType, 0), origBB);
6049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
6149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // load from srcAddr+ind
6249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  Value *val = loop.CreateLoad(loop.CreateGEP(srcAddr, ind), srcVolatile);
6349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // store at dstAddr+ind
6449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  loop.CreateStore(val, loop.CreateGEP(dstAddr, ind), dstVolatile);
6549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
6649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // The value for ind coming from backedge is (ind + 1)
6749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  Value *newind = loop.CreateAdd(ind, ConstantInt::get(indType, 1));
6849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  ind->addIncoming(newind, loopBB);
6949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
7049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  loop.CreateCondBr(loop.CreateICmpULT(newind, len), loopBB, newBB);
7149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski}
7249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
7349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// Lower MemSetInst to loop
7449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskistatic void convertMemSetToLoop(Instruction *splitAt, Value *dstAddr,
7549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                                Value *len, Value *val, LLVMContext &Context,
7649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                                Function &F) {
7749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *origBB = splitAt->getParent();
7849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *newBB = splitAt->getParent()->splitBasicBlock(splitAt, "split");
7949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  BasicBlock *loopBB = BasicBlock::Create(Context, "loadstoreloop", &F, newBB);
8049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
8149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  origBB->getTerminator()->setSuccessor(0, loopBB);
8249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  IRBuilder<> builder(origBB, origBB->getTerminator());
8349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
843639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  unsigned dstAS = dyn_cast<PointerType>(dstAddr->getType())->getAddressSpace();
8549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
8649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Cast pointer to the type of value getting stored
873639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  dstAddr =
883639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      builder.CreateBitCast(dstAddr, PointerType::get(val->getType(), dstAS));
8949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
9049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  IRBuilder<> loop(loopBB);
9149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  PHINode *ind = loop.CreatePHI(len->getType(), 0);
9249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  ind->addIncoming(ConstantInt::get(len->getType(), 0), origBB);
9349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
9449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  loop.CreateStore(val, loop.CreateGEP(dstAddr, ind), false);
9549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
9649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  Value *newind = loop.CreateAdd(ind, ConstantInt::get(len->getType(), 1));
9749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  ind->addIncoming(newind, loopBB);
9849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
9949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  loop.CreateCondBr(loop.CreateICmpULT(newind, len), loopBB, newBB);
10049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski}
10149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
10249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskibool NVPTXLowerAggrCopies::runOnFunction(Function &F) {
10349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  SmallVector<LoadInst *, 4> aggrLoads;
10449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  SmallVector<MemTransferInst *, 4> aggrMemcpys;
10549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  SmallVector<MemSetInst *, 4> aggrMemsets;
10649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1073574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow  DataLayout *TD = &getAnalysis<DataLayout>();
10849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  LLVMContext &Context = F.getParent()->getContext();
10949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
11049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  //
11149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Collect all the aggrLoads, aggrMemcpys and addrMemsets.
11249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  //
11349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  //const BasicBlock *firstBB = &F.front();  // first BB in F
11449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
11549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    //BasicBlock *bb = BI;
11649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE;
1173639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski         ++II) {
1183639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      if (LoadInst *load = dyn_cast<LoadInst>(II)) {
11949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1203639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        if (load->hasOneUse() == false)
1213639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski          continue;
12249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1233639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        if (TD->getTypeStoreSize(load->getType()) < MaxAggrCopySize)
1243639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski          continue;
12549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
12649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        User *use = *(load->use_begin());
1273639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        if (StoreInst *store = dyn_cast<StoreInst>(use)) {
12849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (store->getOperand(0) != load) //getValueOperand
1293639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski            continue;
13049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          aggrLoads.push_back(load);
13149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        }
1323639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      } else if (MemTransferInst *intr = dyn_cast<MemTransferInst>(II)) {
13349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        Value *len = intr->getLength();
13449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        // If the number of elements being copied is greater
13549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        // than MaxAggrCopySize, lower it to a loop
1363639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        if (ConstantInt *len_int = dyn_cast<ConstantInt>(len)) {
13749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (len_int->getZExtValue() >= MaxAggrCopySize) {
13849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            aggrMemcpys.push_back(intr);
13949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          }
14049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        } else {
14149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          // turn variable length memcpy/memmov into loop
14249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          aggrMemcpys.push_back(intr);
14349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        }
1443639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      } else if (MemSetInst *memsetintr = dyn_cast<MemSetInst>(II)) {
14549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        Value *len = memsetintr->getLength();
1463639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        if (ConstantInt *len_int = dyn_cast<ConstantInt>(len)) {
14749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (len_int->getZExtValue() >= MaxAggrCopySize) {
14849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            aggrMemsets.push_back(memsetintr);
14949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          }
15049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        } else {
15149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          // turn variable length memset into loop
15249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          aggrMemsets.push_back(memsetintr);
15349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        }
15449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      }
15549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
15649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
1573639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  if ((aggrLoads.size() == 0) && (aggrMemcpys.size() == 0) &&
1583639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      (aggrMemsets.size() == 0))
1593639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski    return false;
16049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
16149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  //
16249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Do the transformation of an aggr load/copy/set to a loop
16349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  //
16449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  for (unsigned i = 0, e = aggrLoads.size(); i != e; ++i) {
16549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    LoadInst *load = aggrLoads[i];
16649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    StoreInst *store = dyn_cast<StoreInst>(*load->use_begin());
16749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *srcAddr = load->getOperand(0);
16849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *dstAddr = store->getOperand(1);
16949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    unsigned numLoads = TD->getTypeStoreSize(load->getType());
17049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *len = ConstantInt::get(Type::getInt32Ty(Context), numLoads);
17149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
17249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    convertTransferToLoop(store, srcAddr, dstAddr, len, load->isVolatile(),
17349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                          store->isVolatile(), Context, F);
17449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
17549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    store->eraseFromParent();
17649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    load->eraseFromParent();
17749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
17849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
17949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  for (unsigned i = 0, e = aggrMemcpys.size(); i != e; ++i) {
18049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    MemTransferInst *cpy = aggrMemcpys[i];
18149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *len = cpy->getLength();
18249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // llvm 2.7 version of memcpy does not have volatile
18349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // operand yet. So always making it non-volatile
18449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // optimistically, so that we don't see unnecessary
18549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // st.volatile in ptx
18649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    convertTransferToLoop(cpy, cpy->getSource(), cpy->getDest(), len, false,
18749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                          false, Context, F);
18849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    cpy->eraseFromParent();
18949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
19049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
19149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  for (unsigned i = 0, e = aggrMemsets.size(); i != e; ++i) {
19249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    MemSetInst *memsetinst = aggrMemsets[i];
19349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *len = memsetinst->getLength();
19449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    Value *val = memsetinst->getValue();
19549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    convertMemSetToLoop(memsetinst, memsetinst->getDest(), len, val, Context,
19649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                        F);
19749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    memsetinst->eraseFromParent();
19849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
19949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
20049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  return true;
20149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski}
20249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
20349683f3c961379fbc088871a5d6304950f1f1cbcJustin HolewinskiFunctionPass *llvm::createLowerAggrCopies() {
20449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  return new NVPTXLowerAggrCopies();
20549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski}
206