One point that people sometimes overlook is that "trigger an allocation" can happen in some unexpected ways.  In particular any PEI (null pointer exception, array bounds check, etc) can cause the allocation of an exception object, so there are a number of non-obvious GC points in the code.  Similar things happen with unresolved references (trigger class loading that may cause allocation).

You might also want to try asking the opt compiler to print the final MIR (-X:opt:final_mir=true).  It is pretty close to the final machine code, but still contains all of the symbolic information (types, field locations, etc. etc).  It makes it easier to interpret the machine code dump.  I typically dump both of them when I want to look at the code generated.