public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Using and clobbering hard regs in parallel
@ 2001-07-19 18:32 Stephen Clarke
  2001-07-19 18:39 ` Geoff Keating
  0 siblings, 1 reply; 12+ messages in thread
From: Stephen Clarke @ 2001-07-19 18:32 UTC (permalink / raw)
  To: gcc

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?

For example, when compiling for SH, I get the following instruction:

(insn 20 19 22 (parallel[ 
            (set (reg:SI 54)
                (udiv:SI (reg:SI 4 r4)
                    (reg:SI 5 r5)))
            (clobber (reg:SI 18 t))
            (clobber (reg:SI 17 pr))
            (clobber (reg:SI 4 r4))
            (use (reg:SI 55))
        ] ) -1 (nil)
    (expr_list:REG_EQUAL (udiv:SI (mem/f:SI (reg/f:SI 50 virtual-stack-vars) 0)
            (mem/f:SI (plus:SI (reg/f:SI 50 virtual-stack-vars)
                    (const_int 4 [0x4])) 0))
        (insn_list:REG_RETVAL 17 (nil))))

where r4 is read by the set, but also clobbered in another branch
(this instruction is part of a libcall).

The gcc manual says this is okay for pseudo regs:

"There is one other known use for clobbering a pseudo register in
a parallel: when one of the input operands of the insn is also clobbered
by the insn. In this case, using the same pseudo register in the clobber
and elsewhere in the insn produces the expected results."

but is it also okay for hard regs?

(This is a leading question: I have a problem with flow.c, combine.c
and an instruction like this, but I'd like to make sure that this
instruction is reasonable before sharing the main problem.)

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.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-19 18:32 Using and clobbering hard regs in parallel Stephen Clarke
@ 2001-07-19 18:39 ` Geoff Keating
  2001-07-19 19:39   ` Stephen Clarke
  0 siblings, 1 reply; 12+ messages in thread
From: Geoff Keating @ 2001-07-19 18:39 UTC (permalink / raw)
  To: Stephen Clarke; +Cc: gcc

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?
> 
> For example, when compiling for SH, I get the following instruction:
> 
> (insn 20 19 22 (parallel[ 
>             (set (reg:SI 54)
>                 (udiv:SI (reg:SI 4 r4)
>                     (reg:SI 5 r5)))
>             (clobber (reg:SI 18 t))
>             (clobber (reg:SI 17 pr))
>             (clobber (reg:SI 4 r4))
>             (use (reg:SI 55))
>         ] ) -1 (nil)
>     (expr_list:REG_EQUAL (udiv:SI (mem/f:SI (reg/f:SI 50 virtual-stack-vars) 0)
>             (mem/f:SI (plus:SI (reg/f:SI 50 virtual-stack-vars)
>                     (const_int 4 [0x4])) 0))
>         (insn_list:REG_RETVAL 17 (nil))))
> 
> where r4 is read by the set, but also clobbered in another branch
> (this instruction is part of a libcall).

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.

-- 
- Geoffrey Keating <geoffk@geoffk.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-19 18:39 ` Geoff Keating
@ 2001-07-19 19:39   ` Stephen Clarke
  2001-07-20 11:38     ` Joern Rennecke
  2001-07-20 15:27     ` Richard Henderson
  0 siblings, 2 replies; 12+ messages in thread
From: Stephen Clarke @ 2001-07-19 19:39 UTC (permalink / raw)
  To: gcc; +Cc: geoffk

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.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-19 19:39   ` Stephen Clarke
@ 2001-07-20 11:38     ` Joern Rennecke
  2001-07-20 13:11       ` Mark Mitchell
  2001-07-20 15:25       ` Richard Henderson
  2001-07-20 15:27     ` Richard Henderson
  1 sibling, 2 replies; 12+ messages in thread
From: Joern Rennecke @ 2001-07-20 11:38 UTC (permalink / raw)
  To: Stephen Clarke; +Cc: gcc, geoffk

That is a known problem.  The new flow.c code has redefined the
semantics of REG_DEAD / REG_UNUSED notes, while the rest of the
compiler - including the documentation - stays with the old semantics.
Note, the REG_DEAD note was never exactly wrong - but it used to be optional.
Now it is optional in all passes but flow.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 11:38     ` Joern Rennecke
@ 2001-07-20 13:11       ` Mark Mitchell
  2001-07-20 13:56         ` Joern Rennecke
  2001-07-20 15:25       ` Richard Henderson
  1 sibling, 1 reply; 12+ messages in thread
