Skip to content

Commit ee16174

Browse files
Aaron1011aeubanks
andauthored
[DAE] MarkLive in MarkValue(MaybeLive) if any use is live (#82)
While looping through all args or all return values, we may mark a use of a later iteration as live. Previously when we got to that later value it would ignore that and continue adding to Uses instead of marking it live. For example, when looping through arg#0 and arg#1, MarkValue(arg#0, Live) may cause some use of arg#1 to be live, but MarkValue(arg#1, MaybeLive) will not notice that and continue adding into Uses. Now MarkValue(RA, MaybeLive) will MarkLive(RA) if any use is live. Fixes PR47444. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D88529 Co-authored-by: Arthur Eubanks <aeubanks@google.com>
1 parent 655a146 commit ee16174

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class DeadArgumentEliminationPass
128128
Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses);
129129

130130
void SurveyFunction(const Function &F);
131+
bool IsLive(const RetOrArg &RA);
131132
void MarkValue(const RetOrArg &RA, Liveness L,
132133
const UseVector &MaybeLiveUses);
133134
void MarkLive(const RetOrArg &RA);

llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp

+20-9
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ DeadArgumentEliminationPass::Liveness
357357
DeadArgumentEliminationPass::MarkIfNotLive(RetOrArg Use,
358358
UseVector &MaybeLiveUses) {
359359
// We're live if our use or its Function is already marked as live.
360-
if (LiveFunctions.count(Use.F) || LiveValues.count(Use))
360+
if (IsLive(Use))
361361
return Live;
362362

363363
// We're maybe live otherwise, but remember that we must become live if
@@ -657,10 +657,18 @@ void DeadArgumentEliminationPass::MarkValue(const RetOrArg &RA, Liveness L,
657657
MarkLive(RA);
658658
break;
659659
case MaybeLive:
660-
// Note any uses of this value, so this return value can be
661-
// marked live whenever one of the uses becomes live.
662-
for (const auto &MaybeLiveUse : MaybeLiveUses)
663-
Uses.insert(std::make_pair(MaybeLiveUse, RA));
660+
assert(!IsLive(RA) && "Use is already live!");
661+
for (const auto &MaybeLiveUse : MaybeLiveUses) {
662+
if (IsLive(MaybeLiveUse)) {
663+
// A use is live, so this value is live.
664+
MarkLive(RA);
665+
break;
666+
} else {
667+
// Note any uses of this value, so this value can be
668+
// marked live whenever one of the uses becomes live.
669+
Uses.insert(std::make_pair(MaybeLiveUse, RA));
670+
}
671+
}
664672
break;
665673
}
666674
}
@@ -686,17 +694,20 @@ void DeadArgumentEliminationPass::MarkLive(const Function &F) {
686694
/// mark any values that are used by this value (according to Uses) live as
687695
/// well.
688696
void DeadArgumentEliminationPass::MarkLive(const RetOrArg &RA) {
689-
if (LiveFunctions.count(RA.F))
690-
return; // Function was already marked Live.
697+
if (IsLive(RA))
698+
return; // Already marked Live.
691699

692-
if (!LiveValues.insert(RA).second)
693-
return; // We were already marked Live.
700+
LiveValues.insert(RA);
694701

695702
LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Marking "
696703
<< RA.getDescription() << " live\n");
697704
PropagateLiveness(RA);
698705
}
699706

707+
bool DeadArgumentEliminationPass::IsLive(const RetOrArg &RA) {
708+
return LiveFunctions.count(RA.F) || LiveValues.count(RA);
709+
}
710+
700711
/// PropagateLiveness - Given that RA is a live value, propagate it's liveness
701712
/// to any other values it uses (according to Uses).
702713
void DeadArgumentEliminationPass::PropagateLiveness(const RetOrArg &RA) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: opt -S -deadargelim %s | FileCheck %s
2+
3+
define internal { i64, i64 } @f(i64 %a, i64 %b) {
4+
start:
5+
%0 = insertvalue { i64, i64 } undef, i64 %a, 0
6+
%1 = insertvalue { i64, i64 } %0, i64 %b, 1
7+
ret { i64, i64 } %1
8+
}
9+
10+
; Check that we don't delete either of g's return values
11+
12+
; CHECK-LABEL: define internal { i64, i64 } @g(i64 %a, i64 %b)
13+
define internal { i64, i64 } @g(i64 %a, i64 %b) {
14+
start:
15+
%0 = call { i64, i64 } @f(i64 %a, i64 %b)
16+
ret { i64, i64 } %0
17+
}
18+
19+
declare dso_local i32 @test(i64, i64)
20+
21+
define i32 @main(i32 %argc, i8** %argv) {
22+
start:
23+
%x = call { i64, i64 } @g(i64 13, i64 42)
24+
%x.0 = extractvalue { i64, i64 } %x, 0
25+
%x.1 = extractvalue { i64, i64 } %x, 1
26+
%z = bitcast i64 %x.0 to i64
27+
%y = call { i64, i64 } @f(i64 %x.0, i64 %x.1)
28+
%y.1 = extractvalue { i64, i64 } %y, 1
29+
%0 = call i32 @test(i64 %x.0, i64 %y.1)
30+
ret i32 %0
31+
}
32+

0 commit comments

Comments
 (0)