public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Why does IRA force all pseudos live across a setjmp call to be spilled?
@ 2018-03-02 19:45 Peter Bergner
  2018-03-02 19:55 ` Alexander Monakov
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Peter Bergner @ 2018-03-02 19:45 UTC (permalink / raw)
  To: GCC; +Cc: Vladimir N Makarov, Pat Haugen

While debugging the PR84264 ICE caused by the following test case:

  void _setjmp ();
  void a (unsigned long *);
  void
  b ()
  {
    for (;;)
      {
	_setjmp ();
	unsigned long args[9]{};
	a (args);
      }
  }

I noticed that IRA is spilling all pseudos that are live across the call
to setjmp.  Why is that?  Trying to look through the history of this, I see
Jim committed a patch to reload that removed it spilling everything across
all setjmps:

  https://gcc.gnu.org/ml/gcc-patches/2003-11/msg01667.html

But currently ira-lives.c:process_bb_node_lives() has:

  /* Don't allocate allocnos that cross setjmps or any
     call, if this function receives a nonlocal
     goto.  */
  if (cfun->has_nonlocal_label
      || find_reg_note (insn, REG_SETJMP,
			NULL_RTX) != NULL_RTX)
    {
      SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj));
      SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
    }

...which forces us to spill everything live across the setjmp by forcing
the pseudos to interfere all hardregs.  That can't be good for performance.
What am I missing?

Peter


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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-02 19:45 Why does IRA force all pseudos live across a setjmp call to be spilled? Peter Bergner
@ 2018-03-02 19:55 ` Alexander Monakov
  2018-03-02 21:26 ` Jeff Law
  2018-03-03  3:21 ` Vladimir Makarov
  2 siblings, 0 replies; 20+ messages in thread
From: Alexander Monakov @ 2018-03-02 19:55 UTC (permalink / raw)
  To: Peter Bergner; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On Fri, 2 Mar 2018, Peter Bergner wrote:

> But currently ira-lives.c:process_bb_node_lives() has:
> 
>   /* Don't allocate allocnos that cross setjmps or any
>      call, if this function receives a nonlocal
>      goto.  */
>   if (cfun->has_nonlocal_label
>       || find_reg_note (insn, REG_SETJMP,
> 			NULL_RTX) != NULL_RTX)
>     {
>       SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj));
>       SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
>     }
> 
> ...which forces us to spill everything live across the setjmp by forcing
> the pseudos to interfere all hardregs.  That can't be good for performance.
> What am I missing?

FWIW there's a similar issue with exceptions where IRA chooses memory
for pseudos inside the loop even though the throwing call is outside:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82242#c3

Alexander

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-02 19:45 Why does IRA force all pseudos live across a setjmp call to be spilled? Peter Bergner
  2018-03-02 19:55 ` Alexander Monakov
@ 2018-03-02 21:26 ` Jeff Law
  2018-03-03  3:28   ` Peter Bergner
  2018-03-03  3:21 ` Vladimir Makarov
  2 siblings, 1 reply; 20+ messages in thread
From: Jeff Law @ 2018-03-02 21:26 UTC (permalink / raw)
  To: Peter Bergner, GCC; +Cc: Vladimir N Makarov, Pat Haugen

On 03/02/2018 12:45 PM, Peter Bergner wrote:
> While debugging the PR84264 ICE caused by the following test case:
> 
>   void _setjmp ();
>   void a (unsigned long *);
>   void
>   b ()
>   {
>     for (;;)
>       {
> 	_setjmp ();
> 	unsigned long args[9]{};
> 	a (args);
>       }
>   }
> 
> I noticed that IRA is spilling all pseudos that are live across the call
> to setjmp.  Why is that?  Trying to look through the history of this, I see
> Jim committed a patch to reload that removed it spilling everything across
> all setjmps:
> 
>   https://gcc.gnu.org/ml/gcc-patches/2003-11/msg01667.html
> 
> But currently ira-lives.c:process_bb_node_lives() has:
> 
>   /* Don't allocate allocnos that cross setjmps or any
>      call, if this function receives a nonlocal
>      goto.  */
>   if (cfun->has_nonlocal_label
>       || find_reg_note (insn, REG_SETJMP,
> 			NULL_RTX) != NULL_RTX)
>     {
>       SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj));
>       SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
>     }
> 
> ...which forces us to spill everything live across the setjmp by forcing
> the pseudos to interfere all hardregs.  That can't be good for performance.
> What am I missing?
You might want to hold off a bit.  I've got changes for 21161 which can
help this significantly.  Basically the live-across-setjmp set is way
too conservative -- it includes everything live at the setjmp, but it
really just needs what's live on the longjump path.

