Skip to content

Commit 4ae07e6

Browse files
committed
[addr-move-function] Move caller use gatherer next to the caller dataflow and not in the middle of the closure capture analysis.
Just makes jumping around the file less consuing since the topic is consistent within the closure captured variable analysis.
1 parent 2669541 commit 4ae07e6

File tree

1 file changed

+98
-127
lines changed

1 file changed

+98
-127
lines changed

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 98 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -356,133 +356,7 @@ struct UseState {
356356
SILFunction *getFunction() const { return address->getFunction(); }
357357
};
358358

359-
/// Visit all of the uses of a lexical lifetime, initializing useState as we go.
360-
struct GatherLexicalLifetimeUseVisitor : public AccessUseVisitor {
361-
UseState &useState;
362-
363-
GatherLexicalLifetimeUseVisitor(UseState &useState)
364-
: AccessUseVisitor(AccessUseType::Overlapping,
365-
NestedAccessType::IgnoreAccessBegin),
366-
useState(useState) {}
367-
368-
bool visitUse(Operand *op, AccessUseType useTy) override;
369-
void reset(SILValue address) { useState.address = address; }
370-
void clear() { useState.clear(); }
371-
};
372-
373-
} // end anonymous namespace
374-
375-
static void convertMemoryReinitToInitForm(SILInstruction *memInst) {
376-
switch (memInst->getKind()) {
377-
default:
378-
llvm_unreachable("unsupported?!");
379-
380-
case SILInstructionKind::CopyAddrInst: {
381-
auto *cai = cast<CopyAddrInst>(memInst);
382-
cai->setIsInitializationOfDest(IsInitialization_t::IsInitialization);
383-
return;
384-
}
385-
case SILInstructionKind::StoreInst: {
386-
auto *si = cast<StoreInst>(memInst);
387-
si->setOwnershipQualifier(StoreOwnershipQualifier::Init);
388-
return;
389-
}
390-
}
391-
}
392-
393-
static bool memInstMustReinitialize(Operand *memOper) {
394-
SILValue address = memOper->get();
395-
auto *memInst = memOper->getUser();
396-
switch (memInst->getKind()) {
397-
default:
398-
return false;
399-
400-
case SILInstructionKind::CopyAddrInst: {
401-
auto *CAI = cast<CopyAddrInst>(memInst);
402-
return CAI->getDest() == address && !CAI->isInitializationOfDest();
403-
}
404-
case SILInstructionKind::StoreInst: {
405-
auto *si = cast<StoreInst>(memInst);
406-
return si->getDest() == address &&
407-
si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign;
408-
}
409-
}
410-
}
411-
412-
// Filter out recognized uses that do not write to memory.
413-
//
414-
// TODO: Ensure that all of the conditional-write logic below is encapsulated in
415-
// mayWriteToMemory and just call that instead. Possibly add additional
416-
// verification that visitAccessPathUses recognizes all instructions that may
417-
// propagate pointers (even though they don't write).
418-
bool GatherLexicalLifetimeUseVisitor::visitUse(Operand *op,
419-
AccessUseType useTy) {
420-
// If this operand is for a dependent type, then it does not actually access
421-
// the operand's address value. It only uses the metatype defined by the
422-
// operation (e.g. open_existential).
423-
if (op->isTypeDependent()) {
424-
return true;
425-
}
426-
427-
// If we have a move from src, this is a mark_move we want to visit.
428-
if (auto *move = dyn_cast<MarkUnresolvedMoveAddrInst>(op->getUser())) {
429-
if (move->getSrc() == op->get()) {
430-
LLVM_DEBUG(llvm::dbgs() << "Found move: " << *move);
431-
useState.insertMarkUnresolvedMoveAddr(move);
432-
return true;
433-
}
434-
}
435-
436-
if (memInstMustInitialize(op)) {
437-
LLVM_DEBUG(llvm::dbgs() << "Found init: " << *op->getUser());
438-
useState.inits.insert(op->getUser());
439-
return true;
440-
}
441-
442-
if (memInstMustReinitialize(op)) {
443-
LLVM_DEBUG(llvm::dbgs() << "Found reinit: " << *op->getUser());
444-
useState.insertReinit(op->getUser());
445-
return true;
446-
}
447-
448-
if (auto *dvi = dyn_cast<DestroyAddrInst>(op->getUser())) {
449-
// If we see a destroy_addr not on our base address, bail! Just error and
450-
// say that we do not understand the code.
451-
if (dvi->getOperand() != useState.address) {
452-
LLVM_DEBUG(llvm::dbgs()
453-
<< "!!! Error! Found destroy_addr no on base address: "
454-
<< *dvi);
455-
return false;
456-
}
457-
LLVM_DEBUG(llvm::dbgs() << "Found destroy_addr: " << *dvi);
458-
useState.insertDestroy(dvi);
459-
return true;
460-
}
461-
462-
// Then see if we have a inout_aliasable full apply site use. In that case, we
463-
// are going to try and extend move checking into the partial apply using
464-
// cloning to eliminate destroys or reinits.
465-
if (auto fas = FullApplySite::isa(op->getUser())) {
466-
if (fas.getArgumentOperandConvention(*op) ==
467-
SILArgumentConvention::Indirect_InoutAliasable) {
468-
// If we don't find the function, we can't handle this, so bail.
469-
auto *func = fas.getCalleeFunction();
470-
if (!func || !func->isDefer())
471-
return false;
472-
useState.insertClosureOperand(op);
473-
return true;
474-
}
475-
}
476-
477-
// Ignore dealloc_stack.
478-
if (isa<DeallocStackInst>(op->getUser()))
479-
return true;
480-
481-
LLVM_DEBUG(llvm::dbgs() << "Found liveness use: " << *op->getUser());
482-
useState.livenessUses.insert(op->getUser());
483-
484-
return true;
485-
}
359+
} // namespace
486360