From: Mark Mitchell @ 2001-07-20 13:11 UTC (permalink / raw)
  To: Joern Rennecke, Stephen Clarke; +Cc: gcc, geoffk

--On Friday, July 20, 2001 07:38:22 PM +0100 Joern Rennecke 
<amylaar@redhat.com> wrote:

> That is a known problem.  The new flow.c code has redefined the
> semantics of REG_DEAD / REG_UNUSED notes, while the rest of the
> compiler - including the documentation - stays with the old semantics.

Since you seem to understand this issue, would you care to update
the documentation for it?

-- 
Mark Mitchell                mark@codesourcery.com
CodeSourcery, LLC            http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 13:11       ` Mark Mitchell
@ 2001-07-20 13:56         ` Joern Rennecke
  2001-07-20 14:02           ` Mark Mitchell
  0 siblings, 1 reply; 12+ messages in thread
From: Joern Rennecke @ 2001-07-20 13:56 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Joern Rennecke, Stephen Clarke, gcc, geoffk

> Since you seem to understand this issue, would you care to update
> the documentation for it?

But it doesn't make any sense...

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 13:56         ` Joern Rennecke
@ 2001-07-20 14:02           ` Mark Mitchell
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Mitchell @ 2001-07-20 14:02 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: Stephen Clarke, gcc, geoffk

--On Friday, July 20, 2001 09:56:29 PM +0100 Joern Rennecke 
<amylaar@redhat.com> wrote:

>> Since you seem to understand this issue, would you care to update
>> the documentation for it?
>
> But it doesn't make any sense...

Well, then, would you care to make it make sense? :-)  Perhaps by
bothering the perpetrator of the senselessness?

Presently, we are in a state where the compiler documentation does
not match the compiler, so we must fix one or the other!

-- 
Mark Mitchell                mark@codesourcery.com
CodeSourcery, LLC            http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 11:38     ` Joern Rennecke
  2001-07-20 13:11       ` Mark Mitchell
@ 2001-07-20 15:25       ` Richard Henderson
  2001-07-20 15:54         ` Joern Rennecke
  1 sibling, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2001-07-20 15:25 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: Stephen Clarke, gcc, geoffk

On Fri, Jul 20, 2001 at 07:38:22PM +0100, Joern Rennecke wrote:
> That is a known problem.  The new flow.c code has redefined the
> semantics of REG_DEAD / REG_UNUSED notes, while the rest of the
> compiler - including the documentation - stays with the old semantics.

Happy?


r~


Index: rtl.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/doc/rtl.texi,v
retrieving revision 1.13
diff -c -p -d -r1.13 rtl.texi
*** rtl.texi	2001/07/03 00:46:05	1.13
--- rtl.texi	2001/07/20 22:22:08
*************** The value in @var{op} dies in this insn;
*** 2798,2808 ****
  value immediately after this insn would not affect the future behavior
  of the program.
  
! This does not necessarily mean that the register @var{op} has no useful
! value after this insn since it may also be an output of the insn.  In
! such a case, however, a @code{REG_DEAD} note would be redundant and is
! usually not present until after the reload pass, but no code relies on
! this fact.
  
  @findex REG_INC
  @item REG_INC
--- 2798,2814 ----
  value immediately after this insn would not affect the future behavior
  of the program.
  
! It does not follow that the register @var{op} has no useful value after
! this insn since @var{op} is not necessarily modified by this insn.
! Rather, no subsequent instruction uses the contents of @var{op}.
! 
! @findex REG_UNUSED
! @item REG_UNUSED
! The register @var{op} being set by this insn will not be used in a
! subsequent insn.  This differs from a @code{REG_DEAD} note, which
! indicates that the value in an input will not be used subsequently.
! These two notes are independent; both may be present for the same
! register.
  
  @findex REG_INC
  @item REG_INC
*************** destination register.
*** 2916,2929 ****
  Thus, compiler passes prior to register allocation need only check for
  @code{REG_EQUAL} notes and passes subsequent to register allocation
  need only check for @code{REG_EQUIV} notes.
- 
- @findex REG_UNUSED
- @item REG_UNUSED
- The register @var{op} being set by this insn will not be used in a
- subsequent insn.  This differs from a @code{REG_DEAD} note, which
- indicates that the value in an input will not be used subsequently.
- These two notes are independent; both may be present for the same
- register.
  
  @findex REG_WAS_0
  @item REG_WAS_0
--- 2922,2927 ----

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-19 19:39   ` Stephen Clarke
  2001-07-20 11:38     ` Joern Rennecke
@ 2001-07-20 15:27     ` Richard Henderson
  1 sibling, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2001-07-20 15:27 UTC (permalink / raw)
  To: Stephen Clarke; +Cc: gcc, geoffk

