@@ -481,6 +481,17 @@ Instruction *MemCpyOpt::tryMergingIntoMemset(Instruction *StartInst,
481
481
return AMemSet;
482
482
}
483
483
484
+ static unsigned findCommonAlignment (const DataLayout &DL, const StoreInst *SI,
485
+ const LoadInst *LI) {
486
+ unsigned StoreAlign = SI->getAlignment ();
487
+ if (!StoreAlign)
488
+ StoreAlign = DL.getABITypeAlignment (SI->getOperand (0 )->getType ());
489
+ unsigned LoadAlign = LI->getAlignment ();
490
+ if (!LoadAlign)
491
+ LoadAlign = DL.getABITypeAlignment (LI->getType ());
492
+
493
+ return std::min (StoreAlign, LoadAlign);
494
+ }
484
495
485
496
bool MemCpyOpt::processStore (StoreInst *SI, BasicBlock::iterator &BBI) {
486
497
if (!SI->isSimple ()) return false ;
@@ -496,12 +507,70 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
496
507
497
508
const DataLayout &DL = SI->getModule ()->getDataLayout ();
498
509
499
- // Detect cases where we're performing call slot forwarding, but
500
- // happen to be using a load-store pair to implement it, rather than
501
- // a memcpy.
510
+ // Load to store forwarding can be interpreted as memcpy.
502
511
if (LoadInst *LI = dyn_cast<LoadInst>(SI->getOperand (0 ))) {
503
512
if (LI->isSimple () && LI->hasOneUse () &&
504
513
LI->getParent () == SI->getParent ()) {
514
+
515
+ auto *T = LI->getType ();
516
+ if (T->isAggregateType ()) {
517
+ AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults ();
518
+ MemoryLocation LoadLoc = MemoryLocation::get (LI);
519
+
520
+ // We use alias analysis to check if an instruction may store to
521
+ // the memory we load from in between the load and the store. If
522
+ // such an instruction is found, we store it in AI.
523
+ Instruction *AI = nullptr ;
524
+ for (BasicBlock::iterator I = ++LI->getIterator (), E = SI->getIterator ();
525
+ I != E; ++I) {
526
+ if (AA.getModRefInfo (&*I, LoadLoc) & MRI_Mod) {
527
+ AI = &*I;
528
+ break ;
529
+ }
530
+ }
531
+
532
+ // If no aliasing instruction is found, then we can promote the
533
+ // load/store pair to a memcpy at the store loaction.
534
+ if (!AI) {
535
+ // If we load from memory that may alias the memory we store to,
536
+ // memmove must be used to preserve semantic. If not, memcpy can
537
+ // be used.
538
+ bool UseMemMove = false ;
539
+ if (!AA.isNoAlias (MemoryLocation::get (SI), LoadLoc))
540
+ UseMemMove = true ;
541
+
542
+ unsigned Align = findCommonAlignment (DL, SI, LI);
543
+ uint64_t Size = DL.getTypeStoreSize (T);
544
+
545
+ IRBuilder<> Builder (SI);
546
+ Instruction *M;
547
+ if (UseMemMove)
548
+ M = Builder.CreateMemMove (SI->getPointerOperand (),
549
+ LI->getPointerOperand (), Size ,
550
+ Align, SI->isVolatile ());
551
+ else
552
+ M = Builder.CreateMemCpy (SI->getPointerOperand (),
553
+ LI->getPointerOperand (), Size ,
554
+ Align, SI->isVolatile ());
555
+
556
+ DEBUG (dbgs () << " Promoting " << *LI << " to " << *SI
557
+ << " => " << *M << " \n " );
558
+
559
+ MD->removeInstruction (SI);
560
+ SI->eraseFromParent ();
561
+ MD->removeInstruction (LI);
562
+ LI->eraseFromParent ();
563
+ ++NumMemCpyInstr;
564
+
565
+ // Make sure we do not invalidate the iterator.
566
+ BBI = M->getIterator ();
567
+ return true ;
568
+ }
569
+ }
570
+
571
+ // Detect cases where we're performing call slot forwarding, but
572
+ // happen to be using a load-store pair to implement it, rather than
573
+ // a memcpy.
505
574
MemDepResult ldep = MD->getDependency (LI);
506
575
CallInst *C = nullptr ;
507
576
if (ldep.isClobber () && !isa<MemCpyInst>(ldep.getInst ()))
@@ -522,18 +591,11 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
522
591
}
523
592
524
593
if (C) {
525
- unsigned storeAlign = SI->getAlignment ();
526
- if (!storeAlign)
527
- storeAlign = DL.getABITypeAlignment (SI->getOperand (0 )->getType ());
528
- unsigned loadAlign = LI->getAlignment ();
529
- if (!loadAlign)
530
- loadAlign = DL.getABITypeAlignment (LI->getType ());
531
-
532
594
bool changed = performCallSlotOptzn (
533
595
LI, SI->getPointerOperand ()->stripPointerCasts (),
534
596
LI->getPointerOperand ()->stripPointerCasts (),
535
597
DL.getTypeStoreSize (SI->getOperand (0 )->getType ()),
536
- std::min (storeAlign, loadAlign ), C);
598
+ findCommonAlignment (DL, SI, LI ), C);
537
599
if (changed) {
538
600
MD->removeInstruction (SI);
539
601
SI->eraseFromParent ();
0 commit comments