struct __attribute__((packed)) Pair { int x; long y; }; void foo(unsigned long N, struct Pair A[][N]) { for (unsigned long i = 0; i < N; i+=1) A[i][i].y = 0; }
lowered to
%0 = mul nsw i64 %i.0, %N %arrayidx = getelementptr inbounds %struct.Pair, %struct.Pair* %A, i64 %0 %arrayidx1 = getelementptr inbounds %struct.Pair, %struct.Pair* %arrayidx, i64 %i.0 %y = getelementptr inbounds %struct.Pair, %struct.Pair* %arrayidx1, i64 0, i32 1
corresponding to the SCEVExpr
{4,+,(12 + (12 * %N))}<%for.cond>
delinearized to
ArrayDecl[UnknownSize][%N][12] ArrayRef[{0,+,1}<%for.cond>][{0,+,1}<%for.cond>][4]
See test case array_of_struct.ll
This isn't compatible with opaque pointers. The access size needs to be determine exclusively based on load/store element type (using GEP type is inappropriate for this as well, even if it won't outright crash).