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 // TODO: Use different element type if possible? 301 IRBuilder<> CastBuilder(InsertBefore); 302 Type *EltTy = CastBuilder.getInt8Ty(); 303 Type *PtrTy = 304 CastBuilder.getInt8PtrTy(SrcAddr->getType()->getPointerAddressSpace()); 305 SrcAddr = CastBuilder.CreateBitCast(SrcAddr, PtrTy); 306 DstAddr = CastBuilder.CreateBitCast(DstAddr, PtrTy); 307 308 // Create the a comparison of src and dst, based on which we jump to either 309 // the forward-copy part of the function (if src >= dst) or the backwards-copy 310 // part (if src < dst). 311 // SplitBlockAndInsertIfThenElse conveniently creates the basic if-then-else 312 // structure. Its block terminators (unconditional branches) are replaced by 313 // the appropriate conditional branches when the loop is built. 314 ICmpInst *PtrCompare = new ICmpInst(InsertBefore, ICmpInst::ICMP_ULT, 315 SrcAddr, DstAddr, "compare_src_dst"); 316 Instruction *ThenTerm, *ElseTerm; 317 SplitBlockAndInsertIfThenElse(PtrCompare, InsertBefore, &ThenTerm, 318 &ElseTerm); 319 320 // Each part of the function consists of two blocks: 321 // copy_backwards: used to skip the loop when n == 0 322 // copy_backwards_loop: the actual backwards loop BB 323 // copy_forward: used to skip the loop when n == 0 324 // copy_forward_loop: the actual forward loop BB 325 BasicBlock *CopyBackwardsBB = ThenTerm->getParent(); 326 CopyBackwardsBB->setName("copy_backwards"); 327 BasicBlock *CopyForwardBB = ElseTerm->getParent(); 328 CopyForwardBB->setName("copy_forward"); 329 BasicBlock *ExitBB = InsertBefore->getParent(); 330 ExitBB->setName("memmove_done"); 331 332 unsigned PartSize = DL.getTypeStoreSize(EltTy); 333 Align PartSrcAlign(commonAlignment(SrcAlign, PartSize)); 334 Align PartDstAlign(commonAlignment(DstAlign, PartSize)); 335 336 // Initial comparison of n == 0 that lets us skip the loops altogether. Shared 337 // between both backwards and forward copy clauses. 338 ICmpInst *CompareN = 339 new ICmpInst(OrigBB->getTerminator(), ICmpInst::ICMP_EQ, CopyLen, 340 ConstantInt::get(TypeOfCopyLen, 0), "compare_n_to_0"); 341 342 // Copying backwards. 343 BasicBlock *LoopBB = 344 BasicBlock::Create(F->getContext(), "copy_backwards_loop", F, CopyForwardBB); 345 IRBuilder<> LoopBuilder(LoopBB); 346 PHINode *LoopPhi = LoopBuilder.CreatePHI(TypeOfCopyLen, 0); 347 Value *IndexPtr = LoopBuilder.CreateSub( 348 LoopPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_ptr"); 349 Value *Element = LoopBuilder.CreateAlignedLoad( 350 EltTy, LoopBuilder.CreateInBoundsGEP(EltTy, SrcAddr, IndexPtr), 351 PartSrcAlign, "element"); 352 LoopBuilder.CreateAlignedStore( 353 Element, LoopBuilder.CreateInBoundsGEP(EltTy, DstAddr, IndexPtr), 354 PartDstAlign); 355 LoopBuilder.CreateCondBr( 356 LoopBuilder.CreateICmpEQ(IndexPtr, ConstantInt::get(TypeOfCopyLen, 0)), 357 ExitBB, LoopBB); 358 LoopPhi->addIncoming(IndexPtr, LoopBB); 359 LoopPhi->addIncoming(CopyLen, CopyBackwardsBB); 360 BranchInst::Create(ExitBB, LoopBB, CompareN, ThenTerm); 361 ThenTerm->eraseFromParent(); 362 363 // Copying forward. 364 BasicBlock *FwdLoopBB = 365 BasicBlock::Create(F->getContext(), "copy_forward_loop", F, ExitBB); 366 IRBuilder<> FwdLoopBuilder(FwdLoopBB); 367 PHINode *FwdCopyPhi = FwdLoopBuilder.CreatePHI(TypeOfCopyLen, 0, "index_ptr"); 368 Value *SrcGEP = FwdLoopBuilder.CreateInBoundsGEP(EltTy, SrcAddr, FwdCopyPhi); 369 Value *FwdElement = 370 FwdLoopBuilder.CreateAlignedLoad(EltTy, SrcGEP, PartSrcAlign, "element"); 371 Value *DstGEP = FwdLoopBuilder.CreateInBoundsGEP(EltTy, DstAddr, FwdCopyPhi); 372 FwdLoopBuilder.CreateAlignedStore(FwdElement, DstGEP, PartDstAlign); 373 Value *FwdIndexPtr = FwdLoopBuilder.CreateAdd( 374 FwdCopyPhi, ConstantInt::get(TypeOfCopyLen, 1), "index_increment"); 375 FwdLoopBuilder.CreateCondBr(FwdLoopBuilder.CreateICmpEQ(FwdIndexPtr, CopyLen), 376 ExitBB, FwdLoopBB); 377 FwdCopyPhi->addIncoming(FwdIndexPtr, FwdLoopBB); 378 FwdCopyPhi->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), CopyForwardBB); 379 380 BranchInst::Create(ExitBB, FwdLoopBB, CompareN, ElseTerm); 381 ElseTerm->eraseFromParent(); 382 } 383 384 static void createMemSetLoop(Instruction *InsertBefore, Value *DstAddr, 385 Value *CopyLen, Value *SetValue, Align DstAlign, 386 bool IsVolatile) { 387 Type *TypeOfCopyLen = CopyLen->getType(); 388 BasicBlock *OrigBB = InsertBefore->getParent(); 389 Function *F = OrigBB->getParent(); 390 const DataLayout &DL = F->getParent()->getDataLayout(); 391 BasicBlock *NewBB = 392 OrigBB->splitBasicBlock(InsertBefore, "split"); 393 BasicBlock *LoopBB 394 = BasicBlock::Create(F->getContext(), "loadstoreloop", F, NewBB); 395 396 IRBuilder<> Builder(OrigBB->getTerminator()); 397 398 // Cast pointer to the type of value getting stored 399 unsigned dstAS = cast<PointerType>(DstAddr->getType())->getAddressSpace(); 400 DstAddr = Builder.CreateBitCast(DstAddr, 401 PointerType::get(SetValue->getType(), dstAS)); 402 403 Builder.CreateCondBr( 404 Builder.CreateICmpEQ(ConstantInt::get(TypeOfCopyLen, 0), CopyLen), NewBB, 405 LoopBB); 406 OrigBB->getTerminator()->eraseFromParent(); 407 408 unsigned PartSize = DL.getTypeStoreSize(SetValue->getType()); 409 Align PartAlign(commonAlignment(DstAlign, PartSize)); 410 411 IRBuilder<> LoopBuilder(LoopBB); 412 PHINode *LoopIndex = LoopBuilder.CreatePHI(TypeOfCopyLen, 0); 413 LoopIndex->addIncoming(ConstantInt::get(TypeOfCopyLen, 0), OrigBB); 414 415 LoopBuilder.CreateAlignedStore( 416 SetValue, 417 LoopBuilder.CreateInBoundsGEP(SetValue->getType(), DstAddr, LoopIndex), 418 PartAlign, IsVolatile); 419 420 Value *NewIndex = 421 LoopBuilder.CreateAdd(LoopIndex, ConstantInt::get(TypeOfCopyLen, 1)); 422 LoopIndex->addIncoming(NewIndex, LoopBB); 423 424 LoopBuilder.CreateCondBr(LoopBuilder.CreateICmpULT(NewIndex, CopyLen), LoopBB, 425 NewBB); 426 } 427 428 void llvm::expandMemCpyAsLoop(MemCpyInst *Memcpy, 429 const TargetTransformInfo &TTI) { 430 if (ConstantInt *CI = dyn_cast<ConstantInt>(Memcpy->getLength())) { 431 createMemCpyLoopKnownSize( 432 /* InsertBefore */ Memcpy, 433 /* SrcAddr */ Memcpy->getRawSource(), 434 /* DstAddr */ Memcpy->getRawDest(), 435 /* CopyLen */ CI, 436 /* SrcAlign */ Memcpy->getSourceAlign().valueOrOne(), 437 /* DestAlign */ Memcpy->getDestAlign().valueOrOne(), 438 /* SrcIsVolatile */ Memcpy->isVolatile(), 439 /* DstIsVolatile */ Memcpy->isVolatile(), 440 /* TargetTransformInfo */ TTI); 441 } else { 442 createMemCpyLoopUnknownSize( 443 /* InsertBefore */ Memcpy, 444 /* SrcAddr */ Memcpy->getRawSource(), 445 /* DstAddr */ Memcpy->getRawDest(), 446 /* CopyLen */ Memcpy->getLength(), 447 /* SrcAlign */ Memcpy->getSourceAlign().valueOrOne(), 448 /* DestAlign */ Memcpy->getDestAlign().valueOrOne(), 449 /* SrcIsVolatile */ Memcpy->isVolatile(), 450 /* DstIsVolatile */ Memcpy->isVolatile(), 451 /* TargetTransformInfo */ TTI); 452 } 453 } 454 455 void llvm::expandMemMoveAsLoop(MemMoveInst *Memmove) { 456 createMemMoveLoop(/* InsertBefore */ Memmove, 457 /* SrcAddr */ Memmove->getRawSource(), 458 /* DstAddr */ Memmove->getRawDest(), 459 /* CopyLen */ Memmove->getLength(), 460 /* SrcAlign */ Memmove->getSourceAlign().valueOrOne(), 461 /* DestAlign */ Memmove->getDestAlign().valueOrOne(), 462 /* SrcIsVolatile */ Memmove->isVolatile(), 463 /* DstIsVolatile */ Memmove->isVolatile()); 464 } 465 466 void llvm::expandMemSetAsLoop(MemSetInst *Memset) { 467 createMemSetLoop(/* InsertBefore */ Memset, 468 /* DstAddr */ Memset->getRawDest(), 469 /* CopyLen */ Memset->getLength(), 470 /* SetValue */ Memset->getValue(), 471 /* Alignment */ Memset->getDestAlign().valueOrOne(), 472 Memset->isVolatile()); 473 } 474