@@ -311,6 +311,22 @@ INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
311
311
INITIALIZE_PASS_END(MemCpyOptLegacyPass, " memcpyopt" , " MemCpy Optimization" ,
312
312
false , false )
313
313
314
+ // Check that V is either not accessible by the caller, or unwinding cannot
315
+ // occur between Start and End.
316
+ static bool mayBeVisibleThroughUnwinding(Value *V, Instruction *Start,
317
+ Instruction *End) {
318
+ assert (Start->getParent () == End->getParent () && " Must be in same block" );
319
+ if (!Start->getFunction ()->doesNotThrow () &&
320
+ !isa<AllocaInst>(getUnderlyingObject (V))) {
321
+ for (const Instruction &I :
322
+ make_range (Start->getIterator (), End->getIterator ())) {
323
+ if (I.mayThrow ())
324
+ return true ;
325
+ }
326
+ }
327
+ return false ;
328
+ }
329
+
314
330
void MemCpyOptPass::eraseInstruction (Instruction *I) {
315
331
if (MSSAU)
316
332
MSSAU->removeMemoryAccess (I);
@@ -848,16 +864,8 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
848
864
// guaranteed to be executed if C is. As it is a non-atomic access, it
849
865
// renders accesses from other threads undefined.
850
866
// TODO: This is currently not checked.
851
- // TODO: Check underlying object, so we can look through GEPs.
852
- if (!isa<AllocaInst>(cpyDest)) {
853
- assert (C->getParent () == cpyStore->getParent () &&
854
- " call and copy must be in the same block" );
855
- for (const Instruction &I : make_range (C->getIterator (),
856
- cpyStore->getIterator ())) {
857
- if (I.mayThrow ())
858
- return false ;
859
- }
860
- }
867
+ if (mayBeVisibleThroughUnwinding (cpyDest, C, cpyStore))
868
+ return false ;
861
869
862
870
// Check that dest points to memory that is at least as aligned as src.
863
871
Align srcAlign = srcAlloca->getAlign ();
@@ -1094,16 +1102,8 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
1094
1102
Value *DestSize = MemSet->getLength ();
1095
1103
Value *SrcSize = MemCpy->getLength ();
1096
1104
1097
- // If the destination might be accessible by the caller, make sure we cannot
1098
- // unwind between the memset and the memcpy.
1099
- if (!MemCpy->getFunction ()->doesNotThrow () &&
1100
- !isa<AllocaInst>(getUnderlyingObject (Dest))) {
1101
- for (const Instruction &I :
1102
- make_range (MemSet->getIterator (), MemCpy->getIterator ())) {
1103
- if (I.mayThrow ())
1104
- return false ;
1105
- }
1106
- }
1105
+ if (mayBeVisibleThroughUnwinding (Dest, MemSet, MemCpy))
1106
+ return false ;
1107
1107
1108
1108
// By default, create an unaligned memset.
1109
1109
unsigned Align = 1 ;
0 commit comments