On Thu, Jul 19, 2001 at 07:39:01PM -0700, Stephen Clarke wrote:
> 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.

This one is correct.


r~

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 15:25       ` Richard Henderson
@ 2001-07-20 15:54         ` Joern Rennecke
  2001-07-20 16:54           ` Richard Henderson
  0 siblings, 1 reply; 12+ messages in thread
From: Joern Rennecke @ 2001-07-20 15:54 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Joern Rennecke, Stephen Clarke, gcc, geoffk

> ! This does not necessarily mean that the register @var{op} has no useful
> ! value after this insn since it may also be an output of the insn.  In
> ! such a case, however, a @code{REG_DEAD} note would be redundant and is
> ! usually not present until after the reload pass, but no code relies on
> ! this fact.
>   
>   @findex REG_INC
>   @item REG_INC
> --- 2798,2814 ----
>   value immediately after this insn would not affect the future behavior
>   of the program.
>   
> ! It does not follow that the register @var{op} has no useful value after
> ! this insn since @var{op} is not necessarily modified by this insn.

The first half of this sentence is true, but the reason stated is wrong.
It is because @var{op} might be modified that it might contain a useful
value.  The original version had this right.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 15:54         ` Joern Rennecke
@ 2001-07-20 16:54           ` Richard Henderson
  2001-07-20 17:06             ` Joern Rennecke
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2001-07-20 16:54 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: Stephen Clarke, gcc, geoffk

On Fri, Jul 20, 2001 at 11:53:04PM +0100, Joern Rennecke wrote:
> > ! This does not necessarily mean that the register @var{op} has no useful
> > ! value after this insn since it may also be an output of the insn.
> >   
> > ! It does not follow that the register @var{op} has no useful value after
> > ! this insn since @var{op} is not necessarily modified by this insn.
> 
> The first half of this sentence is true, but the reason stated is wrong.
> It is because @var{op} might be modified that it might contain a useful
> value.  The original version had this right.

No, REG_DEAD talks about inputs only; REG_UNUSED talks about outputs only.

The reason that op might be useful is if we wish to extend the lifetime
of the original value.


r~

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Using and clobbering hard regs in parallel
  2001-07-20 16:54           ` Richard Henderson
@ 2001-07-20 17:06             ` Joern Rennecke
  0 siblings, 0 replies; 12+ messages in thread
From: Joern Rennecke @ 2001-07-20 17:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Joern Rennecke, Stephen Clarke, gcc, geoffk

> No, REG_DEAD talks about inputs only; REG_UNUSED talks about outputs only.
> 
> The reason that op might be useful is if we wish to extend the lifetime
> of the original value.

In that case, the first part of the sentence is mismatched.  It should be
something like

It does not follow that the original value of register @var{op} is not
available after this insn...

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2001-07-20 17:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-19 18:32 Using and clobbering hard regs in parallel Stephen Clarke
2001-07-19 18:39 ` Geoff Keating
2001-07-19 19:39   ` Stephen Clarke
2001-07-20 11:38     ` Joern Rennecke
2001-07-20 13:11       ` Mark Mitchell
2001-07-20 13:56         ` Joern Rennecke
2001-07-20 14:02           ` Mark Mitchell
2001-07-20 15:25       ` Richard Henderson
2001-07-20 15:54         ` Joern Rennecke
2001-07-20 16:54           ` Richard Henderson
2001-07-20 17:06             ` Joern Rennecke
2001-07-20 15:27     ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).