------- Comment #15 from vmakarov at redhat dot com 2010-09-03 20:45 ------- (In reply to comment #14) Ulrih, I've just wanted to post the following when I found that you already posted analogous conclusion. I should have been on CC to see your comment right away. The problem is really fundamental. Code for merge_assigned_reloads ignores inheritance (and dependencies between reloads because of inheritance) at all. Here is my post wanted to add.
After thorough examining code for inheritance in reload1.c::choose_reload_regs, I can not find where it can be wrong for this test case. After this function, we have the following reloads: Reload 0: reload_in (SI) = (reg/v/f:SI 132 [ kpte ]) GENERAL_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) Reload 1: reload_in (SI) = (reg/v/f:SI 132 [ kpte ]) DIREG, RELOAD_FOR_INPUT (opnum = 1) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) Reload 2: reload_in (SI) = (reg:SI 600 [ D.29693 ]) BREG, RELOAD_FOR_INPUT (opnum = 2) reload_in_reg: (reg:SI 600 [ D.29693 ]) Reload 3: reload_in (SI) = (reg:SI 356) CREG, RELOAD_FOR_INPUT (opnum = 3) reload_in_reg: (reg:SI 356) Function reload1.c::merge_assigned_reload called after reload1.c::choose_reload_regs for targets with SMALL_REGISTER_CLASSES (i686 case) merges 0th and 1st reloads (merging results in nullifying reload_in in 1st the reload and changing 0th to RELOAD_OTHER) producing Reload 0: reload_in (SI) = (reg/v/f:SI 132 [ kpte ]) GENERAL_REGS, RELOAD_OTHER (opnum = 0) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) reload_reg_rtx: (reg:SI 5 di) Reload 1: DIREG, RELOAD_FOR_INPUT (opnum = 1) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) reload_reg_rtx: (reg:SI 5 di) Reload 2: reload_in (SI) = (reg:SI 2 cx [501]) BREG, RELOAD_FOR_INPUT (opnum = 2) reload_in_reg: (reg:SI 600 [ D.29693 ]) reload_reg_rtx: (reg:SI 3 bx) Reload 3: reload_in (SI) = (reg:SI 356) CREG, RELOAD_FOR_INPUT (opnum = 3) reload_in_reg: (reg:SI 356) reload_reg_rtx: (reg:SI 2 cx) So far everything is ok. But after that, it changes 3rd reload to RELOAD_OTHER which means that it will be issued before 2nd reload instead of after it as it was before. Changing to RELOAD_OTHER is done because the code assumes (on function reg_overlap_mentioned_for_reload_p) that changing 3rd reload will affect 0th reload. In this unfortunate case pseudo 132 (from 0th reload) and pseudo 356 (from 3rd reload) have equivalent memory and reg_overlap_mentioned_for_reload_p is a simplified code which in this case decides that changing equivalent memory of p356 affects equivalent memory of p132. Reload 0: reload_in (SI) = (reg/v/f:SI 132 [ kpte ]) GENERAL_REGS, RELOAD_OTHER (opnum = 0) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) reload_reg_rtx: (reg:SI 5 di) Reload 1: DIREG, RELOAD_FOR_INPUT (opnum = 1) reload_in_reg: (reg/v/f:SI 132 [ kpte ]) reload_reg_rtx: (reg:SI 5 di) Reload 2: reload_in (SI) = (reg:SI 2 cx [501]) BREG, RELOAD_FOR_INPUT (opnum = 2) reload_in_reg: (reg:SI 600 [ D.29693 ]) reload_reg_rtx: (reg:SI 3 bx) Reload 3: reload_in (SI) = (reg:SI 356) CREG, RELOAD_OTHER (opnum = 3) reload_in_reg: (reg:SI 356) reload_reg_rtx: (reg:SI 2 cx) I don't see a good and simple fix for general case (just fixing reg_overlap_mentioned_for_reload_p would wrong and dangerous) for this code when inheritance is used and there are dependencies for reload 2 and 3 in this case. -- vmakarov at redhat dot com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |vmakarov at redhat dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45312