DeadArgumentEliminationPass::MarkIfNotLive(RetOrArg Use,
UseVector &MaybeLiveUses) {
// We're live if our use or its Function is already marked as live.
- if (LiveFunctions.count(Use.F) || LiveValues.count(Use))
+ if (IsLive(Use))
return Live;
// We're maybe live otherwise, but remember that we must become live if
MarkLive(RA);
break;
case MaybeLive:
- // Note any uses of this value, so this return value can be
- // marked live whenever one of the uses becomes live.
- for (const auto &MaybeLiveUse : MaybeLiveUses)
- Uses.insert(std::make_pair(MaybeLiveUse, RA));
+ assert(!IsLive(RA) && "Use is already live!");
+ for (const auto &MaybeLiveUse : MaybeLiveUses) {
+ if (IsLive(MaybeLiveUse)) {
+ // A use is live, so this value is live.
+ MarkLive(RA);
+ break;
+ } else {
+ // Note any uses of this value, so this value can be
+ // marked live whenever one of the uses becomes live.
+ Uses.insert(std::make_pair(MaybeLiveUse, RA));
+ }
+ }
break;
}
}
/// mark any values that are used by this value (according to Uses) live as
/// well.
void DeadArgumentEliminationPass::MarkLive(const RetOrArg &RA) {
- if (LiveFunctions.count(RA.F))
- return; // Function was already marked Live.
+ if (IsLive(RA))
+ return; // Already marked Live.
- if (!LiveValues.insert(RA).second)
- return; // We were already marked Live.
+ LiveValues.insert(RA);
LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Marking "
<< RA.getDescription() << " live\n");
PropagateLiveness(RA);
}
+bool DeadArgumentEliminationPass::IsLive(const RetOrArg &RA) {
+ return LiveFunctions.count(RA.F) || LiveValues.count(RA);
+}
+
/// PropagateLiveness - Given that RA is a live value, propagate it's liveness
/// to any other values it uses (according to Uses).
void DeadArgumentEliminationPass::PropagateLiveness(const RetOrArg &RA) {
--- /dev/null
+; RUN: opt -S -deadargelim %s | FileCheck %s
+
+define internal { i64, i64 } @f(i64 %a, i64 %b) {
+start:
+ %0 = insertvalue { i64, i64 } undef, i64 %a, 0
+ %1 = insertvalue { i64, i64 } %0, i64 %b, 1
+ ret { i64, i64 } %1
+}
+
+; Check that we don't delete either of g's return values
+
+; CHECK-LABEL: define internal { i64, i64 } @g(i64 %a, i64 %b)
+define internal { i64, i64 } @g(i64 %a, i64 %b) {
+start:
+ %0 = call { i64, i64 } @f(i64 %a, i64 %b)
+ ret { i64, i64 } %0
+}
+
+declare dso_local i32 @test(i64, i64)
+
+define i32 @main(i32 %argc, i8** %argv) {
+start:
+ %x = call { i64, i64 } @g(i64 13, i64 42)
+ %x.0 = extractvalue { i64, i64 } %x, 0
+ %x.1 = extractvalue { i64, i64 } %x, 1
+ %z = bitcast i64 %x.0 to i64
+ %y = call { i64, i64 } @f(i64 %x.0, i64 %x.1)
+ %y.1 = extractvalue { i64, i64 } %y, 1
+ %0 = call i32 @test(i64 %x.0, i64 %y.1)
+ ret i32 %0
+}
+