So the combination of the TCB merge plus the pending jump threading
changes apparently has ticked a reload bug which manifests itself with
the stage1 compiler mis-compiling the stage2 compiler.

Upon entry into local-alloc we have the following key insns:

(insn:HI 88 85 89 10 (set (reg:QI 66 [ D.23558 ])
        (mem/s/u:QI (const:SI (plus:SI (symbol_ref:SI
("tree_code_length") [flags 0x40] <var_decl 0xb7ba5870
tree_code_length>)
                    (const_int 50 [0x32]))) [0 tree_code_length+50 S1
A8])) 45 {*movqi_1} (nil)
    (nil))

[ ... ]

(insn:HI 201 177 231 27 (set (reg:QI 66 [ D.23558 ])
        (reg:QI 95 [ tree_code_length+50 ])) 45 {*movqi_1} (nil)
    (expr_list:REG_DEAD (reg:QI 95 [ tree_code_length+50 ])
        (expr_list:REG_EQUAL (mem/s/u:QI (const:SI (plus:SI
(symbol_ref:SI ("tree_code_length") [flags 0x40] <var_decl 0xb7ba5870
tree_code_length>)
                        (const_int 50 [0x32]))) [0 tree_code_length+50
S1 A8])
            (nil))))


[ It is highly likely the second insn initially was an identical copy
  of the first created by jump threading and was later simplified as
  the value of (mem (plus (tree_code_length) (50)) was lying around
  in a convenient place that dominated the second insn. ]

Anyway, we'll end up promoting the REG_EQUAL note in the second
insn into a REG_EQUIV note (update_equiv_regs) and we'll also have
added a REG_EQUIV note to the first insn.

Neither local-alloc nor global allocation are able to assign a hard
register for (reg:QI 66).

So at reload time we have:


(insn:HI 88 85 89 10 (set (reg:QI 66 [ D.23558 ])
        (mem/s/u:QI (const:SI (plus:SI (symbol_ref:SI
("tree_code_length") [flags 0x40] <var_decl 0xb7c81870
tree_code_length>)
                    (const_int 50 [0x32]))) [0 tree_code_length+50 S1
A8])) 45 {*movqi_1} (nil)
    (expr_list:REG_EQUIV (mem/s/u:QI (const:SI (plus:SI (symbol_ref:SI
("tree_code_length") [flags 0x40] <var_decl 0xb7c81870
tree_code_length>)
                    (const_int 50 [0x32]))) [0 tree_code_length+50 S1
A8])
        (nil)))



[ ... ]

(insn:HI 201 177 231 26 (set (reg:QI 66 [ D.23558 ])
        (reg:QI 95 [ tree_code_length+50 ])) 45 {*movqi_1} (nil)
    (expr_list:REG_DEAD (reg:QI 95 [ tree_code_length+50 ])
        (expr_list:REG_EQUIV (mem/s/u:QI (const:SI (plus:SI
(symbol_ref:SI ("tree_code_length") [flags 0x40] <var_decl 0xb7c81870
tree_code_length>)
                        (const_int 50 [0x32]))) [0 tree_code_length+50
S1 A8])
            (nil))))



Insn 88 gets deleted as it sets up the equivalence between (reg:QI 66)
and the memory location.

We record the equivalence between (reg:QI 66) and the memory location
in reg_equiv_mem.

We then proceed to eliminate (reg:QI 66) by replacing it with its
equivalent memory location.  Resulting in:

(insn:HI 201 177 231 26 (set (mem/s/u:QI (const:SI (plus:SI
(symbol_ref:SI ("tree_code_length") [flags 0x40] <var_decl 0xb7ba0870
tree_code_length>)
                    (const_int 50 [0x32]))) [0 tree_code_length+50 S1
A8])
        (reg:QI 1 dx [orig:95 tree_code_length+50 ] [95])) 45 {*movqi_1}
(nil)
    (expr_list:REG_DEAD (reg:QI 1 dx [orig:95 tree_code_length+50 ]
[95])
        (expr_list:REG_EQUIV (mem/s/u:QI (const:SI (plus:SI
(symbol_ref:SI ("tree_code_length") [flags 0x40] <var_decl 0xb7ba0870
tree_code_length>)
                        (const_int 50 [0x32]))) [0 tree_code_length+50
S1 A8])
            (nil))))


Which faults because the memory location is actually  read-only memory.


What's not clear to me is how best to fix this.

We could try to delete all assignments to pseudos which are equivalent
to MEMs.

We could avoid recording equivalences when the pseudo is set more than
once.

Other possibilities?

jeff

Reply via email to