As for why, I believe it's related to trying to make sure everything has
the right values if we perform a longjmp.

I'll can include testing 84264 to see if my work helps there.

jeff

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-02 19:45 Why does IRA force all pseudos live across a setjmp call to be spilled? Peter Bergner
  2018-03-02 19:55 ` Alexander Monakov
  2018-03-02 21:26 ` Jeff Law
@ 2018-03-03  3:21 ` Vladimir Makarov
  2 siblings, 0 replies; 20+ messages in thread
From: Vladimir Makarov @ 2018-03-03  3:21 UTC (permalink / raw)
  To: Peter Bergner, GCC; +Cc: Pat Haugen



On 03/02/2018 02:45 PM, Peter Bergner wrote:
> While debugging the PR84264 ICE caused by the following test case:
>
>    void _setjmp ();
>    void a (unsigned long *);
>    void
>    b ()
>    {
>      for (;;)
>        {
> 	_setjmp ();
> 	unsigned long args[9]{};
> 	a (args);
>        }
>    }
>
> I noticed that IRA is spilling all pseudos that are live across the call
> to setjmp.  Why is that?  Trying to look through the history of this, I see
> Jim committed a patch to reload that removed it spilling everything across
> all setjmps:
>
>    https://gcc.gnu.org/ml/gcc-patches/2003-11/msg01667.html
>
> But currently ira-lives.c:process_bb_node_lives() has:
>
>    /* Don't allocate allocnos that cross setjmps or any
>       call, if this function receives a nonlocal
>       goto.  */
>    if (cfun->has_nonlocal_label
>        || find_reg_note (insn, REG_SETJMP,
> 			NULL_RTX) != NULL_RTX)
>      {
>        SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj));
>        SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
>      }
>
> ...which forces us to spill everything live across the setjmp by forcing
> the pseudos to interfere all hardregs.  That can't be good for performance.
> What am I missing?
>
>
I see.  There are a lot of history in this issue.  The first version of 
IRA (2008) had no such code.  After merging IRA, I got a PR 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37359 for an IA64 code.

To fix the PR, I implemented global.c behaviour for setjmp.  In 
regstat.c pseudos crossing setjmp got REG_LIVE_LENGTH == -1.  In 
global.c pseudos with REG_LIVE_LENGTH == -1 did not get an allocno and a 
hard reg as a consequence.

As I understand Jim Wilson wrote about fixing the issue in reload. I 
guess inheritance could have improved the code generated by global after 
fixing the issue in reload.

So basically IRA behaves as the old global.  Probably we could improve 
the current IRA code working with setjmp.

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-02 21:26 ` Jeff Law
@ 2018-03-03  3:28   ` Peter Bergner
  2018-03-03 16:29     ` Jeff Law
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Bergner @ 2018-03-03  3:28 UTC (permalink / raw)
  To: Jeff Law; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On 3/2/18 3:26 PM, Jeff Law wrote:
> On 03/02/2018 12:45 PM, Peter Bergner wrote:
>> ...which forces us to spill everything live across the setjmp by forcing
>> the pseudos to interfere all hardregs.  That can't be good for performance.
>> What am I missing?
>
> You might want to hold off a bit.  I've got changes for 21161 which can
> help this significantly.  Basically the live-across-setjmp set is way
> too conservative -- it includes everything live at the setjmp, but it
> really just needs what's live on the longjump path.
> 
> As for why, I believe it's related to trying to make sure everything has
> the right values if we perform a longjmp.

I can understand why we might save/restore across functions that can throw
exceptions since the program state hasn't been saved at the point of the
call or in the call, but what is special about setjmp()?  We don't need
to save/restore the volatile regs since all functions clobber them and
the non-volatile regs are saved/restored by setjmp(), just like any
normal function call.  ...and as far as I know, setjmp() doesn't save
or restore the stack contents, just the stack pointer, pc, etc.
So I guess I still don't know why we treat it differently than any
other function call wrt register allocation.

