blob: 91c872d709c00fbe4e651f4bfb56f00ee8b19c7c [file] [log] [blame]
Justin Holewinskiae556d32012-05-04 20:18:50 +00001//===- NVPTXLowerAggrCopies.cpp - ------------------------------*- C++ -*--===//
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//===----------------------------------------------------------------------===//
Eli Benderskyf14af162015-07-16 16:27:19 +00009//
Eli Benderskyf871e092015-07-16 20:42:38 +000010// \file
Justin Holewinskiae556d32012-05-04 20:18:50 +000011// Lower aggregate copies, memset, memcpy, memmov intrinsics into loops when
12// the size is large or is not a compile-time constant.
13//
14//===----------------------------------------------------------------------===//
15
Justin Holewinskiae556d32012-05-04 20:18:50 +000016#include "NVPTXLowerAggrCopies.h"
Benjamin Kramera52f6962015-03-09 15:50:58 +000017#include "llvm/CodeGen/MachineFunctionAnalysis.h"
18#include "llvm/CodeGen/StackProtector.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000019#include "llvm/IR/Constants.h"
20#include "llvm/IR/DataLayout.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/IRBuilder.h"
23#include "llvm/IR/Instructions.h"
24#include "llvm/IR/IntrinsicInst.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/IR/Module.h"
Mehdi Amini46a43552015-03-04 18:43:29 +000028#include "llvm/Support/Debug.h"
Eli Benderskyf14af162015-07-16 16:27:19 +000029#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Mehdi Amini46a43552015-03-04 18:43:29 +000030
31#define DEBUG_TYPE "nvptx"
Justin Holewinskiae556d32012-05-04 20:18:50 +000032
33using namespace llvm;
34
Benjamin Kramera52f6962015-03-09 15:50:58 +000035namespace {
Eli Benderskyf14af162015-07-16 16:27:19 +000036
Benjamin Kramera52f6962015-03-09 15:50:58 +000037// actual analysis class, which is a functionpass
38struct NVPTXLowerAggrCopies : public FunctionPass {
39 static char ID;
40
41 NVPTXLowerAggrCopies() : FunctionPass(ID) {}
42
43 void getAnalysisUsage(AnalysisUsage &AU) const override {
44 AU.addPreserved<MachineFunctionAnalysis>();
45 AU.addPreserved<StackProtector>();
46 }
47
48 bool runOnFunction(Function &F) override;
49
50 static const unsigned MaxAggrCopySize = 128;
51
52 const char *getPassName() const override {
53 return "Lower aggregate copies/intrinsics into loops";
54 }
55};
Justin Holewinskiae556d32012-05-04 20:18:50 +000056
57char NVPTXLowerAggrCopies::ID = 0;
58
Eli Benderskyf14af162015-07-16 16:27:19 +000059// Lower memcpy to loop.
Eli Benderskyf871e092015-07-16 20:42:38 +000060void convertMemCpyToLoop(Instruction *ConvertedInst, Value *SrcAddr,
61 Value *DstAddr, Value *CopyLen, bool SrcIsVolatile,
62 bool DstIsVolatile, LLVMContext &Context,
63 Function &F) {
64 Type *TypeOfCopyLen = CopyLen->getType();
Justin Holewinskiae556d32012-05-04 20:18:50 +000065
Eli Benderskyf871e092015-07-16 20:42:38 +000066 BasicBlock *OrigBB = ConvertedInst->getParent();
67 BasicBlock *NewBB =
68 ConvertedInst->getParent()->splitBasicBlock(ConvertedInst, "split");
69 BasicBlock *LoopBB = BasicBlock::Create(Context, "loadstoreloop", &F, NewBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +000070
Eli Benderskyf871e092015-07-16 20:42:38 +000071 OrigBB->getTerminator()->setSuccessor(0, LoopBB);
72 IRBuilder<> Builder(OrigBB, OrigBB->getTerminator());
Justin Holewinskiae556d32012-05-04 20:18:50 +000073
Eli Benderskyf871e092015-07-16 20:42:38 +000074 // SrcAddr and DstAddr are expected to be pointer types,
Justin Holewinskiae556d32012-05-04 20:18:50 +000075 // so no check is made here.
Eli Benderskyf871e092015-07-16 20:42:38 +000076 unsigned SrcAS = cast<PointerType>(SrcAddr->getType())->getAddressSpace();
77 unsigned DstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace();
Justin Holewinskiae556d32012-05-04 20:18:50 +000078
79 // Cast pointers to (char *)
Eli Benderskyf871e092015-07-16 20:42:38 +000080 SrcAddr = Builder.CreateBitCast(SrcAddr, Builder.getInt8PtrTy(SrcAS));
81 DstAddr = Builder.CreateBitCast(DstAddr, Builder.getInt8PtrTy(DstAS));
Justin Holewinskiae556d32012-05-04 20:18:50 +000082
Eli Benderskyf871e092015-07-16 20:42:38 +000083 IRBuilder<> LoopBuilder(LoopBB);
84 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 0);
85 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +000086
Eli Benderskyf871e092015-07-16 20:42:38 +000087 // load from SrcAddr+LoopIndex
Eli Bendersky5c0039a2015-07-10 15:40:33 +000088 // TODO: we can leverage the align parameter of llvm.memcpy for more efficient
89 // word-sized loads and stores.
Eli Benderskyf871e092015-07-16 20:42:38 +000090 Value *Element = LoopBuilder.CreateLoad(
91 LoopBuilder.CreateGEP(LoopBuilder.getInt8Ty(), SrcAddr, LoopIndex),
92 SrcIsVolatile);
93 // store at DstAddr+LoopIndex
94 LoopBuilder.CreateStore(
95 Element,
96 LoopBuilder.CreateGEP(LoopBuilder.getInt8Ty(), DstAddr, LoopIndex),
97 DstIsVolatile);
Justin Holewinskiae556d32012-05-04 20:18:50 +000098
Eli Benderskyf871e092015-07-16 20:42:38 +000099 // The value for LoopIndex coming from backedge is (LoopIndex + 1)
100 Value *NewIndex =
101 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1));
102 LoopIndex->addIncoming(NewIndex, LoopBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000103
Eli Benderskyf871e092015-07-16 20:42:38 +0000104 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, CopyLen), LoopBB,
105 NewBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000106}
107
Eli Benderskyf14af162015-07-16 16:27:19 +0000108// Lower memmove to IR. memmove is required to correctly copy overlapping memory
109// regions; therefore, it has to check the relative positions of the source and
110// destination pointers and choose the copy direction accordingly.
111//
112// The code below is an IR rendition of this C function:
113//
114// void* memmove(void* dst, const void* src, size_t n) {
115// unsigned char* d = dst;
116// const unsigned char* s = src;
117// if (s < d) {
118// // copy backwards
119// while (n--) {
120// d[n] = s[n];
121// }
122// } else {
123// // copy forward
124// for (size_t i = 0; i < n; ++i) {
125// d[i] = s[i];
126// }
127// }
128// return dst;
129// }
Eli Benderskyf871e092015-07-16 20:42:38 +0000130void convertMemMoveToLoop(Instruction *ConvertedInst, Value *SrcAddr,
131 Value *DstAddr, Value *CopyLen, bool SrcIsVolatile,
132 bool DstIsVolatile, LLVMContext &Context,
133 Function &F) {
134 Type *TypeOfCopyLen = CopyLen->getType();
135 BasicBlock *OrigBB = ConvertedInst->getParent();
Eli Benderskyf14af162015-07-16 16:27:19 +0000136
137 // Create the a comparison of src and dst, based on which we jump to either
138 // the forward-copy part of the function (if src >= dst) or the backwards-copy
139 // part (if src < dst).
140 // SplitBlockAndInsertIfThenElse conveniently creates the basic if-then-else
141 // structure. Its block terminators (unconditional branches) are replaced by
142 // the appropriate conditional branches when the loop is built.
Eli Benderskyf871e092015-07-16 20:42:38 +0000143 ICmpInst *PtrCompare = new ICmpInst(ConvertedInst, ICmpInst::ICMP_ULT,
144 SrcAddr, DstAddr, "compare_src_dst");
Eli Benderskyf14af162015-07-16 16:27:19 +0000145 TerminatorInst *ThenTerm, *ElseTerm;
Eli Benderskyf871e092015-07-16 20:42:38 +0000146 SplitBlockAndInsertIfThenElse(PtrCompare, ConvertedInst, &ThenTerm,
147 &ElseTerm);
Eli Benderskyf14af162015-07-16 16:27:19 +0000148
149 // Each part of the function consists of two blocks:
150 // copy_backwards: used to skip the loop when n == 0
151 // copy_backwards_loop: the actual backwards loop BB
152 // copy_forward: used to skip the loop when n == 0
153 // copy_forward_loop: the actual forward loop BB
154 BasicBlock *CopyBackwardsBB = ThenTerm->getParent();
155 CopyBackwardsBB->setName("copy_backwards");
156 BasicBlock *CopyForwardBB = ElseTerm->getParent();
157 CopyForwardBB->setName("copy_forward");
Eli Benderskyf871e092015-07-16 20:42:38 +0000158 BasicBlock *ExitBB = ConvertedInst->getParent();
Eli Benderskyf14af162015-07-16 16:27:19 +0000159 ExitBB->setName("memmove_done");
160
161 // Initial comparison of n == 0 that lets us skip the loops altogether. Shared
162 // between both backwards and forward copy clauses.
163 ICmpInst *CompareN =
Eli Benderskyf871e092015-07-16 20:42:38 +0000164 new ICmpInst(OrigBB->getTerminator(), ICmpInst::ICMP_EQ, CopyLen,
165 ConstantInt::get(TypeOfCopyLen, 0), "compare_n_to_0");
Eli Benderskyf14af162015-07-16 16:27:19 +0000166
167 // Copying backwards.
168 BasicBlock *LoopBB =
169 BasicBlock::Create(Context, "copy_backwards_loop", &F, CopyForwardBB);
170 IRBuilder<> LoopBuilder(LoopBB);
Eli Benderskyf871e092015-07-16 20:42:38 +0000171 PHINode *LoopPhi = LoopBuilder.CreatePHI(TypeOfCopyLen, 0);
Eli Benderskyf14af162015-07-16 16:27:19 +0000172 Value *IndexPtr = LoopBuilder.CreateSub(
Eli Benderskyf871e092015-07-16 20:42:38 +0000173 LoopPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_ptr");
Eli Benderskyf14af162015-07-16 16:27:19 +0000174 Value *Element = LoopBuilder.CreateLoad(
Eli Benderskyf871e092015-07-16 20:42:38 +0000175 LoopBuilder.CreateInBoundsGEP(SrcAddr, IndexPtr), "element");
Eli Benderskyf14af162015-07-16 16:27:19 +0000176 LoopBuilder.CreateStore(Element,
Eli Benderskyf871e092015-07-16 20:42:38 +0000177 LoopBuilder.CreateInBoundsGEP(DstAddr, IndexPtr));
Eli Benderskyf14af162015-07-16 16:27:19 +0000178 LoopBuilder.CreateCondBr(
Eli Benderskyf871e092015-07-16 20:42:38 +0000179 LoopBuilder.CreateICmpEQ(IndexPtr, ConstantInt::get(TypeOfCopyLen, 0)),
Eli Benderskyf14af162015-07-16 16:27:19 +0000180 ExitBB, LoopBB);
181 LoopPhi->addIncoming(IndexPtr, LoopBB);
Eli Benderskyf871e092015-07-16 20:42:38 +0000182 LoopPhi->addIncoming(CopyLen, CopyBackwardsBB);
Eli Benderskyf14af162015-07-16 16:27:19 +0000183 BranchInst::Create(ExitBB, LoopBB, CompareN, ThenTerm);
Benjamin Kramer5dfd8b62015-07-16 16:51:48 +0000184 ThenTerm->eraseFromParent();
Eli Benderskyf14af162015-07-16 16:27:19 +0000185
186 // Copying forward.
187 BasicBlock *FwdLoopBB =
188 BasicBlock::Create(Context, "copy_forward_loop", &F, ExitBB);
189 IRBuilder<> FwdLoopBuilder(FwdLoopBB);
Eli Benderskyf871e092015-07-16 20:42:38 +0000190 PHINode *FwdCopyPhi = FwdLoopBuilder.CreatePHI(TypeOfCopyLen, 0, "index_ptr");
Eli Benderskyf14af162015-07-16 16:27:19 +0000191 Value *FwdElement = FwdLoopBuilder.CreateLoad(
Eli Benderskyf871e092015-07-16 20:42:38 +0000192 FwdLoopBuilder.CreateInBoundsGEP(SrcAddr, FwdCopyPhi), "element");
Eli Benderskyf14af162015-07-16 16:27:19 +0000193 FwdLoopBuilder.CreateStore(
Eli Benderskyf871e092015-07-16 20:42:38 +0000194 FwdElement, FwdLoopBuilder.CreateInBoundsGEP(DstAddr, FwdCopyPhi));
Eli Benderskyf14af162015-07-16 16:27:19 +0000195 Value *FwdIndexPtr = FwdLoopBuilder.CreateAdd(
Eli Benderskyf871e092015-07-16 20:42:38 +0000196 FwdCopyPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_increment");
197 FwdLoopBuilder.CreateCondBr(FwdLoopBuilder.CreateICmpEQ(FwdIndexPtr, CopyLen),
Eli Benderskyf14af162015-07-16 16:27:19 +0000198 ExitBB, FwdLoopBB);
199 FwdCopyPhi->addIncoming(FwdIndexPtr, FwdLoopBB);
Eli Benderskyf871e092015-07-16 20:42:38 +0000200 FwdCopyPhi->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), CopyForwardBB);
Eli Benderskyf14af162015-07-16 16:27:19 +0000201
202 BranchInst::Create(ExitBB, FwdLoopBB, CompareN, ElseTerm);
Benjamin Kramer5dfd8b62015-07-16 16:51:48 +0000203 ElseTerm->eraseFromParent();
Eli Benderskyf14af162015-07-16 16:27:19 +0000204}
205
206// Lower memset to loop.
Eli Benderskyf871e092015-07-16 20:42:38 +0000207void convertMemSetToLoop(Instruction *ConvertedInst, Value *DstAddr,
208 Value *CopyLen, Value *SetValue, LLVMContext &Context,
209 Function &F) {
210 BasicBlock *OrigBB = ConvertedInst->getParent();
211 BasicBlock *NewBB =
212 ConvertedInst->getParent()->splitBasicBlock(ConvertedInst, "split");
213 BasicBlock *LoopBB = BasicBlock::Create(Context, "loadstoreloop", &F, NewBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000214
Eli Benderskyf871e092015-07-16 20:42:38 +0000215 OrigBB->getTerminator()->setSuccessor(0, LoopBB);
216 IRBuilder<> Builder(OrigBB, OrigBB->getTerminator());
Justin Holewinskiae556d32012-05-04 20:18:50 +0000217
218 // Cast pointer to the type of value getting stored
Eli Benderskyf871e092015-07-16 20:42:38 +0000219 unsigned dstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace();
220 DstAddr = Builder.CreateBitCast(DstAddr,
221 PointerType::get(SetValue->getType(), dstAS));
Justin Holewinskiae556d32012-05-04 20:18:50 +0000222
Eli Benderskyf871e092015-07-16 20:42:38 +0000223 IRBuilder<> LoopBuilder(LoopBB);
224 PHINode *LoopIndex = LoopBuilder.CreatePHI(CopyLen->getType(), 0);
225 LoopIndex->addIncoming(ConstantInt::get(CopyLen->getType(), 0), OrigBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000226
Eli Benderskyf871e092015-07-16 20:42:38 +0000227 LoopBuilder.CreateStore(
228 SetValue, LoopBuilder.CreateGEP(SetValue->getType(), DstAddr, LoopIndex),
229 false);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000230
Eli Benderskyf871e092015-07-16 20:42:38 +0000231 Value *NewIndex =
232 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(CopyLen->getType(), 1));
233 LoopIndex->addIncoming(NewIndex, LoopBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000234
Eli Benderskyf871e092015-07-16 20:42:38 +0000235 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, CopyLen), LoopBB,
236 NewBB);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000237}
238
239bool NVPTXLowerAggrCopies::runOnFunction(Function &F) {
Eli Benderskyf871e092015-07-16 20:42:38 +0000240 SmallVector<LoadInst *, 4> AggrLoads;
Eli Benderskyf14af162015-07-16 16:27:19 +0000241 SmallVector<MemIntrinsic *, 4> MemCalls;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000242
Mehdi Amini46a43552015-03-04 18:43:29 +0000243 const DataLayout &DL = F.getParent()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000244 LLVMContext &Context = F.getParent()->getContext();
245
Eli Benderskyf14af162015-07-16 16:27:19 +0000246 // Collect all aggregate loads and mem* calls.
Justin Holewinskiae556d32012-05-04 20:18:50 +0000247 for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000248 for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000249 ++II) {
Eli Benderskyf871e092015-07-16 20:42:38 +0000250 if (LoadInst *LI = dyn_cast<LoadInst>(II)) {
251 if (!LI->hasOneUse())
Justin Holewinski0497ab12013-03-30 14:29:21 +0000252 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000253
Eli Benderskyf871e092015-07-16 20:42:38 +0000254 if (DL.getTypeStoreSize(LI->getType()) < MaxAggrCopySize)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000255 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000256
Eli Benderskyf871e092015-07-16 20:42:38 +0000257 if (StoreInst *SI = dyn_cast<StoreInst>(LI->user_back())) {
258 if (SI->getOperand(0) != LI)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000259 continue;
Eli Benderskyf871e092015-07-16 20:42:38 +0000260 AggrLoads.push_back(LI);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000261 }
Eli Benderskyf14af162015-07-16 16:27:19 +0000262 } else if (MemIntrinsic *IntrCall = dyn_cast<MemIntrinsic>(II)) {
263 // Convert intrinsic calls with variable size or with constant size
264 // larger than the MaxAggrCopySize threshold.
265 if (ConstantInt *LenCI = dyn_cast<ConstantInt>(IntrCall->getLength())) {
266 if (LenCI->getZExtValue() >= MaxAggrCopySize) {
267 MemCalls.push_back(IntrCall);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000268 }
269 } else {
Eli Benderskyf14af162015-07-16 16:27:19 +0000270 MemCalls.push_back(IntrCall);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000271 }
272 }
273 }
274 }
Eli Benderskyf14af162015-07-16 16:27:19 +0000275
Eli Benderskyf871e092015-07-16 20:42:38 +0000276 if (AggrLoads.size() == 0 && MemCalls.size() == 0) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000277 return false;
Eli Benderskyf14af162015-07-16 16:27:19 +0000278 }
Justin Holewinskiae556d32012-05-04 20:18:50 +0000279
280 //
281 // Do the transformation of an aggr load/copy/set to a loop
282 //
Eli Benderskyf871e092015-07-16 20:42:38 +0000283 for (LoadInst *LI : AggrLoads) {
284 StoreInst *SI = dyn_cast<StoreInst>(*LI->user_begin());
285 Value *SrcAddr = LI->getOperand(0);
286 Value *DstAddr = SI->getOperand(1);
287 unsigned NumLoads = DL.getTypeStoreSize(LI->getType());
288 Value *CopyLen = ConstantInt::get(Type::getInt32Ty(Context), NumLoads);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000289
Eli Benderskyf871e092015-07-16 20:42:38 +0000290 convertMemCpyToLoop(/* ConvertedInst */ SI,
291 /* SrcAddr */ SrcAddr, /* DstAddr */ DstAddr,
292 /* CopyLen */ CopyLen,
293 /* SrcIsVolatile */ LI->isVolatile(),
294 /* DstIsVolatile */ SI->isVolatile(),
295 /* Context */ Context,
296 /* Function F */ F);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000297
Eli Benderskyf871e092015-07-16 20:42:38 +0000298 SI->eraseFromParent();
299 LI->eraseFromParent();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000300 }
301
Eli Benderskyf14af162015-07-16 16:27:19 +0000302 // Transform mem* intrinsic calls.
303 for (MemIntrinsic *MemCall : MemCalls) {
304 if (MemCpyInst *Memcpy = dyn_cast<MemCpyInst>(MemCall)) {
Eli Benderskyf871e092015-07-16 20:42:38 +0000305 convertMemCpyToLoop(/* ConvertedInst */ Memcpy,
306 /* SrcAddr */ Memcpy->getRawSource(),
307 /* DstAddr */ Memcpy->getRawDest(),
308 /* CopyLen */ Memcpy->getLength(),
309 /* SrcIsVolatile */ Memcpy->isVolatile(),
310 /* DstIsVolatile */ Memcpy->isVolatile(),
Eli Bendersky5c0039a2015-07-10 15:40:33 +0000311 /* Context */ Context,
312 /* Function F */ F);
Eli Benderskyf14af162015-07-16 16:27:19 +0000313 } else if (MemMoveInst *Memmove = dyn_cast<MemMoveInst>(MemCall)) {
Eli Benderskyf871e092015-07-16 20:42:38 +0000314 convertMemMoveToLoop(/* ConvertedInst */ Memmove,
315 /* SrcAddr */ Memmove->getRawSource(),
316 /* DstAddr */ Memmove->getRawDest(),
317 /* CopyLen */ Memmove->getLength(),
318 /* SrcIsVolatile */ Memmove->isVolatile(),
319 /* DstIsVolatile */ Memmove->isVolatile(),
Eli Benderskyf14af162015-07-16 16:27:19 +0000320 /* Context */ Context,
321 /* Function F */ F);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000322
Eli Benderskyf14af162015-07-16 16:27:19 +0000323 } else if (MemSetInst *Memset = dyn_cast<MemSetInst>(MemCall)) {
Eli Benderskyf871e092015-07-16 20:42:38 +0000324 convertMemSetToLoop(/* ConvertedInst */ Memset,
325 /* DstAddr */ Memset->getRawDest(),
326 /* CopyLen */ Memset->getLength(),
327 /* SetValue */ Memset->getValue(),
Eli Benderskyf14af162015-07-16 16:27:19 +0000328 /* Context */ Context,
Eli Benderskyf871e092015-07-16 20:42:38 +0000329 /* Function F */ F);
Eli Benderskyf14af162015-07-16 16:27:19 +0000330 }
331 MemCall->eraseFromParent();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000332 }
333
334 return true;
335}
336
Eli Benderskyf14af162015-07-16 16:27:19 +0000337} // namespace
338
339namespace llvm {
340void initializeNVPTXLowerAggrCopiesPass(PassRegistry &);
341}
342
343INITIALIZE_PASS(NVPTXLowerAggrCopies, "nvptx-lower-aggr-copies",
344 "Lower aggregate copies, and llvm.mem* intrinsics into loops",
345 false, false)
346
Justin Holewinskiae556d32012-05-04 20:18:50 +0000347FunctionPass *llvm::createLowerAggrCopies() {
348 return new NVPTXLowerAggrCopies();
349}