This is an archive of the discontinued LLVM Phabricator instance.

[DAE] Don't DAE if we musttail call a "live" (non-DAE-able) function
ClosedPublic

Authored by mtrofin on Mar 2 2023, 6:48 PM.

Details

Summary

There are 2 such base cases: indirect calls and calls to functions external to the module; and then any musttail calls to live functions (because of the first 2 reasons or otherwise).

The IR validator reports, in these cases, that it "cannot guarantee tail call due to mismatched parameter counts".

The fix is two-fold: first, we mark as "live" (i.e. non-DAE-able) functions that make an indirect musttail call. Then, we propagate live-ness to musttail callers of live functions.

Declared functions are already marked "live".

Diff Detail

Event Timeline

mtrofin created this revision.Mar 2 2023, 6:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 2 2023, 6:48 PM
mtrofin requested review of this revision.Mar 2 2023, 6:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 2 2023, 6:48 PM
mtrofin retitled this revision from [DeadArgElim] Don't change the return type if we have virtual musttail calls to [DAE] Don't change the return type if we have virtual musttail calls.Mar 2 2023, 6:48 PM
mtrofin added a reviewer: rnk.
mtrofin updated this revision to Diff 502038.Mar 2 2023, 6:49 PM

newline at end of test file

efriedma added inline comments.
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Please explain why this matters. Intuitively, whether a function is virtual shouldn't affect liveness... do we handle the non-virtual case somewhere else?

mtrofin marked an inline comment as done.Mar 2 2023, 10:22 PM
mtrofin added inline comments.
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Not sure I understand. It's about virtual musttail calls, not just virtual. "Liveness" in this pass means "it can't change".

Without the patch, the test fails in the validator, because the module is transformed to:

define internal void @test(ptr %fptr, i32 %a, i32 %b) {
  %r = musttail call i32 %fptr(ptr %fptr, i32 %a, i32 0)
  ret void
}

The error is what the test checks isn't present: cannot guarantee tail call due to mismatched parameter counts

The patch is actually incomplete - about to update it. This marking needs to be also propagated to users of the function.

mtrofin updated this revision to Diff 502052.Mar 2 2023, 10:55 PM
mtrofin marked an inline comment as done.

propagate

nikic added a reviewer: nikic.Mar 3 2023, 12:13 AM
nikic added a subscriber: nikic.
nikic added inline comments.
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

I believe Eli's point is that this is also true for non-virtual functions. For example, this example without virtual calls fails in the same way:

define internal i32 @test() {
  %r = musttail call i32 @foo()
  ret i32 %r
}

declare i32 @foo()
mtrofin updated this revision to Diff 502135.Mar 3 2023, 8:04 AM

non-virt

mtrofin retitled this revision from [DAE] Don't change the return type if we have virtual musttail calls to [DAE] Don't DAE if we musttail a "live" (non-DAE-able) function .Mar 3 2023, 8:06 AM
mtrofin edited the summary of this revision. (Show Details)
mtrofin updated this revision to Diff 502182.Mar 3 2023, 10:33 AM
mtrofin retitled this revision from [DAE] Don't DAE if we musttail a "live" (non-DAE-able) function to [DAE] Don't DAE if we musttail a "live" (non-DAE-able) function.

remove spurious member

mtrofin retitled this revision from [DAE] Don't DAE if we musttail a "live" (non-DAE-able) function to [DAE] Don't DAE if we musttail call a "live" (non-DAE-able) function.Mar 3 2023, 10:39 AM
mtrofin updated this revision to Diff 502192.Mar 3 2023, 11:00 AM

<eyeroll>

mtrofin updated this revision to Diff 502197.Mar 3 2023, 11:14 AM

handle cycles

I *think* @rnk is out for a few weeks, @nikic, does the patch look reasonable to you?

llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Oh, I see. Let me update then.

efriedma added inline comments.Mar 6 2023, 1:08 PM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Please add a comment explaining why direct calls and indirect calls are handled differently. (Is it related to the usage of getCalledFunction() in surveyUse?)

mtrofin updated this revision to Diff 502775.Mar 6 2023, 1:25 PM

clarify it's not about indirect calls only

llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Ah, it's not "direct" vs "indirect", rather, it's "can the callee be statically known and is it defined in this module". If it is, then we know that whatever transformations we plan on making at the callsite will also be reflected in the body of that callee. But if it's not, we don't know if that could happen.

