[PATCH] Vectorizing Global Structures - Take 2

Arnold Schwaighofer aschwaighofer at apple.com
Thu Feb 14 21:49:32 PST 2013


On Feb 14, 2013, at 10:21 PM, Daniel Berlin <dberlin at dberlin.org> wrote:
> What I meant by saying "understanding independent objects inside a structure" to is that just by looking at an llvm type say for example struct { int A[100]; int B[100]} you and seeing two gep accesses that index into the first and second field of the type you can not necessarily say that the access is not overlapping without fully evaluating the address computation:
> 
> Yes, you need to fully evaluate it, but that's not really related to TBAA :)



I was thinking of type trees that encoded fields giving more guarantees than LLVM IR currently conveys. Admittedly, I have not though this through, whether this could even remotely work for C.

In LLVM IR:

struct { int A[100]; int B[100]} S;

ptr = gep S, 0, 0, x
ptr2 = gep S, 0, 1, y

= load ptr, !tbaa !"structS::A"
= load ptr2, !tbaa !"structS::B"

using this you could tell that ptr and ptr2 do not alias without knowing about x and y. Assuming certain language guarantees, which I don't know we could assume :).

Where the type dag looks something like:

           /->structS::A <- int
structS->structS::B <- int

>  
> 
> struct { int A[100]; int B[100]} S;
> 
> ptr1 = getelementpr S, 0, 1, x
> ptr2  = getelementpr S, 0, 0, y
> 
> ptr1 and ptr2 mayalias for some x and y (for example x = 0 and y = 100, the ir makes no guarantee that you cannot run over the length of an array within a struct as long as you are within the struct, http://llvm.org/docs/GetElementPtr.html#what-happens-if-an-array-index-is-out-of-bounds)
> Yup.
>  
> 
> If you can symbolically reason about x and y - the full address computation then yes you can make more concise statements.
> 
> Correct me if I am wrong but this is how it understand the semantics of a gep. I would love to be able to treat a type like a tree :).
> 
> I have not had a look at what ben hardekopf is doing. Does he handle the case I mention above correctly?
> 
> Yes.  Hardekopf's work is an extension of work done by David Pearce, who I worked with to get this right in all the weird edge cases, and implemented in GCC.  See http://dl.acm.org/citation.cfm?id=1290524
> 
> (David made this work, Ben Hardekopf made it work *really fast*)
> 
> Even though C/C++ does not legally allow to happen what LLVM IR does, it was common enough that we had to assume it can anyway.
>  

Okay.

> 
> I know that the existing TBAA can not handle cases with struct fields, but an improved one might. 
> 
> TBAA is type based, and language specific.   At least in C/C++/most other languages i'm aware of, the TBAA tree will always say the above accesses can alias because they validly point to accesses of the same type.
> 
> your example above is the C equivalent of
> 
> struct a {
> int b[100];
> int c[100];
> };
> 
> struct a foo;
> int (*x[100]) = &foo.b;
> int (*y[100]) = &foo.c;
> 

> TBAA will *never* say that *x and *y are no-alias, because they are both validly access an int *.
> The same is true for 
> 
> int *z1 = *x;
> int *z2 = *y;
> 
> TBAA will never say *z1 and *z2 are no-alias, because they both validly access ints.
> 
> So i can't see how you could extend TBAA to account for your example, since it's only about types, and both of these are the same type, but maybe i'm missing something?  

I was thinking type dags or trees that encode the full access path, in the example above struct_a::b or struct_a::c.

> If you mean you could make TBAA evaluate address computations and calculate whether these the resulting addresses ever access the same objects in memory, this isn't TBAA anymore, that is pointer analysis.  At least for inclusion based versions, it's O(N^3) worst case :P 
> 

No, that is not what I thought of TBAA. I was looking for a powerful TBAA system to encode more knowledge about the access (guarantees that subfields of a structure do not overlap).


> In any case the point of field sensitive pointer analysis above is *exactly* to say "these both point to different fields in the structure, and the bit size of the access guarantees they will never overrun".
> 

Okay, I was unsure about the bit size of access part :).


> In the case of pointer loops that iterate over your example type, it will properly discover that it overruns into the next field, and properly mark it as pointing-to that field as well.


So for the following example it will conservatively say arrayidx and arrayidx2 alias?

%struct.anon = type { [256 x i64], i64, [256 x i64] }

define void @foo(i32 %x, i32 %y) {
  %arrayidx = getelementptr inbounds %struct.anon* @Foo, i32 0, i32 0, i32 %x
  %0 = store i64* %arrayidx, align 8
  %arrayidx2 = getelementptr inbounds %struct.anon* @Foo, i32 0, i32 2, i32 %y
  %1 = store i64* %arrayidx2, align 8
}

Thanks,
Arnold
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130214/7247f9d5/attachment.html>


More information about the llvm-commits mailing list