This revision patched up three different things regarding StratifiedAttrs.
- There are two overloaded version of StratifiedSets::noteAttribute(): one version accepts an unsigned index as its second argument, and the other one accepts a bitset. The two overloads perform slightly different operations. For some reason, when StratifiedSets::noteAttribute() is invoked with an unsigned integer (the intention was to invoke the first overloaded version), my toolchain (clang-3.8 + libstdc++-5.3) always construct a bitset out of the given integer and invoke the second overloaded version. The wrongly resolved overload function call leads to subtle error in StratifiedAttrs computation, and the error is not caught by any of the existing regression tests.
To eliminate the potential ambiguity in overload resolution, the patch gets rid of the first overloaded version and make every caller of noteAttribute() to call the second overloaded version instead.
- Previously, AttrUnknown and AttrAll were treated in the same way. There was no practical differences between the two. This patch removes AttrAll competely and relies on AttrUnknown to label values that are not understood by CFLAA.
- A new StratifiedAttr, called "AttrEscaped", is added. The motivation for this attribute is to make the analysis more precise by distinguish between "values that escape the current function" and "values that do not escape the current function". The major difference between the two classes of values is that the former class does not alias global/argument/unknown values the the latter class may alias them. Consider this example:
define void @foo() { %a = alloca i32 %b = alloca i32 %i = ptrtoint %a ... }
Here we cast %a to an integer and thus let it escape from the world that CFLAA can understand. CFLAA was conservative on cases like this: as long as a value escapes, the value will be marked as unknown. Therefore the analysis concludes that %a and %b may alias each other (but it is obvious from the function body that they don't).
We can be more aggressive about it because an escaped value isn't completely opaque to CFLAA: the analysis still keeps track of the value. A value escapes only means that it is possible for other opaque values to alias it.
This patch uses AttrEscaped for ptrtoint only. Our ultimate goal is to improve upon interprocedural case like this:
; Assume @external_func is opaque in the current translation unit declare @external_func(i32*, i32*) define void @foo() { %a = alloca i32 %b = alloca i32 call void @external_func(i32* %a, i32* %b) ret void }
Here %a and %b escaped @foo yet they should not be aliases. CFLAA currently cannot prove this. The idea is to mark %a and %b as AttrEscaped, but we need additional mechanisms to guarantee soundness -- they will be added in subsequent patches.
Style nits: attr -> Attr, and we generally try to keep "static" functions static and out of unnamed namespaces.