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