This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Using and clobbering hard regs in parallel


geoffk@geoffk.org wrote:
> 
> Stephen Clarke <Stephen.Clarke@st.com> writes:
> 
> > Is it valid in RTL to read a hard reg in one branch of a parallel,
> > and clobber the same hard reg in another branch?
> >
> Yes, what this means is that r4 holds an input at the start of the
> insn but some other (unspecified) value at the end of the insn.

Okay, good, so here's the main problem.

I'm getting an abort in the instruction scheduler, 

divtest.c:9: Internal compiler error in schedule_insns, at sched-rgn.c:3070

which appears to be related to an instruction that both reads and
clobbers a hard reg.

After lifetime analysis, I have the following sequence.  Notice
that lifetime analysis has put a REG_DEAD (reg:SI 4 r4) note on insn 20.

--- after lifetime analysis
(insn 15 7 17 (set (reg/f:DI 161)
        (symbol_ref:DI ("__udivsi3"))) 126 {*movdi} (nil)
    (expr_list:REG_EQUAL (symbol_ref:DI ("__udivsi3"))
        (nil)))
 
(insn 17 15 19 (set (reg:SI 4 r4)
        (subreg/s:SI (reg/v:DI 158) 0)) 116 {*movsi} (insn_list 4 (nil))
    (expr_list:REG_DEAD (reg/v:DI 158)
        (insn_list:REG_LIBCALL 20 (nil))))
 
(insn 19 17 20 (set (reg:SI 5 r5)
        (subreg/s:SI (reg/v:DI 159) 0)) 116 {*movsi} (insn_list 6 (nil))
    (expr_list:REG_DEAD (reg/v:DI 159)
        (nil)))
 
(insn 20 19 21 (parallel[
            (set (reg:SI 160)
                (udiv:SI (reg:SI 4 r4)
                    (reg:SI 5 r5)))
            (clobber (reg:SI 19 r19))
            (clobber (reg:SI 18 r18))
            (clobber (reg:SI 4 r4))
            (clobber (reg:DI 128 tr0))
            (clobber (reg:DI 129 tr1))
            (clobber (reg:DI 130 tr2))
            (use (reg/f:DI 161))
        ] ) 32 {udivsi3_i1_media} (insn_list 15 (insn_list 17 (insn_list 19 (nil))))
    (expr_list:REG_DEAD (reg/f:DI 161)
        (expr_list:REG_DEAD (reg:SI 4 r4)
            (expr_list:REG_DEAD (reg:SI 5 r5)
                (expr_list:REG_UNUSED (reg:SI 19 r19)
                    (expr_list:REG_UNUSED (reg:SI 18 r18)
                        (expr_list:REG_UNUSED (reg:SI 4 r4)
                            (expr_list:REG_UNUSED (reg:DI 128 tr0)
                                (expr_list:REG_UNUSED (reg:DI 129 tr1)
                                    (expr_list:REG_UNUSED (reg:DI 130 tr2)
                                        (expr_list:REG_EQUAL (udiv:SI (subreg/s:SI (reg/v:DI 158) 0)
                                                (subreg/s:SI (reg/v:DI 159) 0))
                                            (insn_list:REG_RETVAL 17 (nil)))))))))))))
---

Later on, combine.c combines insns 15 and 20, as follows.
Note that the REG_DEAD (reg:SI 4 r4) note has been discarded from the
combined insn 20.

--- after combination
(note 15 7 17 NOTE_INSN_DELETED 0)
 
(insn 17 15 19 (set (reg:SI 4 r4)
        (subreg/s:SI (reg/v:DI 158) 0)) 116 {*movsi} (insn_list 4 (nil))
    (expr_list:REG_DEAD (reg/v:DI 158)
        (insn_list:REG_LIBCALL 20 (nil))))
        
(insn 19 17 20 (set (reg:SI 5 r5)
        (subreg/s:SI (reg/v:DI 159) 0)) 116 {*movsi} (insn_list 6 (nil))
    (expr_list:REG_DEAD (reg/v:DI 159)
        (nil)))
                    
(insn 20 19 21 (parallel[
            (set (reg:SI 160)
                (udiv:SI (reg:SI 4 r4)
                    (reg:SI 5 r5)))   
            (clobber (reg:SI 19 r19)) 
            (clobber (reg:SI 18 r18)) 
            (clobber (reg:SI 4 r4))
            (clobber (reg:DI 128 tr0))
            (clobber (reg:DI 129 tr1))
            (clobber (reg:DI 130 tr2))   
            (use (symbol_ref:DI ("__udivsi3")))
        ] ) 32 {udivsi3_i1_media} (insn_list 19 (insn_list 17 (nil)))
    (insn_list:REG_RETVAL 17 (expr_list:REG_UNUSED (reg:DI 130 tr2)
            (expr_list:REG_UNUSED (reg:DI 129 tr1)
                (expr_list:REG_UNUSED (reg:DI 128 tr0)
                    (expr_list:REG_UNUSED (reg:SI 4 r4)
                        (expr_list:REG_UNUSED (reg:SI 18 r18)
                            (expr_list:REG_UNUSED (reg:SI 19 r19)
                                (expr_list:REG_DEAD (reg:SI 5 r5)
                                    (nil))))))))))
---

Later again, the instruction scheduler schedules these instructions,
and calls update_life_info() in flow.c to recreate all the REG_DEAD notes -
this call adds the REG_DEAD (reg:SI 4 r4) back to insn 20.

The instruction scheduler (schedule_insns()) then calls
count_or_remove_death_notes() to verify that the number of REG_DEAD notes is
the same before and after scheduling: it isn't, because of the note that
update_life_info() has added, and so the instruction scheduler aborts.

I can think of three possible reasons for the problem, but
I have no objective idea which is correct, or whether there are
other reasons:

1.  flow.c should not put the REG_DEAD (reg:SI 4 r4) note on insn 20.
      Rationale: the comment at the top of flow.c states that the REG_DEAD
      note should only be added if the instruction does not replace the
      value in the register - is a clobber considered to have replaced
      the value?

2.  combine.c should preserve the REG_DEAD (reg:SI 4 r4) note on insn 20.
      Rationale: ummm, not sure -- maybe because if flow.c thinks
      the REG_DEAD note should be there, then combine.c should think so too.

3.  The instruction scheduler should not assume that the number of
    REG_DEAD notes should be exactly the same before and after scheduling.
      Rationale: REG_DEAD notes are optional in a situation like insn 20,
      so the assumption is invalid.

Can anyone provide opinions on this?

Thanks,
Steve.
-- 
Stephen Clarke, Micro Cores & Development Tools, STMicroelectronics
Phone:1-408-922-4062, Fax:1-408-895-3069, mailto:Stephen.Clarke@st.com
Mail:  STMicroelectronics, 1060 E. Brokaw Rd., San Jose, CA 95131.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]