Peter


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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-03  3:28   ` Peter Bergner
@ 2018-03-03 16:29     ` Jeff Law
  2018-03-03 23:47       ` Peter Bergner
  0 siblings, 1 reply; 20+ messages in thread
From: Jeff Law @ 2018-03-03 16:29 UTC (permalink / raw)
  To: Peter Bergner; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On 03/02/2018 08:28 PM, Peter Bergner wrote:
> On 3/2/18 3:26 PM, Jeff Law wrote:
>> On 03/02/2018 12:45 PM, Peter Bergner wrote:
>>> ...which forces us to spill everything live across the setjmp by forcing
>>> the pseudos to interfere all hardregs.  That can't be good for performance.
>>> What am I missing?
>>
>> You might want to hold off a bit.  I've got changes for 21161 which can
>> help this significantly.  Basically the live-across-setjmp set is way
>> too conservative -- it includes everything live at the setjmp, but it
>> really just needs what's live on the longjump path.
>>
>> As for why, I believe it's related to trying to make sure everything has
>> the right values if we perform a longjmp.
> 
> I can understand why we might save/restore across functions that can throw
> exceptions since the program state hasn't been saved at the point of the
> call or in the call, but what is special about setjmp()?  We don't need
> to save/restore the volatile regs since all functions clobber them and
> the non-volatile regs are saved/restored by setjmp(), just like any
> normal function call.  ...and as far as I know, setjmp() doesn't save
> or restore the stack contents, just the stack pointer, pc, etc.
> So I guess I still don't know why we treat it differently than any
> other function call wrt register allocation.
Here's the comment from regstat.c:

              /* We have a problem with any pseudoreg that lives
                 across the setjmp.  ANSI says that if a user variable
                 does not change in value between the setjmp and the
                 longjmp, then the longjmp preserves it.  This
                 includes longjmp from a place where the pseudo
                 appears dead.  (In principle, the value still exists
                 if it is in scope.)  If the pseudo goes in a hard
                 reg, some other value may occupy that hard reg where
                 this pseudo is dead, thus clobbering the pseudo.
                 Conclusion: such a pseudo must not go in a hard
                 reg.  */


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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-03 16:29     ` Jeff Law
@ 2018-03-03 23:47       ` Peter Bergner
  2018-03-04  0:30         ` Peter Bergner
  2018-03-04 13:57         ` Eric Botcazou
  0 siblings, 2 replies; 20+ messages in thread
From: Peter Bergner @ 2018-03-03 23:47 UTC (permalink / raw)
  To: Jeff Law; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On 3/3/18 10:29 AM, Jeff Law wrote:
> Here's the comment from regstat.c:
> 
>               /* We have a problem with any pseudoreg that lives
>                  across the setjmp.  ANSI says that if a user variable
>                  does not change in value between the setjmp and the
>                  longjmp, then the longjmp preserves it.  This
>                  includes longjmp from a place where the pseudo
>                  appears dead.  (In principle, the value still exists
>                  if it is in scope.)  If the pseudo goes in a hard
>                  reg, some other value may occupy that hard reg where
>                  this pseudo is dead, thus clobbering the pseudo.
>                  Conclusion: such a pseudo must not go in a hard
>                  reg.  */

I can't argue with anything in that comment, other than the conclusion. :-)
It's not the compiler's job to implement the setjmp/longjmp save/restore.
Maybe Kenny was working around a problem with some target's buggy setjmp
and spilling everything "fixed" it?

It is absolutely fine for a pseudo that is live across a setjmp call to
occupy a (non-volatile) hard register at the setjmp's call site, even if
some other value eventually occupies the same hard register between the
setjmp and the longjmp.  The reason is that setjmp saves all of the non-
volatile hard registers in the jmp_buf.  If our pseudo was assigned to
one of those non-volatile hard registers, then its value at the time of
the setjmp call is saved, so even if its hard register is clobbered before
we get to the longjmp call, the longjmp will restore the pseudos value from
the jmp_buf into the hard register, restoring the value it had at the time
of the setjmp call.

The only way I can see the above not working is either setjmp doesn't
save the entire register state it should, the jmp_buf somehow gets clobbered
before the longjmp call or longjmp doesn't restore the entire register
state that it should.  All of those would be bugs in my book.

The only thing the register allocator should need to do, is treat setjmp
just like any other function call and make all pseudos that are live across
it interfere with all volatile hard registers, so that they will be assigned
to either non-volatile hard registers or spilled (if no non-volatile registers
are available).

Peter

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-03 23:47       ` Peter Bergner
@ 2018-03-04  0:30         ` Peter Bergner
  2018-03-04  8:57           ` Richard Biener
  2018-03-04 13:57         ` Eric Botcazou
  1 sibling, 1 reply; 20+ messages in thread
From: Peter Bergner @ 2018-03-04  0:30 UTC (permalink / raw)
  To: Jeff Law; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On 3/3/18 5:47 PM, Peter Bergner wrote:
> On 3/3/18 10:29 AM, Jeff Law wrote:
>> Here's the comment from regstat.c:
>>
>>               /* We have a problem with any pseudoreg that lives
>>                  across the setjmp.  ANSI says that if a user variable
>>                  does not change in value between the setjmp and the
>>                  longjmp, then the longjmp preserves it.  This
>>                  includes longjmp from a place where the pseudo
>>                  appears dead.  (In principle, the value still exists
>>                  if it is in scope.)  If the pseudo goes in a hard
>>                  reg, some other value may occupy that hard reg where
>>                  this pseudo is dead, thus clobbering the pseudo.
>>                  Conclusion: such a pseudo must not go in a hard
>>                  reg.  */
> 
> I can't argue with anything in that comment, other than the conclusion. :-)
> It's not the compiler's job to implement the setjmp/longjmp save/restore.
> Maybe Kenny was working around a problem with some target's buggy setjmp
> and spilling everything "fixed" it?

The only observable difference I can see between a variable that has been
spilled to memory versus one that is assigned to a non-volatile hard reg
is if it is modified between the setjmp and the longjmp.  In the case
where the variable is spilled to memory, the "new" updated value is the
value you _may_ see on the return from setjmp (the return caused by the
call to longjmp), whereas if it is assigned to a non-volatile register,
then you _will_ see the "old" value that was saved by the setjmp call.
I say _may_ see above, because there are cases were we might not store
the "new" updated value to memory, even if we've spilled the pseudo.
Examples would be spill code optimization, or the variable has been
broken into separate live ranges/pseudos. etc. etc.  I guess I can even
think of cases where we could see both "old" and "new" values of a
variable.  Think of a variable that has been spilled/split like below:

    a = <old value> [start of live range, a assigned to non-volatile reg]
    spill store a
    ...
    setjmp()
    ...
1)  ... = ... a ...     [end of live range]
    ...                 [a not assigned to a reg in this region]
    spill load a        [start of live range]
2)  ... = ... a ...     [end of live range]
    ...
    if (...)
       a = <new value>  [start of live range]
3)     spill store a    [end of live range]
    ...                 [a not assigned to a reg in this region]
    longjmp()


On return from setjmp (the return caused by the call to longjmp),
the use of "a" at "1)" will use the non-volatile hard register
that was saved by the initial call to setjmp, so it will see the
"old" value of "a".  However, since the use of "a" at "2)" loads
the value from memory, it will use the "new" value stored by
the spill load at "3)"!

That said, the comment above only talks about variables that do not
change between the setjmp and the longjmp and in that case, you will
see the same "old" value (which is the only value, since it wasn't
modified) regardless of whether it was spilled or not.

What does ANSI (or any spec) say about what should happen to variables
that are modified between the setjmp and longjmp calls?  Maybe all bets
are off, given the example above, since even spilling a variable live
across a setjmp can still lead to strange behavior unless you don't
allow spill/split optimization and I don't think we'd want that at all.

Peter


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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04  0:30         ` Peter Bergner
@ 2018-03-04  8:57           ` Richard Biener
  2018-03-04  9:11             ` Andreas Schwab
  2018-03-05  2:12             ` Jeff Law
  0 siblings, 2 replies; 20+ messages in thread
From: Richard Biener @ 2018-03-04  8:57 UTC (permalink / raw)
  To: gcc, Peter Bergner, Jeff Law; +Cc: GCC, Vladimir N Makarov, Pat Haugen

On March 4, 2018 1:30:39 AM GMT+01:00, Peter Bergner <bergner@vnet.ibm.com> wrote:
>On 3/3/18 5:47 PM, Peter Bergner wrote:
>> On 3/3/18 10:29 AM, Jeff Law wrote:
>>> Here's the comment from regstat.c:
>>>
>>>               /* We have a problem with any pseudoreg that lives
>>>                  across the setjmp.  ANSI says that if a user
>variable
>>>                  does not change in value between the setjmp and the
>>>                  longjmp, then the longjmp preserves it.  This
>>>                  includes longjmp from a place where the pseudo
>>>                  appears dead.  (In principle, the value still
>exists
>>>                  if it is in scope.)  If the pseudo goes in a hard
>>>                  reg, some other value may occupy that hard reg
>where
>>>                  this pseudo is dead, thus clobbering the pseudo.
>>>                  Conclusion: such a pseudo must not go in a hard
>>>                  reg.  */
>> 
>> I can't argue with anything in that comment, other than the
>conclusion. :-)
>> It's not the compiler's job to implement the setjmp/longjmp
>save/restore.
>> Maybe Kenny was working around a problem with some target's buggy
>setjmp
>> and spilling everything "fixed" it?
>
>The only observable difference I can see between a variable that has
>been
>spilled to memory versus one that is assigned to a non-volatile hard
>reg
>is if it is modified between the setjmp and the longjmp.  In the case
>where the variable is spilled to memory, the "new" updated value is the
>value you _may_ see on the return from setjmp (the return caused by the
>call to longjmp), whereas if it is assigned to a non-volatile register,
>then you _will_ see the "old" value that was saved by the setjmp call.
>I say _may_ see above, because there are cases were we might not store
>the "new" updated value to memory, even if we've spilled the pseudo.
>Examples would be spill code optimization, or the variable has been
>broken into separate live ranges/pseudos. etc. etc.  I guess I can even
>think of cases where we could see both "old" and "new" values of a
>variable.  Think of a variable that has been spilled/split like below:
>
>  a = <old value> [start of live range, a assigned to non-volatile reg]
>    spill store a
>    ...
>    setjmp()
>    ...
>1)  ... = ... a ...     [end of live range]
>    ...                 [a not assigned to a reg in this region]
>    spill load a        [start of live range]
>2)  ... = ... a ...     [end of live range]
>    ...
>    if (...)
>       a = <new value>  [start of live range]
>3)     spill store a    [end of live range]
>    ...                 [a not assigned to a reg in this region]
>    longjmp()
>
>
>On return from setjmp (the return caused by the call to longjmp),
>the use of "a" at "1)" will use the non-volatile hard register
>that was saved by the initial call to setjmp, so it will see the
>"old" value of "a".  However, since the use of "a" at "2)" loads
>the value from memory, it will use the "new" value stored by
>the spill load at "3)"!
>
>That said, the comment above only talks about variables that do not
>change between the setjmp and the longjmp and in that case, you will
>see the same "old" value (which is the only value, since it wasn't
>modified) regardless of whether it was spilled or not.
>
>What does ANSI (or any spec) say about what should happen to variables
>that are modified between the setjmp and longjmp calls?  Maybe all bets
>are off, given the example above, since even spilling a variable live
>across a setjmp can still lead to strange behavior unless you don't
>allow spill/split optimization and I don't think we'd want that at all.

I think posix says you have to mark such variables volatile. So I fully agree with your analysis of why setjmp isn't special for RA. It would be only making non-conforming code work by accident. 

Richard. 


>Peter

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04  8:57           ` Richard Biener
@ 2018-03-04  9:11             ` Andreas Schwab
  2018-03-05  2:12             ` Jeff Law
  1 sibling, 0 replies; 20+ messages in thread
