The following is legal LLVM code in which ptr, ptr2, and ptr3 are all
%ptr2 = getelementptr %struct* %ptr1
%ptr3 = getelementptr %struct* %ptr2, uint 0
Should our pass a) ignore this, not replace %ptr1, let copy-propagation
fix the problem, or b) catch this obvious aliasing and replace uses of
fields of %ptr2 and %ptr3 with the replaced scalar fields of ptr1?
I don't know what the "real answer" (ie, the one you'll get graded on) is,
but I can give you a philosophical answer.
One answer is that the -instcombine pass will cannonicalize the above two
instructions away, so you pass need not handle this due to "seperation of
Another answer (which I prefer is that this is a really easy case to
check for and handle. You already have to check to see if the pointer
index is not zero, so you might as well check to see if the # operands is
<= 2 as well. By handling this case, you don't make it basically
_required_ that the instcombine pass run before yours.
This completely breaks seperation of concerns, but it is a more pragmatic
answer. Basically it's SOC in moderation: don't go too far out of your
way when seperation of concerns will help you, and do _not_ make your code
harder to understand by handling tons of special cases. On the other
hand, if you can make your pass more robust with very little cost in code
complexity, then I say go for it.
In the case of the LLVM compiler (which is basically the "gccas" tool),
scalar replacement of aggregates would be run immediately after "level
raising" and immediately before the mem2reg pass. If the special case
was not handled, we would also have to add an instcombine pass, which
would just slow the compiler down, compared to implementing the special
case in the SRoA pass.
That said, I don't know what you'll be graded on.