Declarations ended up being marked as "live" just below. So we'd pick up that in propagateVirtMustcallLiveness.

All that being said, I think handling both callee cases here is more clear (+clarifying comment)

WDYT?

mtrofin edited the summary of this revision. (Show Details)Mar 6 2023, 1:30 PM
mtrofin edited the summary of this revision. (Show Details)
efriedma added inline comments.Mar 6 2023, 7:57 PM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

The concept makes sense to me... I'd prefer some more obvious way to quantify "calls to functions we can't analyze" to make it more obvious this is the inverse of the calls we do analyze.

mtrofin added inline comments.Mar 7 2023, 7:20 AM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

Would a isCalleeAnalyzable member that does the !TC->getCalledFunction() || TC->getCalledFunction()->isDeclaration() address that?

efriedma added inline comments.Mar 7 2023, 10:31 AM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

That's reasonable.

mtrofin updated this revision to Diff 503100.Mar 7 2023, 10:56 AM

more clarity

mtrofin marked 2 inline comments as done.Mar 7 2023, 10:57 AM
mtrofin added inline comments.
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
531

done, ptal (ended up just a function, no need for a member)

mtrofin marked an inline comment as done.Mar 8 2023, 7:34 AM

@efriedma , is this patch good to go? Thanks!

efriedma accepted this revision.Mar 8 2023, 12:36 PM

I'm not really an expert on this pass, but sure, seems fine, assuming @nikic doesn't have any further comments.

This revision is now accepted and ready to land.Mar 8 2023, 12:36 PM
nikic added inline comments.Mar 9 2023, 3:18 AM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
89

Is isDeclaration() the right criterion here? Shouldn't we be checking for hasLocalLinkage()?

1115

It's not really clear to me why we need a separate loop to do this, and this can't be included as part of the existing liveness propagation. E.g. surveyFunction() already looks at all the users, and even checks for musttail callers there. Currently, that's only used to mark all the arguments as live, but not the return values. Would it be sufficient to force live return values at that point?

llvm/test/Transforms/DeadArgElim/musttail-indirect.ll
2

verify is unnecessary, as is 2>&1, as is the CHECK-NOT. Verification failure causes a crash and will fail the test regardless of output.

Please also update update_test_checks.py.

mtrofin updated this revision to Diff 503773.Mar 9 2023, 8:08 AM
mtrofin marked 3 inline comments as done.

feedback

mtrofin added inline comments.Mar 9 2023, 8:11 AM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
89

Line 544 has the hasLocalLinkage bit. The case here is about callees of musttail calls.

Maybe I can rename this to isMusttailCalleeAnalyzable and hoist up the rest of the test, for clarity.

1115

IIUC, if both argument and return values are marked, it'd be equivalent to the function being marked as live.

But that aside, we can have A->B->C->x (all are musttail calls), and C has the unanalyzable callsite. That needs to "taint" all in the call chain. We could do that propagation in surveyFunction, but that would be equivalent to this patch, unless I'm missing something?

llvm/test/Transforms/DeadArgElim/musttail-indirect.ll
2

done, sending a separate patch w the change in 2010-04-30-DbgInfo.ll, seems unrelated.

nikic added inline comments.Mar 10 2023, 7:04 AM
llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
1115

DAE already propagates liveness across call chains, so it is best to reuse existing propagation is possible. However, after looking a bit closer I don't think we can actually use it, because for return values the propagation will go in the wrong direction. In that case, doing this separate propagation is reasonable.

llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
111 ↗(On Diff #503773)

Why the changes to this file? I don't see any musttail usage.

llvm/test/Transforms/DeadArgElim/musttail-indirect.ll
2

This still has an unnecessary verify and doesn't use update_test_checks.

mtrofin updated this revision to Diff 505121.Mar 14 2023, 8:47 AM

gen test with update_test_checks

mtrofin marked 2 inline comments as done.Mar 14 2023, 8:48 AM
mtrofin added inline comments.
llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll
111 ↗(On Diff #503773)

Misunderstanding on my part.

llvm/test/Transforms/DeadArgElim/musttail-indirect.ll
2

Ah, I misunderstood - I thought you meant "run update_test_checks on the other tests" - to see if they need a refresh due to this change (I assumed).

mtrofin marked 2 inline comments as done.Mar 15 2023, 10:53 AM