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