mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[AllocBoxToStack] Lexical borrowees get lexical alloc_stacks.
Previously, whenever an alloc_box that was promoted to an alloc_stack, the new alloc_stack would be lexical. The result was that alloc_boxes which didn't need (or explicitly didn't want, in the case of eager move vars) received lexical alloc_stacks. Here, only add the lexical flag to the new alloc_stack instruction if any of the box's uses are `begin_borrow [lexical]`. That way, alloc_boxes end up having lexical alloc_stacks only if they were "lexical alloc_boxes".
This commit is contained in:
@@ -13,12 +13,13 @@
|
||||
#define DEBUG_TYPE "allocbox-to-stack"
|
||||
#include "swift/AST/DiagnosticsSIL.h"
|
||||
#include "swift/Basic/BlotMapVector.h"
|
||||
#include "swift/Basic/GraphNodeWorklist.h"
|
||||
#include "swift/SIL/ApplySite.h"
|
||||
#include "swift/SIL/BasicBlockDatastructures.h"
|
||||
#include "swift/SIL/Dominance.h"
|
||||
#include "swift/SIL/SILArgument.h"
|
||||
#include "swift/SIL/SILBuilder.h"
|
||||
#include "swift/SIL/SILCloner.h"
|
||||
#include "swift/SIL/BasicBlockDatastructures.h"
|
||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||
#include "swift/SILOptimizer/PassManager/Transforms.h"
|
||||
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "swift/SILOptimizer/Utils/StackNesting.h"
|
||||
#include "swift/SILOptimizer/Utils/ValueLifetime.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@@ -538,13 +540,35 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) {
|
||||
SILBuilderWithScope Builder(ABI);
|
||||
assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
|
||||
&& "rewriting multi-field box not implemented");
|
||||
auto &mod = ABI->getFunction()->getModule();
|
||||
bool isLexical = mod.getASTContext().SILOpts.supportsLexicalLifetimes(mod);
|
||||
auto *ASI = Builder.createAllocStack(
|
||||
ABI->getLoc(),
|
||||
getSILBoxFieldType(TypeExpansionContext(*ABI->getFunction()),
|
||||
ABI->getBoxType(), ABI->getModule().Types, 0),
|
||||
ABI->getVarInfo(), ABI->hasDynamicLifetime(), isLexical);
|
||||
auto ty = getSILBoxFieldType(TypeExpansionContext(*ABI->getFunction()),
|
||||
ABI->getBoxType(), ABI->getModule().Types, 0);
|
||||
auto isLexical = [&]() -> bool {
|
||||
auto &mod = ABI->getFunction()->getModule();
|
||||
bool lexicalLifetimesEnabled =
|
||||
mod.getASTContext().SILOpts.supportsLexicalLifetimes(mod);
|
||||
if (!lexicalLifetimesEnabled)
|
||||
return false;
|
||||
// Look for lexical borrows of the alloc_box.
|
||||
GraphNodeWorklist<Operand *, 4> worklist;
|
||||
worklist.initializeRange(ABI->getUses());
|
||||
while (auto *use = worklist.pop()) {
|
||||
// See through mark_uninitialized and non-lexical begin_borrow
|
||||
// instructions. It's verified that lexical begin_borrows of SILBoxType
|
||||
// values originate either from AllocBoxInsts or SILFunctionArguments.
|
||||
if (auto *mui = dyn_cast<MarkUninitializedInst>(use->getUser())) {
|
||||
for (auto *use : mui->getUses())
|
||||
worklist.insert(use);
|
||||
} else if (auto *bbi = dyn_cast<BeginBorrowInst>(use->getUser())) {
|
||||
if (bbi->isLexical())
|
||||
return true;
|
||||
for (auto *use : bbi->getUses())
|
||||
worklist.insert(use);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
auto *ASI = Builder.createAllocStack(ABI->getLoc(), ty, ABI->getVarInfo(),
|
||||
ABI->hasDynamicLifetime(), isLexical());
|
||||
|
||||
// Transfer a mark_uninitialized if we have one.
|
||||
SILValue StackBox = ASI;
|
||||
|
||||
Reference in New Issue
Block a user