[PATCH] Vectorizing Global Structures - Take 2

Daniel Berlin dberlin at dberlin.org
Fri Feb 15 16:38:22 PST 2013


On Fri, Feb 15, 2013 at 7:57 AM, Arnold <aschwaighofer at apple.com> wrote:
>
>
>
> Sent from my iPhone
>
> On Feb 15, 2013, at 3:46 AM, Renato Golin <renato.golin at linaro.org> wrote:
>
> On 15 February 2013 05:49, Arnold Schwaighofer <aschwaighofer at apple.com> wrote:
>>
>> 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 :).
>
>
> Without inspecting the induction range and step, I don't know if you can ever say they don't alias.
>
> C allows you to do:
>
> A[150] = B[51];
>
> And if you rely only on the type being different, you might say then don't alias, when they actually do.
>
>
> Yes this is where I am not sure whether C's strict aliasing would allow or forbid that kind of access.
>
> I know it forbids a float *  aliasing an int * but it does it forbit struct.a[x] aliasing struct.b[x]?


yes, it does, but this is somewhat irrelevant to C.

The pointers will not be of type struct.a[x] *, they will be of type
int (*[100])) or int * or whatever.
Given a pointer of that type alone, you cannot tell whether it is an
access of struct.a[x], struct.b[x], or a random non-structure array
variable.



>
>
> If it allows it then yes all my example won't work. You would need a different language that had such a semantic that would guarantee that such accesses are not allowed.
>
>
>> 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
>> }
>
>
> It's still valid C to do A[300] and end up reading B.
>
>
> Yes, precisely and it's also valid in llvm ir semantics.


>From what I read (it's been quite a while) t's actually not valid in
C, but valid in LLVM IR.
At least, as written.

§6.5.2.1, paragraph 2:

A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).

So it's going to be a pointer plus an address.

§6.5.6, paragraph 8:

When an expression that has integer type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If the
pointer operand points to an element of an array object, and the array
is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integer expression.
In other words, if the expression P points to the i-th element of an
array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
(where N has the value n) point to, respectively, the i+n-th and
i-n-th elements of the array object, provided they exist. Moreover, if
the expression P points to the last element of an array object, the
expression (P)+1 points one past the last element of the array object,
and if the expression Q points one past the last element of an array
object, the expression (Q)-1 points to the last element of the array
object. If both the pointer operand and the result point to elements
of the same array object, or one past the last element of the array
object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element
of the array object, it shall not be used as the operand of a unary *
operator that is evaluated.


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.




>
>
>
>
> In that form, I'd never try to do anything with that function, not without enough RT checks. ;)
>
> --renato
>
>
>
>
>




More information about the llvm-commits mailing list