Comment 4 for bug 1502611

Revision history for this message
Senthil Kumar Selvaraj (senthil-thecoder) wrote :

FWIW, here's what I found (originally reported at http://www.avrfreaks.net/comment/1682166#comment-1682166)

The reorg pass places constant addresses in the literal pool and modifies instructions to load from them (arm_reorg in gcc/config/arm/arm.c). The code there sees if there is a constant operand involving memory access in an insn, and if yes, marks it for pooling later. This is why you're not seeing the problem if the address is not known at compile time (extern, in your example) - there is no constant operand.

So why doesn't it happen always? Turns out the postreload pass that runs before it adjusts some, but not all insns to reuse the existing value (address) in the register and just bump up the offset.

thumb1_size_rtx_costs sets the size to 8 if the immediate value being loaded satisfies the J or K constraint (constant is in range of -1 to -255, or is in range of 0 to 255 multipled by any power of 2). This makes postreload prefer the alternative rtx of adding the offset to existing register value. For others, the size cost (and speed cost) of both alternatives work out to be the same i.e. 4, and postreload keeps the original rtx that loads the immediate constant. This explains why, in your example, some constant addresses were kept in the literal pool whereas others were computed.

Not sure what the best way is to fix this though. I don't know why costs are higher (8) for immediate constants that can actually be loaded easily, and are lower for those that require some computation to load, although tat turned out to help improve code in this case. Best left to the ARM maintainers I guess.