It turns out that assembler relaxation (as in, choosing the right size of instruction automatically depending on the magnitude of its operands) wasn’t really working, which meant that the largest size of instruction was being used far more than necessary. This gave code that worked, but which was needlessly bloated.
This was mainly, or at least partly, because I was trying to use relaxation too much: CGEN’s RELAXABLE/RELAXED attributes for insns, or RELAX attribute for operands, seem to work best when they’re only used for PC-relative operands, but I was trying to use them for absolute operands too. It works a bit better when you don’t try to do the latter.
But, that’s not the whole story: we still want auto-ranging to work for immediate instructions, and for them generally to choose a sensible size of instruction. So if we have:
mov r0,#0 mov r0,#100
We want to choose the smallest (16-bit) instruction for the first, but a larger insn size for the second (there’s a 32-bit
mov variant with a 16-bit immediate). The insn size can also depend on the size of some particular section of code:
.L2: <some code> <some code> mov r0,#. - .L2
here, we still want to choose the smallest size of insn possible. In yet another case, we don’t know how big the immediate might be until link time:
in this case, we want to use the largest insn size possible, since the address of SomeSymbol likely won’t fit any of the smaller insns.
Anyway: I thought we needed the relaxation machinery to make all that work, but it turns out that we don’t — the missing step is that we just need to be careful to reject immediates that would need relocations on small bitfields, and everything seems to work OK.
One other thing: sometimes it’s useful for the compiler to know exactly which insn it’s generating: for those cases, I’ve added optional
.s/.m/.l/.x suffixes (for small/medium/large/extra-large) to several ambiguous instructions so that it can do so. But, those aren’t wired up in the compiler proper yet.