update_equiv_regs() and dependency chains

David S. Miller davem@redhat.com
Fri May 17 04:48:00 GMT 2002


update_equiv_regs() seems to not be able to handle reg_equiv[] sources
that are first replaced by other equivalences.

In the case I am looking at it is presented with this RTL:

(insn 57 62 61 (set (reg:SI 127)
        (mem/s:SI (lo_sum:SI (reg/s/f:SI 120)
                (symbol_ref:SI ("x"))) [5 <variable>.a+0 S4 A32])) 51 {*movsi_insn} (nil)
    (expr_list:REG_DEAD (reg/s/f:SI 120)
        (nil)))
 ...
(insn 225 228 229 (set (reg/f:SI 184)
        (high:SI (symbol_ref:SI ("x")))) 53 {*movsi_high} (nil)
    (expr_list:REG_EQUAL (high:SI (symbol_ref:SI ("x")))
        (nil)))
 ...
(insn 302 321 305 (set (reg/s/f:SI 120)
        (reg/f:SI 184)) 51 {*movsi_insn} (nil)
    (expr_list:REG_DEAD (reg/f:SI 184)
        (expr_list:REG_EQUAL (high:SI (symbol_ref:SI ("x")))
            (nil))))

After the insn scan, the reg_equiv[] for reg 184 looks like this:

	replace = 1
	replacement = 0x701f7510 (high:SI (symbol_ref:SI ("x")))
	src = 0x7001bce0 (high:SI (symbol_ref:SI ("x")))
	loop_depth = 0
	init_insns = 0x70202d60

	(insn 225 228 229 (set (reg/f:SI 184)
	        (high:SI (symbol_ref:SI ("x")))) 53 {*movsi_high} (nil)
	    (expr_list:REG_EQUIV (high:SI (symbol_ref:SI ("x")))
	        (nil)))

And the reg_equiv[] for reg 120 looks like this:

	replace = 1
	replacement = 0x701f7530 (high:SI (symbol_ref:SI ("x")))
	src = 0x701f85f0 (reg/f:SI 184)
	loop_depth = 0
	init_insns = 0x70202d70

	(insn 302 321 305 (set (reg/s/f:SI 120)
	        (reg/f:SI 184)) 51 {*movsi_insn} (nil)
	    (expr_list:REG_DEAD (reg/f:SI 184)
	        (expr_list:REG_EQUIV (high:SI (symbol_ref:SI ("x")))
	            (nil))))

So update_equiv_regs() goes plugging away, first it handles REG
184.  It transforms insn "302" above into:

(insn 302 321 305 (set (reg/s/f:SI 120)
        (high:SI (symbol_ref:SI ("x")))) 53 {*movsi_high} (nil)
    (expr_list:REG_DEAD (reg/f:SI 184)
        (expr_list:REG_EQUIV (high:SI (symbol_ref:SI ("x")))
            (nil))))

and it deletes insn "225".

So now we have a problem because the 'src' in reg_equiv[120] still
refers to REG 184 even though we've killed it off.  That is, the
reg_equiv[].src members are not updated when an equivalence
transformation is performed.

Later we hit the REG 120 equivalence and this proceeds to transform
insn "57" into:

(insn 57 62 61 (set (reg:SI 127)
        (mem/s:SI (lo_sum:SI (reg/f:SI 184)
                (symbol_ref:SI ("x"))) [5 <variable>.a+0 S4 A32])) 51 {*movsi_insn} (nil)
    (expr_list:REG_DEAD (reg/s/f:SI 120)
        (nil)))

And insn "302" gets deleted.  Now we have troubles because we have
a reference to this REG 184 which is never set.

What ends up happening eventually is that reload doesn't do anything
to the REG 184 in insn "57" and the compiler aborts in reload_cse_regs
because the insn doesn't strictly match it's constraints due to the
pseudo.  This is PR/6689

How is this equivalence stuff supposed to work when we have a chain of
equivalences via register sets like this?

I stared at the code for a few more moments before firing off this
email, and I noticed this comment in update_equiv_regs():

          /* ????? This test isn't good enough; we might see a MEM with a use of
             a pseudo register before we see its setting insn that will cause
             reg_equiv[].replace for that pseudo to be set.
             Equivalences to MEMs should be made in another pass, after the
             reg_equiv[].replace information has been gathered.  */

This sounds similar (but not the same) to the case that is being hit
here.  There must be something in this code that is trying to prevent
the situation I am hitting, but I simply cannot find it.



More information about the Gcc-bugs mailing list