Skip to content

Commit ae29e87

Browse files
authored
Merge pull request #70975 from gottesmm/region-isolation-more-instructions
[region-isolation] Add support for more instructions and make it harder for instruction classifier/base look through to get out of sync
2 parents be35394 + c51d288 commit ae29e87

File tree

3 files changed

+394
-38
lines changed

3 files changed

+394
-38
lines changed

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 127 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,85 @@ struct UseDefChainVisitor
177177

178178
} // namespace
179179

180+
/// Classify an instructions as look through when we are looking through
181+
/// values. We assert that all instructions that are CONSTANT_TRANSLATION
182+
/// LookThrough to make sure they stay in sync.
183+
static bool isStaticallyLookThroughInst(SILInstruction *inst) {
184+
if (auto cast = SILDynamicCastInst::getAs(inst))
185+
if (cast.isRCIdentityPreserving())
186+
return true;
187+
188+
switch (inst->getKind()) {
189+
default:
190+
return false;
191+
case SILInstructionKind::BeginAccessInst:
192+
case SILInstructionKind::BeginBorrowInst:
193+
case SILInstructionKind::BeginDeallocRefInst:
194+
case SILInstructionKind::BridgeObjectToRefInst:
195+
case SILInstructionKind::CopyValueInst:
196+
case SILInstructionKind::CopyableToMoveOnlyWrapperAddrInst:
197+
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
198+
case SILInstructionKind::DestructureStructInst:
199+
case SILInstructionKind::DestructureTupleInst:
200+
case SILInstructionKind::DropDeinitInst:
201+
case SILInstructionKind::EndCOWMutationInst:
202+
case SILInstructionKind::EndInitLetRefInst:
203+
case SILInstructionKind::ExplicitCopyValueInst:
204+
case SILInstructionKind::InitEnumDataAddrInst:
205+
case SILInstructionKind::MarkDependenceInst:
206+
case SILInstructionKind::MarkUninitializedInst:
207+
case SILInstructionKind::MarkUnresolvedNonCopyableValueInst:
208+
case SILInstructionKind::MarkUnresolvedReferenceBindingInst:
209+
case SILInstructionKind::MoveOnlyWrapperToCopyableAddrInst:
210+
case SILInstructionKind::MoveOnlyWrapperToCopyableBoxInst:
211+
case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
212+
case SILInstructionKind::MoveValueInst:
213+
case SILInstructionKind::OpenExistentialAddrInst:
214+
case SILInstructionKind::ProjectBlockStorageInst:
215+
case SILInstructionKind::ProjectBoxInst:
216+
case SILInstructionKind::RefToBridgeObjectInst:
217+
case SILInstructionKind::RefToUnownedInst:
218+
case SILInstructionKind::UncheckedRefCastInst:
219+
case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
220+
case SILInstructionKind::UnownedCopyValueInst:
221+
case SILInstructionKind::UnownedToRefInst:
222+
case SILInstructionKind::UpcastInst:
223+
case SILInstructionKind::ValueToBridgeObjectInst:
224+
return true;
225+
}
226+
}
227+
228+
static bool isLookThroughIfResultNonSendable(SILInstruction *inst) {
229+
switch (inst->getKind()) {
230+
default:
231+
return false;
232+
case SILInstructionKind::TupleElementAddrInst:
233+
case SILInstructionKind::StructElementAddrInst:
234+
case SILInstructionKind::RawPointerToRefInst:
235+
return true;
236+
}
237+
}
238+
239+
static bool isLookThroughIfOperandNonSendable(SILInstruction *inst) {
240+
switch (inst->getKind()) {
241+
default:
242+
return false;
243+
case SILInstructionKind::RefToRawPointerInst:
244+
return true;
245+
}
246+
}
247+
248+
static bool isLookThroughIfOperandAndResultSendable(SILInstruction *inst) {
249+
switch (inst->getKind()) {
250+
default:
251+
return false;
252+
case SILInstructionKind::UncheckedTrivialBitCastInst:
253+
case SILInstructionKind::UncheckedBitwiseCastInst:
254+
case SILInstructionKind::UncheckedValueCastInst:
255+
return true;
256+
}
257+
}
258+
180259
static SILValue getUnderlyingTrackedObjectValue(SILValue value) {
181260
auto *fn = value->getFunction();
182261
SILValue result = value;
@@ -189,47 +268,37 @@ static SILValue getUnderlyingTrackedObjectValue(SILValue value) {
189268
temp = lookThroughOwnershipInsts(temp);
190269

191270
if (auto *svi = dyn_cast<SingleValueInstruction>(temp)) {
192-
if (isa<ExplicitCopyValueInst, CopyableToMoveOnlyWrapperValueInst,
193-
MoveOnlyWrapperToCopyableValueInst,
194-
MoveOnlyWrapperToCopyableBoxInst, BeginAccessInst,
195-
MarkDependenceInst>(svi) ||
196-
isIdentityPreservingRefCast(svi)) {
271+
if (isStaticallyLookThroughInst(svi)) {
197272
temp = svi->getOperand(0);
198273
}
199274

200275
// If we have a cast and our operand and result are non-Sendable, treat it
201276
// as a look through.
202-
if (isa<UncheckedTrivialBitCastInst, UncheckedBitwiseCastInst,
203-
UncheckedValueCastInst>(svi)) {
277+
if (isLookThroughIfOperandAndResultSendable(svi)) {
204278
if (isNonSendableType(svi->getType(), fn) &&
205279
isNonSendableType(svi->getOperand(0)->getType(), fn)) {
206280
temp = svi->getOperand(0);
207281
}
208282
}
209-
}
210283

211-
if (auto *r = dyn_cast<RefToRawPointerInst>(temp)) {
212-
// If our operand is a non-Sendable type, look through this instruction.
213-
if (isNonSendableType(r->getOperand()->getType(), fn)) {
214-
temp = r->getOperand();
284+
if (isLookThroughIfResultNonSendable(svi)) {
285+
if (isNonSendableType(svi->getType(), fn)) {
286+
temp = svi->getOperand(0);
287+
}
215288
}
216-
}
217289

218-
if (auto *r = dyn_cast<RawPointerToRefInst>(temp)) {
219-
// If our result is a non-Sendable type, look through this
220-
// instruction. Builtin.RawPointer is always non-Sendable.
221-
if (isNonSendableType(r->getType(), fn)) {
222-
temp = r->getOperand();
290+
if (isLookThroughIfOperandNonSendable(svi)) {
291+
// If our operand is a non-Sendable type, look through this instruction.
292+
if (isNonSendableType(svi->getOperand(0)->getType(), fn)) {
293+
temp = svi->getOperand(0);
294+
}
223295
}
224296
}
225297

226-
if (auto *dsi = dyn_cast_or_null<DestructureStructInst>(
227-
temp->getDefiningInstruction())) {
228-
temp = dsi->getOperand();
229-
}
230-
if (auto *dti = dyn_cast_or_null<DestructureTupleInst>(
231-
temp->getDefiningInstruction())) {
232-
temp = dti->getOperand();
298+
if (auto *inst = temp->getDefiningInstruction()) {
299+
if (isStaticallyLookThroughInst(inst)) {
300+
temp = inst->getOperand(0);
301+
}
233302
}
234303

235304
if (temp != result) {
@@ -1787,6 +1856,11 @@ class PartitionOpTranslator {
17871856

17881857
case TranslationSemantics::LookThrough:
17891858
assert(inst->getNumOperands() == 1);
1859+
assert((isStaticallyLookThroughInst(inst) ||
1860+
isLookThroughIfResultNonSendable(inst) ||
1861+
isLookThroughIfOperandNonSendable(inst) ||
1862+
isLookThroughIfOperandAndResultSendable(inst)) &&
1863+
"Out of sync... should return true for one of these categories!");
17901864
return translateSILLookThrough(inst->getResults(), inst->getOperand(0));
17911865

17921866
case TranslationSemantics::Store:
@@ -1895,6 +1969,12 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
18951969

18961970
#define CONSTANT_TRANSLATION(INST, Kind) \
18971971
TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
1972+
assert((TranslationSemantics::Kind != TranslationSemantics::LookThrough || \
1973+
isStaticallyLookThroughInst(inst)) && \
1974+
"Out of sync?!"); \
1975+
assert((TranslationSemantics::Kind == TranslationSemantics::LookThrough || \
1976+
!isStaticallyLookThroughInst(inst)) && \
1977+
"Out of sync?!"); \
18981978
return TranslationSemantics::Kind; \
18991979
}
19001980

@@ -2008,6 +2088,11 @@ CONSTANT_TRANSLATION(MarkUninitializedInst, LookThrough)
20082088
CONSTANT_TRANSLATION(DestructureTupleInst, LookThrough)
20092089
CONSTANT_TRANSLATION(DestructureStructInst, LookThrough)
20102090
CONSTANT_TRANSLATION(ProjectBlockStorageInst, LookThrough)
2091+
CONSTANT_TRANSLATION(RefToUnownedInst, LookThrough)
2092+
CONSTANT_TRANSLATION(UnownedToRefInst, LookThrough)
2093+
CONSTANT_TRANSLATION(UnownedCopyValueInst, LookThrough)
2094+
CONSTANT_TRANSLATION(DropDeinitInst, LookThrough)
2095+
CONSTANT_TRANSLATION(ValueToBridgeObjectInst, LookThrough)
20112096

20122097
//===---
20132098
// Store
@@ -2032,6 +2117,7 @@ CONSTANT_TRANSLATION(MarkUnresolvedMoveAddrInst, Store)
20322117
// value is within or because even though they are technically a use we would
20332118
// rather emit an error on a better instruction.
20342119
CONSTANT_TRANSLATION(AllocGlobalInst, Ignored)
2120+
CONSTANT_TRANSLATION(AutoreleaseValueInst, Ignored)
20352121
CONSTANT_TRANSLATION(DeallocBoxInst, Ignored)
20362122
CONSTANT_TRANSLATION(DeallocStackInst, Ignored)
20372123
CONSTANT_TRANSLATION(DebugValueInst, Ignored)
@@ -2046,13 +2132,17 @@ CONSTANT_TRANSLATION(IsEscapingClosureInst, Ignored)
20462132
CONSTANT_TRANSLATION(MetatypeInst, Ignored)
20472133
CONSTANT_TRANSLATION(EndApplyInst, Ignored)
20482134
CONSTANT_TRANSLATION(AbortApplyInst, Ignored)
2135+
CONSTANT_TRANSLATION(DebugStepInst, Ignored)
20492136

20502137
//===---
20512138
// Require
20522139
//
20532140

20542141
// Instructions that only require that the region of the value be live:
20552142
CONSTANT_TRANSLATION(FixLifetimeInst, Require)
2143+
CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Require)
2144+
CONSTANT_TRANSLATION(BridgeObjectToWordInst, Require)
2145+
CONSTANT_TRANSLATION(IsUniqueInst, Require)
20562146

20572147
//===---
20582148
// Terminators
@@ -2094,20 +2184,12 @@ CONSTANT_TRANSLATION(DeallocExistentialBoxInst, Ignored)
20942184
// Unhandled Instructions
20952185
//
20962186

2097-
CONSTANT_TRANSLATION(RefToUnownedInst, Unhandled)
2098-
CONSTANT_TRANSLATION(UnownedToRefInst, Unhandled)
2099-
CONSTANT_TRANSLATION(BridgeObjectToWordInst, Unhandled)
21002187
CONSTANT_TRANSLATION(ObjCToThickMetatypeInst, Unhandled)
21012188
CONSTANT_TRANSLATION(ObjCMetatypeToObjectInst, Unhandled)
21022189
CONSTANT_TRANSLATION(ObjCExistentialMetatypeToObjectInst, Unhandled)
2103-
CONSTANT_TRANSLATION(ClassifyBridgeObjectInst, Unhandled)
2104-
CONSTANT_TRANSLATION(ValueToBridgeObjectInst, Unhandled)
2105-
CONSTANT_TRANSLATION(UnownedCopyValueInst, Unhandled)
21062190
CONSTANT_TRANSLATION(WeakCopyValueInst, Unhandled)
21072191
CONSTANT_TRANSLATION(StrongCopyWeakValueInst, Unhandled)
21082192
CONSTANT_TRANSLATION(StrongCopyUnmanagedValueInst, Unhandled)
2109-
CONSTANT_TRANSLATION(DropDeinitInst, Unhandled)
2110-
CONSTANT_TRANSLATION(IsUniqueInst, Unhandled)
21112193
CONSTANT_TRANSLATION(LoadUnownedInst, Unhandled)
21122194
CONSTANT_TRANSLATION(ValueMetatypeInst, Unhandled)
21132195
CONSTANT_TRANSLATION(ExistentialMetatypeInst, Unhandled)
@@ -2144,14 +2226,12 @@ CONSTANT_TRANSLATION(DeallocPartialRefInst, Unhandled)
21442226
CONSTANT_TRANSLATION(UnmanagedRetainValueInst, Unhandled)
21452227
CONSTANT_TRANSLATION(UnmanagedReleaseValueInst, Unhandled)
21462228
CONSTANT_TRANSLATION(UnmanagedAutoreleaseValueInst, Unhandled)
2147-
CONSTANT_TRANSLATION(AutoreleaseValueInst, Unhandled)
21482229
CONSTANT_TRANSLATION(BeginUnpairedAccessInst, Unhandled)
21492230
CONSTANT_TRANSLATION(EndUnpairedAccessInst, Unhandled)
21502231
CONSTANT_TRANSLATION(AssignInst, Unhandled)
21512232
CONSTANT_TRANSLATION(AssignByWrapperInst, Unhandled)
21522233
CONSTANT_TRANSLATION(AssignOrInitInst, Unhandled)
21532234
CONSTANT_TRANSLATION(MarkFunctionEscapeInst, Unhandled)
2154-
CONSTANT_TRANSLATION(DebugStepInst, Unhandled)
21552235
CONSTANT_TRANSLATION(TestSpecificationInst, Unhandled)
21562236
CONSTANT_TRANSLATION(StoreUnownedInst, Unhandled)
21572237
CONSTANT_TRANSLATION(DeinitExistentialAddrInst, Unhandled)
@@ -2211,6 +2291,7 @@ CONSTANT_TRANSLATION(DeallocPackMetadataInst, Asserting)
22112291
// of the Sendable addr. That would require adding more logic though.
22122292
#define LOOKTHROUGH_IF_NONSENDABLE_RESULT_REQUIRE_OTHERWISE(INST) \
22132293
TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
2294+
assert(isLookThroughIfResultNonSendable(inst) && "Out of sync?!"); \
22142295
if (isNonSendableType(inst->getType())) { \
22152296
return TranslationSemantics::LookThrough; \
22162297
} \
@@ -2246,6 +2327,7 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
22462327
#define CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(INST) \
22472328
\
22482329
TranslationSemantics PartitionOpTranslator::visit##INST(INST *cast) { \
2330+
assert(isLookThroughIfOperandAndResultSendable(cast) && "Out of sync"); \
22492331
bool isOperandNonSendable = \
22502332
isNonSendableType(cast->getOperand()->getType()); \
22512333
bool isResultNonSendable = isNonSendableType(cast->getType()); \
@@ -2276,6 +2358,7 @@ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
22762358

22772359
TranslationSemantics
22782360
PartitionOpTranslator::visitRawPointerToRefInst(RawPointerToRefInst *r) {
2361+
assert(isLookThroughIfResultNonSendable(r) && "Out of sync");
22792362
// If our result is non sendable, perform a look through.
22802363
if (isNonSendableType(r->getType()))
22812364
return TranslationSemantics::LookThrough;
@@ -2286,6 +2369,8 @@ PartitionOpTranslator::visitRawPointerToRefInst(RawPointerToRefInst *r) {
22862369

22872370
TranslationSemantics
22882371
PartitionOpTranslator::visitRefToRawPointerInst(RefToRawPointerInst *r) {
2372+
assert(isLookThroughIfOperandNonSendable(r) && "Out of sync");
2373+
22892374
// If our source ref is non sendable, perform a look through.
22902375
if (isNonSendableType(r->getOperand()->getType()))
22912376
return TranslationSemantics::LookThrough;
@@ -2297,7 +2382,8 @@ PartitionOpTranslator::visitRefToRawPointerInst(RefToRawPointerInst *r) {
22972382

22982383
TranslationSemantics
22992384
PartitionOpTranslator::visitMarkDependenceInst(MarkDependenceInst *mdi) {
2300-
translateSILAssign(mdi, mdi->getValue());
2385+
assert(isStaticallyLookThroughInst(mdi) && "Out of sync");
2386+
translateSILLookThrough(mdi->getResults(), mdi->getValue());
23012387
translateSILRequire(mdi->getBase());
23022388
return TranslationSemantics::Special;
23032389
}
@@ -2312,8 +2398,12 @@ PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
23122398

23132399
TranslationSemantics PartitionOpTranslator::visitUnconditionalCheckedCastInst(
23142400
UnconditionalCheckedCastInst *ucci) {
2315-
if (SILDynamicCastInst(ucci).isRCIdentityPreserving())
2401+
if (SILDynamicCastInst(ucci).isRCIdentityPreserving()) {
2402+
assert(isStaticallyLookThroughInst(ucci) && "Out of sync");
23162403
return TranslationSemantics::LookThrough;
2404+
}
2405+
2406+
assert(!isStaticallyLookThroughInst(ucci) && "Out of sync");
23172407
return TranslationSemantics::Assign;
23182408
}
23192409

0 commit comments

Comments
 (0)