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.

Reply via email to