Skip to content

Commit 0ac1040

Browse files
authored
Merge pull request swiftlang#41718 from gottesmm/pr-2fa50bd880db04a10e5bbc6885b69db9dcc3f777
[move-function] Rather than breaking block at the SIL level after moved dbg_value, do it late as an LLVM pass on llvm.dbg.addr
2 parents b9bdaed + a553b87 commit 0ac1040

File tree

11 files changed

+118
-130
lines changed

11 files changed

+118
-130
lines changed

include/swift/LLVMPasses/Passes.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ namespace swift {
102102
static char ID;
103103
InlineTreePrinter() : llvm::ModulePass(ID) {}
104104
};
105-
106105
} // end namespace swift
107106

108107
#endif

include/swift/LLVMPasses/PassesFwd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace llvm {
2525
void initializeSwiftARCContractPass(PassRegistry &);
2626
void initializeInlineTreePrinterPass(PassRegistry &);
2727
void initializeSwiftMergeFunctionsPass(PassRegistry &);
28+
void initializeSwiftDbgAddrBlockSplitterPass(PassRegistry &);
2829
}
2930

3031
namespace swift {
@@ -33,6 +34,7 @@ namespace swift {
3334
llvm::ModulePass *createInlineTreePrinterPass();
3435
llvm::ModulePass *createSwiftMergeFunctionsPass(bool ptrAuthEnabled,
3536
unsigned ptrAuthKey);
37+
llvm::FunctionPass *createSwiftDbgAddrBlockSplitter();
3638
llvm::ImmutablePass *createSwiftAAWrapperPass();
3739
llvm::ImmutablePass *createSwiftRCIdentityPass();
3840
} // end namespace swift

lib/IRGen/IRGen.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
146146
PM.add(createThreadSanitizerLegacyPassPass());
147147
}
148148

149+
static void addSwiftDbgAddrBlockSplitterPass(const PassManagerBuilder &Builder,
150+
legacy::PassManagerBase &PM) {
151+
PM.add(createSwiftDbgAddrBlockSplitter());
152+
}
153+
149154
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
150155
legacy::PassManagerBase &PM) {
151156
const PassManagerBuilderWrapper &BuilderWrapper =
@@ -289,6 +294,13 @@ void swift::performLLVMOptimizations(const IRGenOptions &Opts,
289294
});
290295
}
291296

