Skip to content

Commit 819a56e

Browse files
committed
[cfg] Extract out erasePhiArgument utility from SimplifyCFG -> CFG.h.
I needed this functionality to fix an edge case bug in closure lifetime fixup.
1 parent da61cc8 commit 819a56e

File tree

3 files changed

+87
-80
lines changed

3 files changed

+87
-80
lines changed

include/swift/SILOptimizer/Utils/CFG.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ TermInst *addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest,
4545
TermInst *changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, size_t Idx,
4646
SILValue Val);
4747

48+
/// Deletes the edge value between a branch and a destination basic block at the
49+
/// specified index. Asserts internally that the argument along the edge does
50+
/// not have uses.
51+
TermInst *deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
52+
size_t argIndex);
53+
54+
/// Erase the \p argIndex phi argument from \p block. Asserts that the argument
55+
/// is a /real/ phi argument. Removes all incoming values for the argument from
56+
/// predecessor terminators. Asserts internally that it only ever is given
57+
/// "true" phi argument.
58+
void erasePhiArgument(SILBasicBlock *block, unsigned argIndex);
59+
4860
/// Replace a branch target.
4961
///
5062
/// \param T The terminating instruction to modify.

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 4 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,84 +2712,6 @@ bool SimplifyCFG::tailDuplicateObjCMethodCallSuccessorBlocks() {
27122712
return Changed;
27132713
}
27142714

2715-
static void
2716-
deleteTriviallyDeadOperandsOfDeadArgument(MutableArrayRef<Operand> TermOperands,
2717-
unsigned DeadArgIndex) {
2718-
Operand &Op = TermOperands[DeadArgIndex];
2719-
auto *I = Op.get()->getDefiningInstruction();
2720-
if (!I)
2721-
return;
2722-
Op.set(SILUndef::get(Op.get()->getType(), *I->getFunction()));
2723-
recursivelyDeleteTriviallyDeadInstructions(I);
2724-
}
2725-
2726-
static void removeArgumentFromTerminator(SILBasicBlock *BB, SILBasicBlock *Dest,
2727-
int idx) {
2728-
TermInst *Branch = BB->getTerminator();
2729-
SILBuilderWithScope Builder(Branch);
2730-
LLVM_DEBUG(llvm::dbgs() << "remove dead argument " << idx << " from "
2731-
<< *Branch);
2732-
2733-
if (auto *CBI = dyn_cast<CondBranchInst>(Branch)) {
2734-
SmallVector<SILValue, 8> TrueArgs;
2735-
SmallVector<SILValue, 8> FalseArgs;
2736-
2737-
for (auto A : CBI->getTrueArgs())
2738-
TrueArgs.push_back(A);
2739-
2740-
for (auto A : CBI->getFalseArgs())
2741-
FalseArgs.push_back(A);
2742-
2743-
if (Dest == CBI->getTrueBB()) {
2744-
deleteTriviallyDeadOperandsOfDeadArgument(CBI->getTrueOperands(), idx);
2745-
TrueArgs.erase(TrueArgs.begin() + idx);
2746-
}
2747-
2748-
if (Dest == CBI->getFalseBB()) {
2749-
deleteTriviallyDeadOperandsOfDeadArgument(CBI->getFalseOperands(), idx);
2750-
FalseArgs.erase(FalseArgs.begin() + idx);
2751-
}
2752-
2753-
Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(),
2754-
CBI->getTrueBB(), TrueArgs, CBI->getFalseBB(),
2755-
FalseArgs, CBI->getTrueBBCount(),
2756-
CBI->getFalseBBCount());
2757-
Branch->eraseFromParent();
2758-
return;
2759-
}
2760-
2761-
if (auto *BI = dyn_cast<BranchInst>(Branch)) {
2762-
SmallVector<SILValue, 8> Args;
2763-
2764-
for (auto A : BI->getArgs())
2765-
Args.push_back(A);
2766-
2767-
deleteTriviallyDeadOperandsOfDeadArgument(BI->getAllOperands(), idx);
2768-
Args.erase(Args.begin() + idx);
2769-
Builder.createBranch(BI->getLoc(), BI->getDestBB(), Args);
2770-
Branch->eraseFromParent();
2771-
return;
2772-
}
2773-
llvm_unreachable("unsupported terminator");
2774-
}
2775-
2776-
static void removeArgument(SILBasicBlock *BB, unsigned i) {
2777-
NumDeadArguments++;
2778-
BB->eraseArgument(i);
2779-
2780-
// Determine the set of predecessors in case any predecessor has
2781-
// two edges to this block (e.g. a conditional branch where both
2782-
// sides reach this block).
2783-
llvm::SetVector<SILBasicBlock *,SmallVector<SILBasicBlock *, 8>,
2784-
SmallPtrSet<SILBasicBlock *, 8>> PredBBs;
2785-
2786-
for (auto *Pred : BB->getPredecessorBlocks())
2787-
PredBBs.insert(Pred);
2788-
2789-
for (auto *Pred : PredBBs)
2790-
removeArgumentFromTerminator(Pred, BB, i);
2791-
}
2792-
27932715
namespace {
27942716

27952717
class ArgumentSplitter {
@@ -3026,7 +2948,8 @@ bool ArgumentSplitter::split() {
30262948
Worklist.push_back(A);
30272949
continue;
30282950
}
3029-
removeArgument(ParentBB, i);
2951+
erasePhiArgument(ParentBB, i);
2952+
++NumDeadArguments;
30302953
}
30312954

30322955
return true;
@@ -3766,7 +3689,8 @@ bool SimplifyCFG::simplifyArgs(SILBasicBlock *BB) {
37663689
continue;
37673690
}
37683691

3769-
removeArgument(BB, i);
3692+
erasePhiArgument(BB, i);
3693+
++NumDeadArguments;
37703694
Changed = true;
37713695
}
37723696

