[PATCH] D21536: [CFLAA] Include externally-visible memory aliasing information in function summaries
George Burgess IV via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 21 15:30:03 PDT 2016
george.burgess.iv added a comment.
Woohoo bugfixes! Thanks for the patch.
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:747
@@ -746,3 +774,1 @@
- // Collect StratifiedInfo for each parameter
- SmallVector<Optional<StratifiedInfo>, ExpectedMaxArgs> ParamInfos;
for (auto &Param : Fn.args()) {
----------------
FWIW, MSVC2013 didn't like templating on a local (yes, even though said local was `const`. I can't wait until we bump passed 2013), so I had to change this code a bit. Please rebase. :)
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:755
@@ +754,3 @@
+ // the same StratifiedIndex.
+ DenseMap<StratifiedIndex, std::vector<InterfaceValue>> InterfaceMap;
+ // Insert the given parameter/return value as well as the values below it into
----------------
This still seems n^2-ish in some cases, which I believe ultimately makes this algorithm n^3 time, and n^2 storage. Imagine we have:
```
void foo(int **a, int ***b, int ****c) {
*c = b;
*b = a;
int *d = *a;
}
```
That would give us one "chain" of
```
a
^
b
^
c
^
d
```
When scanning these, it looks like we'll add 4 entries for `a`, 3 entries for `b`, and 2 for `c`. It also looks like we may end up with 6 entries in cases like:
```
void foo(int ***a, int ***b) {
int **ad = *a;
int *add = *ad;
int **bd = *b;
int *bdd = *bd;
}
```
When I think we shouldn't have more than 2 (or 4, depending on how we want to handle attributes).
Assuming I'm not missing something, I think we can improve on this. AIUI, given two stratifiedset chains:
```
a
^
b e
^ ^
c f
^ ^
d g
^
h
```
Adding an assignment edge between b and e (or c and f, or d and g) produces the same result as adding assignment edges between all of the aforementioned pairs.
If this is correct, we can knock down the time+space complexity a bit, I think. The rough idea I have for how to do this is:
- Build a map, M, of StratifiedIndex -> vector<Value *>, where each vector is the list of Args/Return values that are in that StratifiedSet
- For each element, E, in the above map:
- Add entries to `RetParamRelations` that represent assignment between `E.second[0]` and `E.second[1..E.second.size()]` (**)
- For each set index S below `E.first`:
- If we don't find a mapping in M for S, try the next lower set.
- Otherwise, given said mapping, M', for a set N levels below E, add an entry that represents N levels of dereference between `E.second[0]` and `M'.second[0]` in `RetParamRelations`.
(** If you want, you can probably do this when building the map, and just make the map a StratifiedIndex -> Value* map. I realized this after writing the above, and am lazy :) )
With this, it looks like we'll end up with a linear number of entries (worst-case; best case, we'll have 0), and we'll end up walking N*M StratifiedSets total (N = number of args/returns, M = max(chain length))
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:758
@@ +757,3 @@
+ // InterfaceMap
+ auto AddToInterfaceMap = [this, &InterfaceMap](unsigned InterfaceIndex,
+ StratifiedIndex SetIndex) {
----------------
I don't care either way, but if you want to just use `[&]` for captures in the future, you're welcome to. :)
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:764
@@ +763,3 @@
+ auto &Link = Sets.getLink(SetIndex);
+ if (Link.hasBelow()) {
+ ++Level;
----------------
Nit: `if (!Link.hasBelow()) break;` seems cleaner to me
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:784
@@ +783,3 @@
+ // Populate InterfaceMap for return values
+ for (unsigned I = 0, E = RetVals.size(); I != E; ++I) {
+ auto RetInfo = Sets.find(RetVals[I]);
----------------
`for (auto *V : RetVals)`?
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:785
@@ +784,3 @@
+ for (unsigned I = 0, E = RetVals.size(); I != E; ++I) {
+ auto RetInfo = Sets.find(RetVals[I]);
+ if (RetInfo.hasValue())
----------------
Can we assert that `RetVals[I]` is a pointer here? I realize that it's only meant to hold values of pointer type, but that isn't exactly locally obvious IMO. :)
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:792
@@ +791,3 @@
+ // RetParamRelations
+ for (const auto &mapping : InterfaceMap) {
+ auto &Interfaces = mapping.second;
----------------
Nit: Mapping
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:792
@@ +791,3 @@
+ // RetParamRelations
+ for (const auto &mapping : InterfaceMap) {
+ auto &Interfaces = mapping.second;
----------------
george.burgess.iv wrote:
> Nit: Mapping
It looks like there are cases where this won't add the correct StratifiedAttrs to sets. Consider:
```
int **g;
void foo(int **a) {
*a = *g;
}
void bar() {
int *p, *p2;
*g = p2;
int **a = &p;
foo(a);
// p and p2 now alias
}
```
Because there's only arg and no return values when analyzing `foo`, `Interfaces.size()` will never be > 1, so we'll end up with no `RetParamRelations`. We need to somehow apply the attributes from the set containing `a` in `foo` to the set containing `a` in `bar`, though.
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:799
@@ -802,1 +798,3 @@
+ for (size_t I = 1, E = Interfaces.size(); I < E; ++I)
+ RetParamRelations.push_back(ExternalRelation{Base, Interfaces[I]});
}
----------------
Looks like `RetParamRelations` will hold n^2 elements, because `InterfaceMap` holds n^2 elements.
================
Comment at: lib/Analysis/CFLAliasAnalysis.cpp:863
@@ +862,3 @@
+ SetBuilder.add(ToVal);
+ SetBuilder.addBelowWith(FromVal, Edge.From.DerefLevel, ToVal,
+ Edge.To.DerefLevel);
----------------
Looks like we do a linear walk of StratifiedSet chains for every iteration of this loop, so this might be n^3ish overall, assuming `RetParamRelations` contains n^2 elements?
http://reviews.llvm.org/D21536
More information about the llvm-commits
mailing list