https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80352
Bug ID: 80352 Summary: Improper reload of operands with equiv pseudo Product: gcc Version: 7.0 Status: UNCONFIRMED Keywords: ra Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: thopre01 at gcc dot gnu.org CC: vmakarov at gcc dot gnu.org Target Milestone: --- Hi, r235184 introduced the ability to reload expressions with equiv but reload happens incorrectly due to some failed assumptions: 1) Endless series of reloads due to creation of pseudo reg with NO_REGS class When a memory constraint is matched to an expression with equiv, the alternative is given the default class: NO_REGS. In curr_insn_transform the memory reload code is skipped because MEM_P is false and instead the default register reload is used. It creates a pseudo reg with the class from goal_alt hence NO_REGS. When analyzing this new insn process_alt_operands fails the in_class_p check for the register because its class (NO_REGS) have no intersect with GENERAL_REGS (from the subunion). A reload must then happen again, etc. 2) reload_nregs is increased despite needing a register reload reload_nregs is only updated when !no_regs_p is true. Hence the cost of memory reload is not accurate. Fortunately the fix from Jiong in r237277 seems to be enough to avoid memory reload when register reload is available. I believe the issues are due to the assumption that memory constraint does not need a register and has different reload. However with expression with equiv a register reload is needed followed by a register spill. Regarding 2) winreg could be used to signal a register is needed and the check to update reload_nregs use winreg instead. I am not sure how to solve 1) but I believe get_reload_reg should no be called with NO_REGS class (an assert could be added btw). The issue can be reproduced on arm-none-eabi target by compiling the below code with arm-none-eabi-gcc -S -mcpu=cortex-m7 -mthumb -O2: void fn2(int *); void fn1() { int a[1]; while (1) fn2(a); }