@@ -756,9 +756,8 @@ struct DSEState {
756
756
SmallVector<MemoryDef *, 64 > MemDefs;
757
757
// Any that should be skipped as they are already deleted
758
758
SmallPtrSet<MemoryAccess *, 4 > SkipStores;
759
- // Keep track of all of the objects that are invisible to the caller before
760
- // the function returns.
761
- DenseMap<const Value *, bool > InvisibleToCallerBeforeRet;
759
+ // Keep track whether a given object is captured before return or not.
760
+ DenseMap<const Value *, bool > CapturedBeforeReturn;
762
761
// Keep track of all of the objects that are invisible to the caller after
763
762
// the function returns.
764
763
DenseMap<const Value *, bool > InvisibleToCallerAfterRet;
@@ -801,12 +800,8 @@ struct DSEState {
801
800
// Treat byval or inalloca arguments the same as Allocas, stores to them are
802
801
// dead at the end of the function.
803
802
for (Argument &AI : F.args ())
804
- if (AI.hasPassPointeeByValueCopyAttr ()) {
805
- // For byval, the caller doesn't know the address of the allocation.
806
- if (AI.hasByValAttr ())
807
- InvisibleToCallerBeforeRet.insert ({&AI, true });
803
+ if (AI.hasPassPointeeByValueCopyAttr ())
808
804
InvisibleToCallerAfterRet.insert ({&AI, true });
809
- }
810
805
811
806
// Collect whether there is any irreducible control flow in the function.
812
807
ContainsIrreducibleLoops = mayContainIrreducibleControl (F, &LI);
@@ -953,7 +948,7 @@ struct DSEState {
953
948
return true ;
954
949
auto I = InvisibleToCallerAfterRet.insert ({V, false });
955
950
if (I.second ) {
956
- if (!isInvisibleToCallerBeforeRet (V)) {
951
+ if (!isInvisibleToCallerOnUnwind (V)) {
957
952
I.first ->second = false ;
958
953
} else if (isNoAliasCall (V)) {
959
954
I.first ->second = !PointerMayBeCaptured (V, true , false );
@@ -962,17 +957,21 @@ struct DSEState {
962
957
return I.first ->second ;
963
958
}
964
959
965
- bool isInvisibleToCallerBeforeRet (const Value *V) {
966
- if (isa<AllocaInst>(V))
960
+ bool isInvisibleToCallerOnUnwind (const Value *V) {
961
+ bool RequiresNoCaptureBeforeUnwind;
962
+ if (!isNotVisibleOnUnwind (V, RequiresNoCaptureBeforeUnwind))
963
+ return false ;
964
+ if (!RequiresNoCaptureBeforeUnwind)
967
965
return true ;
968
- auto I = InvisibleToCallerBeforeRet.insert ({V, false });
969
- if (I.second && isNoAliasCall (V))
966
+
967
+ auto I = CapturedBeforeReturn.insert ({V, true });
968
+ if (I.second )
970
969
// NOTE: This could be made more precise by PointerMayBeCapturedBefore
971
970
// with the killing MemoryDef. But we refrain from doing so for now to
972
971
// limit compile-time and this does not cause any changes to the number
973
972
// of stores removed on a large test set in practice.
974
- I.first ->second = ! PointerMayBeCaptured (V, false , true );
975
- return I.first ->second ;
973
+ I.first ->second = PointerMayBeCaptured (V, false , true );
974
+ return ! I.first ->second ;
976
975
}
977
976
978
977
Optional<MemoryLocation> getLocForWrite (Instruction *I) const {
@@ -1260,8 +1259,7 @@ struct DSEState {
1260
1259
MemoryDef *CurrentDef = cast<MemoryDef>(Current);
1261
1260
Instruction *CurrentI = CurrentDef->getMemoryInst ();
1262
1261
1263
- if (canSkipDef (CurrentDef,
1264
- !isInvisibleToCallerBeforeRet (KillingUndObj))) {
1262
+ if (canSkipDef (CurrentDef, !isInvisibleToCallerOnUnwind (KillingUndObj))) {
1265
1263
CanOptimize = false ;
1266
1264
continue ;
1267
1265
}
@@ -1433,7 +1431,7 @@ struct DSEState {
1433
1431
continue ;
1434
1432
}
1435
1433
1436
- if (UseInst->mayThrow () && !isInvisibleToCallerBeforeRet (KillingUndObj)) {
1434
+ if (UseInst->mayThrow () && !isInvisibleToCallerOnUnwind (KillingUndObj)) {
1437
1435
LLVM_DEBUG (dbgs () << " ... found throwing instruction\n " );
1438
1436
return None;
1439
1437
}
@@ -1614,7 +1612,7 @@ struct DSEState {
1614
1612
// First see if we can ignore it by using the fact that KillingI is an
1615
1613
// alloca/alloca like object that is not visible to the caller during
1616
1614
// execution of the function.
1617
- if (KillingUndObj && isInvisibleToCallerBeforeRet (KillingUndObj))
1615
+ if (KillingUndObj && isInvisibleToCallerOnUnwind (KillingUndObj))
1618
1616
return false ;
1619
1617
1620
1618
if (KillingI->getParent () == DeadI->getParent ())
@@ -1630,7 +1628,7 @@ struct DSEState {
1630
1628
bool isDSEBarrier (const Value *KillingUndObj, Instruction *DeadI) {
1631
1629
// If DeadI may throw it acts as a barrier, unless we are to an
1632
1630
// alloca/alloca like object that does not escape.
1633
- if (DeadI->mayThrow () && !isInvisibleToCallerBeforeRet (KillingUndObj))
1631
+ if (DeadI->mayThrow () && !isInvisibleToCallerOnUnwind (KillingUndObj))
1634
1632
return true ;
1635
1633
1636
1634
// If DeadI is an atomic load/store stronger than monotonic, do not try to
0 commit comments