Skip to content

Commit 053e30d

Browse files
committed
[region-isolation] Make sure not to run RegionAnalysis on functions that we do not support.
Before this commit, this was done at the beginning of TransferNonSendable. I thought that those checks would be sufficient to ensure that RegionAnalysisFunctionInfo was not created for functions that we do not support. Turns out when we perform certain forms of verification, we force all function analyses to be created for all functions meaning that we would create a RegionAnalysisFunctionInfo for such an unsupported function causing us to hit asserts. In this commit, I move the check to whether or not we support a function into RegionAnalysisFunctionInfo itself and use that to determine if we should run TransferNonSendable. This additionally allows me to change RegionAnalysisFunctionInfo so that one can construct one for an unsupported function... as long as one doesn't actually touch any of its methods. If one does, I put in an assert so we will know that operator error has occured.
1 parent a9dc4ed commit 053e30d

File tree

3 files changed

+98
-35
lines changed

3 files changed

+98
-35
lines changed

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,25 @@ class RegionAnalysisFunctionInfo {
358358

359359
PostOrderFunctionInfo *pofi;
360360

361+
/// Set to true if we have already processed our regions.
361362
bool solved;
362363

364+
/// Set to true if this is a function that we know how to process regions for.
365+
///
366+
/// DISCUSSION: We do not support if the correct features are not enabled, if
367+
/// the function doesn't have a parent module, or if the function doesn't have
368+
/// ownership.
369+
bool supportedFunction;
370+
363371
public:
364372
using LazyType = LazyFunctionInfo<RegionAnalysis, RegionAnalysisFunctionInfo>;
365373

366374
RegionAnalysisFunctionInfo(SILFunction *fn, PostOrderFunctionInfo *pofi);
367375
~RegionAnalysisFunctionInfo();
368376

369377
BlockPartitionState &getPartitionState(SILBasicBlock *block) const {
378+
assert(supportedFunction &&
379+
"Cannot getPartitionState for a non-supported function");
370380
// Lazily run the dataflow.
371381
if (!solved)
372382
const_cast<RegionAnalysisFunctionInfo *>(this)->runDataflow();
@@ -375,20 +385,46 @@ class RegionAnalysisFunctionInfo {
375385

376386
SILFunction *getFunction() const { return fn; }
377387

388+
bool isSupportedFunction() const { return supportedFunction; }
389+
378390
using iterator = BasicBlockData::iterator;
379391
using const_iterator = BasicBlockData::const_iterator;
380392
using reverse_iterator = BasicBlockData::reverse_iterator;
381393
using const_reverse_iterator = BasicBlockData::const_reverse_iterator;
382394

383-
iterator begin() { return blockStates->begin(); }
384-
iterator end() { return blockStates->end(); }
385-
const_iterator begin() const { return blockStates->begin(); }
386-
const_iterator end() const { return blockStates->end(); }
395+
iterator begin() {
396+
assert(supportedFunction && "Unsupported Function?!");
397+
return blockStates->begin();
398+
}
399+
iterator end() {
400+
assert(supportedFunction && "Unsupported Function?!");
401+
return blockStates->end();
402+
}
403+
const_iterator begin() const {
404+
assert(supportedFunction && "Unsupported Function?!");
405+
return blockStates->begin();
406+
}
407+
const_iterator end() const {
408+
assert(supportedFunction && "Unsupported Function?!");
409+
return blockStates->end();
410+
}
387411

388-
reverse_iterator rbegin() { return blockStates->rbegin(); }
389-
reverse_iterator rend() { return blockStates->rend(); }
390-
const_reverse_iterator rbegin() const { return blockStates->rbegin(); }
391-
const_reverse_iterator rend() const { return blockStates->rend(); }
412+
reverse_iterator rbegin() {
413+
assert(supportedFunction && "Unsupported Function?!");
414+
return blockStates->rbegin();
415+
}
416+
reverse_iterator rend() {
417+
assert(supportedFunction && "Unsupported Function?!");
418+
return blockStates->rend();
419+
}
420+
const_reverse_iterator rbegin() const {
421+
assert(supportedFunction && "Unsupported Function?!");
422+
return blockStates->rbegin();
423+
}
424+
const_reverse_iterator rend() const {
425+
assert(supportedFunction && "Unsupported Function?!");
426+
return blockStates->rend();
427+
}
392428

393429
using range = llvm::iterator_range<iterator>;
394430
using const_range = llvm::iterator_range<const_iterator>;
@@ -401,10 +437,14 @@ class RegionAnalysisFunctionInfo {
401437
const_reverse_range getReverseRange() const { return {rbegin(), rend()}; }
402438

403439
TransferringOperandSetFactory &getOperandSetFactory() {
440+
assert(supportedFunction && "Unsupported Function?!");
404441
return ptrSetFactory;
405442
}
406443

407-
RegionAnalysisValueMap &getValueMap() { return valueMap; }
444+
RegionAnalysisValueMap &getValueMap() {
445+
assert(supportedFunction && "Unsupported Function?!");
446+
return valueMap;
447+
}
408448

409449
bool isClosureCaptured(SILValue value, Operand *op);
410450

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,11 +2472,44 @@ void BlockPartitionState::print(llvm::raw_ostream &os) const {
24722472
// MARK: Dataflow Entrypoint
24732473
//===----------------------------------------------------------------------===//
24742474

2475+
static bool canComputeRegionsForFunction(SILFunction *fn) {
2476+
if (!fn->getASTContext().LangOpts.hasFeature(Feature::RegionBasedIsolation))
2477+
return false;
2478+
2479+
// If this function does not correspond to a syntactic declContext and it
2480+
// doesn't have a parent module, don't check it since we cannot check if a
2481+
// type is sendable.
2482+
if (!fn->getDeclContext() && !fn->getParentModule()) {
2483+
return false;
2484+
}
2485+
2486+
if (!fn->hasOwnership()) {
2487+
LLVM_DEBUG(llvm::dbgs() << "Only runs on Ownership SSA, skipping!\n");
2488+
return false;
2489+
}
2490+
2491+
// The sendable protocol should /always/ be available if TransferNonSendable
2492+
// is enabled. If not, there is a major bug in the compiler and we should
2493+
// fail loudly.
2494+
if (!fn->getASTContext().getProtocol(KnownProtocolKind::Sendable))
2495+
return false;
2496+
2497+
return true;
2498+
}
2499+
24752500
RegionAnalysisFunctionInfo::RegionAnalysisFunctionInfo(
24762501
SILFunction *fn, PostOrderFunctionInfo *pofi)
2477-
: allocator(), fn(fn),
2478-
translator(new(allocator) PartitionOpTranslator(fn, pofi, valueMap)),
2479-
ptrSetFactory(allocator), blockStates(), pofi(pofi), solved(false) {
2502+
: allocator(), fn(fn), translator(), ptrSetFactory(allocator),
2503+
blockStates(), pofi(pofi), solved(false), supportedFunction(true) {
2504+
// Before we do anything, make sure that we support processing this function.
2505+
//
2506+
// NOTE: See documentation on supportedFunction for criteria.
2507+
if (!canComputeRegionsForFunction(fn)) {
2508+
supportedFunction = false;
2509+
return;
2510+
}
2511+
2512+
translator = new (allocator) PartitionOpTranslator(fn, pofi, valueMap);
24802513
blockStates.emplace(fn, [this](SILBasicBlock *block) -> BlockPartitionState {
24812514
return BlockPartitionState(block, *translator, ptrSetFactory);
24822515
});
@@ -2491,12 +2524,18 @@ RegionAnalysisFunctionInfo::RegionAnalysisFunctionInfo(
24912524
}
24922525

24932526
RegionAnalysisFunctionInfo::~RegionAnalysisFunctionInfo() {
2527+
// If we had a non-supported function, we didn't create a translator, so we do
2528+
// not need to tear anything down.
2529+
if (!supportedFunction)
2530+
return;
2531+
24942532
// Tear down translator before we tear down the allocator.
24952533
translator->~PartitionOpTranslator();
24962534
}
24972535

24982536
bool RegionAnalysisFunctionInfo::isClosureCaptured(SILValue value,
24992537
Operand *op) {
2538+
assert(supportedFunction && "Unsupported Function?!");
25002539
return translator->isClosureCaptured(value, op->getUser());
25012540
}
25022541

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -663,34 +663,18 @@ class TransferNonSendable : public SILFunctionTransform {
663663
void run() override {
664664
SILFunction *function = getFunction();
665665

666-
if (!function->getASTContext().LangOpts.hasFeature(
667-
Feature::RegionBasedIsolation))
668-
return;
666+
auto *functionInfo = getAnalysis<RegionAnalysis>()->get(function);
667+
if (!functionInfo->isSupportedFunction()) {
668+
LLVM_DEBUG(llvm::dbgs() << "===> SKIPPING UNSUPPORTED FUNCTION: "
669+
<< function->getName() << '\n');
669670

670-
LLVM_DEBUG(llvm::dbgs()
671-
<< "===> PROCESSING: " << function->getName() << '\n');
672-
673-
// If this function does not correspond to a syntactic declContext and it
674-
// doesn't have a parent module, don't check it since we cannot check if a
675-
// type is sendable.
676-
if (!function->getDeclContext() && !function->getParentModule()) {
677-
LLVM_DEBUG(llvm::dbgs() << "No Decl Context! Skipping!\n");
678671
return;
679672
}
680673

681-
if (!function->hasOwnership()) {
682-
LLVM_DEBUG(llvm::dbgs() << "Only runs on Ownership SSA, skipping!\n");
683-
return;
684-
}
685-
686-
// The sendable protocol should /always/ be available if TransferNonSendable
687-
// is enabled. If not, there is a major bug in the compiler and we should
688-
// fail loudly.
689-
if (!function->getASTContext().getProtocol(KnownProtocolKind::Sendable))
690-
llvm::report_fatal_error("Sendable protocol not available!");
674+
LLVM_DEBUG(llvm::dbgs()
675+
<< "===> PROCESSING: " << function->getName() << '\n');
691676

692-
auto *analysis = this->getAnalysis<RegionAnalysis>()->get(function);
693-
emitDiagnostics(analysis);
677+
emitDiagnostics(functionInfo);
694678
}
695679
};
696680

0 commit comments

Comments
 (0)