http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47464
--- Comment #4 from Jeffrey A. Law <law at redhat dot com> 2011-01-26 05:59:56 UTC --- ifcvt thinks the memory reference in insn 69 is safe to move because it is marked as notrap.... That's obviously incorrect. The marking as notrap occurs due to a very interesting sequence of events. First we have a pseudo (83) which is set once from a MEM (with a varying address) and used once: (insn 27 26 28 3 (set (reg:SI 83 [ MEM[(const struct VEC_tree_base *)D.17991_13].num ]) (mem/s:SI (reg/f:DI 71 [ D.17991 ]) [6 MEM[(const struct VEC_tree_base *)D.17991_13].num+0 S4 A64])) j.c:7464 64 {*movsi_internal} (nil)) (insn 28 27 65 3 (parallel [ (set (reg/v:SI 75 [ ix ]) (plus:SI (reg:SI 83 [ MEM[(const struct VEC_tree_base *)D.17991_13].num ]) (const_int -1 [0xffffffffffffffff]))) (clobber (reg:CC 17 flags)) ]) j.c:7464 252 {*addsi_1} (expr_list:REG_DEAD (reg:SI 83 [ MEM[(const struct VEC_tree_base *)D.17991_13].num ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (expr_list:REG_EQUAL (plus:SI (mem/s:SI (reg/f:DI 71 [ D.17991 ]) [6 MEM[(const struct VEC_tree_base *)D.17991_13].num+0 S4 A64]) (const_int -1 [0xffffffffffffffff])) (nil))))) ira.c::update_equiv_regs attaches a REG_EQUIV note to insn 27. This is the first place where I started to question the compiler's correctness. Based on my reading of REG_EQUIV, it's correct. It would be valid (from a dataflow standpoint) to replace every occurrence of (reg:SI 83) with (mem:SI (reg:DI 71)). IRA decides that (reg:SI 83) is best left in memory. A reasonable choice. Reload also decides to leave it in memory and replace the pseudo with its equivalent memory location. In that code reload sets the MEM_NOTRAP_P bit for the equivalent memory location. This is the point at which I believe things have gone wrong. Anyway, later ifcvt looks as the MEM_NOTRAP_P flag and decides it can move the memory reference with abandon and moves the memory reference before the address check guard triggering the fault. As I mentioned, I believe the point at which we've taken the wrong step is setting MEM_NOTRAP_P. While it is true that the insn can't trap as long as it stays in its original context, ifcvt can change the context in which the MEM occurs thus making MEM_NOTRAP_P inconsistent with reality. So I think we've got two approaches to fix this problem. First we can avoid setting MEM_NOTRAP_P so aggressively in reload. Or we can change ifcvt to not move MEM_NOTRAP_P insns so aggressively. I'm going to attempt the first approach.