This is an archive of the discontinued LLVM Phabricator instance.

New alias analysis for static global variables
AbandonedPublic

Authored by samparker on May 27 2015, 6:42 AM.

Details

Reviewers
hfinkel
Summary

Hi,

After comments and suggestions on my original patch, including being pointed to GlobalsModRef AA, I decided to model a new AA pass on GlobalsModRef but one that is more light weight than GlobalsModRef. This pass is designed to just track static global variables which we find are often used in embedded applications. Hal originally asked for better analysis of GlobalsModRef, so I have run LNT multiple times on my desktop, even runs are with this new pass and odd are without:

	        geometric mean

run compile time execution time
1 0.1219 0.0052
2 0.1071 0.0052
3 0.1085 0.0053
4 0.109 0.0055
5 0.1078 0.0052
6 0.108 0.0051
7 0.1078 0.0052
8 0.1085 0.0053
9 0.1067 0.0053
10 0.1073 0.0053
11 0.11 0.0053
12 0.1041 0.005
13 0.1073 0.0051
14 0.1085 0.0049
15 0.1079 0.0052
16 0.1072 0.0054
17 0.1057 0.0051
18 0.1074 0.0052
19 0.1074 0.005
20 0.1061 0.0052

Cheers,
Sam

Diff Detail

Event Timeline

samparker updated this revision to Diff 26590.May 27 2015, 6:42 AM
samparker retitled this revision from to New alias analysis for static global variables.
samparker updated this object.
samparker edited the test plan for this revision. (Show Details)
samparker added a subscriber: Unknown Object (MLST).

The compile-time numbers look good (in the sense that there is no significant difference between the even- and odd-numbered runs).

Please comment on exactly what makes this lighter weight than GlobalsModRef AA, and why this should be a separate pass.

include/llvm/Analysis/Passes.h
27

This needs a comment like the others.

