158
158
#include " swift/SIL/SILVisitor.h"
159
159
#include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
160
160
#include " swift/SILOptimizer/Analysis/ClosureScope.h"
161
+ #include " swift/SILOptimizer/Analysis/LoopAnalysis.h"
161
162
#include " swift/SILOptimizer/PassManager/Transforms.h"
163
+ #include " swift/SILOptimizer/Utils/CFGOptUtils.h"
162
164
#include " swift/SILOptimizer/Utils/CanonicalOSSALifetime.h"
163
165
#include " swift/SILOptimizer/Utils/InstOptUtils.h"
164
166
#include " swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
@@ -1396,17 +1398,19 @@ struct DataflowState {
1396
1398
applySiteToPromotedArgIndices (applySiteToPromotedArgIndices),
1397
1399
closureConsumes(closureConsumes) {}
1398
1400
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);
1402
1405
bool handleSingleBlockClosure (SILArgument *address,
1403
1406
ClosureOperandState &state);
1404
1407
bool cleanupAllDestroyAddr (
1405
1408
SILValue address, SILFunction *fn, SmallBitVector &destroyIndices,
1406
1409
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
1407
1410
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
1408
1411
BasicBlockSet &blocksWithMovesThatAreNowTakes,
1409
- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
1412
+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1413
+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints);
1410
1414
void clear () {
1411
1415
useBlocks.clear ();
1412
1416
initBlocks.clear ();
@@ -1425,7 +1429,8 @@ bool DataflowState::cleanupAllDestroyAddr(
1425
1429
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
1426
1430
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
1427
1431
BasicBlockSet &blocksWithMovesThatAreNowTakes,
1428
- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1432
+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1433
+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints) {
1429
1434
bool madeChange = false ;
1430
1435
BasicBlockWorklist worklist (fn);
1431
1436
@@ -1538,8 +1543,13 @@ bool DataflowState::cleanupAllDestroyAddr(
1538
1543
if (debugVarInst) {
1539
1544
if (auto varInfo = debugVarInst.getVarInfo ()) {
1540
1545
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);
1543
1553
}
1544
1554
}
1545
1555
madeChange = true ;
@@ -1581,7 +1591,8 @@ bool DataflowState::cleanupAllDestroyAddr(
1581
1591
1582
1592
bool DataflowState::process (
1583
1593
SILValue address,
1584
- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1594
+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers,
1595
+ SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints) {
1585
1596
SILFunction *fn = address->getFunction ();
1586
1597
assert (fn);
1587
1598
@@ -1778,9 +1789,9 @@ bool DataflowState::process(
1778
1789
debug.markAsMoved ();
1779
1790
if (auto varInfo = debug.getVarInfo ()) {
1780
1791
SILBuilderWithScope undefBuilder (builder);
1781
- undefBuilder.setCurrentDebugScope (debug. inst ->getDebugScope ());
1792
+ undefBuilder.setCurrentDebugScope (debug->getDebugScope ());
1782
1793
undefBuilder.createDebugValue (
1783
- debug. inst ->getLoc (),
1794
+ debug->getLoc (),
1784
1795
SILUndef::get (address->getType (), builder.getModule ()), *varInfo,
1785
1796
false /* poison*/ , true /* was moved*/ );
1786
1797
}
@@ -1800,13 +1811,25 @@ bool DataflowState::process(
1800
1811
if (!convertedMarkMoveToTake)
1801
1812
return madeChange;
1802
1813
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
+
1803
1826
// Now that we have processed all of our mark_moves, eliminate all of the
1804
1827
// destroy_addr.
1805
1828
madeChange |= cleanupAllDestroyAddr (
1806
1829
address, fn, getIndicesOfPairedDestroys (), getIndicesOfPairedReinits (),
1807
1830
getIndicesOfPairedConsumingClosureUses (),
1808
1831
blocksVisitedWhenProcessingNewTakes, blocksWithMovesThatAreNowTakes,
1809
- postDominatingConsumingUsers);
1832
+ postDominatingConsumingUsers, debugInfoBlockSplitPoints );
1810
1833
1811
1834
return madeChange;
1812
1835
}
@@ -1895,9 +1918,10 @@ void DataflowState::init() {
1895
1918
// Returns true if we emitted a diagnostic and handled the single block
1896
1919
// case. Returns false if we visited all of the uses and seeded the UseState
1897
1920
// 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) {
1901
1925
// First scan downwards to make sure we are move out of this block.
1902
1926
auto &useState = dataflowState.useState ;
1903
1927
auto &applySiteToPromotedArgIndices =
@@ -1926,6 +1950,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
1926
1950
if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
1927
1951
if (auto varInfo = debug.getVarInfo ()) {
1928
1952
SILBuilderWithScope undefBuilder (builder);
1953
+ debugInfoBlockSplitPoints.insert (*debug);
1929
1954
undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
1930
1955
undefBuilder.createDebugValue (
1931
1956
debug.inst ->getLoc (),
@@ -2036,6 +2061,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
2036
2061
if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
2037
2062
if (auto varInfo = debug.getVarInfo ()) {
2038
2063
{
2064
+ debugInfoBlockSplitPoints.insert (*debug);
2039
2065
SILBuilderWithScope undefBuilder (builder);
2040
2066
undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
2041
2067
undefBuilder.createDebugValue (
@@ -2049,8 +2075,11 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
2049
2075
// reinit instruction so we reshow the variable.
2050
2076
auto *next = interestingUser->getNextInstruction ();
2051
2077
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);
2054
2083
}
2055
2084
}
2056
2085
debug.markAsMoved ();
@@ -2086,6 +2115,7 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
2086
2115
dumpBitVector (llvm::dbgs (), bitVector); llvm::dbgs () << ' \n ' );
2087
2116
if (auto debug = DebugVarCarryingInst::getFromValue (address)) {
2088
2117
if (auto varInfo = debug.getVarInfo ()) {
2118
+ debugInfoBlockSplitPoints.insert (*debug);
2089
2119
SILBuilderWithScope undefBuilder (builder);
2090
2120
undefBuilder.setCurrentDebugScope (debug.inst ->getDebugScope ());
2091
2121
undefBuilder.createDebugValue (
@@ -2137,6 +2167,19 @@ struct MoveKillsCopyableAddressesChecker {
2137
2167
applySiteToPromotedArgIndices;
2138
2168
SmallBlotSetVector<SILInstruction *, 8 > closureConsumes;
2139
2169
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
+
2140
2183
MoveKillsCopyableAddressesChecker (SILFunction *fn,
2141
2184
SILOptFunctionBuilder &funcBuilder)
2142
2185
: fn(fn), useState(),
@@ -2145,6 +2188,12 @@ struct MoveKillsCopyableAddressesChecker {
2145
2188
closureUseState(), closureUseDataflowState(closureUseState),
2146
2189
funcBuilder(funcBuilder) {}
2147
2190
2191
+ void setDominanceToUpdate (DominanceInfo *newInfo) {
2192
+ dominanceToUpdate = newInfo;
2193
+ }
2194
+
2195
+ void setLoopInfoToUpdate (SILLoopInfo *newInfo) { loopInfoToUpdate = newInfo; }
2196
+
2148
2197
void cloneDeferCalleeAndRewriteUses (
2149
2198
SmallVectorImpl<SILValue> &temporaryStorage,
2150
2199
const SmallBitVector &bitVector, FullApplySite oldApplySite,
@@ -2156,6 +2205,19 @@ struct MoveKillsCopyableAddressesChecker {
2156
2205
2157
2206
void emitDiagnosticForMove (SILValue borrowedValue,
2158
2207
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
+ }
2159
2221
2160
2222
ASTContext &getASTContext () const { return fn->getASTContext (); }
2161
2223
};
@@ -2332,8 +2394,8 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
2332
2394
// diagnostic.
2333
2395
bool emittedSingleBBDiagnostic = false ;
2334
2396
for (auto *mvi : useState.markMoves ) {
2335
- emittedSingleBBDiagnostic |=
2336
- performSingleBasicBlockAnalysis ( dataflowState, address, mvi);
2397
+ emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (
2398
+ dataflowState, debugInfoBlockSplitPoints , address, mvi);
2337
2399
}
2338
2400
2339
2401
if (emittedSingleBBDiagnostic) {
@@ -2353,7 +2415,8 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
2353
2415
// Ok, we need to perform global dataflow for one of our moves. Initialize our
2354
2416
// dataflow state engine and then run the dataflow itself.
2355
2417
dataflowState.init ();
2356
- bool result = dataflowState.process (address, closureConsumes);
2418
+ bool result = dataflowState.process (address, closureConsumes,
2419
+ debugInfoBlockSplitPoints);
2357
2420
return result;
2358
2421
}
2359
2422
@@ -2405,9 +2468,19 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
2405
2468
llvm::makeArrayRef (addressesToCheck.begin (), addressesToCheck.end ());
2406
2469
2407
2470
SILOptFunctionBuilder funcBuilder (*this );
2471
+
2408
2472
MoveKillsCopyableAddressesChecker checker (getFunction (), funcBuilder);
2409
- bool madeChange = false ;
2410
2473
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 ;
2411
2484
while (!addressToProcess.empty ()) {
2412
2485
auto address = addressToProcess.front ();
2413
2486
addressToProcess = addressToProcess.drop_front (1 );
@@ -2419,6 +2492,13 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
2419
2492
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
2420
2493
}
2421
2494
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
+
2422
2502
// Now go through and clone any apply sites that we need to clone.
2423
2503
SmallVector<SILValue, 8 > newArgs;
2424
2504
bool rewroteCallee = false ;
0 commit comments