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