What you are saying is that compiler must keep the variable ordering on the stack the same. That is the only way that `&(p+1) == &q` would hold consistently.
Now if we have `char p[1] = {0}; int a; char q[1] = {0};` the compiler cannot move p and q together so that a can properly aligned with less padding (I assume alignment is a concern on stack space as well?). The compiler also cannot do any loop invariant hoisting. It cannot remove any unused variables. Because all of them can change the behavior of the program just be existing. Any random pointer could have been aliasing one of those positions.
Every single optimisation would require full program analysis to determine whether something could possibly alias. And if you do any non trivial pointer arithmetic (after integer casting) or use user input in it, you lose that. Not just in that place but everywhere in the program.