487361
//===----------------------------------------------------------------------===//
488362
// Dataflow
@@ -1356,6 +1230,103 @@ void ClosureArgumentInOutToOutCloner::populateCloned() {
13561230
});
13571231
}
13581232

1233+
/////////////////////////////////////
1234+
// Caller Lexical Lifetime Visitor //
1235+
/////////////////////////////////////
1236+
1237+
namespace {
1238+
1239+
/// Visit all of the uses of a lexical lifetime, initializing useState as we go.
1240+
struct GatherLexicalLifetimeUseVisitor : public AccessUseVisitor {
1241+
UseState &useState;
1242+
1243+
GatherLexicalLifetimeUseVisitor(UseState &useState)
1244+
: AccessUseVisitor(AccessUseType::Overlapping,
1245+
NestedAccessType::IgnoreAccessBegin),
1246+
useState(useState) {}
1247+
1248+
bool visitUse(Operand *op, AccessUseType useTy) override;
1249+
void reset(SILValue address) { useState.address = address; }
1250+
void clear() { useState.clear(); }
1251+
};
1252+
1253+
} // end anonymous namespace
1254+
1255+
// Filter out recognized uses that do not write to memory.
1256+
//
1257+
// TODO: Ensure that all of the conditional-write logic below is encapsulated in
1258+
// mayWriteToMemory and just call that instead. Possibly add additional
1259+
// verification that visitAccessPathUses recognizes all instructions that may
1260+
// propagate pointers (even though they don't write).
1261+
bool GatherLexicalLifetimeUseVisitor::visitUse(Operand *op,
1262+
AccessUseType useTy) {
1263+
// If this operand is for a dependent type, then it does not actually access
1264+
// the operand's address value. It only uses the metatype defined by the
1265+
// operation (e.g. open_existential).
1266+
if (op->isTypeDependent()) {
1267+
return true;
1268+
}
1269+
1270+
// If we have a move from src, this is a mark_move we want to visit.
1271+
if (auto *move = dyn_cast<MarkUnresolvedMoveAddrInst>(op->getUser())) {
1272+
if (move->getSrc() == op->get()) {
1273+
LLVM_DEBUG(llvm::dbgs() << "Found move: " << *move);
1274+
useState.insertMarkUnresolvedMoveAddr(move);
1275+
return true;
1276+
}
1277+
}
1278+
1279+
if (memInstMustInitialize(op)) {
1280+
LLVM_DEBUG(llvm::dbgs() << "Found init: " << *op->getUser());
1281+
useState.inits.insert(op->getUser());
1282+
return true;
1283+
}
1284+
1285+
if (memInstMustReinitialize(op)) {
1286+
LLVM_DEBUG(llvm::dbgs() << "Found reinit: " << *op->getUser());
1287+
useState.insertReinit(op->getUser());
1288+
return true;
1289+
}
1290+
1291+
if (auto *dvi = dyn_cast<DestroyAddrInst>(op->getUser())) {
1292+
// If we see a destroy_addr not on our base address, bail! Just error and
1293+
// say that we do not understand the code.
1294+
if (dvi->getOperand() != useState.address) {
1295+
LLVM_DEBUG(llvm::dbgs()
1296+
<< "!!! Error! Found destroy_addr no on base address: "
1297+
<< *dvi);
1298+
return false;
1299+
}
1300+
LLVM_DEBUG(llvm::dbgs() << "Found destroy_addr: " << *dvi);
1301+
useState.insertDestroy(dvi);
1302+
return true;
1303+
}
1304+
1305+
// Then see if we have a inout_aliasable full apply site use. In that case, we
1306+
// are going to try and extend move checking into the partial apply using
1307+
// cloning to eliminate destroys or reinits.
1308+
if (auto fas = FullApplySite::isa(op->getUser())) {
1309+
if (fas.getArgumentOperandConvention(*op) ==
1310+
SILArgumentConvention::Indirect_InoutAliasable) {
1311+
// If we don't find the function, we can't handle this, so bail.
1312+
auto *func = fas.getCalleeFunction();
1313+
if (!func || !func->isDefer())
1314+
return false;
1315+
useState.insertClosureOperand(op);
1316+
return true;
1317+
}
1318+
}
1319+
1320+
// Ignore dealloc_stack.
1321+
if (isa<DeallocStackInst>(op->getUser()))
1322+
return true;
1323+
1324+
LLVM_DEBUG(llvm::dbgs() << "Found liveness use: " << *op->getUser());
1325+
useState.livenessUses.insert(op->getUser());
1326+
1327+
return true;
1328+
}
1329+
13591330
//===----------------------------------------------------------------------===//
13601331
// Global Dataflow
13611332
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)