Skip to content

Commit c248b95

Browse files
authored
Merge pull request #69933 from gottesmm/pr-d97426e35a99d98bd9cb4a751cede10ba6a2336e
[region-isolation] Loosen handling around fields that are safe to access concurrently.
2 parents b749f10 + 7653552 commit c248b95

File tree

2 files changed

+360
-6
lines changed

2 files changed

+360
-6
lines changed

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,30 @@ struct UseDefChainVisitor
145145
case ProjectionKind::Tuple: {
146146
// These are merges if we have multiple fields.
147147
auto *tti = cast<TupleElementAddrInst>(inst);
148+
149+
// See if our result type is a sendable type. In such a case, we do not
150+
// want to look through the tuple_element_addr since we do not want to
151+
// identify the sendable type with the non-sendable operand. These we
152+
// are always going to ignore anyways since a sendable let/var field of
153+
// a struct can always be used.
154+
if (!isNonSendableType(tti->getType(), tti->getFunction()))
155+
return SILValue();
156+
148157
isMerge |= tti->getOperand()->getType().getNumTupleElements() > 1;
149158
break;
150159
}
151160
case ProjectionKind::Struct:
152-
// These are merges if we have multiple fields.
153161
auto *sea = cast<StructElementAddrInst>(inst);
162+
163+
// See if our result type is a sendable type. In such a case, we do not
164+
// want to look through the struct_element_addr since we do not want to
165+
// identify the sendable type with the non-sendable operand. These we
166+
// are always going to ignore anyways since a sendable let/var field of
167+
// a struct can always be used.
168+
if (!isNonSendableType(sea->getType(), sea->getFunction()))
169+
return SILValue();
170+
171+
// These are merges if we have multiple fields.
154172
isMerge |= sea->getOperand()->getType().getNumNominalFields() > 1;
155173
break;
156174
}
@@ -1147,13 +1165,21 @@ class PartitionOpTranslator {
11471165
case SILInstructionKind::EndInitLetRefInst:
11481166
case SILInstructionKind::InitEnumDataAddrInst:
11491167
case SILInstructionKind::OpenExistentialAddrInst:
1150-
case SILInstructionKind::StructElementAddrInst:
1151-
case SILInstructionKind::TupleElementAddrInst:
11521168
case SILInstructionKind::UncheckedRefCastInst:
11531169
case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
11541170
case SILInstructionKind::UpcastInst:
11551171
return translateSILLookThrough(inst->getResult(0), inst->getOperand(0));
11561172

1173+
case SILInstructionKind::TupleElementAddrInst:
1174+
case SILInstructionKind::StructElementAddrInst: {
1175+
auto *svi = cast<SingleValueInstruction>(inst);
1176+
// If we have a sendable field... we can always access it after
1177+
// transferring... so do not track this.
1178+
if (!isNonSendableType(svi->getType()))
1179+
return;
1180+
return translateSILLookThrough(svi->getResult(0), svi->getOperand(0));
1181+
}
1182+
11571183
// We identify tuple results with their operand's id.
11581184
case SILInstructionKind::DestructureTupleInst:
11591185
case SILInstructionKind::DestructureStructInst:
@@ -1183,23 +1209,44 @@ class PartitionOpTranslator {
11831209
case SILInstructionKind::PointerToAddressInst:
11841210
case SILInstructionKind::ProjectBlockStorageInst:
11851211
case SILInstructionKind::RefToUnmanagedInst:
1186-
case SILInstructionKind::StructExtractInst:
11871212
case SILInstructionKind::TailAddrInst:
11881213
case SILInstructionKind::ThickToObjCMetatypeInst:
11891214
case SILInstructionKind::ThinToThickFunctionInst:
11901215
case SILInstructionKind::UncheckedAddrCastInst:
11911216
case SILInstructionKind::UncheckedEnumDataInst:
11921217
case SILInstructionKind::UncheckedOwnershipConversionInst:
11931218
case SILInstructionKind::UnmanagedToRefInst:
1219+
return translateSILAssign(inst);
11941220

11951221
// RefElementAddrInst is not considered to be a lookThrough since we want to
11961222
// consider the address projected from the class to be a separate value that
11971223
// is in the same region as the parent operand. The reason that we want to
11981224
// do this is to ensure that if we assign into the ref_element_addr memory,
11991225
// we do not consider writes into the struct that contains the
12001226
// ref_element_addr to be merged into.
1201-
case SILInstructionKind::RefElementAddrInst:
1227+
case SILInstructionKind::RefElementAddrInst: {
1228+
auto *reai = cast<RefElementAddrInst>(inst);
1229+
// If we are accessing a let of a Sendable type, do not treat the
1230+
// ref_element_addr as a require use.
1231+
if (reai->getField()->isLet() && !isNonSendableType(reai->getType())) {
1232+
LLVM_DEBUG(llvm::dbgs() << " Found a let! Not tracking!\n");
1233+
return;
1234+
}
1235+
return translateSILAssign(inst);
1236+
}
1237+
1238+
case SILInstructionKind::TupleExtractInst:
1239+
case SILInstructionKind::StructExtractInst: {
1240+
auto *svi = cast<SingleValueInstruction>(inst);
1241+
// If our result is a Sendable type regardless of if it is a let or a var,
1242+
// we do not need to track it.
1243+
if (!isNonSendableType(svi->getType())) {
1244+
LLVM_DEBUG(llvm::dbgs()
1245+
<< " Found a sendable field... Not Tracking!\n");
1246+
return;
1247+
}
12021248
return translateSILAssign(inst);
1249+
}
12031250

12041251
/// Enum inst is handled specially since if it does not have an argument,
12051252
/// we must assign fresh. Otherwise, we must propagate.

0 commit comments

Comments
 (0)