Here's an optimization you probably won't get from the compiler: read it as an array.
Compilers use pointer arithmetic all the time. They're not made as dumb as you think.
They can even re-order non volatile statements to fit the arithmetic.
It's quite standard to use pointer + offset to refer to a stack frame, for example. That's easy to set up, though: the variables are allocated in specific locations, they can be used independently -- and the offset can be called out independently, thanks to instructions like MOV reg,[reg+imm].
It's not obvious that a compiler would know how to resolve that into an array access: one where the pointer itself is moving. That would complicate other stack accesses, at the very least: if you use one MOV reg,[reg++] instruction, now all subsequent offsets have to be one less, and so on. If it's inside a loop, the offsets vary from time to time, and you can't make that assumption at all. Then you need to use a new pointer register (which is available on many platforms, at least).
I don't know that compilers will ever create a loop to optimize for size; speed is the most common optimization after all, and it's nice that unrolling a loop is a much more well-defined problem than rolling one up is!
Bruce seems to have confirmed my suspicion, so at least I'm not completely wrong for once.
Tim