Skip to content

Commit da6adba

Browse files
author
git apple-llvm automerger
committed
Merge commit '7d29f1315e5d' from apple/master into swift/master-next
2 parents 39d05a6 + 7d29f13 commit da6adba

File tree

2 files changed

+59
-70
lines changed

2 files changed

+59
-70
lines changed

llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ class MemCpyOptPass : public PassInfoMixin<MemCpyOptPass> {
5959
bool processStore(StoreInst *SI, BasicBlock::iterator &BBI);
6060
bool processMemSet(MemSetInst *SI, BasicBlock::iterator &BBI);
6161
bool processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI);
62-
bool processMemMove(MemMoveInst *M, BasicBlock::iterator &BBI);
62+
bool processMemMove(MemMoveInst *M);
6363
bool performCallSlotOptzn(Instruction *cpy, Value *cpyDst, Value *cpySrc,
6464
uint64_t cpyLen, Align cpyAlign, CallInst *C);
65-
Instruction *processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep);
66-
Instruction *processMemSetMemCpyDependence(MemCpyInst *M, MemSetInst *MDep);
67-
Instruction *performMemCpyToMemSetOptzn(MemCpyInst *M, MemSetInst *MDep);
65+
bool processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep);
66+
bool processMemSetMemCpyDependence(MemCpyInst *M, MemSetInst *MDep);
67+
bool performMemCpyToMemSetOptzn(MemCpyInst *M, MemSetInst *MDep);
6868
bool processByValArgument(CallBase &CB, unsigned ArgNo);
6969
Instruction *tryMergingIntoMemset(Instruction *I, Value *StartPtr,
7070
Value *ByteVal);

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 55 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,6 @@ static bool moveUp(AliasAnalysis &AA, StoreInst *SI, Instruction *P,
501501
return true;
502502
}
503503

504-
/// If changes are made, return true and set BBI to the next instruction to
505-
/// visit.
506504
bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
507505
if (!SI->isSimple()) return false;
508506

@@ -580,6 +578,7 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
580578
LI->eraseFromParent();
581579
++NumMemCpyInstr;
582580

581+
// Make sure we do not invalidate the iterator.
583582
BBI = M->getIterator();
584583
return true;
585584
}
@@ -643,7 +642,7 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
643642
if (Value *ByteVal = isBytewiseValue(V, DL)) {
644643
if (Instruction *I = tryMergingIntoMemset(SI, SI->getPointerOperand(),
645644
ByteVal)) {
646-
BBI = I->getIterator();
645+
BBI = I->getIterator(); // Don't invalidate iterator.
647646
return true;
648647
}
649648

@@ -663,6 +662,7 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
663662
SI->eraseFromParent();
664663
NumMemSetInfer++;
665664

665+
// Make sure we do not invalidate the iterator.
666666
BBI = M->getIterator();
667667
return true;
668668
}
@@ -671,15 +671,13 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
671671
return false;
672672
}
673673

