@@ -410,8 +410,7 @@ class COWArrayOpt {
410
410
// analyzing.
411
411
SILValue CurrentArrayAddr;
412
412
public:
413
- COWArrayOpt (RCIdentityFunctionInfo *RCIA, SILLoop *L,
414
- DominanceAnalysis *DA)
413
+ COWArrayOpt (RCIdentityFunctionInfo *RCIA, SILLoop *L, DominanceAnalysis *DA)
415
414
: RCIA(RCIA), Function(L->getHeader ()->getParent()), Loop(L),
416
415
Preheader(L->getLoopPreheader ()), DomTree(DA->get (Function)),
417
416
ColdBlocks(DA), CachedSafeLoop(false , false ) {}
@@ -427,7 +426,8 @@ class COWArrayOpt {
427
426
bool checkSafeArrayValueUses (UserList &ArrayValueUsers);
428
427
bool checkSafeArrayElementUse (SILInstruction *UseInst, SILValue ArrayVal);
429
428
bool checkSafeElementValueUses (UserOperList &ElementValueUsers);
430
- bool hoistMakeMutable (ArraySemanticsCall MakeMutable);
429
+ bool hoistMakeMutable (ArraySemanticsCall MakeMutable, bool dominatesExits);
430
+ bool dominatesExitingBlocks (SILBasicBlock *BB);
431
431
void hoistAddressProjections (Operand &ArrayOp);
432
432
bool hasLoopOnlyDestructorSafeArrayOperations ();
433
433
SILValue getArrayAddressBase (SILValue V);
@@ -1037,7 +1037,8 @@ void COWArrayOpt::hoistAddressProjections(Operand &ArrayOp) {
1037
1037
1038
1038
// / Check if this call to "make_mutable" is hoistable, and move it, or delete it
1039
1039
// / if it's already hoisted.
1040
- bool COWArrayOpt::hoistMakeMutable (ArraySemanticsCall MakeMutable) {
1040
+ bool COWArrayOpt::hoistMakeMutable (ArraySemanticsCall MakeMutable,
1041
+ bool dominatesExits) {
1041
1042
LLVM_DEBUG (llvm::dbgs () << " Checking mutable array: " <<CurrentArrayAddr);
1042
1043
1043
1044
// We can hoist address projections (even if they are only conditionally
@@ -1056,7 +1057,12 @@ bool COWArrayOpt::hoistMakeMutable(ArraySemanticsCall MakeMutable) {
1056
1057
1057
1058
// Check whether we can hoist make_mutable based on the operations that are
1058
1059
// in the loop.
1059
- if (hasLoopOnlyDestructorSafeArrayOperations ()) {
1060
+ // Note that in this case we don't verify that the array buffer is not aliased
1061
+ // and therefore we must be conservative if the make_mutable is executed
1062
+ // conditionally (i.e. doesn't dominate all exit blocks).
1063
+ // The test SILOptimizer/cowarray_opt.sil: dont_hoist_if_executed_conditionally
1064
+ // shows the problem.
1065
+ if (hasLoopOnlyDestructorSafeArrayOperations () && dominatesExits) {
1060
1066
// Done. We can hoist the make_mutable.
1061
1067
// We still need the array uses later to check if we can add loads to
1062
1068
// HoistableLoads.
@@ -1106,6 +1112,16 @@ bool COWArrayOpt::hoistMakeMutable(ArraySemanticsCall MakeMutable) {
1106
1112
return true ;
1107
1113
}
1108
1114
1115
+ bool COWArrayOpt::dominatesExitingBlocks (SILBasicBlock *BB) {
1116
+ llvm::SmallVector<SILBasicBlock *, 8 > ExitingBlocks;
1117
+ Loop->getExitingBlocks (ExitingBlocks);
1118
+ for (SILBasicBlock *Exiting : ExitingBlocks) {
1119
+ if (!DomTree->dominates (BB, Exiting))
1120
+ return false ;
1121
+ }
1122
+ return true ;
1123
+ }
1124
+
1109
1125
bool COWArrayOpt::run () {
1110
1126
LLVM_DEBUG (llvm::dbgs () << " Array Opts in Loop " << *Loop);
1111
1127
@@ -1123,6 +1139,7 @@ bool COWArrayOpt::run() {
1123
1139
for (auto *BB : Loop->getBlocks ()) {
1124
1140
if (ColdBlocks.isCold (BB))
1125
1141
continue ;
1142
+ bool dominatesExits = dominatesExitingBlocks (BB);
1126
1143
for (auto II = BB->begin (), IE = BB->end (); II != IE;) {
1127
1144
// Inst may be moved by hoistMakeMutable.
1128
1145
SILInstruction *Inst = &*II;
@@ -1134,7 +1151,7 @@ bool COWArrayOpt::run() {
1134
1151
CurrentArrayAddr = MakeMutableCall.getSelf ();
1135
1152
auto HoistedCallEntry = ArrayMakeMutableMap.find (CurrentArrayAddr);
1136
1153
if (HoistedCallEntry == ArrayMakeMutableMap.end ()) {
1137
- if (!hoistMakeMutable (MakeMutableCall)) {
1154
+ if (!hoistMakeMutable (MakeMutableCall, dominatesExits )) {
1138
1155
ArrayMakeMutableMap[CurrentArrayAddr] = nullptr ;
1139
1156
continue ;
1140
1157
}
0 commit comments