From: Andreas Schwab @ 2018-03-04  9:11 UTC (permalink / raw)
  To: Richard Biener
  Cc: gcc, Peter Bergner, Jeff Law, Vladimir N Makarov, Pat Haugen

On Mär 04 2018, Richard Biener <richard.guenther@gmail.com> wrote:

> I think posix says you have to mark such variables volatile.

It's the C standard that does that:

7.13.2.1#3 All accessible objects have values, and all other components
of the abstract machine have state, as of the time the longjmp function
was called, except that the values of objects of automatic storage
duration that are local to the function containing the invocation of the
corresponding setjmp macro that do not have volatile-qualified type and
have been changed between the setjmp invocation and longjmp call are
indeterminate.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-03 23:47       ` Peter Bergner
  2018-03-04  0:30         ` Peter Bergner
@ 2018-03-04 13:57         ` Eric Botcazou
  2018-03-04 16:40           ` Peter Bergner
  2018-03-05  0:16           ` Segher Boessenkool
  1 sibling, 2 replies; 20+ messages in thread
From: Eric Botcazou @ 2018-03-04 13:57 UTC (permalink / raw)
  To: Peter Bergner; +Cc: gcc, Jeff Law, Vladimir N Makarov, Pat Haugen

> I can't argue with anything in that comment, other than the conclusion. :-)
> It's not the compiler's job to implement the setjmp/longjmp save/restore.
> Maybe Kenny was working around a problem with some target's buggy setjmp
> and spilling everything "fixed" it?

What are the requirements imposed on setjmp exactly and by whom?  The psABI on 
SPARC (the SCD) has an explicit note saying that setjmp/sigsetjmp/vfork don't 
(have to) preserve the usual non-volatile registers.

-- 
Eric Botcazou

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04 13:57         ` Eric Botcazou
@ 2018-03-04 16:40           ` Peter Bergner
  2018-03-04 17:39             ` Andreas Schwab
  2018-03-05  0:16           ` Segher Boessenkool
  1 sibling, 1 reply; 20+ messages in thread
From: Peter Bergner @ 2018-03-04 16:40 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc, Jeff Law, Vladimir N Makarov, Pat Haugen

On 3/4/18 7:57 AM, Eric Botcazou wrote:
>> I can't argue with anything in that comment, other than the conclusion. :-)
>> It's not the compiler's job to implement the setjmp/longjmp save/restore.
>> Maybe Kenny was working around a problem with some target's buggy setjmp
>> and spilling everything "fixed" it?
> 
> What are the requirements imposed on setjmp exactly and by whom?  The psABI on 
> SPARC (the SCD) has an explicit note saying that setjmp/sigsetjmp/vfork don't 
> (have to) preserve the usual non-volatile registers.

I'm not a language lawyer and I don't play one on TV either, but I believe
the requirements come from multiple sources.  You've pointed out your ABI
and Andreas pointed out the C standard also places requirements:

    https://gcc.gnu.org/ml/gcc/2018-03/msg00030.html

I wouldn't be surprised if there are more specs/standards that place
restrictions too.  Clearly returning from the function that calls
setjmp before calling longjmp must be illegal, since that would result
in clobbering of the stack frame the longjmp would attempt to restore to.
I don't know off hand who/what states that restriction.

Peter


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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04 16:40           ` Peter Bergner
@ 2018-03-04 17:39             ` Andreas Schwab
  0 siblings, 0 replies; 20+ messages in thread
From: Andreas Schwab @ 2018-03-04 17:39 UTC (permalink / raw)
  To: Peter Bergner
  Cc: Eric Botcazou, gcc, Jeff Law, Vladimir N Makarov, Pat Haugen

On Mär 04 2018, Peter Bergner <bergner@vnet.ibm.com> wrote:

> Clearly returning from the function that calls
> setjmp before calling longjmp must be illegal, since that would result
> in clobbering of the stack frame the longjmp would attempt to restore to.
> I don't know off hand who/what states that restriction.

7.13.2.1#2 ... if the function containing the invocation of the setjmp
macro has terminated execution in the interim, ... the behavior is
undefined.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04 13:57         ` Eric Botcazou
  2018-03-04 16:40           ` Peter Bergner
@ 2018-03-05  0:16           ` Segher Boessenkool
  2018-03-05  7:01             ` Eric Botcazou
  1 sibling, 1 reply; 20+ messages in thread
From: Segher Boessenkool @ 2018-03-05  0:16 UTC (permalink / raw)
  To: Eric Botcazou
  Cc: Peter Bergner, gcc, Jeff Law, Vladimir N Makarov, Pat Haugen

On Sun, Mar 04, 2018 at 02:57:38PM +0100, Eric Botcazou wrote:
> > I can't argue with anything in that comment, other than the conclusion. :-)
> > It's not the compiler's job to implement the setjmp/longjmp save/restore.
> > Maybe Kenny was working around a problem with some target's buggy setjmp
> > and spilling everything "fixed" it?
> 
> What are the requirements imposed on setjmp exactly and by whom?  The psABI on 
> SPARC (the SCD) has an explicit note saying that setjmp/sigsetjmp/vfork don't 
> (have to) preserve the usual non-volatile registers.

C11 says in 7.13.2.1/2
"The longjmp function restores the environment saved by the most recent
invocation of the setjmp macro in the same invocation of the program with
the corresponding jmp_buf argument."
where "environment" is not really defined, but it includes all information
a program will need to return to its caller (so it has to restore the
non-volatile registers, set stack pointers correctly, that kind of thing).

But there is 7.13.2.1/3 as well:
"All accessible objects have values, and all other components of the
abstract machine have state, as of the time the longjmp function was
called, except that the values of objects of automatic storage duration
that are local to the function containing the invocation of the
corresponding setjmp macro that do not have volatile-qualified type and
have been changed between the setjmp invocation and longjmp call are
indeterminate."

So, an auto var that is *not* changed between setjmp and longjmp has
to keep its value.  If the auto var lives in memory that works out fine;
if it lives in a non-volatile reg and setjmp saves those, that works as
well; but if it lives in a *volatile* register it does not (because it
might be moved to some other reg for example; in the abstract machine
that did not change anything, but in the real machine it does).

If setjmp clobbers everything a function call does, this still works
fine as far as I see.  And GCC gives warnings if not (not that that
makes things compliant).


Segher

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-04  8:57           ` Richard Biener
  2018-03-04  9:11             ` Andreas Schwab
@ 2018-03-05  2:12             ` Jeff Law
  1 sibling, 0 replies; 20+ messages in thread