674-
/// If changes are made, return true and set BBI to the next instruction to
675-
/// visit.
676674
bool MemCpyOptPass::processMemSet(MemSetInst *MSI, BasicBlock::iterator &BBI) {
677675
// See if there is another memset or store neighboring this memset which
678676
// allows us to widen out the memset to do a single larger store.
679677
if (isa<ConstantInt>(MSI->getLength()) && !MSI->isVolatile())
680678
if (Instruction *I = tryMergingIntoMemset(MSI, MSI->getDest(),
681679
MSI->getValue())) {
682-
BBI = I->getIterator();
680+
BBI = I->getIterator(); // Don't invalidate iterator.
683681
return true;
684682
}
685683
return false;
@@ -888,27 +886,27 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpy, Value *cpyDest,
888886

889887
/// We've found that the (upward scanning) memory dependence of memcpy 'M' is
890888
/// the memcpy 'MDep'. Try to simplify M to copy from MDep's input if we can.
891-
Instruction *MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
892-
MemCpyInst *MDep) {
889+
bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
890+
MemCpyInst *MDep) {
893891
// We can only transforms memcpy's where the dest of one is the source of the
894892
// other.
895893
if (M->getSource() != MDep->getDest() || MDep->isVolatile())
896-
return nullptr;
894+
return false;
897895

898896
// If dep instruction is reading from our current input, then it is a noop
899897
// transfer and substituting the input won't change this instruction. Just
900898
// ignore the input and let someone else zap MDep. This handles cases like:
901899
// memcpy(a <- a)
902900
// memcpy(b <- a)
903901
if (M->getSource() == MDep->getSource())
904-
return nullptr;
902+
return false;
905903

906904
// Second, the length of the memcpy's must be the same, or the preceding one
907905
// must be larger than the following one.
908906
ConstantInt *MDepLen = dyn_cast<ConstantInt>(MDep->getLength());
909907
ConstantInt *MLen = dyn_cast<ConstantInt>(M->getLength());
910908
if (!MDepLen || !MLen || MDepLen->getZExtValue() < MLen->getZExtValue())
911-
return nullptr;
909+
return false;
912910

913911
AliasAnalysis &AA = LookupAliasAnalysis();
914912

@@ -928,7 +926,7 @@ Instruction *MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
928926
MD->getPointerDependencyFrom(MemoryLocation::getForSource(MDep), false,
929927
M->getIterator(), M->getParent());
930928
if (!SourceDep.isClobber() || SourceDep.getInst() != MDep)
931-
return nullptr;
929+
return false;
932930

933931
// If the dest of the second might alias the source of the first, then the
934932
// source and dest might overlap. We still want to eliminate the intermediate
@@ -945,21 +943,20 @@ Instruction *MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
945943
// TODO: Is this worth it if we're creating a less aligned memcpy? For
946944
// example we could be moving from movaps -> movq on x86.
947945
IRBuilder<> Builder(M);
948-
Instruction *MC;
949946
if (UseMemMove)
950-
MC = Builder.CreateMemMove(M->getRawDest(), M->getDestAlign(),
951-
MDep->getRawSource(), MDep->getSourceAlign(),
952-
M->getLength(), M->isVolatile());
947+
Builder.CreateMemMove(M->getRawDest(), M->getDestAlign(),
948+
MDep->getRawSource(), MDep->getSourceAlign(),
949+
M->getLength(), M->isVolatile());
953950
else
954-
MC = Builder.CreateMemCpy(M->getRawDest(), M->getDestAlign(),
955-
MDep->getRawSource(), MDep->getSourceAlign(),
956-
M->getLength(), M->isVolatile());
951+
Builder.CreateMemCpy(M->getRawDest(), M->getDestAlign(),
952+
MDep->getRawSource(), MDep->getSourceAlign(),
953+
M->getLength(), M->isVolatile());
957954

958955
// Remove the instruction we're replacing.
959956
MD->removeInstruction(M);
960957
M->eraseFromParent();
961958
++NumMemCpyInstr;
962-
return MC;
959+
return true;
963960
}
964961

