158158#include " swift/SIL/SILVisitor.h"
159159#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
160160#include " swift/SILOptimizer/Analysis/ClosureScope.h"
161+ #include " swift/SILOptimizer/Analysis/LoopAnalysis.h"
161162#include " swift/SILOptimizer/PassManager/Transforms.h"
163+ #include " swift/SILOptimizer/Utils/CFGOptUtils.h"
162164#include " swift/SILOptimizer/Utils/CanonicalOSSALifetime.h"
163165#include " swift/SILOptimizer/Utils/InstOptUtils.h"
164166#include " swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
@@ -1396,17 +1398,19 @@ struct DataflowState {
13961398 applySiteToPromotedArgIndices (applySiteToPromotedArgIndices),
13971399 closureConsumes(closureConsumes) {}
13981400 void init ();
1399- bool process (
1400- SILValue address,
1401- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
1401+ bool
1402+ process (SILValue address,
1403+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1404+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints);
14021405 bool handleSingleBlockClosure (SILArgument *address,
14031406 ClosureOperandState &state);
14041407 bool cleanupAllDestroyAddr (
14051408 SILValue address, SILFunction *fn, SmallBitVector &destroyIndices,
14061409 SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
14071410 BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
14081411 BasicBlockSet &blocksWithMovesThatAreNowTakes,
1409- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
1412+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1413+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints);
14101414 void clear () {
14111415 useBlocks.clear ();
14121416 initBlocks.clear ();
@@ -1425,7 +1429,8 @@ bool DataflowState::cleanupAllDestroyAddr(
14251429 SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
14261430 BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
14271431 BasicBlockSet &blocksWithMovesThatAreNowTakes,
1428- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1432+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1433+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints) {
14291434 bool madeChange = false ;
14301435 BasicBlockWorklist worklist (fn);
14311436
@@ -1538,8 +1543,13 @@ bool DataflowState::cleanupAllDestroyAddr(
15381543 if (debugVarInst) {
15391544 if (auto varInfo = debugVarInst.getVarInfo ()) {
15401545 SILBuilderWithScope reinitBuilder (*reinit);
1541- reinitBuilder.createDebugValue (debugVarInst.inst ->getLoc (), address,
1542- *varInfo, false , /* was moved*/ true );
1546+ reinitBuilder.setCurrentDebugScope (debugVarInst->getDebugScope ());
1547+ auto *dvi =
1548+ reinitBuilder.createDebugValue (debugVarInst.inst ->getLoc (), address,
1549+ *varInfo, false , /* was moved*/ true );
1550+ // After we are done processing, we are going to split at the reinit
1551+ // point.
1552+ debugInfoBlockSplitPoints.insert (dvi);
15431553 }
15441554 }
15451555 madeChange = true ;
@@ -1581,7 +1591,8 @@ bool DataflowState::cleanupAllDestroyAddr(
15811591
15821592bool DataflowState::process (
15831593 SILValue address,
1584- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1594+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1595+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints) {
15851596 SILFunction *fn = address->getFunction ();
15861597 assert (fn);
15871598
@@ -1778,9 +1789,9 @@ bool DataflowState::process(
17781789 debug.markAsMoved ();
17791790 if (auto varInfo = debug.getVarInfo ()) {
17801791 SILBuilderWithScope undefBuilder (builder);
1781- undefBuilder.setCurrentDebugScope (debug. inst ->getDebugScope ());
1792+ undefBuilder.setCurrentDebugScope (debug->getDebugScope ());
17821793 undefBuilder.createDebugValue (
1783- debug. inst ->getLoc (),
1794+ debug->getLoc (),
17841795 SILUndef::get (address->getType (), builder.getModule ()), *varInfo,
17851796 false /* poison*/ , true /* was moved*/ );
17861797 }
@@ -1800,13 +1811,25 @@ bool DataflowState::process(
18001811 if (!convertedMarkMoveToTake)
18011812 return madeChange;
18021813
1814+ // Now if we had a debug var carrying inst for our address, add the debug var
1815+ // carrying inst to debugInfoBlockSplitPoints so when we are done processing
1816+ // we can break blocks at those locations. This is done to ensure that we
1817+ // don't have to worry about the CFG changing while we are processing. The
1818+ // reason why we do this is that we are working around a bug in SelectionDAG
1819+ // that results in llvm.dbg.addr being sunk to the end of blocks. This can
1820+ // cause the value to appear to not be available after it is initialized. By
1821+ // breaking the block here, we guarantee that SelectionDAG's sinking has no
1822+ // effect since we are the end of the block.
1823+ if (auto debug = DebugVarCarryingInst::getFromValue (address))
1824+ debugInfoBlockSplitPoints.insert (*debug);
1825+
18031826 // Now that we have processed all of our mark_moves, eliminate all of the
18041827 // destroy_addr.
18051828 madeChange |= cleanupAllDestroyAddr (
18061829 address, fn, getIndicesOfPairedDestroys (), getIndicesOfPairedReinits (),
18071830 getIndicesOfPairedConsumingClosureUses (),
18081831 blocksVisitedWhenProcessingNewTakes, blocksWithMovesThatAreNowTakes,
1809- postDominatingConsumingUsers);
1832+ postDominatingConsumingUsers, debugInfoBlockSplitPoints );
18101833
18111834 return madeChange;
18121835}
@@ -1895,9 +1918,10 @@ void DataflowState::init() {
18951918// Returns true if we emitted a diagnostic and handled the single block
18961919// case. Returns false if we visited all of the uses and seeded the UseState
18971920// struct with the information needed to perform our interprocedural dataflow.
1898- static bool performSingleBasicBlockAnalysis (DataflowState &dataflowState,
1899- SILValue address,
1900- MarkUnresolvedMoveAddrInst *mvi) {
1921+ static bool performSingleBasicBlockAnalysis (
1922+ DataflowState &dataflowState,
1923+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints,
1924+ SILValue address, MarkUnresolvedMoveAddrInst *mvi) {
19011925 // First scan downwards to make sure we are move out of this block.
19021926 auto &useState = dataflowState.useState ;
19031927 auto &applySiteToPromotedArgIndices =
@@ -1926,6 +1950,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
19261950 if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
19271951 if (auto varInfo = debug.getVarInfo ()) {
19281952 SILBuilderWithScope undefBuilder (builder);
1953+ debugInfoBlockSplitPoints.insert (*debug);
19291954 undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
19301955 undefBuilder.createDebugValue (
19311956 debug.inst ->getLoc (),
@@ -2036,6 +2061,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
20362061 if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
20372062 if (auto varInfo = debug.getVarInfo ()) {
20382063 {
2064+ debugInfoBlockSplitPoints.insert (*debug);
20392065 SILBuilderWithScope undefBuilder (builder);
20402066 undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
20412067 undefBuilder.createDebugValue (
@@ -2049,8 +2075,11 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
20492075 // reinit instruction so we reshow the variable.
20502076 auto *next = interestingUser->getNextInstruction ();
20512077 SILBuilderWithScope reinitBuilder (next);
2052- reinitBuilder.createDebugValue (debug.inst ->getLoc (), address,
2053- *varInfo, false , /* was moved*/ true );
2078+ reinitBuilder.setCurrentDebugScope (debug->getDebugScope ());
2079+ auto *dvi = reinitBuilder.createDebugValue (debug.inst ->getLoc (),
2080+ address, *varInfo, false ,
2081+ /* was moved*/ true );
2082+ debugInfoBlockSplitPoints.insert (dvi);
20542083 }
20552084 }
20562085 debug.markAsMoved ();
@@ -2086,6 +2115,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
20862115 dumpBitVector (llvm::dbgs (), bitVector); llvm::dbgs () << ' \n ' );
20872116 if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
20882117 if (auto varInfo = debug.getVarInfo ()) {
2118+ debugInfoBlockSplitPoints.insert (*debug);
20892119 SILBuilderWithScope undefBuilder (builder);
20902120 undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
20912121 undefBuilder.createDebugValue (
@@ -2137,6 +2167,19 @@ struct MoveKillsCopyableAddressesChecker {
21372167 applySiteToPromotedArgIndices;
21382168 SmallBlotSetVector<SILInstruction *, 8 > closureConsumes;
21392169
2170+ // / A list of instructions where to work around the behavior of SelectionDAG,
2171+ // / we break the block. These are debug var carrying insts or debug_value
2172+ // / associated with reinits. This is initialized when we process all of the
2173+ // / addresses. Then as a final step after wards we use this as a worklist and
2174+ // / break blocks at each of these instructions. We update DebugInfo, LoopInfo
2175+ // / if we found that they already exist.
2176+ // /
2177+ // / We on purpose use a set vector to ensure that we only ever split a block
2178+ // / once.
2179+ SmallSetVector<SILInstruction *, 8 > debugInfoBlockSplitPoints;
2180+ DominanceInfo *dominanceToUpdate = nullptr ;
2181+ SILLoopInfo *loopInfoToUpdate = nullptr ;
2182+
21402183 MoveKillsCopyableAddressesChecker (SILFunction *fn,
21412184 SILOptFunctionBuilder &funcBuilder)
21422185 : fn(fn), useState(),
@@ -2145,6 +2188,12 @@ struct MoveKillsCopyableAddressesChecker {
21452188 closureUseState(), closureUseDataflowState(closureUseState),
21462189 funcBuilder(funcBuilder) {}
21472190
2191+ void setDominanceToUpdate (DominanceInfo *newInfo) {
2192+ dominanceToUpdate = newInfo;
2193+ }
2194+
2195+ void setLoopInfoToUpdate (SILLoopInfo *newInfo) { loopInfoToUpdate = newInfo; }
2196+
21482197 void cloneDeferCalleeAndRewriteUses (
21492198 SmallVectorImpl<SILValue> &temporaryStorage,
21502199 const SmallBitVector &bitVector, FullApplySite oldApplySite,
@@ -2156,6 +2205,19 @@ struct MoveKillsCopyableAddressesChecker {
21562205
21572206 void emitDiagnosticForMove (SILValue borrowedValue,
21582207 StringRef borrowedValueName, MoveValueInst *mvi);
2208+ bool splitBlocksAfterDebugInfoCarryingInst (SILModule &mod) {
2209+ if (debugInfoBlockSplitPoints.empty ())
2210+ return false ;
2211+
2212+ SILBuilderContext ctx (mod);
2213+ do {
2214+ auto *next = debugInfoBlockSplitPoints.pop_back_val ();
2215+ splitBasicBlockAndBranch (ctx, next->getNextInstruction (),
2216+ dominanceToUpdate, loopInfoToUpdate);
2217+ } while (!debugInfoBlockSplitPoints.empty ());
2218+
2219+ return true ;
2220+ }
21592221
21602222 ASTContext &getASTContext () const { return fn->getASTContext (); }
21612223};
@@ -2332,8 +2394,8 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
23322394 // diagnostic.
23332395 bool emittedSingleBBDiagnostic = false ;
23342396 for (auto *mvi : useState.markMoves ) {
2335- emittedSingleBBDiagnostic |=
2336- performSingleBasicBlockAnalysis ( dataflowState, address, mvi);
2397+ emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (
2398+ dataflowState, debugInfoBlockSplitPoints , address, mvi);
23372399 }
23382400
23392401 if (emittedSingleBBDiagnostic) {
@@ -2353,7 +2415,8 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
23532415 // Ok, we need to perform global dataflow for one of our moves. Initialize our
23542416 // dataflow state engine and then run the dataflow itself.
23552417 dataflowState.init ();
2356- bool result = dataflowState.process (address, closureConsumes);
2418+ bool result = dataflowState.process (address, closureConsumes,
2419+ debugInfoBlockSplitPoints);
23572420 return result;
23582421}
23592422
@@ -2405,9 +2468,19 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
24052468 llvm::makeArrayRef (addressesToCheck.begin (), addressesToCheck.end ());
24062469
24072470 SILOptFunctionBuilder funcBuilder (*this );
2471+
24082472 MoveKillsCopyableAddressesChecker checker (getFunction (), funcBuilder);
2409- bool madeChange = false ;
24102473
2474+ // If we already had dominance or loop info generated, update them when
2475+ // splitting blocks.
2476+ auto *dominanceAnalysis = getAnalysis<DominanceAnalysis>();
2477+ if (dominanceAnalysis->hasFunctionInfo (fn))
2478+ checker.setDominanceToUpdate (dominanceAnalysis->get (fn));
2479+ auto *loopAnalysis = getAnalysis<SILLoopAnalysis>();
2480+ if (loopAnalysis->hasFunctionInfo (fn))
2481+ checker.setLoopInfoToUpdate (loopAnalysis->get (fn));
2482+
2483+ bool madeChange = false ;
24112484 while (!addressToProcess.empty ()) {
24122485 auto address = addressToProcess.front ();
24132486 addressToProcess = addressToProcess.drop_front (1 );
@@ -2419,6 +2492,13 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
24192492 invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
24202493 }
24212494
2495+ // We update debug info/loop info here, so we just invalidate instructions.
2496+ if (checker.splitBlocksAfterDebugInfoCarryingInst (fn->getModule ())) {
2497+ AnalysisPreserver preserveDominance (dominanceAnalysis);
2498+ AnalysisPreserver preserveLoop (loopAnalysis);
2499+ invalidateAnalysis (SILAnalysis::InvalidationKind::BranchesAndInstructions);
2500+ }
2501+
24222502 // Now go through and clone any apply sites that we need to clone.
24232503 SmallVector<SILValue, 8 > newArgs;
24242504 bool rewroteCallee = false ;
0 commit comments