From: Jeff Law @ 2018-03-05  2:12 UTC (permalink / raw)
  To: Richard Biener, gcc, Peter Bergner; +Cc: Vladimir N Makarov, Pat Haugen

On 03/04/2018 01:57 AM, Richard Biener wrote:
> 
> I think posix says you have to mark such variables volatile. So I
> fully agree with your analysis of why setjmp isn't special for RA. It
> would be only making non-conforming code work by accident.
Note the code we're carrying around has its origins prior to the
introduction of volatile into the C standard.  It may be the case that
we can and should rethink all this behavior in a modern world where
setjmp/longjmp semantics are better refined and programmers are expected
to use volatile to indicate the behavior they want.

I'm not sure I'd want to do that during stage4 though.  Seems like a
gcc-9 kind of thing.

jeff

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-05  0:16           ` Segher Boessenkool
@ 2018-03-05  7:01             ` Eric Botcazou
  2018-03-05  7:09               ` Eric Botcazou
  2018-03-05 15:33               ` Segher Boessenkool
  0 siblings, 2 replies; 20+ messages in thread
From: Eric Botcazou @ 2018-03-05  7:01 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: gcc, Peter Bergner, Jeff Law, Vladimir N Makarov, Pat Haugen

> C11 says in 7.13.2.1/2
> "The longjmp function restores the environment saved by the most recent
> invocation of the setjmp macro in the same invocation of the program with
> the corresponding jmp_buf argument."
> where "environment" is not really defined, but it includes all information
> a program will need to return to its caller (so it has to restore the
> non-volatile registers, set stack pointers correctly, that kind of thing).

