Skip to content

Commit 2dcefe5

Browse files
committed
[move-function] Move the single basic block dataflow also onto that helper struct.
1 parent fe4e16b commit 2dcefe5

File tree

1 file changed

+97
-98
lines changed

1 file changed

+97
-98
lines changed

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 97 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,97 @@ void DataflowState::init() {
804804
}
805805
}
806806

807+
// Returns true if we emitted a diagnostic and handled the single block
808+
// case. Returns false if we visited all of the uses and seeded the UseState
809+
// struct with the information needed to perform our interprocedural dataflow.
810+
static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
811+
SILValue address,
812+
MarkUnresolvedMoveAddrInst *mvi) {
813+
// First scan downwards to make sure we are move out of this block.
814+
auto &useState = dataflowState.useState;
815+
SILInstruction *interestingUser = nullptr;
816+
switch (downwardScanForMoveOut(mvi, useState, &interestingUser)) {
817+
case DownwardScanResult::Invalid:
818+
llvm_unreachable("invalid");
819+
case DownwardScanResult::Destroy: {
820+
// If we found a destroy, then we found a single block case that we can
821+
// handle. Remove the destroy and convert the mark_unresolved_move_addr
822+
// into a true move.
823+
auto *dvi = cast<DestroyAddrInst>(interestingUser);
824+
SILBuilderWithScope builder(mvi);
825+
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(), IsTake,
826+
IsInitialization);
827+
useState.destroys.erase(dvi);
828+
mvi->eraseFromParent();
829+
dvi->eraseFromParent();
830+
return false;
831+
}
832+
case DownwardScanResult::UseForDiagnostic: {
833+
// Then check if we found a user that violated our dataflow rules. In such
834+
// a case, emit an error, cleanup our mark_unresolved_move_addr, and
835+
// finally continue.
836+
auto &astCtx = mvi->getFunction()->getASTContext();
837+
{
838+
auto diag =
839+
diag::sil_movekillscopyablevalue_value_consumed_more_than_once;
840+
StringRef name = getDebugVarName(address);
841+
diagnose(astCtx, getSourceLocFromValue(address), diag, name);
842+
}
843+
844+
{
845+
auto diag = diag::sil_movekillscopyablevalue_move_here;
846+
diagnose(astCtx, mvi->getLoc().getSourceLoc(), diag);
847+
}
848+
849+
{
850+
auto diag = diag::sil_movekillscopyablevalue_use_here;
851+
diagnose(astCtx, interestingUser->getLoc().getSourceLoc(), diag);
852+
}
853+
854+
// We purposely continue to see if at least in simple cases, we can flag
855+
// mistakes from other moves. Since we are setting emittedDiagnostic to
856+
// true, we will not perform the actual dataflow due to a check after
857+
// the loop.
858+
//
859+
// We also clean up mvi by converting it to a copy_addr init so we do not
860+
// emit fail errors later.
861+
//
862+
// TODO: Can we handle multiple errors in the same block for a single
863+
// move?
864+
SILBuilderWithScope builder(mvi);
865+
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(),
866+
IsNotTake, IsInitialization);
867+
mvi->eraseFromParent();
868+
return true;
869+
}
870+
case DownwardScanResult::Reinit: {
871+
convertMemoryReinitToInitForm(interestingUser);
872+
useState.reinits.erase(interestingUser);
873+
SILBuilderWithScope builder(mvi);
874+
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(), IsTake,
875+
IsInitialization);
876+
mvi->eraseFromParent();
877+
return false;
878+
}
879+
case DownwardScanResult::MoveOut:
880+
break;
881+
}
882+
883+
// If we did not found any uses later in the block that was an interesting
884+
// use, we need to perform dataflow.
885+
LLVM_DEBUG(llvm::dbgs() << "Our move is live out, so we need to process "
886+
"it with the dataflow.\n");
887+
dataflowState.markMovesToDataflow.emplace_back(mvi);
888+
889+
// Now scan up to see if mvi is also a use to seed the dataflow. This could
890+
// happen if we have an earlier move.
891+
if (upwardScanForUseOut(mvi, dataflowState.useState)) {
892+
LLVM_DEBUG(llvm::dbgs() << "MVI projects a use up");
893+
dataflowState.useBlocks[mvi->getParent()] = mvi;
894+
}
895+
return false;
896+
}
897+
807898
//===----------------------------------------------------------------------===//
808899
// Address Checker
809900
//===----------------------------------------------------------------------===//
@@ -817,7 +908,6 @@ struct MoveKillsCopyableAddressesObjectChecker {
817908

818909
MoveKillsCopyableAddressesObjectChecker(SILFunction *fn)
819910
: fn(fn), useState(), dataflowState(useState) {}
820-
bool performSingleBasicBlockAnalysisForAllMarkMoves(SILValue address);
821911

822912
bool check(SILValue address);
823913

@@ -829,102 +919,6 @@ struct MoveKillsCopyableAddressesObjectChecker {
829919

830920
} // namespace
831921

832-
// Returns true if we emitted a diagnostic and handled the single block
833-
// case. Returns false if we visited all of the uses and seeded the UseState
834-
// struct with the information needed to perform our interprocedural dataflow.
835-
bool MoveKillsCopyableAddressesObjectChecker::
836-
performSingleBasicBlockAnalysisForAllMarkMoves(SILValue address) {
837-
bool didEmitSingleBlockDiagnostic = false;
838-
for (auto *mvi : useState.markMoves) {
839-
// First scan downwards to make sure we are move out of this block.
840-
841-
SILInstruction *interestingUser = nullptr;
842-
switch (downwardScanForMoveOut(mvi, useState, &interestingUser)) {
843-
case DownwardScanResult::Invalid:
844-
llvm_unreachable("invalid");
845-
case DownwardScanResult::Destroy: {
846-
// If we found a destroy, then we found a single block case that we can
847-
// handle. Remove the destroy and convert the mark_unresolved_move_addr
848-
// into a true move.
849-
auto *dvi = cast<DestroyAddrInst>(interestingUser);
850-
SILBuilderWithScope builder(mvi);
851-
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(),
852-
IsTake, IsInitialization);
853-
useState.destroys.erase(dvi);
854-
mvi->eraseFromParent();
855-
dvi->eraseFromParent();
856-
continue;
857-
}
858-
case DownwardScanResult::UseForDiagnostic: {
859-
// Then check if we found a user that violated our dataflow rules. In such
860-
// a case, emit an error, cleanup our mark_unresolved_move_addr, and
861-
// finally continue.
862-
didEmitSingleBlockDiagnostic = true;
863-
864-
{
865-
auto diag =
866-
diag::sil_movekillscopyablevalue_value_consumed_more_than_once;
867-
StringRef name = getDebugVarName(address);
868-
diagnose(getASTContext(), getSourceLocFromValue(address), diag, name);
869-
}
870-
871-
{
872-
auto diag = diag::sil_movekillscopyablevalue_move_here;
873-
diagnose(getASTContext(), mvi->getLoc().getSourceLoc(), diag);
874-
}
875-
876-
{
877-
auto diag = diag::sil_movekillscopyablevalue_use_here;
878-
diagnose(getASTContext(), interestingUser->getLoc().getSourceLoc(),
879-
diag);
880-
}
881-
882-
// We purposely continue to see if at least in simple cases, we can flag
883-
// mistakes from other moves. Since we are setting emittedDiagnostic to
884-
// true, we will not perform the actual dataflow due to a check after
885-
// the loop.
886-
//
887-
// We also clean up mvi by converting it to a copy_addr init so we do not
888-
// emit fail errors later.
889-
//
890-
// TODO: Can we handle multiple errors in the same block for a single
891-
// move?
892-
SILBuilderWithScope builder(mvi);
893-
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(),
894-
IsNotTake, IsInitialization);
895-
mvi->eraseFromParent();
896-
continue;
897-
}
898-
case DownwardScanResult::Reinit: {
899-
convertMemoryReinitToInitForm(interestingUser);
900-
useState.reinits.erase(interestingUser);
901-
SILBuilderWithScope builder(mvi);
902-
builder.createCopyAddr(mvi->getLoc(), mvi->getSrc(), mvi->getDest(),
903-
IsTake, IsInitialization);
904-
mvi->eraseFromParent();
905-
continue;
906-
}
907-
case DownwardScanResult::MoveOut:
908-
break;
909-
}
910-
911-
// If we did not found any uses later in the block that was an interesting
912-
// use, we need to perform dataflow.
913-
LLVM_DEBUG(llvm::dbgs() << "Our move is live out, so we need to process "
914-
"it with the dataflow.\n");
915-
dataflowState.markMovesToDataflow.emplace_back(mvi);
916-
917-
// Now scan up to see if mvi is also a use to seed the dataflow. This could
918-
// happen if we have an earlier move.
919-
if (upwardScanForUseOut(mvi, useState)) {
920-
LLVM_DEBUG(llvm::dbgs() << "MVI projects a use up");
921-
dataflowState.useBlocks[mvi->getParent()] = mvi;
922-
}
923-
}
924-
925-
return didEmitSingleBlockDiagnostic;
926-
}
927-
928922
bool MoveKillsCopyableAddressesObjectChecker::check(SILValue address) {
929923
auto accessPathWithBase = AccessPathWithBase::compute(address);
930924
auto accessPath = accessPathWithBase.accessPath;
@@ -968,7 +962,12 @@ bool MoveKillsCopyableAddressesObjectChecker::check(SILValue address) {
968962
// mark_move that propagates its state out of the current block, this
969963
// routine also prepares the pass for running the multi-basic block
970964
// diagnostic.
971-
if (performSingleBasicBlockAnalysisForAllMarkMoves(address)) {
965+
bool emittedSingleBBDiagnostic = false;
966+
for (auto *mvi : useState.markMoves) {
967+
emittedSingleBBDiagnostic |=
968+
performSingleBasicBlockAnalysis(dataflowState, address, mvi);
969+
}
970+
if (emittedSingleBBDiagnostic) {
972971
LLVM_DEBUG(llvm::dbgs() << "Performed single block analysis!\n");
973972
return true;
974973
}

0 commit comments

Comments
 (0)