lib/SILOptimizer/Utils/CFG.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,77 @@ TermInst *swift::addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest,
7777
return NewBr;
7878
}
7979

80+
static void
81+
deleteTriviallyDeadOperandsOfDeadArgument(MutableArrayRef<Operand> termOperands,
82+
unsigned deadArgIndex) {
83+
Operand &op = termOperands[deadArgIndex];
84+
auto *i = op.get()->getDefiningInstruction();
85+
if (!i)
86+
return;
87+
op.set(SILUndef::get(op.get()->getType(), *i->getFunction()));
88+
recursivelyDeleteTriviallyDeadInstructions(i);
89+
}
90+
91+
// Our implementation assumes that our caller is attempting to remove a dead
92+
// SILPhiArgument from a SILBasicBlock and has already RAUWed the argument.
93+
TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
94+
size_t argIndex) {
95+
if (auto *cbi = dyn_cast<CondBranchInst>(branch)) {
96+
SmallVector<SILValue, 8> trueArgs;
97+
SmallVector<SILValue, 8> falseArgs;
98+
99+
copy(cbi->getTrueArgs(), std::back_inserter(trueArgs));
100+
copy(cbi->getFalseArgs(), std::back_inserter(falseArgs));
101+
102+
if (destBlock == cbi->getTrueBB()) {
103+
deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(), argIndex);
104+
trueArgs.erase(trueArgs.begin() + argIndex);
105+
}
106+
107+
if (destBlock == cbi->getFalseBB()) {
108+
deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(), argIndex);
109+
falseArgs.erase(falseArgs.begin() + argIndex);
110+
}
111+
112+
SILBuilderWithScope builder(cbi);
113+
auto *result = builder.createCondBranch(cbi->getLoc(), cbi->getCondition(),
114+
cbi->getTrueBB(), trueArgs, cbi->getFalseBB(),
115+
falseArgs, cbi->getTrueBBCount(),
116+
cbi->getFalseBBCount());
117+
branch->eraseFromParent();
118+
return result;
119+
}
120+
121+
if (auto *bi = dyn_cast<BranchInst>(branch)) {
122+
SmallVector<SILValue, 8> args;
123+
copy(bi->getArgs(), std::back_inserter(args));
124+
125+
deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex);
126+
args.erase(args.begin() + argIndex);
127+
auto *result = SILBuilderWithScope(bi).createBranch(bi->getLoc(), bi->getDestBB(), args);
128+
branch->eraseFromParent();
129+
return result;
130+
}
131+
132+
llvm_unreachable("unsupported terminator");
133+
}
134+
135+
void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex) {
136+
assert(block->getArgument(argIndex)->isPhiArgument() &&
137+
"Only should be used on phi arguments");
138+
block->eraseArgument(argIndex);
139+
140+
// Determine the set of predecessors in case any predecessor has
141+
// two edges to this block (e.g. a conditional branch where both
142+
// sides reach this block).
143+
SmallVector<SILBasicBlock *, 8> predBlocks(block->pred_begin(),
144+
block->pred_end());
145+
sortUnique(predBlocks);
146+
147+
for (auto *pred : predBlocks)
148+
deleteEdgeValue(pred->getTerminator(), block, argIndex);
149+
}
150+
80151
/// Changes the edge value between a branch and destination basic block
81152
/// at the specified index. Changes all edges from \p Branch to \p Dest to carry
82153
/// the value.

0 commit comments

Comments
 (0)