965962
/// We've found that the (upward scanning) memory dependence of \p MemCpy is
@@ -976,18 +973,18 @@ Instruction *MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
976973
/// memcpy(dst, src, src_size);
977974
/// memset(dst + src_size, c, dst_size <= src_size ? 0 : dst_size - src_size);
978975
/// \endcode
979-
Instruction *MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
980-
MemSetInst *MemSet) {
976+
bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
977+
MemSetInst *MemSet) {
981978
// We can only transform memset/memcpy with the same destination.
982979
if (MemSet->getDest() != MemCpy->getDest())
983-
return nullptr;
980+
return false;
984981

985982
// Check that there are no other dependencies on the memset destination.
986983
MemDepResult DstDepInfo =
987984
MD->getPointerDependencyFrom(MemoryLocation::getForDest(MemSet), false,
988985
MemCpy->getIterator(), MemCpy->getParent());
989986
if (DstDepInfo.getInst() != MemSet)
990-
return nullptr;
987+
return false;
991988

992989
// Use the same i8* dest as the memcpy, killing the memset dest if different.
993990
Value *Dest = MemCpy->getRawDest();
@@ -1019,14 +1016,14 @@ Instruction *MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
10191016
Value *SizeDiff = Builder.CreateSub(DestSize, SrcSize);
10201017
Value *MemsetLen = Builder.CreateSelect(
10211018
Ule, ConstantInt::getNullValue(DestSize->getType()), SizeDiff);
1022-
auto *MS = Builder.CreateMemSet(
1019+
Builder.CreateMemSet(
10231020
Builder.CreateGEP(Dest->getType()->getPointerElementType(), Dest,
10241021
SrcSize),
10251022
MemSet->getOperand(1), MemsetLen, MaybeAlign(Align));
10261023

10271024
MD->removeInstruction(MemSet);
10281025
MemSet->eraseFromParent();
1029-
return MS;
1026+
return true;
10301027
}
10311028

10321029
/// Determine whether the instruction has undefined content for the given Size,
@@ -1058,19 +1055,19 @@ static bool hasUndefContents(Instruction *I, ConstantInt *Size) {
10581055
/// When dst2_size <= dst1_size.
10591056
///
10601057
/// The \p MemCpy must have a Constant length.
1061-
Instruction *MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
1062-
MemSetInst *MemSet) {
1058+
bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
1059+
MemSetInst *MemSet) {
10631060
AliasAnalysis &AA = LookupAliasAnalysis();
10641061

10651062
// Make sure that memcpy(..., memset(...), ...), that is we are memsetting and
10661063
// memcpying from the same address. Otherwise it is hard to reason about.
10671064
if (!AA.isMustAlias(MemSet->getRawDest(), MemCpy->getRawSource()))
1068-
return nullptr;
1065+
return false;
10691066

10701067
// A known memset size is required.
10711068
ConstantInt *MemSetSize = dyn_cast<ConstantInt>(MemSet->getLength());
10721069
if (!MemSetSize)
1073-
return nullptr;
1070+
return false;
10741071

10751072
// Make sure the memcpy doesn't read any more than what the memset wrote.
10761073
// Don't worry about sizes larger than i64.
@@ -1086,62 +1083,54 @@ Instruction *MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
10861083
if (DepInfo.isDef() && hasUndefContents(DepInfo.getInst(), CopySize))
10871084
CopySize = MemSetSize;
10881085
else
1089-
return nullptr;
1086+
return false;
10901087
}
10911088

10921089
IRBuilder<> Builder(MemCpy);
1093-
return Builder.CreateMemSet(MemCpy->getRawDest(), MemSet->getOperand(1),
1094-
CopySize, MaybeAlign(MemCpy->getDestAlignment()));
1090+
Builder.CreateMemSet(MemCpy->getRawDest(), MemSet->getOperand(1), CopySize,
1091+
MaybeAlign(MemCpy->getDestAlignment()));
1092+
return true;
10951093
}
10961094

10971095
/// Perform simplification of memcpy's. If we have memcpy A
10981096
/// which copies X to Y, and memcpy B which copies Y to Z, then we can rewrite
10991097
/// B to be a memcpy from X to Z (or potentially a memmove, depending on
11001098
/// circumstances). This allows later passes to remove the first memcpy
11011099
/// altogether.
1102-
/// If changes are made, return true and set BBI to the next instruction to
1103-
/// visit.
11041100
bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
11051101
// We can only optimize non-volatile memcpy's.
11061102
if (M->isVolatile()) return false;
11071103

11081104
// If the source and destination of the memcpy are the same, then zap it.
11091105
if (M->getSource() == M->getDest()) {
1106+
++BBI;
11101107
MD->removeInstruction(M);
11111108
M->eraseFromParent();
11121109
return true;
11131110
}
11141111

11151112
// If copying from a constant, try to turn the memcpy into a memset.
1116-
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(M->getSource())) {
1117-
if (GV->isConstant() && GV->hasDefinitiveInitializer()) {
1113+
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(M->getSource()))
1114+
if (GV->isConstant() && GV->hasDefinitiveInitializer())
11181115
if (Value *ByteVal = isBytewiseValue(GV->getInitializer(),
11191116
M->getModule()->getDataLayout())) {
11201117
IRBuilder<> Builder(M);
1121-
auto *MS =
1122-
Builder.CreateMemSet(M->getRawDest(), ByteVal, M->getLength(),
1123-
MaybeAlign(M->getDestAlignment()), false);
1118+
Builder.CreateMemSet(M->getRawDest(), ByteVal, M->getLength(),
1119+
MaybeAlign(M->getDestAlignment()), false);
11241120
MD->removeInstruction(M);
11251121
M->eraseFromParent();
11261122
++NumCpyToSet;
1127-
BBI = MS->getIterator();
11281123
return true;
11291124
}
1130-
}
1131-
}
11321125

11331126
MemDepResult DepInfo = MD->getDependency(M);
11341127

11351128
// Try to turn a partially redundant memset + memcpy into
11361129
// memcpy + smaller memset. We don't need the memcpy size for this.
1137-
if (DepInfo.isClobber()) {
1138-
if (MemSetInst *MDep = dyn_cast<MemSetInst>(DepInfo.getInst())) {
1139-
if (auto *MS = processMemSetMemCpyDependence(M, MDep)) {
1140-
BBI = MS->getIterator();
1130+
if (DepInfo.isClobber())
1131+
if (MemSetInst *MDep = dyn_cast<MemSetInst>(DepInfo.getInst()))
1132+
if (processMemSetMemCpyDependence(M, MDep))
11411133
return true;
1142-
}
1143-
}
1144-
}
11451134

