[PATCH] Vectorizing Global Structures - Take 2

Daniel Berlin dberlin at dberlin.org
Sat Feb 16 16:52:00 PST 2013


On Sat, Feb 16, 2013 at 8:38 AM, Arnold Schwaighofer
<aschwaighofer at apple.com> wrote:
> I think what Daniel meant here is that you can have
>
>   struct S { int a[2]; int b[2];}g;
>   char *ptr = &g.a[1];
>   ++ptr;
>   *ptr = …// you are now accessing S.b (without knowing it by just looking
> at the type of access "char *")
>
> This is all defined behavior in C and a TBAA system would have to make sure
> it correctly says that ptr might alias &structS.a/b. But this is fine with
> my envisioned enhanced TBAA because *ptr is an access through a char pointer
> and an access through a char pointer aliases with any access in a TBAA
> system for C.
>
> (Although I have to admit, I have not tried to break it for long, so I don't
> feel comfortable to say I know it is gonna work but only I believe - maybe
> Daniel knows it won't work - he has way more experience working on Pointer
> Analysis than I have ;)
What you suggest in general works, it's just I probably would make it
separate metadata.

First though, if you talk about the types and field accesses to types
in the metadata (IE where you treat all accesses to a given type's
field as the same variable, and call that variable "struct a.F" or
whatever), it's very hard to make a sound pointer analysis that spits
out this metadata (There are edge cases that are expensive to detect,
and you have to punt and say it could point to anything, but you need
to detect them to get it right).    Depending on the language, it can
be *much* less accurate than not doing that at all (because you are
now merging accesses from separate variables, where before you at
least treated the variables separately, even if every field inside of
them was treated the same.

Of course, *none* of that matters for the basic structure access case.

Second, whether two structure field accesses overlap could is more
specific to the language rules about structure access (and alignment,
and padding, and ..).

You are really trying to calculate the byte range inside a memory
object two given accesses can touch, and see if the byte ranges
intersect (You could also do it using "access path expressions", that
have been formalized, but this is more complicated).
Everything else is just about the rules that tell you what the byte
ranges are.  Even if you don't have target info to know the sizes, you
can just represent them as fake units.

Why do it this way?

You really don't want to be doing linear walks up a tree to check
common ancestry when you have something like:

union A {

struct S {
   union {
    int a;
    int b;
   }
   int c;
} s;

struct T {
   int d;
   union {
    int e;
    int f;
   }
} t;

};

union A foo;

foo.s.a = ...
foo.s.b = ...
foo.s.c = ...
foo.t.d = ...
foo.t.e = ...
foo.t.f = ...


Unlike TBAA, this can all simply be tagged as a bunch of byte range
accesses inside "foo". Then calculating aliasing is just a constant
time intersection.
If you want to talk about the type instead of the variable (IE tag
these with union A.s.a, A.s.b,etc) for each independent type, you can
calculate the possible separate byte ranges that could be accessed on
a per-type basis.



>
> On Feb 16, 2013, at 6:57 AM, Renato Golin <renato.golin at linaro.org> wrote:
>
> On 16 February 2013 00:38, Daniel Berlin <dberlin at dberlin.org> wrote:
>>
>> you fall into the "otherwise, the behavior is undefined".
>>
>> It would be explicitly valid to convert it to char *, and read it up
>> to and through B, but not using the array access operator.
>
>
> Unfortunately, "undefined behaviour" is valid C. It means you'll have to
> compile that without error (possibly a warning), but you're allowed to do
> whatever you want.
>
> Clang sometimes remove accesses if they're going to go outside the
> boundaries (if it can tell) as optimization, as we seen in the Livermore
> Loops example. GCC vectorizes a loop when the only aliasing possible is with
> out-of-bounds access (thus getting different results). All that falls into
> the category of "user error", so both Clang and GCC won't change their
> behaviour on optimized builds.
>
> cheers,
> --renato
>
>




More information about the llvm-commits mailing list