Apparently the authors of the SPARC psABI thought that the last part of your 
sentence is an interpolation and that the (historical) requirements were vague 
enough to allow their interpretation, IOW that the compiler can do the work.

-- 
Eric Botcazou

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-05  7:01             ` Eric Botcazou
@ 2018-03-05  7:09               ` Eric Botcazou
  2018-03-05 15:33               ` Segher Boessenkool
  1 sibling, 0 replies; 20+ messages in thread
From: Eric Botcazou @ 2018-03-05  7:09 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: gcc, Peter Bergner, Jeff Law, Vladimir N Makarov, Pat Haugen

> Apparently the authors of the SPARC psABI thought that the last part of your
> sentence is an interpolation and that the (historical) requirements were
> vague enough to allow their interpretation, IOW that the compiler can do
> the work.

And, as PR target/83368 showed, both the GNU and the Solaris libc make use of 
the leeway given by the psABI for setjmp at least in some cases.

-- 
Eric Botcazou

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-05  7:01             ` Eric Botcazou
  2018-03-05  7:09               ` Eric Botcazou
@ 2018-03-05 15:33               ` Segher Boessenkool
  2018-03-05 16:18                 ` Eric Botcazou
  2018-03-06 16:20                 ` Peter Bergner
  1 sibling, 2 replies; 20+ messages in thread
