1 //===- LowerMemIntrinsics.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 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h" 11 #include "llvm/Analysis/TargetTransformInfo.h" 12 #include "llvm/IR/IRBuilder.h" 13 #include "llvm/IR/IntrinsicInst.h" 14 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 15 16 using namespace llvm; 17 18 static unsigned getLoopOperandSizeInBytes(Type *Type) { 19 if (VectorType *VTy = dyn_cast<VectorType>(Type)) { 20 return VTy->getBitWidth() / 8; 21 } 22 23 return Type->getPrimitiveSizeInBits() / 8; 24 } 25 26 void llvm::createMemCpyLoopKnownSize(Instruction *InsertBefore, Value *SrcAddr, 27 Value *DstAddr, ConstantInt *CopyLen, 28 unsigned SrcAlign, unsigned DestAlign, 29 bool SrcIsVolatile, bool DstIsVolatile, 30 const TargetTransformInfo &TTI) { 31 // No need to expand zero length copies. 32 if (CopyLen->isZero()) 33 return; 34 35 BasicBlock *PreLoopBB = InsertBefore->getParent(); 36 BasicBlock *PostLoopBB = nullptr; 37 Function *ParentFunc = PreLoopBB->getParent(); 38 LLVMContext &Ctx = PreLoopBB->getContext(); 39 40 Type *TypeOfCopyLen = CopyLen->getType(); 41 Type *LoopOpType = 42 TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAlign, DestAlign); 43 44 unsigned LoopOpSize = getLoopOperandSizeInBytes(LoopOpType); 45 uint64_t LoopEndCount = CopyLen->getZExtValue() / LoopOpSize; 46 47 unsigned SrcAS = cast<PointerType>(SrcAddr->getType())->getAddressSpace(); 48 unsigned DstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace(); 49 50 if (LoopEndCount != 0) { 51 // Split 52 PostLoopBB = PreLoopBB->splitBasicBlock(InsertBefore, "memcpy-split"); 53 BasicBlock *LoopBB = 54 BasicBlock::Create(Ctx, "load-store-loop", ParentFunc, PostLoopBB); 55 PreLoopBB->getTerminator()->setSuccessor(0, LoopBB); 56 57 IRBuilder<> PLBuilder(PreLoopBB->getTerminator()); 58 59 // Cast the Src and Dst pointers to pointers to the loop operand type (if 60 // needed). 61 PointerType *SrcOpType = PointerType::get(LoopOpType, SrcAS); 62 PointerType *DstOpType = PointerType::get(LoopOpType, DstAS); 63 if (SrcAddr->getType() != SrcOpType) { 64 SrcAddr = PLBuilder.CreateBitCast(SrcAddr, SrcOpType); 65 } 66 if (DstAddr->getType() != DstOpType) { 67 DstAddr = PLBuilder.CreateBitCast(DstAddr, DstOpType); 68 } 69 70 IRBuilder<> LoopBuilder(LoopBB); 71 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 2, "loop-index"); 72 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0U), PreLoopBB); 73 // Loop Body 74 Value *SrcGEP = 75 LoopBuilder.CreateInBoundsGEP(LoopOpType, SrcAddr, LoopIndex); 76 Value *Load = LoopBuilder.CreateLoad(SrcGEP, SrcIsVolatile); 77 Value *DstGEP = 78 LoopBuilder.CreateInBoundsGEP(LoopOpType, DstAddr, LoopIndex); 79 LoopBuilder.CreateStore(Load, DstGEP, DstIsVolatile); 80 81 Value *NewIndex = 82 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1U)); 83 LoopIndex->addIncoming(NewIndex, LoopBB); 84 85 // Create the loop branch condition. 86 Constant *LoopEndCI = ConstantInt::get(TypeOfCopyLen, LoopEndCount); 87 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, LoopEndCI), 88 LoopBB, PostLoopBB); 89 } 90 91 uint64_t BytesCopied = LoopEndCount * LoopOpSize; 92 uint64_t RemainingBytes = CopyLen->getZExtValue() - BytesCopied; 93 if (RemainingBytes) { 94 IRBuilder<> RBuilder(PostLoopBB ? PostLoopBB->getFirstNonPHI() 95 : InsertBefore); 96 97 // Update the alignment based on the copy size used in the loop body. 98 SrcAlign = std::min(SrcAlign, LoopOpSize); 99 DestAlign = std::min(DestAlign, LoopOpSize); 100 101 SmallVector<Type *, 5> RemainingOps; 102 TTI.getMemcpyLoopResidualLoweringType(RemainingOps, Ctx, RemainingBytes, 103 SrcAlign, DestAlign); 104 105 for (auto OpTy : RemainingOps) { 106 // Calaculate the new index 107 unsigned OperandSize = getLoopOperandSizeInBytes(OpTy); 108 uint64_t GepIndex = BytesCopied / OperandSize; 109 assert(GepIndex * OperandSize == BytesCopied && 110 "Division should have no Remainder!"); 111 // Cast source to operand type and load 112 PointerType *SrcPtrType = PointerType::get(OpTy, SrcAS); 113 Value *CastedSrc = SrcAddr->getType() == SrcPtrType 114 ? SrcAddr 115 : RBuilder.CreateBitCast(SrcAddr, SrcPtrType); 116 Value *SrcGEP = RBuilder.CreateInBoundsGEP( 117 OpTy, CastedSrc, ConstantInt::get(TypeOfCopyLen, GepIndex)); 118 Value *Load = RBuilder.CreateLoad(SrcGEP, SrcIsVolatile); 119 120 // Cast destination to operand type and store. 121 PointerType *DstPtrType = PointerType::get(OpTy, DstAS); 122 Value *CastedDst = DstAddr->getType() == DstPtrType 123 ? DstAddr 124 : RBuilder.CreateBitCast(DstAddr, DstPtrType); 125 Value *DstGEP = RBuilder.CreateInBoundsGEP( 126 OpTy, CastedDst, ConstantInt::get(TypeOfCopyLen, GepIndex)); 127 RBuilder.CreateStore(Load, DstGEP, DstIsVolatile); 128 129 BytesCopied += OperandSize; 130 } 131 } 132 assert(BytesCopied == CopyLen->getZExtValue() && 133 "Bytes copied should match size in the call!"); 134 } 135 136 void llvm::createMemCpyLoopUnknownSize(Instruction *InsertBefore, 137 Value *SrcAddr, Value *DstAddr, 138 Value *CopyLen, unsigned SrcAlign, 139 unsigned DestAlign, bool SrcIsVolatile, 140 bool DstIsVolatile, 141 const TargetTransformInfo &TTI) { 142 BasicBlock *PreLoopBB = InsertBefore->getParent(); 143 BasicBlock *PostLoopBB = 144 PreLoopBB->splitBasicBlock(InsertBefore, "post-loop-memcpy-expansion"); 145 146 Function *ParentFunc = PreLoopBB->getParent(); 147 LLVMContext &Ctx = PreLoopBB->getContext(); 148 149 Type *LoopOpType = 150 TTI.getMemcpyLoopLoweringType(Ctx, CopyLen, SrcAlign, DestAlign); 151 unsigned LoopOpSize = getLoopOperandSizeInBytes(LoopOpType); 152 153 IRBuilder<> PLBuilder(PreLoopBB->getTerminator()); 154 155 unsigned SrcAS = cast<PointerType>(SrcAddr->getType())->getAddressSpace(); 156 unsigned DstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace(); 157 PointerType *SrcOpType = PointerType::get(LoopOpType, SrcAS); 158 PointerType *DstOpType = PointerType::get(LoopOpType, DstAS); 159 if (SrcAddr->getType() != SrcOpType) { 160 SrcAddr = PLBuilder.CreateBitCast(SrcAddr, SrcOpType); 161 } 162 if (DstAddr->getType() != DstOpType) { 163 DstAddr = PLBuilder.CreateBitCast(DstAddr, DstOpType); 164 } 165 166 // Calculate the loop trip count, and remaining bytes to copy after the loop. 167 Type *CopyLenType = CopyLen->getType(); 168 IntegerType *ILengthType = dyn_cast<IntegerType>(CopyLenType); 169 assert(ILengthType && 170 "expected size argument to memcpy to be an integer type!"); 171 ConstantInt *CILoopOpSize = ConstantInt::get(ILengthType, LoopOpSize); 172 Value *RuntimeLoopCount = PLBuilder.CreateUDiv(CopyLen, CILoopOpSize); 173 Value *RuntimeResidual = PLBuilder.CreateURem(CopyLen, CILoopOpSize); 174 Value *RuntimeBytesCopied = PLBuilder.CreateSub(CopyLen, RuntimeResidual); 175 176 BasicBlock *LoopBB = 177 BasicBlock::Create(Ctx, "loop-memcpy-expansion", ParentFunc, nullptr); 178 IRBuilder<> LoopBuilder(LoopBB); 179 180 PHINode *LoopIndex = LoopBuilder.CreatePHI(CopyLenType, 2, "loop-index"); 181 LoopIndex->addIncoming(ConstantInt::get(CopyLenType, 0U), PreLoopBB); 182 183 Value *SrcGEP = LoopBuilder.CreateInBoundsGEP(LoopOpType, SrcAddr, LoopIndex); 184 Value *Load = LoopBuilder.CreateLoad(SrcGEP, SrcIsVolatile); 185 Value *DstGEP = LoopBuilder.CreateInBoundsGEP(LoopOpType, DstAddr, LoopIndex); 186 LoopBuilder.CreateStore(Load, DstGEP, DstIsVolatile); 187 188 Value *NewIndex = 189 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(CopyLenType, 1U)); 190 LoopIndex->addIncoming(NewIndex, LoopBB); 191 192 Type *Int8Type = Type::getInt8Ty(Ctx); 193 if (LoopOpType != Int8Type) { 194 // Loop body for the residual copy. 195 BasicBlock *ResLoopBB = BasicBlock::Create(Ctx, "loop-memcpy-residual", 196 PreLoopBB->getParent(), nullptr); 197 // Residual loop header. 198 BasicBlock *ResHeaderBB = BasicBlock::Create( 199 Ctx, "loop-memcpy-residual-header", PreLoopBB->getParent(), nullptr); 200 201 // Need to update the pre-loop basic block to branch to the correct place. 202 // branch to the main loop if the count is non-zero, branch to the residual 203 // loop if the copy size is smaller then 1 iteration of the main loop but 204 // non-zero and finally branch to after the residual loop if the memcpy 205 // size is zero. 206 ConstantInt *Zero = ConstantInt::get(ILengthType, 0U); 207 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopCount, Zero), 208 LoopBB, ResHeaderBB); 209 PreLoopBB->getTerminator()->eraseFromParent(); 210 211 LoopBuilder.CreateCondBr( 212 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopCount), LoopBB, 213 ResHeaderBB); 214 215 // Determine if we need to branch to the residual loop or bypass it. 216 IRBuilder<> RHBuilder(ResHeaderBB); 217 RHBuilder.CreateCondBr(RHBuilder.CreateICmpNE(RuntimeResidual, Zero), 218 ResLoopBB, PostLoopBB); 219 220 // Copy the residual with single byte load/store loop. 221 IRBuilder<> ResBuilder(ResLoopBB); 222 PHINode *ResidualIndex = 223 ResBuilder.CreatePHI(CopyLenType, 2, "residual-loop-index"); 224 ResidualIndex->addIncoming(Zero, ResHeaderBB); 225 226 Value *SrcAsInt8 = 227 ResBuilder.CreateBitCast(SrcAddr, PointerType::get(Int8Type, SrcAS)); 228 Value *DstAsInt8 = 229 ResBuilder.CreateBitCast(DstAddr, PointerType::get(Int8Type, DstAS)); 230 Value *FullOffset = ResBuilder.CreateAdd(RuntimeBytesCopied, ResidualIndex); 231 Value *SrcGEP = 232 ResBuilder.CreateInBoundsGEP(Int8Type, SrcAsInt8, FullOffset); 233 Value *Load = ResBuilder.CreateLoad(SrcGEP, SrcIsVolatile); 234 Value *DstGEP = 235 ResBuilder.CreateInBoundsGEP(Int8Type, DstAsInt8, FullOffset); 236 ResBuilder.CreateStore(Load, DstGEP, DstIsVolatile); 237 238 Value *ResNewIndex = 239 ResBuilder.CreateAdd(ResidualIndex, ConstantInt::get(CopyLenType, 1U)); 240 ResidualIndex->addIncoming(ResNewIndex, ResLoopBB); 241 242 // Create the loop branch condition. 243 ResBuilder.CreateCondBr( 244 ResBuilder.CreateICmpULT(ResNewIndex, RuntimeResidual), ResLoopBB, 245 PostLoopBB); 246 } else { 247 // In this case the loop operand type was a byte, and there is no need for a 248 // residual loop to copy the remaining memory after the main loop. 249 // We do however need to patch up the control flow by creating the 250 // terminators for the preloop block and the memcpy loop. 251 ConstantInt *Zero = ConstantInt::get(ILengthType, 0U); 252 PLBuilder.CreateCondBr(PLBuilder.CreateICmpNE(RuntimeLoopCount, Zero), 253 LoopBB, PostLoopBB); 254 PreLoopBB->getTerminator()->eraseFromParent(); 255 LoopBuilder.CreateCondBr( 256 LoopBuilder.CreateICmpULT(NewIndex, RuntimeLoopCount), LoopBB, 257 PostLoopBB); 258 } 259 } 260 261 void llvm::createMemCpyLoop(Instruction *InsertBefore, 262 Value *SrcAddr, Value *DstAddr, Value *CopyLen, 263 unsigned SrcAlign, unsigned DestAlign, 264 bool SrcIsVolatile, bool DstIsVolatile) { 265 Type *TypeOfCopyLen = CopyLen->getType(); 266 267 BasicBlock *OrigBB = InsertBefore->getParent(); 268 Function *F = OrigBB->getParent(); 269 BasicBlock *NewBB = 270 InsertBefore->getParent()->splitBasicBlock(InsertBefore, "split"); 271 BasicBlock *LoopBB = BasicBlock::Create(F->getContext(), "loadstoreloop", 272 F, NewBB); 273 274 IRBuilder<> Builder(OrigBB->getTerminator()); 275 276 // SrcAddr and DstAddr are expected to be pointer types, 277 // so no check is made here. 278 unsigned SrcAS = cast<PointerType>(SrcAddr->getType())->getAddressSpace(); 279 unsigned DstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace(); 280 281 // Cast pointers to (char *) 282 SrcAddr = Builder.CreateBitCast(SrcAddr, Builder.getInt8PtrTy(SrcAS)); 283 DstAddr = Builder.CreateBitCast(DstAddr, Builder.getInt8PtrTy(DstAS)); 284 285 Builder.CreateCondBr( 286 Builder.CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB, 287 LoopBB); 288 OrigBB->getTerminator()->eraseFromParent(); 289 290 IRBuilder<> LoopBuilder(LoopBB); 291 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 0); 292 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB); 293 294 // load from SrcAddr+LoopIndex 295 // TODO: we can leverage the align parameter of llvm.memcpy for more efficient 296 // word-sized loads and stores. 297 Value *Element = 298 LoopBuilder.CreateLoad(LoopBuilder.CreateInBoundsGEP( 299 LoopBuilder.getInt8Ty(), SrcAddr, LoopIndex), 300 SrcIsVolatile); 301 // store at DstAddr+LoopIndex 302 LoopBuilder.CreateStore(Element, 303 LoopBuilder.CreateInBoundsGEP(LoopBuilder.getInt8Ty(), 304 DstAddr, LoopIndex), 305 DstIsVolatile); 306 307 // The value for LoopIndex coming from backedge is (LoopIndex + 1) 308 Value *NewIndex = 309 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1)); 310 LoopIndex->addIncoming(NewIndex, LoopBB); 311 312 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, CopyLen), LoopBB, 313 NewBB); 314 } 315 316 // Lower memmove to IR. memmove is required to correctly copy overlapping memory 317 // regions; therefore, it has to check the relative positions of the source and 318 // destination pointers and choose the copy direction accordingly. 319 // 320 // The code below is an IR rendition of this C function: 321 // 322 // void* memmove(void* dst, const void* src, size_t n) { 323 // unsigned char* d = dst; 324 // const unsigned char* s = src; 325 // if (s < d) { 326 // // copy backwards 327 // while (n--) { 328 // d[n] = s[n]; 329 // } 330 // } else { 331 // // copy forward 332 // for (size_t i = 0; i < n; ++i) { 333 // d[i] = s[i]; 334 // } 335 // } 336 // return dst; 337 // } 338 static void createMemMoveLoop(Instruction *InsertBefore, 339 Value *SrcAddr, Value *DstAddr, Value *CopyLen, 340 unsigned SrcAlign, unsigned DestAlign, 341 bool SrcIsVolatile, bool DstIsVolatile) { 342 Type *TypeOfCopyLen = CopyLen->getType(); 343 BasicBlock *OrigBB = InsertBefore->getParent(); 344 Function *F = OrigBB->getParent(); 345 346 // Create the a comparison of src and dst, based on which we jump to either 347 // the forward-copy part of the function (if src >= dst) or the backwards-copy 348 // part (if src < dst). 349 // SplitBlockAndInsertIfThenElse conveniently creates the basic if-then-else 350 // structure. Its block terminators (unconditional branches) are replaced by 351 // the appropriate conditional branches when the loop is built. 352 ICmpInst *PtrCompare = new ICmpInst(InsertBefore, ICmpInst::ICMP_ULT, 353 SrcAddr, DstAddr, "compare_src_dst"); 354 TerminatorInst *ThenTerm, *ElseTerm; 355 SplitBlockAndInsertIfThenElse(PtrCompare, InsertBefore, &ThenTerm, 356 &ElseTerm); 357 358 // Each part of the function consists of two blocks: 359 // copy_backwards: used to skip the loop when n == 0 360 // copy_backwards_loop: the actual backwards loop BB 361 // copy_forward: used to skip the loop when n == 0 362 // copy_forward_loop: the actual forward loop BB 363 BasicBlock *CopyBackwardsBB = ThenTerm->getParent(); 364 CopyBackwardsBB->setName("copy_backwards"); 365 BasicBlock *CopyForwardBB = ElseTerm->getParent(); 366 CopyForwardBB->setName("copy_forward"); 367 BasicBlock *ExitBB = InsertBefore->getParent(); 368 ExitBB->setName("memmove_done"); 369 370 // Initial comparison of n == 0 that lets us skip the loops altogether. Shared 371 // between both backwards and forward copy clauses. 372 ICmpInst *CompareN = 373 new ICmpInst(OrigBB->getTerminator(), ICmpInst::ICMP_EQ, CopyLen, 374 ConstantInt::get(TypeOfCopyLen, 0), "compare_n_to_0"); 375 376 // Copying backwards. 377 BasicBlock *LoopBB = 378 BasicBlock::Create(F->getContext(), "copy_backwards_loop", F, CopyForwardBB); 379 IRBuilder<> LoopBuilder(LoopBB); 380 PHINode *LoopPhi = LoopBuilder.CreatePHI(TypeOfCopyLen, 0); 381 Value *IndexPtr = LoopBuilder.CreateSub( 382 LoopPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_ptr"); 383 Value *Element = LoopBuilder.CreateLoad( 384 LoopBuilder.CreateInBoundsGEP(SrcAddr, IndexPtr), "element"); 385 LoopBuilder.CreateStore(Element, 386 LoopBuilder.CreateInBoundsGEP(DstAddr, IndexPtr)); 387 LoopBuilder.CreateCondBr( 388 LoopBuilder.CreateICmpEQ(IndexPtr, ConstantInt::get(TypeOfCopyLen, 0)), 389 ExitBB, LoopBB); 390 LoopPhi->addIncoming(IndexPtr, LoopBB); 391 LoopPhi->addIncoming(CopyLen, CopyBackwardsBB); 392 BranchInst::Create(ExitBB, LoopBB, CompareN, ThenTerm); 393 ThenTerm->eraseFromParent(); 394 395 // Copying forward. 396 BasicBlock *FwdLoopBB = 397 BasicBlock::Create(F->getContext(), "copy_forward_loop", F, ExitBB); 398 IRBuilder<> FwdLoopBuilder(FwdLoopBB); 399 PHINode *FwdCopyPhi = FwdLoopBuilder.CreatePHI(TypeOfCopyLen, 0, "index_ptr"); 400 Value *FwdElement = FwdLoopBuilder.CreateLoad( 401 FwdLoopBuilder.CreateInBoundsGEP(SrcAddr, FwdCopyPhi), "element"); 402 FwdLoopBuilder.CreateStore( 403 FwdElement, FwdLoopBuilder.CreateInBoundsGEP(DstAddr, FwdCopyPhi)); 404 Value *FwdIndexPtr = FwdLoopBuilder.CreateAdd( 405 FwdCopyPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_increment"); 406 FwdLoopBuilder.CreateCondBr(FwdLoopBuilder.CreateICmpEQ(FwdIndexPtr, CopyLen), 407 ExitBB, FwdLoopBB); 408 FwdCopyPhi->addIncoming(FwdIndexPtr, FwdLoopBB); 409 FwdCopyPhi->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), CopyForwardBB); 410 411 BranchInst::Create(ExitBB, FwdLoopBB, CompareN, ElseTerm); 412 ElseTerm->eraseFromParent(); 413 } 414 415 static void createMemSetLoop(Instruction *InsertBefore, 416 Value *DstAddr, Value *CopyLen, Value *SetValue, 417 unsigned Align, bool IsVolatile) { 418 Type *TypeOfCopyLen = CopyLen->getType(); 419 BasicBlock *OrigBB = InsertBefore->getParent(); 420 Function *F = OrigBB->getParent(); 421 BasicBlock *NewBB = 422 OrigBB->splitBasicBlock(InsertBefore, "split"); 423 BasicBlock *LoopBB 424 = BasicBlock::Create(F->getContext(), "loadstoreloop", F, NewBB); 425 426 IRBuilder<> Builder(OrigBB->getTerminator()); 427 428 // Cast pointer to the type of value getting stored 429 unsigned dstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace(); 430 DstAddr = Builder.CreateBitCast(DstAddr, 431 PointerType::get(SetValue->getType(), dstAS)); 432 433 Builder.CreateCondBr( 434 Builder.CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB, 435 LoopBB); 436 OrigBB->getTerminator()->eraseFromParent(); 437 438 IRBuilder<> LoopBuilder(LoopBB); 439 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 0); 440 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB); 441 442 LoopBuilder.CreateStore( 443 SetValue, 444 LoopBuilder.CreateInBoundsGEP(SetValue->getType(), DstAddr, LoopIndex), 445 IsVolatile); 446 447 Value *NewIndex = 448 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1)); 449 LoopIndex->addIncoming(NewIndex, LoopBB); 450 451 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, CopyLen), LoopBB, 452 NewBB); 453 } 454 455 void llvm::expandMemCpyAsLoop(MemCpyInst *Memcpy, 456 const TargetTransformInfo &TTI) { 457 // Original implementation 458 if (!TTI.useWideIRMemcpyLoopLowering()) { 459 createMemCpyLoop(/* InsertBefore */ Memcpy, 460 /* SrcAddr */ Memcpy->getRawSource(), 461 /* DstAddr */ Memcpy->getRawDest(), 462 /* CopyLen */ Memcpy->getLength(), 463 /* SrcAlign */ Memcpy->getAlignment(), 464 /* DestAlign */ Memcpy->getAlignment(), 465 /* SrcIsVolatile */ Memcpy->isVolatile(), 466 /* DstIsVolatile */ Memcpy->isVolatile()); 467 } else { 468 if (ConstantInt *CI = dyn_cast<ConstantInt>(Memcpy->getLength())) { 469 createMemCpyLoopKnownSize(/* InsertBefore */ Memcpy, 470 /* SrcAddr */ Memcpy->getRawSource(), 471 /* DstAddr */ Memcpy->getRawDest(), 472 /* CopyLen */ CI, 473 /* SrcAlign */ Memcpy->getAlignment(), 474 /* DestAlign */ Memcpy->getAlignment(), 475 /* SrcIsVolatile */ Memcpy->isVolatile(), 476 /* DstIsVolatile */ Memcpy->isVolatile(), 477 /* TargetTransformInfo */ TTI); 478 } else { 479 createMemCpyLoopUnknownSize(/* InsertBefore */ Memcpy, 480 /* SrcAddr */ Memcpy->getRawSource(), 481 /* DstAddr */ Memcpy->getRawDest(), 482 /* CopyLen */ Memcpy->getLength(), 483 /* SrcAlign */ Memcpy->getAlignment(), 484 /* DestAlign */ Memcpy->getAlignment(), 485 /* SrcIsVolatile */ Memcpy->isVolatile(), 486 /* DstIsVolatile */ Memcpy->isVolatile(), 487 /* TargetTransfomrInfo */ TTI); 488 } 489 } 490 } 491 492 void llvm::expandMemMoveAsLoop(MemMoveInst *Memmove) { 493 createMemMoveLoop(/* InsertBefore */ Memmove, 494 /* SrcAddr */ Memmove->getRawSource(), 495 /* DstAddr */ Memmove->getRawDest(), 496 /* CopyLen */ Memmove->getLength(), 497 /* SrcAlign */ Memmove->getAlignment(), 498 /* DestAlign */ Memmove->getAlignment(), 499 /* SrcIsVolatile */ Memmove->isVolatile(), 500 /* DstIsVolatile */ Memmove->isVolatile()); 501 } 502 503 void llvm::expandMemSetAsLoop(MemSetInst *Memset) { 504 createMemSetLoop(/* InsertBefore */ Memset, 505 /* DstAddr */ Memset->getRawDest(), 506 /* CopyLen */ Memset->getLength(), 507 /* SetValue */ Memset->getValue(), 508 /* Alignment */ Memset->getAlignment(), 509 Memset->isVolatile()); 510 } 511