On 01/28/2011 09:45 PM, Ian Lance Taylor wrote: > Jean-Marc Saffroy <[email protected]> writes: > >> On 01/28/2011 06:44 PM, Ian Lance Taylor wrote: >>> Jean-Marc Saffroy <[email protected]> writes: >>> >>>> error: insn does not satisfy its constraints: >>>> (insn 1424 1423 141 (set (reg:DI 2 r2) >>>> (plus:DI (reg:DI 2 r2) >>>> (const_int 40 [0x28]))) >>>> /home/jmsaffroy/cygnus/src/newlib/libc/time/strptime.c:165 24 {adddi3} >>>> (expr_list:REG_EQUIV (plus:DI (reg/f:DI 70 a6) >>>> (const_int 40 [0x28])) >>>> (nil))) >>> >>> You should find out what is creating this insn. Is it being created by >>> reload, or is it being created by some pass that runs after reload? >> >> With gcc -da, I see that it appears in dump .195r.ira, so that's reload, >> right? > > Right. > > >>> It is likely that you need to make adddi3 a define_expand which tests >>> reload_in_progress and reload_completed. If those are the case, you >>> will need to explicitly convert >>> (set (reg:DI DREG1) (plus:DI (reg:DI DREG2) (const_int N))) >>> into >>> (set (reg:DI DREG1) (const_int N)) >>> (set (reg:DI DREG1) (plus:DI (reg:DI DREG1) (REG:DI DREG2))) >>> >> >> Ah, but here it happens that DREG1 and DREG2 (r2 and a6 above) are >> different types of registers, and I can't add them directly. > > The insn you showed is adding a constant to a DREG. There is no > addition of a DREG and an AREG, and I would not expect reload to > generate any such addition either. Are you looking at a different insn? > Don't get confused by the REG_EQUIV note, it's irrelevant here.
Actually, looking at the full dumps, I see that this incorrect insn shown in the ICE above is emitted when eliminating the arg pointer: a6 is the frame pointer (a6+40 probably points to the args on stack). Running cc1 under gdb, I see that gen_reload is tasked with reloading (plus AREG N) into (DREG): the first attempts fail (the generated insns are rejected by emit_insn_if_valid_for_reload), and so gen_reload recurses (reload.c:8550), generates a 2-insn sequence that does: (set DREG AREG) (set DREG (plus DREG N)) But this N is not a valid immediate for an add to a DREG, according to the predicates I defined for adddi3, which are not checked at this point, but only later on in final_scan_insn. So it seems I will have to have adddi3 be a define_expand that splits the increment by N into smaller increments when called with (reload_in_progress||reload_completed). Does that sound reasonable? It's worth noting that I'm developing with an old svn checkout of the gcc trunk from last October, I will update ASAP just in case. Jean-Marc