From: Segher Boessenkool @ 2018-03-05 15:33 UTC (permalink / raw)
  To: Eric Botcazou
  Cc: gcc, Peter Bergner, Jeff Law, Vladimir N Makarov, Pat Haugen

On Mon, Mar 05, 2018 at 08:01:14AM +0100, Eric Botcazou wrote:
> > C11 says in 7.13.2.1/2
> > "The longjmp function restores the environment saved by the most recent
> > invocation of the setjmp macro in the same invocation of the program with
> > the corresponding jmp_buf argument."
> > where "environment" is not really defined, but it includes all information
> > a program will need to return to its caller (so it has to restore the
> > non-volatile registers, set stack pointers correctly, that kind of thing).
> 
> Apparently the authors of the SPARC psABI thought that the last part of your 
> sentence is an interpolation and that the (historical) requirements were vague 
> enough to allow their interpretation, IOW that the compiler can do the work.

Maybe we should have a target hook that says setjmp/longjmp are
implemented by simple function calls (or as-if by function calls), so
as not to penalize everyone who has an, erm, more conservative ABI?


Segher

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-05 15:33               ` Segher Boessenkool
@ 2018-03-05 16:18                 ` Eric Botcazou
  2018-03-06 16:20                 ` Peter Bergner
  1 sibling, 0 replies; 20+ messages in thread
From: Eric Botcazou @ 2018-03-05 16:18 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: gcc, Peter Bergner, Jeff Law, Vladimir N Makarov, Pat Haugen

> Maybe we should have a target hook that says setjmp/longjmp are
> implemented by simple function calls (or as-if by function calls), so
> as not to penalize everyone who has an, erm, more conservative ABI?

Yes, that sounds a sensible compromise to me.

-- 
Eric Botcazou

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

* Re: Why does IRA force all pseudos live across a setjmp call to be spilled?
  2018-03-05 15:33               ` Segher Boessenkool
  2018-03-05 16:18                 ` Eric Botcazou
@ 2018-03-06 16:20                 ` Peter Bergner
  1 sibling, 0 replies; 20+ messages in thread
