This is an archive of the discontinued LLVM Phabricator instance.

[FunctionAttrs] Consider recursive argmem effects (PR63936)
ClosedPublic

Authored by nikic on Jul 21 2023, 7:54 AM.

Details

Summary

When inspecting the function body, we can't simply ignore effects of functions in the SCC entirely, because an argmem access of a recursive call might result in an access to another location in the callee.

Fix this by separately tracking memory effects that would occur if the SCC accesses argmem, and then later add those.

Fixes https://github.com/llvm/llvm-project/issues/63936.

Diff Detail

Event Timeline

nikic created this revision.Jul 21 2023, 7:54 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 21 2023, 7:54 AM
nikic requested review of this revision.Jul 21 2023, 7:54 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 21 2023, 7:54 AM
goldstein.w.n added inline comments.
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
154–160

IMO Needs a comment describing what each item in the pair refers to.

nikic updated this revision to Diff 544730.Jul 27 2023, 5:55 AM

Add comment describing return value.

nikic marked an inline comment as done.Jul 27 2023, 5:55 AM
goldstein.w.n added inline comments.Aug 7 2023, 6:46 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
183–187

This comment needs to be updated.

191

Maximum depth on recursion?

248

Style on &

nikic updated this revision to Diff 548529.Aug 9 2023, 2:30 AM
nikic marked an inline comment as done.

Rebase over test changes, update comment.

nikic added inline comments.Aug 9 2023, 2:30 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
191

There is no recursion here.

248

Not sure what you mean here. The & is a bitwise and rather than a reference, so I think the style is correct?

goldstein.w.n added inline comments.Aug 9 2023, 12:11 PM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
177–178

Imo ME needs a different name, its extremely confusing to have it shadow the non-scoped version.

183–187

Imo ME needs a different name, its extremely confusing to have it shadow the non-scoped version.

280

I don't really understand the rationale behind creating a seperate recursive variable.

It seems the original intent is to track calls with bundled arguments for which apprently IRMemLocation is incomplete.
But if you only add back recursive args if memloc indicates mod/ref, doesn't that defeat the purpose?
If so, why not just update ME directly for bundled calls?

nikic added inline comments.Aug 9 2023, 1:00 PM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

Lets take a case like this:

define void @test_recursive_argmem_read(ptr %p) {
  %pval = load ptr, ptr %p
  call void @test_recursive_argmem_read(ptr %pval)
  ret void
}

At the point where we inspect the recursive @test_recursive_argmem_read call, we don't know whether that call will read or write %pval. (Well, in this specific example we do if we scan instructions from top to bottom, but generally we don't, because it depends on visitation order.)

We could just conservatively assume that all pointers passed to a recursive access will be read+write accessed and add the corresponding effects right away. That would be correct, but it would also be overly conservative. In this case, it is sufficient to only add read effects for the affected locations, we don't need to add any write effects.

goldstein.w.n added inline comments.Aug 9 2023, 1:22 PM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

But why do you need a seperate variable to track that? Can't that just as easily be added directly to ME?

nikic added inline comments.Aug 10 2023, 12:20 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

I don't really understand what you have in mind here. The current code does AddArgLocs(RecursiveArgME, ModRefInfo::ModRef), what would I replace it with?

I can replace it with AddArgLocs(ME, ModRefInfo::ModRef), but that would add unnecessary effects if the SCC is not argmem: readwrite.

nikic updated this revision to Diff 548911.Aug 10 2023, 1:06 AM

Rebase over NFC changes.

goldstein.w.n added inline comments.Aug 10 2023, 8:33 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

I'm just wondering why we need a new variable at L171 (as opposed to just doing this all in ME on L169).
Why would that unduly add argmen: readwrite?

Sorry for this to be like pulling teeth, not super familiar with FunctionAttrs.

nikic added inline comments.Aug 10 2023, 9:23 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

This is what happens if you directly add to ME instead of using a separate variable: https://gist.github.com/nikic/ff98bde042030ce6ebaca392237f7e46

goldstein.w.n added inline comments.Aug 10 2023, 9:27 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

Is there some intuition for why that is?

goldstein.w.n added inline comments.Aug 10 2023, 3:16 PM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
192

Why is arg3 ModRefInfo::ModRef and not AAR.getMemoryEffects(Call).getModRef(IRMemLocation::ArgMem)?

goldstein.w.n accepted this revision.Aug 10 2023, 4:08 PM

LGTM.

I'm only somewhat familiar with this system. No on else has come review this so approving, but maybe wait at least a day or two before pushing to give time to someone more familiar to review.

llvm/lib/Transforms/IPO/FunctionAttrs.cpp
280

Okay I see, its because we want to isolate only ArgMem affects and if you apply directly the ME it ends up setting things like other (thats what happening in the regressions at least).

That makes sense.

This revision is now accepted and ready to land.Aug 10 2023, 4:08 PM
goldstein.w.n added inline comments.Aug 11 2023, 12:31 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
192

Note: you could change this codes to:

MemoryEffects RecursiveArgME = MemoryEffects::none();
ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
if (ArgMR != ModRefInfo::NoModRef)
  ME |= RecursiveArgME & MemoryEffects(ArgMR);

and get rid of the returning pair logic.
Personally think thats cleaner but not particularly important.

nikic added inline comments.Aug 11 2023, 12:37 AM
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
192

That's a complicated way of saying addArgLocs(ME, Call, ME.getModRef(IRMemLocation::ArgMem), AAR). The problem is that this uses the ME at the current point of the analysis -- however, additional effects may be added later (either in this function, or a different function in the same SCC), which we would fail to account for.

This revision was landed with ongoing or failed builds.Aug 14 2023, 5:40 AM
This revision was automatically updated to reflect the committed changes.