lib/Analysis/IPA/StaticGlobalsAA.cpp
28 ↗(On Diff #26590)

You should collect some statistics on this. It is not clear to be that this is necessarily small, nor that 32 is the right number.

57 ↗(On Diff #26590)

Remove commented-out code.

82 ↗(On Diff #26590)

This function seems to be doing exactly what PointerMayBeCaptured does (see lib/Analysis/CaptureTracking.cpp), can you use that instead?

103 ↗(On Diff #26590)

Unguarded recursion should be avoided. Add a depth limit or use a worklist.

105 ↗(On Diff #26590)

You probably want to filter out comparisons with null, which also don't really capture the address.

138 ↗(On Diff #26590)

This seems unnecessarily limiting. Why not use GetUnderlyingObjects, and just make sure the condition is satisfied for all underlying pointers?

lib/Transforms/IPO/PassManagerBuilder.cpp
202

Should this be part of the preceeding function?

275

Remove commented-out code.

majnemer added inline comments.
lib/Analysis/IPA/StaticGlobalsAA.cpp
123 ↗(On Diff #26590)

How can GV be a Function?

124 ↗(On Diff #26590)

What if the local global variable has an external alias?

The compile-time numbers look good (in the sense that there is no significant difference between the even- and odd-numbered runs).

Please comment on exactly what makes this lighter weight than GlobalsModRef AA, and why this should be a separate pass.

Hi Hal,

GlobalsModRef AA analyses all global values with no limit on the depth of the search, whereas this pass only analyses static variables and obeys the search threshold defined in CaptureTracking. In addition, GlobalsModRef also checks for indirect access to global memory and analyses the call graph. I originally implemented this logic in BasicAA to fill a gap in its understanding of global variables, however I was informed that BasicAA is designed to be stateless, so this pass has been created to maintain the state of the module.

Cheers,
sam

lib/Analysis/IPA/StaticGlobalsAA.cpp
82 ↗(On Diff #26590)

Looks like it, it also is recursive with a worklist and a threshold

123 ↗(On Diff #26590)

Ah, good point, I just looked at the inheritance diagram and not properly at the API.

124 ↗(On Diff #26590)

would it sufficient to additionally check if !isa<GlobalAlias>?

lib/Transforms/IPO/PassManagerBuilder.cpp
202

I tried that, but it caused LLVM to crash. I believe its because that function is also called by populateFunctionPassManager function.

samparker updated this revision to Diff 26772.May 29 2015, 3:42 AM

It looks like you just uploaded a diff against the previous patch. Please upload the full diff against trunk instead (with full context).

lib/Transforms/IPO/PassManagerBuilder.cpp
202

Okay; please add a comment noting that.

samparker updated this revision to Diff 27441.Jun 10 2015, 7:18 AM

I have rewritten the pass as an Immutable pass, as the module pass seemed to get invalidated and hardly ever used. This does mean that it has to perform the analysis fully every time it is queried, and this increases compilation time of LNT by ~1.1%. It now uses the CaptureTracking system already provided in the LLVM code base.

Hal,

Would you be able to be my reviewer?

Cheers,
sam

Hi Sam,

Yes, I'll look at this sometime over the next couple of days.

-Hal

  • Original Message -----

From: "Sam Parker" <sam.parker@arm.com>
To: "sam parker" <sam.parker@arm.com>
Cc: "david majnemer" <david.majnemer@gmail.com>, hfinkel@anl.gov, llvm-commits@cs.uiuc.edu
Sent: Monday, June 15, 2015 8:08:47 AM
Subject: Re: [PATCH] New alias analysis for static global variables

Hal,

Would you be able to be my reviewer?

Cheers,
sam

http://reviews.llvm.org/D10059

EMAIL PREFERENCES

http://reviews.llvm.org/settings/panel/emailpreferences/
hfinkel edited edge metadata.Jun 22 2015, 7:32 PM

I have rewritten the pass as an Immutable pass, as the module pass seemed to get invalidated and hardly ever used. This does mean that it has to perform the analysis fully every time it is queried, and this increases compilation time of LNT by ~1.1%. It now uses the CaptureTracking system already provided in the LLVM code base.

It seems sad that you really can't cache the results. You could mark all of the transformations are preserving the analysis. Do we have any transformations that would capture the address of a global where it had not been captured before?

lib/Analysis/StaticGlobalsAA.cpp
146

I'd like to see these calls to GetUnderlyingObjects, and then you can check "all" of the underlying objects to see if all underlying objects in one of the sets are derived from non-addr-taken globals.

Hi Hal,

From the documentation it seems that it doesn't matter if the transformation passes state that they are preserving the analysis or not. I'm not sure about which transformation would affect it except where values are removed or renamed in the global optimiser and GVN.

Hi Hal,

From the documentation it seems that it doesn't matter if the transformation passes state that they are preserving the analysis or not.

Which documentation?

I'm not sure about which transformation would affect it except where values are removed or renamed in the global optimiser and GVN.

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run? The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

No, I think we'd need to mark all passes, and just have it run once. But I don't think we have any passes that would not preserve this particular analysis, do we? They'd need to take the address of a global variable such that the address might no longer appear derived from the original global symbol. This is certainly possible to do, but I can't think of any transformation that would actually do this currently.

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

No, I think we'd need to mark all passes, and just have it run once. But I don't think we have any passes that would not preserve this particular analysis, do we? They'd need to take the address of a global variable such that the address might no longer appear derived from the original global symbol. This is certainly possible to do, but I can't think of any transformation that would actually do this currently.

Ok. I think the only problem is when global variables get split or renamed.

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

No, I think we'd need to mark all passes, and just have it run once. But I don't think we have any passes that would not preserve this particular analysis, do we? They'd need to take the address of a global variable such that the address might no longer appear derived from the original global symbol. This is certainly possible to do, but I can't think of any transformation that would actually do this currently.

Ok. I think the only problem is when global variables get split or renamed.

Can you be more specific. Since we have a conservative fallback for unknown globals, why are these a problem?

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

No, I think we'd need to mark all passes, and just have it run once. But I don't think we have any passes that would not preserve this particular analysis, do we? They'd need to take the address of a global variable such that the address might no longer appear derived from the original global symbol. This is certainly possible to do, but I can't think of any transformation that would actually do this currently.

Ok. I think the only problem is when global variables get split or renamed.

Can you be more specific. Since we have a conservative fallback for unknown globals, why are these a problem?

Sorry, problem is probably the wrong word, the analysis pass just won't be as effective if it isn't updated when new global values are introduced.

That's a bit misleading. You can preserve underlying AA passes (although not the AliasAnalysis analysis group itself). The problems is that if *any* pass does not preserve it, it will be invalidated, and nothing will cause it to be regenerated (unless it is inserted again specifically in the pass manager).

The question here is: Do we have *any* passes in-tree that would not preserve the cache trivially?

I'm not sure I follow. The immutable AA passes have no state so how are they invalidated, or does being an ImmutablePass mean that they always run?

An immutable pass is never invalidated and always available.

The previous patch used a ModulePass that created a cache, but was not actually queried unless run directly before some of the transformations, so how would you propose querying the cache once its created?

The reason it is only available when run directly before a transformation is because no transformation preserved the analysis, so it was always invalidated. If all transformations were marked as preserving the analysis then it would stick around.

ok, thanks for the clarification. Would it be sensible to only mark the pass as preserved for the passes that already state they preserve the AliasAnalysis group? Then run the pass before these passes? Would this be accepted, it seems quite a departure from the current method?

No, I think we'd need to mark all passes, and just have it run once. But I don't think we have any passes that would not preserve this particular analysis, do we? They'd need to take the address of a global variable such that the address might no longer appear derived from the original global symbol. This is certainly possible to do, but I can't think of any transformation that would actually do this currently.

Ok. I think the only problem is when global variables get split or renamed.

Can you be more specific. Since we have a conservative fallback for unknown globals, why are these a problem?

Sorry, problem is probably the wrong word, the analysis pass just won't be as effective if it isn't updated when new global values are introduced.

Agreed; but I'm not sure we have passes that really do that. Do we?

hfinkel edited edge metadata.Jul 8 2015, 5:05 PM
hfinkel added a subscriber: chandlerc.

Chandler,

Can you lend an opinion here on how we can/should fit this into the pass manager infrastructure? I'd like to be able to have caching here so that we can do the right thing and also not see a compile-time hit.

Thanks!

FWIW, this is just a minor part of GlobalsModRef factored out.

I think that if we want something like this, we should break apart GlobalsModRef rather than duplicating its code here and fixing relatively minor aspects of it.

However, this pattern has all of the problems that GlobalsModRef has (see my recent llvmdev mails). I don't think there is any way to make it sound and reasonable.

Sam, your approach works, but violates the fundamental contract when queried by function passes -- it examines the state of other functions. It also has significant compile time costs than I'm not sure we really should be imposing on LLVM.

I think the right way to get this kind of stuff into LLVM is:

  1. Get the pass manager into decent shape
  2. Add a constraint about function passes not invalidating some conservative analysis of how globals are escaped and/or captured.
  3. Use the above constraint for IP analysis and a conservative and sound local analysis (either forwards like capture tracking or backwards like GetUnderlyingObject) which definitively identifies when one of the memory locations in an alias query comes from outside the function (and thus an escaped memory location).

I'm not even sure we want this, as it sounds expensive and brittle... but it would at least be reasonable relative to the current examples of GlobalsModRef or this pass...

samparker abandoned this revision.Oct 12 2016, 7:21 AM