Skip to content

Commit bb7844c

Browse files
committed
DeadCodeElimination: a small cleanup
Split `markValueLive(SILNode *)` into `markValueLive(SILValue)` and `markInstructionLive(SILInstruction*)`
1 parent 2927688 commit bb7844c

File tree

2 files changed

+55
-34
lines changed

2 files changed

+55
-34
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ class DCE {
9797
typedef llvm::DomTreeNodeBase<SILBasicBlock> PostDomTreeNode;
9898

9999
SILFunction *F;
100-
llvm::SmallPtrSet<SILNode *, 16> LiveValues;
100+
llvm::SmallPtrSet<SILArgument *, 16> LiveArguments;
101+
llvm::SmallPtrSet<SILInstruction *, 16> LiveInstructions;
101102
BasicBlockSet LiveBlocks;
102103
llvm::SmallVector<SILInstruction *, 64> Worklist;
103104
PostDominanceInfo *PDT;
@@ -138,7 +139,8 @@ class DCE {
138139
void computeMinPredecessorLevels(PostDomTreeNode *root);
139140
void insertControllingInfo(SILBasicBlock *Block, unsigned Level);
140141

141-
void markValueLive(SILNode *V);
142+
void markValueLive(SILValue V);
143+
void markInstructionLive(SILInstruction *Inst);
142144
void markTerminatorArgsLive(SILBasicBlock *Pred, SILBasicBlock *Succ,
143145
size_t ArgIndex);
144146
void markControllingTerminatorsLive(SILBasicBlock *Block);
@@ -173,32 +175,33 @@ class DCE {
173175

174176
// Keep track of the fact that V is live and add it to our worklist
175177
// so that we can process the values it depends on.
176-
void DCE::markValueLive(SILNode *V) {
177-
V = V->getRepresentativeSILNodeInObject();
178-
if (LiveValues.count(V) || isa<SILUndef>(V))
179-
return;
180-
181-
LLVM_DEBUG(llvm::dbgs() << "Marking as live:\n");
182-
LLVM_DEBUG(V->dump());
178+
void DCE::markValueLive(SILValue V) {
179+
if (SILInstruction *inst = V->getDefiningInstruction())
180+
return markInstructionLive(inst);
183181

184-
LiveValues.insert(V);
185-
186-
if (auto *Def = dyn_cast<SILInstruction>(V)) {
187-
markControllingTerminatorsLive(Def->getParent());
188-
Worklist.push_back(Def);
182+
if (isa<SILUndef>(V))
189183
return;
190-
}
191184

192-
// TODO: MultiValueInstruction
193-
194-
assert(isa<SILArgument>(V) &&
195-
"Only expected instructions and arguments!");
185+
LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *V);
196186

197187
auto *Arg = cast<SILArgument>(V);
188+
if (!LiveArguments.insert(Arg).second)
189+
return;
190+
198191
markControllingTerminatorsLive(Arg->getParent());
199192
propagateLiveBlockArgument(Arg);
200193
}
201194

195+
void DCE::markInstructionLive(SILInstruction *Inst) {
196+
if (!LiveInstructions.insert(Inst).second)
197+
return;
198+
199+
LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *Inst);
200+
201+
markControllingTerminatorsLive(Inst->getParent());
202+
Worklist.push_back(Inst);
203+
}
204+
202205
/// Gets the producing instruction of a cond_fail condition. Currently these
203206
/// are overflow builtins but may be extended to other instructions in the
204207
/// future.
@@ -228,7 +231,7 @@ void DCE::markLive() {
228231
if (auto *Prod = getProducer(cast<CondFailInst>(&I))) {
229232
addReverseDependency(Prod, &I);
230233
} else {
231-
markValueLive(&I);
234+
markInstructionLive(&I);
232235
}
233236
break;
234237
}
@@ -237,7 +240,7 @@ void DCE::markLive() {
237240
if (!Op->getType().isAddress()) {
238241
addReverseDependency(Op, &I);
239242
} else {
240-
markValueLive(&I);
243+
markInstructionLive(&I);
241244
}
242245
break;
243246
}
@@ -255,7 +258,7 @@ void DCE::markLive() {
255258
}
256259
default:
257260
if (seemsUseful(&I))
258-
markValueLive(&I);
261+
markInstructionLive(&I);
259262
}
260263
}
261264
}
@@ -284,7 +287,7 @@ void DCE::markTerminatorArgsLive(SILBasicBlock *Pred,
284287

285288
// If the arguments are live, we need to keep the terminator that
286289
// delivers those arguments.
287-
markValueLive(Term);
290+
markInstructionLive(Term);
288291

289292
switch (Term->getTermKind()) {
290293
case TermKind::ReturnInst:
@@ -345,11 +348,11 @@ void DCE::propagateLiveBlockArgument(SILArgument *Arg) {
345348
// is in reverse direction: Only if its definition (the Arg) is alive, also
346349
// the debug_value instruction is alive.
347350
for (Operand *DU : getDebugUses(Arg))
348-
markValueLive(DU->getUser());
351+
markInstructionLive(DU->getUser());
349352

350353
// Mark all reverse dependencies on the Arg live
351354
for (auto *depInst : ReverseDependencies.lookup(Arg)) {
352-
markValueLive(depInst);
355+
markInstructionLive(depInst);
353356
}
354357

355358
auto *Block = Arg->getParent();
@@ -371,14 +374,14 @@ void DCE::propagateLiveness(SILInstruction *I) {
371374
// debug_value instruction is alive.
372375
for (auto result : I->getResults())
373376
for (Operand *DU : getDebugUses(result))
374-
markValueLive(DU->getUser());
377+
markInstructionLive(DU->getUser());
375378

376379
// Handle all other reverse-dependency instructions, like cond_fail,
377380
// fix_lifetime, destroy_value, etc. Only if the definition is alive, the
378381
// user itself is alive.
379382
for (auto res : I->getResults()) {
380383
for (auto *depInst : ReverseDependencies.lookup(res)) {
381-
markValueLive(depInst);
384+
markInstructionLive(depInst);
382385
}
383386
}
384387
return;
@@ -448,7 +451,7 @@ void DCE::replaceBranchWithJump(SILInstruction *Inst, SILBasicBlock *Block) {
448451
std::vector<SILValue> Args;
449452
auto E = Block->args_end();
450453
for (auto A = Block->args_begin(); A != E; ++A) {
451-
assert(!LiveValues.count(*A) && "Unexpected live block argument!");
454+
assert(!LiveArguments.count(*A) && "Unexpected live block argument!");
452455
Args.push_back(SILUndef::get((*A)->getType(), *(*A)->getFunction()));
453456
}
454457
Branch =
@@ -462,8 +465,12 @@ void DCE::replaceBranchWithJump(SILInstruction *Inst, SILBasicBlock *Block) {
462465
}
463466

464467
void DCE::endLifetimeOfLiveValue(SILValue value, SILInstruction *insertPt) {
465-
if (!LiveValues.count(value->getRepresentativeSILNodeInObject())) {
466-
return;
468+
if (SILInstruction *inst = value->getDefiningInstruction()) {
469+
if (!LiveInstructions.count(inst))
470+
return;
471+
} else if (auto *arg = dyn_cast<SILArgument>(value)) {
472+
if (!LiveArguments.count(arg))
473+
return;
467474
}
468475
SILBuilderWithScope builder(insertPt);
469476
if (value.getOwnershipKind() == OwnershipKind::Owned) {
@@ -483,7 +490,7 @@ bool DCE::removeDead() {
483490
for (auto &BB : *F) {
484491
for (unsigned i = 0; i < BB.getArguments().size();) {
485492
auto *arg = BB.getArgument(i);
486-
if (LiveValues.count(arg)) {
493+
if (LiveArguments.count(arg)) {
487494
i++;
488495
continue;
489496
}
@@ -509,7 +516,7 @@ bool DCE::removeDead() {
509516
auto insertPt = getInsertAfterPoint(arg).getValue();
510517
SILBuilderWithScope builder(insertPt);
511518
auto *destroy = builder.createDestroyValue(insertPt->getLoc(), arg);
512-
LiveValues.insert(destroy->getRepresentativeSILNodeInObject());
519+
LiveInstructions.insert(destroy);
513520
}
514521
i++;
515522
Changed = true;
@@ -534,7 +541,7 @@ bool DCE::removeDead() {
534541
for (auto I = BB.begin(), E = BB.end(); I != E; ) {
535542
auto *Inst = &*I;
536543
++I;
537-
if (LiveValues.count(Inst) || isa<BranchInst>(Inst))
544+
if (LiveInstructions.count(Inst) || isa<BranchInst>(Inst))
538545
continue;
539546

540547
// We want to replace dead terminators with unconditional branches to
@@ -770,7 +777,7 @@ void DCE::markControllingTerminatorsLive(SILBasicBlock *Block) {
770777
collectControllingBlocks(Block, ControllingBlocks);
771778

772779
for (auto BB : ControllingBlocks)
773-
markValueLive(BB->getTerminator());
780+
markInstructionLive(BB->getTerminator());
774781
}
775782

776783
class DCEPass : public SILFunctionTransform {

test/SILOptimizer/dead_code_elimination_ossa.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,17 @@ bb0(%0 : $*Container):
275275
return %999 : $()
276276
}
277277

278+
// CHECK-LABEL: sil [ossa] @nested_destructure_tuple :
279+
// CHECK: bb0(%0 : @owned $(String, (Int, Int, String))):
280+
// CHECK-NEXT: (%1, %2) = destructure_tuple %0 : $(String, (Int, Int, String))
281+
// CHECK-NEXT: destroy_value %2
282+
// CHECK-NEXT: return %1
283+
// CHECK: } // end sil function 'nested_destructure_tuple'
284+
sil [ossa] @nested_destructure_tuple : $@convention(thin) (@owned (String, (Int, Int, String))) -> @owned String {
285+
bb0(%0 : @owned $(String, (Int, Int, String))):
286+
(%1, %2) = destructure_tuple %0 : $(String, (Int, Int, String))
287+
(%3, %4, %5) = destructure_tuple %2 : $(Int, Int, String)
288+
destroy_value %5 : $String
289+
return %1 : $String
290+
}
291+

0 commit comments

Comments
 (0)