I'd like to understand how register allocation works in the case where an instruction is folded into another one. Where in the code would be a good place to start looking at?
I don't think you've got two instructions folded together. On the
output side that would just be a single instruction.
After ISEL, one of the instructions has another instruction folded into it, which looks like this
t1: i32,i1,i1,i1,i1 = ADDRR TargetFrameIndex:i32<0>, MOVRI:i32,i1,i1
I've never seen anything displayed like that, and it worries me. I
thought only constants of some kind were inlined, which a MOVRI
instruction almost certainly doesn't qualify as.
You'll want to look at how that's serialized after the DAG phase to
diagnose the issue. To the extent that it's meaningful, it ought to be
entirely equivalent to:
%v0 = MOVRI [...]
%t1 = ADDRR frameindex<0>, %v0, [...]
Generally, the "-print-after-all" option for llc is the quickest way
to access this kind of information. The first time the ADDRR
instruction occurs is just after an opaque "DAG ISel" phase that
you've been introspecting.
But during the 'Assembly Printer' pass, when emitting the assembly for ADDRR, the assertion at the beginning of getRegisterName() in XXXGenAsmWriter.inc fails because RegNo is 0. I'd like to know how that happened.
Assembly printer is very late. In fact it's the very last pass LLVM
runs. Generally any assertion failure there can be traced to bad input
(unless you're literally implementing the AsmPrinter at the time),
which again points to "-print-after-all" as a diagnostic tool.
There's usually something obviously wrong with the final instructions,
which can be traced back to something less-obviously-but-still wrong
before register allocation (often mismatched register classes). The
trick is establishing the first phase were things are incorrect and
working out why.
From what you've said I'd bet on ISel unfortunately (it's a big phase).