11461135
// The optimizations after this point require the memcpy size.
11471136
ConstantInt *CopySize = dyn_cast<ConstantInt>(M->getLength());
@@ -1174,13 +1163,8 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
11741163
SrcLoc, true, M->getIterator(), M->getParent());
11751164

11761165
if (SrcDepInfo.isClobber()) {
1177-
if (MemCpyInst *MDep = dyn_cast<MemCpyInst>(SrcDepInfo.getInst())) {
1178-
if (auto *MC = processMemCpyMemCpyDependence(M, MDep)) {
1179-
BBI = MC->getIterator();
1180-
return true;
1181-
}
1182-
return false;
1183-
}
1166+
if (MemCpyInst *MDep = dyn_cast<MemCpyInst>(SrcDepInfo.getInst()))
1167+
return processMemCpyMemCpyDependence(M, MDep);
11841168
} else if (SrcDepInfo.isDef()) {
11851169
if (hasUndefContents(SrcDepInfo.getInst(), CopySize)) {
11861170
MD->removeInstruction(M);
@@ -1192,11 +1176,10 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
11921176

11931177
if (SrcDepInfo.isClobber())
11941178
if (MemSetInst *MDep = dyn_cast<MemSetInst>(SrcDepInfo.getInst()))
1195-
if (auto *MS = performMemCpyToMemSetOptzn(M, MDep)) {
1179+
if (performMemCpyToMemSetOptzn(M, MDep)) {
11961180
MD->removeInstruction(M);
11971181
M->eraseFromParent();
11981182
++NumCpyToSet;
1199-
BBI = MS->getIterator();
12001183
return true;
12011184
}
12021185

@@ -1205,9 +1188,7 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
12051188

12061189
/// Transforms memmove calls to memcpy calls when the src/dst are guaranteed
12071190
/// not to alias.
1208-
/// If changes are made, return true and set BBI to the next instruction to
1209-
/// visit.
1210-
bool MemCpyOptPass::processMemMove(MemMoveInst *M, BasicBlock::iterator &BBI) {
1191+
bool MemCpyOptPass::processMemMove(MemMoveInst *M) {
12111192
AliasAnalysis &AA = LookupAliasAnalysis();
12121193

12131194
if (!TLI->has(LibFunc_memmove))
@@ -1233,7 +1214,6 @@ bool MemCpyOptPass::processMemMove(MemMoveInst *M, BasicBlock::iterator &BBI) {
12331214
MD->removeInstruction(M);
12341215

12351216
++NumMoveToCpy;
1236-
BBI = M->getIterator();
12371217
return true;
12381218
}
12391219

@@ -1336,19 +1316,28 @@ bool MemCpyOptPass::iterateOnFunction(Function &F) {
13361316
// Avoid invalidating the iterator.
13371317
Instruction *I = &*BI++;
13381318

1319+
bool RepeatInstruction = false;
1320+
13391321
if (StoreInst *SI = dyn_cast<StoreInst>(I))
13401322
MadeChange |= processStore(SI, BI);
13411323
else if (MemSetInst *M = dyn_cast<MemSetInst>(I))
1342-
MadeChange = processMemSet(M, BI);
1324+
RepeatInstruction = processMemSet(M, BI);
13431325
else if (MemCpyInst *M = dyn_cast<MemCpyInst>(I))
1344-
MadeChange = processMemCpy(M, BI);
1326+
RepeatInstruction = processMemCpy(M, BI);
13451327
else if (MemMoveInst *M = dyn_cast<MemMoveInst>(I))
1346-
MadeChange = processMemMove(M, BI);
1328+
RepeatInstruction = processMemMove(M);
13471329
else if (auto *CB = dyn_cast<CallBase>(I)) {
13481330
for (unsigned i = 0, e = CB->arg_size(); i != e; ++i)
13491331
if (CB->isByValArgument(i))
13501332
MadeChange |= processByValArgument(*CB, i);
13511333
}
1334+
1335+
// Reprocess the instruction if desired.
1336+
if (RepeatInstruction) {
1337+
if (BI != BB.begin())
1338+
--BI;
1339+
MadeChange = true;
1340+
}
13521341
}
13531342
}
13541343

0 commit comments

Comments
 (0)