Hi gang,
This ICE tends to crop up in the course of converting a port from assembly to rtl pro/epilogue generation. In my case, I find it's happening because: - the function I'm compiling has an attribute I've defined to mean 'isr handler' applied to it, and - as a result, in the prologue I'm saving volatile (callee-save) registers, even though they aren't marked in regs_ever_live[], and - in the epilogue, I emit sets to reload those ("unexpectedly-saved") registers, and - flow2 later attempts to delete one of the SET insns that restores an unexpectedly-saved GPR that is not marked in regs_ever_live[]. On looking into it a bit, I've found two techniques used to handle this: - In the ARM port, it emits lots of what it describes as USEs in the comments (actually, they're unspec's of the form (unspec:SI (reg:SI nn) UNSPEC_PROLOGUE_USE), and pretty-much everything is separated off with unspec_volatiles which it refers to as "blockage" insns, and which it says "claim that all hard registers are used and clobbered by this point". - In an email thread from last august, I found it suggested that it was better to use EPILOGUE_USES instead: http://www.nabble.com/forum/ViewTopic.jtp?topic=195757&tview=dump#a546107 On looking through resource.c to find out how EPILOGUE_USES is made use of, I see ---------------------------------------------<snip> /* Indicate what resources are required to be valid at the end of the current function. The condition code never is and memory always is. If the frame pointer is needed, it is and so is the stack pointer unless EXIT_IGNORE_STACK is nonzero. If the frame pointer is not needed, the stack pointer is. Registers used to return the function value are needed. Registers holding global variables are needed. */ ---------------------------------------------<snip> for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (global_regs[i] #ifdef EPILOGUE_USES || EPILOGUE_USES (i) #endif ) SET_HARD_REG_BIT (end_of_function_needs.regs, i); /* The registers required to be live at the end of the function are represented in the flow information as being dead just prior to reaching the end of the function. For example, the return of a value might be represented by a USE of the return register immediately followed by an unconditional jump to the return label where the return label is the end of the RTL chain. The end of the RTL chain is then taken to mean that the return register is live. This sequence is no longer maintained when epilogue instructions are added to the RTL chain. To reconstruct the original meaning, the start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the point where these registers become live (start_of_epilogue_needs). If epilogue instructions are present, the registers set by those instructions won't have been processed by flow. Thus, those registers are additionally required at the end of the RTL chain (end_of_function_needs). */ start_of_epilogue_needs = end_of_function_needs; ---------------------------------------------<snip> So, I have tried marking those unexpectedly-saved registers in EPILOGUE_USES (but only after reload; doing so beforehand stops the RA from using them!), and that's fixed my ICE, and the generated code and the rtl that leads up to it all looks good, and I even think I understand why it works, but I'm still left a bit puzzled: Is there any particular advantage or disadvantage to doing it the way the arm does, rather than the EPILOGUE_USES way? Is it just done that way because of historical baggage? Is adding the unexpectedly-saved registers to EPILOGUE_USES actually as correct as it seems to me that it is? cheers, DaveK -- Can't think of a witty .sigline today....