Re: Register allocation in special circumstancies (Christian Bau)
15 Feb 2001 00:29:54 -0500

          From comp.compilers

Related articles
Register allocation in special circumstancies (Andrey S. Bokhanko) (2001-02-01)
Re: Register allocation in special circumstancies (Andy Johnson) (2001-02-04)
Re: Register allocation in special circumstancies (Tom Payne) (2001-02-04)
Re: Register allocation in special circumstancies (2001-02-04)
Re: Register allocation in special circumstancies (2001-02-12)
Re: Register allocation in special circumstancies (2001-02-15)
Re: Register allocation in special circumstancies (2001-02-15)
Re: Register allocation in special circumstancies (Vince Del Vecchio) (2001-02-15)
Re: Register allocation in special circumstancies (Dennis Ritchie) (2001-02-15)
| List of all articles for this month |

From: (Christian Bau)
Newsgroups: comp.compilers
Date: 15 Feb 2001 00:29:54 -0500
Organization: Insignia Solutions
References: 01-02-014 01-02-048
Keywords: C, registers
Posted-Date: 15 Feb 2001 00:29:54 EST

"Andrey S. Bokhanko" <> writes:
> >As we all know, C language has nasty (for compiler developers)
> >feature: setjmp/longjmp.
> >But we can't disable one special optimization: register
> >allocation. So, that's where the problem is: if r.a. based on
> >classical graph coloring approach, we must construct Register
> >Interference Graph (RIG), and hence we must take into account this
> >nasty feature of "setjmp" points. But how to do it? (Torben AEgidius Mogensen) wrote:
> The simplest thing would be to wrap every setjmp inside a function,
> which isn't inlined. This way, it won't affect the register allocation
> of the function that uses setjmp. And inside the new function you have
> a well-defined register state defined by the calling convention, which
> makes saving the state fairly simple.

This will not work at all, because calling longjmp will cause the code
to resume inside the wrapper function which has long since gone,
leading most likely to a horrible crash.

After reading the C standard and doing some serious thinking my
conclusion is this:

1. setjmp should better be written to obey the calling conventions for
"normal" C functions, both in the case where it is called directly and
in the case where "setjmp" returns a second (or third etc. ) time due
to a call to longjmp. If setjmp doesn't do this then the compiler
writer has a problem.

2. Minor trap for the compiler writer: setjmp is usually a macro that
will eventually call another function like __setjmp or
__builtin_setjmp or __vec_setjmp or something like this. So the author
of the compiler and the person creating the <setjmp.h> header file
better agree about what they are doing. Doesn't help if the compiler
looks for a function named "setjmp" and setjmp is a macro calling

3. A not very optimising compiler will be ok, as long as it doesn't
put any volatile variables into registers and doesn't put any cached
values of static or external variables into registers. Even reusing
the same register for different variables doesn't hurt, because if
longjmp returns to the point after a setjmp call, the mapping between
variables and registers is the same again. So the original poster
might be just fine if he ignores the problem completely.

4. Two optimisations that will go wrong are these: a. Handling alias
information. If I write for example

      int i, j, *p = &j;
      if (setjmp (...) == 0) {
            p = &i;
            longjmp (...);
      } else (
              *p = 1;

the compiler might wrongly believe that the assignment p = 1; modifies
j when in reality it modifies i (because a "real" call to setjmp
always returns 0, and the second "return" from the call caused by
calling longjmp will always return a non-zero value, the assignment *p
= 1 can actually be proven to change i).

b. If the compiler finds dead variables and reuses locations on the
stack for different variables then things can go wrong. In the setjmp
() == 0 case the compiler could conclude that a variable is dead and
reuse the memory location and overwrite the variable. Note that this
is no problem if registers are reused.

5. To fix this, the compiler must recognize every call to the function
that is used to implement setjmp, and then every function call that
cannot be proven not to call longjmp must be assumed to branch
conditionally directly past the setjmp call, returning a non-zero

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.