297+
if (RunSwiftSpecificLLVMOptzns) {
298+
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
299+
addSwiftDbgAddrBlockSplitterPass);
300+
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
301+
addSwiftDbgAddrBlockSplitterPass);
302+
}
303+
292304
// Configure the function passes.
293305
legacy::FunctionPassManager FunctionPasses(Module);
294306
FunctionPasses.add(createTargetTransformInfoWrapperPass(

lib/LLVMPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_swift_host_library(swiftLLVMPasses STATIC
66
LLVMARCContract.cpp
77
LLVMInlineTree.cpp
88
LLVMMergeFunctions.cpp
9+
DbgAddrBlockSplitter.cpp
910

1011
LLVM_LINK_COMPONENTS
1112
analysis
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//===--- DbgAddrBlockSplitter.cpp -----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// This simple pass runs late after all LLVM level optimization passes have
14+
/// completed and break blocks at llvm.dbg.addr when we are compiling at
15+
/// -Onone. This helps us avoid bad behavior in SelectionDAG where SelectionDAG
16+
/// in certain cases sink llvm.dbg.addr to the end of blocks.
17+
///
18+
//===----------------------------------------------------------------------===//
19+
20+
#include "swift/LLVMPasses/Passes.h"
21+
#include "swift/LLVMPasses/PassesFwd.h"
22+
#include "llvm/IR/IntrinsicInst.h"
23+
#include "llvm/Pass.h"
24+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
25+
26+
using namespace llvm;
27+
28+
namespace {
29+
30+
struct SwiftDbgAddrBlockSplitter : FunctionPass {
31+
static char ID;
32+
SwiftDbgAddrBlockSplitter() : FunctionPass(ID) {}
33+
34+
bool runOnFunction(Function &fn) override;
35+
};
36+
37+
} // namespace
38+
39+
bool SwiftDbgAddrBlockSplitter::runOnFunction(Function &fn) {
40+
SmallVector<Instruction *, 32> breakBlockPoints;
41+
42+
for (auto &block : fn) {
43+
for (auto &inst : block) {
44+
if (isa<DbgAddrIntrinsic>(&inst)) {
45+
breakBlockPoints.push_back(&*std::next(inst.getIterator()));
46+
}
47+
}
48+
}
49+
50+
if (breakBlockPoints.empty())
51+
return false;
52+
53+
bool madeChange = false;
54+
55+
while (!breakBlockPoints.empty()) {
56+
auto *i = breakBlockPoints.pop_back_val();
57+
if (i->isTerminator())
58+
continue;
59+
SplitBlock(i->getParent(), i);
60+
madeChange = true;
61+
}
62+
63+
return madeChange;
64+
}
65+
66+
char SwiftDbgAddrBlockSplitter::ID = 0;
67+
INITIALIZE_PASS_BEGIN(SwiftDbgAddrBlockSplitter,
68+
"swift-dbg-addr-block-splitter",
69+
"Swift pass that splits blocks after llvm.dbg.addr",
70+
false, false)
71+
INITIALIZE_PASS_END(SwiftDbgAddrBlockSplitter, "swift-dbg-addr-block-splitter",
72+
"Swift pass that splits blocks after llvm.dbg.addr", false,
73+
false)
74+
75+
llvm::FunctionPass *swift::createSwiftDbgAddrBlockSplitter() {
76+
initializeSwiftDbgAddrBlockSplitterPass(
77+
*llvm::PassRegistry::getPassRegistry());
78+
return new SwiftDbgAddrBlockSplitter();
79+
}

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 13 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,19 +1398,17 @@ struct DataflowState {
13981398
applySiteToPromotedArgIndices(applySiteToPromotedArgIndices),
13991399
closureConsumes(closureConsumes) {}
14001400
void init();
1401-
bool
1402-
process(SILValue address,
1403-
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers,
1404-
SmallSetVector<SILInstruction *, 8> &debugInfoBlockSplitPoints);
1401+
bool process(
1402+
SILValue address,
1403+
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers);
14051404
bool handleSingleBlockClosure(SILArgument *address,
14061405
ClosureOperandState &state);
14071406
bool cleanupAllDestroyAddr(
14081407
SILValue address, SILFunction *fn, SmallBitVector &destroyIndices,
14091408
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
14101409
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
14111410
BasicBlockSet &blocksWithMovesThatAreNowTakes,
1412-
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers,
1413-
SmallSetVector<SILInstruction *, 8> &debugInfoBlockSplitPoints);
1411+
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers);
14141412
void clear() {
14151413
useBlocks.clear();
14161414
initBlocks.clear();
@@ -1429,8 +1427,7 @@ bool DataflowState::cleanupAllDestroyAddr(
14291427
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
14301428
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
14311429
BasicBlockSet &blocksWithMovesThatAreNowTakes,
1432-
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers,
1433-
SmallSetVector<SILInstruction *, 8> &debugInfoBlockSplitPoints) {
1430+
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers) {
14341431
bool madeChange = false;
14351432
BasicBlockWorklist worklist(fn);
14361433

@@ -1544,12 +1541,8 @@ bool DataflowState::cleanupAllDestroyAddr(
15441541
if (auto varInfo = debugVarInst.getVarInfo()) {
15451542
SILBuilderWithScope reinitBuilder(*reinit);
15461543
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);
1544+
reinitBuilder.createDebugValue(debugVarInst.inst->getLoc(), address,
1545+
*varInfo, false, /*was moved*/ true);
15531546
}
15541547
}
15551548
madeChange = true;
@@ -1591,8 +1584,7 @@ bool DataflowState::cleanupAllDestroyAddr(
15911584

15921585
bool DataflowState::process(
15931586
SILValue address,
1594-
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers,
1595-
SmallSetVector<SILInstruction *, 8> &debugInfoBlockSplitPoints) {
1587+
SmallBlotSetVector<SILInstruction *, 8> &postDominatingConsumingUsers) {
15961588
SILFunction *fn = address->getFunction();
15971589
assert(fn);
15981590

@@ -1811,25 +1803,13 @@ bool DataflowState::process(
18111803
if (!convertedMarkMoveToTake)
18121804
return madeChange;
18131805

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-
18261806
// Now that we have processed all of our mark_moves, eliminate all of the
18271807
// destroy_addr.
18281808
madeChange |= cleanupAllDestroyAddr(
18291809
address, fn, getIndicesOfPairedDestroys(), getIndicesOfPairedReinits(),
18301810
getIndicesOfPairedConsumingClosureUses(),
18311811
blocksVisitedWhenProcessingNewTakes, blocksWithMovesThatAreNowTakes,
1832-
postDominatingConsumingUsers, debugInfoBlockSplitPoints);
1812+
postDominatingConsumingUsers);
18331813

18341814
return madeChange;
18351815
}
@@ -1932,19 +1912,6 @@ struct MoveKillsCopyableAddressesChecker {
19321912
applySiteToPromotedArgIndices;
19331913
SmallBlotSetVector<SILInstruction *, 8> closureConsumes;
19341914

1935-
/// A list of instructions where to work around the behavior of SelectionDAG,
1936-
/// we break the block. These are debug var carrying insts or debug_value
1937-
/// associated with reinits. This is initialized when we process all of the
1938-
/// addresses. Then as a final step after wards we use this as a worklist and
1939-
/// break blocks at each of these instructions. We update DebugInfo, LoopInfo
1940-
/// if we found that they already exist.
1941-
///
1942-
/// We on purpose use a set vector to ensure that we only ever split a block
1943-
/// once.
1944-
SmallSetVector<SILInstruction *, 8> debugInfoBlockSplitPoints;
1945-
DominanceInfo *dominanceToUpdate = nullptr;
1946-
SILLoopInfo *loopInfoToUpdate = nullptr;
1947-
19481915
MoveKillsCopyableAddressesChecker(SILFunction *fn,
19491916
SILOptFunctionBuilder &funcBuilder)
19501917
: fn(fn), useState(),
@@ -1953,12 +1920,6 @@ struct MoveKillsCopyableAddressesChecker {
19531920
closureUseState(), closureUseDataflowState(closureUseState),
19541921
funcBuilder(funcBuilder) {}
19551922

1956-
void setDominanceToUpdate(DominanceInfo *newInfo) {
1957-
dominanceToUpdate = newInfo;
1958-
}
1959-
1960-
void setLoopInfoToUpdate(SILLoopInfo *newInfo) { loopInfoToUpdate = newInfo; }
1961-
19621923
void cloneDeferCalleeAndRewriteUses(
19631924
SmallVectorImpl<SILValue> &temporaryStorage,
19641925
const SmallBitVector &bitVector, FullApplySite oldApplySite,
@@ -1970,20 +1931,6 @@ struct MoveKillsCopyableAddressesChecker {
19701931

19711932
void emitDiagnosticForMove(SILValue borrowedValue,
19721933
StringRef borrowedValueName, MoveValueInst *mvi);
1973-
bool splitBlocksAfterDebugInfoCarryingInst(SILModule &mod) {
1974-
if (debugInfoBlockSplitPoints.empty())
1975-
return false;
1976-
1977-
SILBuilderContext ctx(mod);
1978-
do {
1979-
auto *next = debugInfoBlockSplitPoints.pop_back_val();
1980-
splitBasicBlockAndBranch(ctx, next->getNextInstruction(),
1981-
dominanceToUpdate, loopInfoToUpdate);
1982-
} while (!debugInfoBlockSplitPoints.empty());
1983-
1984-
return true;
1985-
}
1986-
19871934
bool performSingleBasicBlockAnalysis(SILValue address,
19881935
MarkUnresolvedMoveAddrInst *mvi);
19891936

@@ -2131,7 +2078,6 @@ bool MoveKillsCopyableAddressesChecker::performSingleBasicBlockAnalysis(
21312078
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
21322079
if (auto varInfo = debug.getVarInfo()) {
21332080
SILBuilderWithScope undefBuilder(builder);
2134-
debugInfoBlockSplitPoints.insert(*debug);
21352081
undefBuilder.setCurrentDebugScope(debug->getDebugScope());
21362082
undefBuilder.createDebugValue(
21372083
debug->getLoc(),
@@ -2242,7 +2188,6 @@ bool MoveKillsCopyableAddressesChecker::performSingleBasicBlockAnalysis(
22422188
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
22432189
if (auto varInfo = debug.getVarInfo()) {
22442190
{
2245-
debugInfoBlockSplitPoints.insert(*debug);
22462191
SILBuilderWithScope undefBuilder(builder);
22472192
undefBuilder.setCurrentDebugScope(debug->getDebugScope());
22482193
undefBuilder.createDebugValue(
@@ -2257,10 +2202,9 @@ bool MoveKillsCopyableAddressesChecker::performSingleBasicBlockAnalysis(
22572202
auto *next = interestingUser->getNextInstruction();
22582203
SILBuilderWithScope reinitBuilder(next);
22592204
reinitBuilder.setCurrentDebugScope(debug->getDebugScope());
2260-
auto *dvi = reinitBuilder.createDebugValue(debug->getLoc(),
2261-
address, *varInfo, false,
2262-
/*was moved*/ true);
2263-
debugInfoBlockSplitPoints.insert(dvi);
2205+
reinitBuilder.createDebugValue(debug->getLoc(), address, *varInfo,
2206+
false,
2207+
/*was moved*/ true);
22642208
}
22652209
}
22662210
debug.markAsMoved();
@@ -2296,7 +2240,6 @@ bool MoveKillsCopyableAddressesChecker::performSingleBasicBlockAnalysis(
22962240
dumpBitVector(llvm::dbgs(), bitVector); llvm::dbgs() << '\n');
22972241
if (auto debug = DebugVarCarryingInst::getFromValue(address)) {
22982242
if (auto varInfo = debug.getVarInfo()) {
2299-
debugInfoBlockSplitPoints.insert(*debug);
23002243
SILBuilderWithScope undefBuilder(builder);
23012244
undefBuilder.setCurrentDebugScope(debug->getDebugScope());
23022245
undefBuilder.createDebugValue(
@@ -2415,8 +2358,7 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
24152358
// Ok, we need to perform global dataflow for one of our moves. Initialize our
24162359
// dataflow state engine and then run the dataflow itself.
24172360
dataflowState.init();
2418-
bool result = dataflowState.process(address, closureConsumes,
2419-
debugInfoBlockSplitPoints);
2361+
bool result = dataflowState.process(address, closureConsumes);
24202362
return result;
24212363
}
24222364

@@ -2471,15 +2413,6 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
24712413

24722414
MoveKillsCopyableAddressesChecker checker(getFunction(), funcBuilder);
24732415

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-
24832416
bool madeChange = false;
24842417
while (!addressToProcess.empty()) {
24852418
auto address = addressToProcess.front();
@@ -2492,13 +2425,6 @@ class MoveKillsCopyableAddressesCheckerPass : public SILFunctionTransform {
24922425
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
24932426
}
24942427

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-
25022428
// Now go through and clone any apply sites that we need to clone.
25032429
SmallVector<SILValue, 8> newArgs;
25042430
bool rewroteCallee = false;

lib/SILOptimizer/Mandatory/MoveKillsCopyableValuesChecker.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,6 @@ bool MoveKillsCopyableValuesChecker::check() {
380380
//
381381
// TODO: We should add llvm.dbg.addr support for fastisel and also teach
382382
// CodeGen how to handle llvm.dbg.addr better.
383-
SmallVector<SILInstruction *, 8> successMovesDbgInfoCarryingInsts;
384383
bool emittedDiagnostic = false;
385384
while (!valuesToProcess.empty()) {
386385
auto lexicalValue = valuesToProcess.front();
@@ -421,7 +420,6 @@ bool MoveKillsCopyableValuesChecker::check() {
421420
} else {
422421
LLVM_DEBUG(llvm::dbgs() << " WithinBoundary: No!\n");
423422
if (auto varInfo = dbgVarInst.getVarInfo()) {
424-
successMovesDbgInfoCarryingInsts.push_back(*dbgVarInst);
425423
auto *next = mvi->getNextInstruction();
426424
SILBuilderWithScope builder(next);
427425
// We need to make sure any undefs we put in are the same loc/debug
@@ -445,24 +443,6 @@ bool MoveKillsCopyableValuesChecker::check() {
445443
}
446444
}
447445

448-
// If we emitted any diagnostics, we are going to fail and thus don't need to
449-
// use any compile time to break blocks since a user will never debug such
450-
// programs.
451-
if (emittedDiagnostic)
452-
return false;
453-
454-
// Ok! Now break before the instruction after our debug info generating inst
455-
// so that the SelectionDAG behavior mentioned above on the declaration of
456-
// successMovesDbgInfoCarryingInst.
457-
if (!successMovesDbgInfoCarryingInsts.empty()) {
458-
SILBuilderContext ctx(mod);
459-
do {
460-
auto *next = successMovesDbgInfoCarryingInsts.pop_back_val();
461-
splitBasicBlockAndBranch(ctx, next->getNextInstruction(),
462-
dominanceToUpdate, loopInfoToUpdate);
463-
} while (!successMovesDbgInfoCarryingInsts.empty());
464-
}
465-
466446
return false;
467447
}
468448

0 commit comments

Comments
 (0)