From: Peter Bergner @ 2018-03-06 16:20 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Eric Botcazou, gcc, Jeff Law, Vladimir N Makarov, Pat Haugen

On 3/5/18 9:33 AM, Segher Boessenkool wrote:
> On Mon, Mar 05, 2018 at 08:01:14AM +0100, Eric Botcazou wrote:
>> Apparently the authors of the SPARC psABI thought that the last part of your 
>> sentence is an interpolation and that the (historical) requirements were vague 
>> enough to allow their interpretation, IOW that the compiler can do the work.
> 
> Maybe we should have a target hook that says setjmp/longjmp are
> implemented by simple function calls (or as-if by function calls), so
> as not to penalize everyone who has an, erm, more conservative ABI?

Unless someone really wants to work on this, I'll have a look at
adding this once stage1 opens up.

Peter

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

end of thread, other threads:[~2018-03-06 16:20 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-02 19:45 Why does IRA force all pseudos live across a setjmp call to be spilled? Peter Bergner
2018-03-02 19:55 ` Alexander Monakov
2018-03-02 21:26 ` Jeff Law
2018-03-03  3:28   ` Peter Bergner
2018-03-03 16:29     ` Jeff Law
2018-03-03 23:47       ` Peter Bergner
2018-03-04  0:30         ` Peter Bergner
2018-03-04  8:57           ` Richard Biener
2018-03-04  9:11             ` Andreas Schwab
2018-03-05  2:12             ` Jeff Law
2018-03-04 13:57         ` Eric Botcazou
2018-03-04 16:40           ` Peter Bergner
2018-03-04 17:39             ` Andreas Schwab
2018-03-05  0:16           ` Segher Boessenkool
2018-03-05  7:01             ` Eric Botcazou
2018-03-05  7:09               ` Eric Botcazou
2018-03-05 15:33               ` Segher Boessenkool
2018-03-05 16:18                 ` Eric Botcazou
2018-03-06 16:20                 ` Peter Bergner
2018-03-03  3:21 ` Vladimir Makarov

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).