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