Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about "register"

0 views
Skip to first unread message

Joona I Palaste

unread,
Jul 10, 2002, 3:23:11 PM7/10/02
to
I have understood that the keyword "register" is meant as a hint to the
compiler that the variable should be placed in a processor register, if
possible. The compiler is a liberty to disobey this hint.
Now my question is: Is the compiler allowed to actually implement
"register" *in reverse*? I.e. usage of the "register" keyword would
actually *prevent* the variable from being placed in a processor
register, while otherwise it could be placed there? Does the Standard
say anything about this?

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Remember: There are only three kinds of people - those who can count and those
who can't."
- Vampyra

Tom St Denis

unread,
Jul 10, 2002, 3:27:06 PM7/10/02
to
Joona I Palaste wrote:
> I have understood that the keyword "register" is meant as a hint to the
> compiler that the variable should be placed in a processor register, if
> possible. The compiler is a liberty to disobey this hint.
> Now my question is: Is the compiler allowed to actually implement
> "register" *in reverse*? I.e. usage of the "register" keyword would
> actually *prevent* the variable from being placed in a processor
> register, while otherwise it could be placed there? Does the Standard
> say anything about this?

AFAIK its just a suggestion so yeah, the compiler could ignore it or
take it backwards.

Good compilers will simply ignore the keyword since their optimizers
will already have chopped/hacked/mutated the code to their advantage.

For proof check out GCC 3.1+ compiled code [get an assembler listing].
It can get fairly messy but for the most part very well optimized.

Tom

Ben Pfaff

unread,
Jul 10, 2002, 3:37:01 PM7/10/02
to
Joona I Palaste <pal...@cc.helsinki.fi> writes:

> I have understood that the keyword "register" is meant as a hint to the
> compiler that the variable should be placed in a processor register, if
> possible. The compiler is a liberty to disobey this hint.
> Now my question is: Is the compiler allowed to actually implement
> "register" *in reverse*? I.e. usage of the "register" keyword would
> actually *prevent* the variable from being placed in a processor
> register, while otherwise it could be placed there? Does the Standard
> say anything about this?

The standard just uses the word "suggests" in connection with the
description of `register', so the compiler may do anything it
likes, including pessimization. If the word was "shall" then the
compiler would be obliged to optimize:

4 A declaration of an identifier for an object with storage-class
specifier register suggests that access to the object be as
fast as possible. The extent to which such suggestions are
effective is implementation-defined.100)

Sam Reynolds

unread,
Jul 10, 2002, 3:51:11 PM7/10/02
to
Tom St Denis wrote:
[snip]

>
> AFAIK its just a suggestion so yeah, the compiler could ignore it or
> take it backwards.
>
> Good compilers will simply ignore the keyword since their optimizers
> will already have chopped/hacked/mutated the code to their advantage.
>
> For proof check out GCC 3.1+ compiled code [get an assembler listing].
> It can get fairly messy but for the most part very well optimized.

It may ignore it in regard to optimization, but by my reading it is
required to prohibit taking the address of the variable.

--
Sam Reynolds
cl...@chool.com

Joona I Palaste

unread,
Jul 10, 2002, 4:04:38 PM7/10/02
to
Sam Reynolds <cl...@chool.com> scribbled the following:

This evokes a further question. If, as previously said by St Denis and
Pfaff, the compiler is allowed to *lessen* the chance of registerness
when it sees the register keyword, then it must be possible for some
compiler somewhere to place non-register-qualified variables in
registers. Is the compiler still required to allow taking the address
of such variables, and have the address be meaningful? By "meaningful"
I do not mean that the address should represent any physical entity
within the computer's incestines, just that the basic indirection
operations (*, [] and ->) should work.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/

"Products like that make me wish I could menstruate."
- Andy Richter

Ben Pfaff

unread,
Jul 10, 2002, 4:09:14 PM7/10/02
to
Joona I Palaste <pal...@cc.helsinki.fi> writes:

> This evokes a further question. If, as previously said by St Denis and
> Pfaff, the compiler is allowed to *lessen* the chance of registerness
> when it sees the register keyword, then it must be possible for some
> compiler somewhere to place non-register-qualified variables in
> registers.

Of *course* the compiler is allowed to put variables without
`register' qualification in registers! Otherwise, the code
generated might be ridiculously and unnecessarily slow, and
there'd be few ways to take advantage of all the registers
available on many architectures. C compilers have been doing
this since the very beginning AFAIK.

> Is the compiler still required to allow taking the address
> of such variables, and have the address be meaningful? By "meaningful"
> I do not mean that the address should represent any physical entity
> within the computer's incestines, just that the basic indirection
> operations (*, [] and ->) should work.

Usually compilers won't put variables in registers if their
addresses are taken.
--
"It would be a much better example of undefined behavior
if the behavior were undefined."
--Michael Rubenstein

willem veenhoven

unread,
Jul 10, 2002, 4:33:57 PM7/10/02
to
Ben Pfaff wrote:
>
> Joona I Palaste <pal...@cc.helsinki.fi> writes:
>
> > Is the compiler still required to allow taking the address
> > of such variables, and have the address be meaningful?
>
> Usually compilers won't put variables in registers if their
> addresses are taken.

Well, Eric Sosman's example of hiding addresses behind a cast
and/or in a non-pointer object -in another thread- comes to
mind here. I have experienced weird behaviour in this respect
myself, although I can't reproduce the problems right now.

willem

Tom St Denis

unread,
Jul 10, 2002, 5:20:31 PM7/10/02
to
Joona I Palaste wrote:
> Sam Reynolds <cl...@chool.com> scribbled the following:
>
>>Tom St Denis wrote:
>>
>>>AFAIK its just a suggestion so yeah, the compiler could ignore it or
>>>take it backwards.
>>>
>>>Good compilers will simply ignore the keyword since their optimizers
>>>will already have chopped/hacked/mutated the code to their advantage.
>>>
>>>For proof check out GCC 3.1+ compiled code [get an assembler listing].
>>>It can get fairly messy but for the most part very well optimized.
>>
>
>>It may ignore it in regard to optimization, but by my reading it is
>>required to prohibit taking the address of the variable.
>
>
> This evokes a further question. If, as previously said by St Denis and
> Pfaff, the compiler is allowed to *lessen* the chance of registerness
> when it sees the register keyword, then it must be possible for some
> compiler somewhere to place non-register-qualified variables in
> registers. Is the compiler still required to allow taking the address
> of such variables, and have the address be meaningful? By "meaningful"
> I do not mean that the address should represent any physical entity
> within the computer's incestines, just that the basic indirection
> operations (*, [] and ->) should work.

Ah but if you need to use the address of a variable e.g..

int x, *px;
px = &x;

if you do

x = 4;

in one thread and

if (*px == 4) { ... }

in another then the compiler doesn't have to guarantee synchronization.

If you want to compiler to take special care against keeping variables
in registers make them volatile, e.g.

volatile int x;

IIRC will suggest to the compiler [I can't recall if volatile is
mandatory to be followed strictly] that 'x' should be kept in memory.

register int x;

just suggests that 'x' should be in a register. But its possible that
just simply

int x;

'x' gets in a register.

In all cases IIRC &x is expected to be the address of x regardless of
which suggestion you use.

In most cases variables that get stored in registers [if for part of the
code] still consume memory. In GCC for example it will only chop a
variable [e.g. remove it from the output completely] if it can optimize
it fully. e.g. in GCC the code

int test(void)
{
int a, b, c;

c = 23;
for (b = a = 0; a < 40; a++) {
b = (b << 1) ^ a;
}
return b;
}

produces the following x86 code

test:
pushl %ebp
xorl %edx, %edx
movl %esp, %ebp
xorl %eax, %eax
.p2align 4,,15
.L6:
addl %eax, %eax
xorl %edx, %eax
incl %edx
cmpl $39, %edx
jle .L6
popl %ebp
ret
.Lfe1:
.size test,.Lfe1-test
.ident "GCC: (GNU) 3.1"

You can see that none of the ints are stored on the stack at all. in
fact 'c' is completely ignored (not even initialized!) since its not
used in the loop.

At anyrate I'd still have to say avoid using "register" since the
compiler (in this case the almightly cool GCC 3.1) will do a fairly good
job optimizing the code for you. Only use "volatile" in multi-threaded
applications [which read, if you write you should use a mutex].

Tom

Dann Corbit

unread,
Jul 10, 2002, 5:01:49 PM7/10/02
to
"Ben Pfaff" <b...@cs.stanford.edu> wrote in message
news:87wus31...@pfaff.Stanford.EDU...


Wouldn't such code require a diagnostic?
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm


Ben Pfaff

unread,
Jul 10, 2002, 6:58:07 PM7/10/02
to
"Dann Corbit" <dco...@connx.com> writes:

> "Ben Pfaff" <b...@cs.stanford.edu> wrote in message
> news:87wus31...@pfaff.Stanford.EDU...
> > Joona I Palaste <pal...@cc.helsinki.fi> writes:
> >
> > > This evokes a further question. If, as previously said by St Denis and
> > > Pfaff, the compiler is allowed to *lessen* the chance of registerness
> > > when it sees the register keyword, then it must be possible for some
> > > compiler somewhere to place non-register-qualified variables in
> > > registers.
> >
> > Of *course* the compiler is allowed to put variables without
> > `register' qualification in registers! Otherwise, the code
> > generated might be ridiculously and unnecessarily slow, and
> > there'd be few ways to take advantage of all the registers
> > available on many architectures. C compilers have been doing
> > this since the very beginning AFAIK.
> >
> > > Is the compiler still required to allow taking the address
> > > of such variables, and have the address be meaningful? By "meaningful"
> > > I do not mean that the address should represent any physical entity
> > > within the computer's incestines, just that the basic indirection
> > > operations (*, [] and ->) should work.
> >
> > Usually compilers won't put variables in registers if their
> > addresses are taken.
>
> Wouldn't such code require a diagnostic?

Why? AFAICT we are talking about the compiler putting
non-register qualified variables into registers, not about taking
the address of a register-qualified variable.
--
"I should killfile you where you stand, worthless human." --Kaz

Bill Godfrey

unread,
Jul 11, 2002, 5:36:44 AM7/11/02
to
Joona I Palaste <pal...@cc.helsinki.fi> writes:

> registers. Is the compiler still required to allow taking the address
> of such variables, and have the address be meaningful? By "meaningful"
> I do not mean that the address should represent any physical entity
> within the computer's incestines, just that the basic indirection
> operations (*, [] and ->) should work.

The standard requires that any &ing of register objects requires a
disagnostic.

(An easy get out for register-ignoring-compilers is a warning whenver
it sees the register keyword, &ed or not.
"Warning: Use of register is ignored." )

Some 6502 compilers will interpret register (or latterly, make it's own
mind up about which objects get register-ified) as placing them in the
"zero page" area of memory, that is the 256 bytes 0x0000 to 0x00FF.

(The 6502 has three conventional registers A, X and Y. All are needed at
various stages and true registerification would be inconvient, although
I wouldn't be surprised to see for control variable find thier way into
the Y register occasionly.)

The 6502 has an addressing mode called "zero page addressing" which works
in a similar way to normal memory addressing, except only one byte of
address opcode is required. This optimised area of memory access makes
an ideal place for registerification of variables.

This type of architecture would indeed make &ing a register (via a register
keyword or by the compiler deciding for itself) object quite meaningful.
The generated pointer would still the same two byte pointer we are all
used to and dereferencing it would be a simple memory read.

Zero page addressing appears to be the exception in the general purpose
CPU world. Modern RISC CPUs come with a bazillion of registers, but
you cant just use the same memory access opcodes to read them like the
6502 could.

There's nothing really stopping compilers from using special pointers
which could either refer to a memory location or a register. The code to
dereference would be a bit... odd. Especially since most CPUs that I know
of don't have a way to access arbitary registers at run time, without
resorting to self modifying code.

Bill, LD R1,*R2.

Dave Vandervies

unread,
Jul 11, 2002, 6:14:03 AM7/11/02
to
In article <i2p4rf6...@cvhf434.gpt.co.uk>,
Bill Godfrey <bi...@bacchae.f9.co.uk> wrote:

>(The 6502 has three conventional registers A, X and Y. All are needed at
>various stages and true registerification would be inconvient, although
>I wouldn't be surprised to see for control variable find thier way into
>the Y register occasionly.)
>
>The 6502 has an addressing mode called "zero page addressing" which works
>in a similar way to normal memory addressing, except only one byte of
>address opcode is required. This optimised area of memory access makes
>an ideal place for registerification of variables.

Zero page was essentially a set of 256 8-bit registers in the sense
that "register" is used nowadays, if I remember correctly. This was
before processors' accesses to on-board storage was orders of magnitude
faster than accesses to main memory, so it was possible to access
zero-page memory with small opcodes in only one or two clock cycles,
and actual on-CPU storage was mainly useful for deciding which bytes in
memory you wanted to access. (If I remember correctly, almost all of
the opcodes that used X and Y used them to index a memory access off
of a base pointer; A was the only one that was actually useful as a
general-purpose register.)


>This type of architecture would indeed make &ing a register (via a register
>keyword or by the compiler deciding for itself) object quite meaningful.
>The generated pointer would still the same two byte pointer we are all
>used to and dereferencing it would be a simple memory read.

Didn't the PDP-11 also have its registers memory-mapped into the "low"
end of its memory address space? I recall hearing about how a small
enough loop could execute a few orders of magnitude faster by running
it directly from the memory-mapped registers on such a system.


>Zero page addressing appears to be the exception in the general purpose
>CPU world. Modern RISC CPUs come with a bazillion of registers, but
>you cant just use the same memory access opcodes to read them like the
>6502 could.

I seem to recall reading about some RISCy design (MMIX, perhaps?) that
used memory-mapped registers as well, but I could be wrong about that.
Unfortunately, I'm not sufficiently into low-level-ish stuff to fully
grok how incredibly cool that would be.


dave

--
Dave Vandervies dj3v...@calum.csclub.uwaterloo.ca

The only thing worse than X is every other GUI in common usage today.
--Chris Rovers in the Scary Devil Monastery

Dan Pop

unread,
Jul 11, 2002, 6:49:48 AM7/11/02
to
In <agi1iv$2vu$1...@oravannahka.helsinki.fi> Joona I Palaste <pal...@cc.helsinki.fi> writes:

>I have understood that the keyword "register" is meant as a hint to the
>compiler that the variable should be placed in a processor register, if
>possible. The compiler is a liberty to disobey this hint.
>Now my question is: Is the compiler allowed to actually implement
>"register" *in reverse*? I.e. usage of the "register" keyword would
>actually *prevent* the variable from being placed in a processor
>register, while otherwise it could be placed there? Does the Standard
>say anything about this?

[#1] The semantic descriptions in this International
Standard describe the behavior of an abstract machine in
which issues of optimization are irrelevant.

And, of course, the "as if" rule: if no strictly conforming program can
tell the difference, the compiler is not even allowed to implement the
semantics of the abstract machine. Although this rule is usually used
for optimising the generated code, it works in the other direction, too.

So, the only thing that is guaranteed about "register" is that register
objects can't have their address taken. No other objects (with the
exception of bit-fields) are subject to this limitation, so, if the
compiler keeps a non-register object in a machine register and the
address of this object is taken, the compiler must do the right thing
in order to preserve the (observable) semantics of the abstract machine.
Which usually means that a memory location will be reserved for that
object and the register will be saved to that location at "critical"
points and reloaded afterwards.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Dan Pop

unread,
Jul 11, 2002, 9:11:56 AM7/11/02
to
In <agjlpb$ra0$1...@tabloid.uwaterloo.ca> dj3v...@calum.csclub.uwaterloo.ca (Dave Vandervies) writes:

>Didn't the PDP-11 also have its registers memory-mapped into the "low"
>end of its memory address space?

Nope. They were pseudo-mapped into the high end of the I/O space.
The mapping was usable only from the console's switch register and the
registers were allocated successive UNIBUS addresses, i.e. you had an
8-bit address allocated for each 16-bit register:

777700 - R0
777701 - R1
777702 - R2
...

Although the I/O space was addressable as ordinary memory, it is obvious
that you couldn't address the registers in this way.

>I recall hearing about how a small
>enough loop could execute a few orders of magnitude faster by running
>it directly from the memory-mapped registers on such a system.

There were other systems which had their CPU registers mapped at the
beginning of their address space and where this trick could have worked,
but the PDP-11 was not one of them.

There were also systems who could use any contiguous memory area (or only
certain contiguous memory areas) as CPU registers: TMS9900, i8048, i8051.

Paul Hughett

unread,
Jul 11, 2002, 9:58:11 AM7/11/02
to
Dave Vandervies <dj3v...@calum.csclub.uwaterloo.ca> wrote:

: Didn't the PDP-11 also have its registers memory-mapped into the "low"


: end of its memory address space? I recall hearing about how a small
: enough loop could execute a few orders of magnitude faster by running
: it directly from the memory-mapped registers on such a system.

I don't know about the PDP-11 but the PDP-10 certainly did. Memory
addresses 0-17 (octal) actually referred to registers 0-17. I don't
think you could get a few orders of magnitude speedup, however;
perhaps 2 to 4 times, though. One trick used in the ITS operating
system was to put the OS idle loop in the registers so that it would
run without ever accessing memory.


Paul Hughett

Paul Hughett

unread,
Jul 11, 2002, 10:00:56 AM7/11/02
to
Dan Pop <Dan...@ifh.de> wrote:

: So, the only thing that is guaranteed about "register" is that register


: objects can't have their address taken.

Let me ask a language-lawyer question: Could a compiler generate a warning
rather than error and still be conforming?

Paul Hughett

Jeremy Yallop

unread,
Jul 11, 2002, 10:12:03 AM7/11/02
to

It could: only a "diagnostic" is required. The standard doesn't really
distinguish between errors and warnings (with the exception of #error
(in C99, at least)).

Jeremy.

Dave Vandervies

unread,
Jul 11, 2002, 10:29:22 AM7/11/02
to
In article <agk2tj$sa7$1...@netnews.upenn.edu>,

Paul Hughett <hug...@mercur.uphs.upenn.edu> wrote:
>Dave Vandervies <dj3v...@calum.csclub.uwaterloo.ca> wrote:
>
>: Didn't the PDP-11 also have its registers memory-mapped into the "low"
>: end of its memory address space? I recall hearing about how a small
>: enough loop could execute a few orders of magnitude faster by running
>: it directly from the memory-mapped registers on such a system.
>
>I don't know about the PDP-11 but the PDP-10 certainly did. Memory
>addresses 0-17 (octal) actually referred to registers 0-17.

Ah. If it was at least a PDP-something, that indicates that my memory
for random stuff that I read about that happened before I was around
isn't completely nonexistent. Whether this is a Good Thing is yet to
be determined.

> I don't
>think you could get a few orders of magnitude speedup, however;
>perhaps 2 to 4 times, though.

I'll blame an imperfect memory for `Ooh, Shiny!' stuff that I come across
once or twice for that.


> One trick used in the ITS operating
>system was to put the OS idle loop in the registers so that it would
>run without ever accessing memory.

I assume that the modern equivalent of this would be to make the idle
loop small enough to fit in the processor cache, which is getting easier
and easier as time and processor architecture move on?

Richard Heathfield

unread,
Jul 11, 2002, 1:34:30 PM7/11/02
to

A diagnostic is a diagnostic. The compiler is allowed to continue with
the translation, if that's what you mean.

--
Richard Heathfield : bin...@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Gordon Burditt

unread,
Jul 11, 2002, 2:01:18 PM7/11/02
to
>: So, the only thing that is guaranteed about "register" is that register
>: objects can't have their address taken.
>
>Let me ask a language-lawyer question: Could a compiler generate a warning
>rather than error and still be conforming?

ANSI C does not define "warnings" or "errors". It refers to
"diagnostics". If an error is defined as "a diagnostic that also
prevents the production of an executable program" and a warning is
defined as "a diagnostic that does not prevent the production of
an executable program", then a compiler may issue warnings for any
reason, however stupid, wrong, or irrelevant. (Some of these that
come to mind are "spelling error in comment" (even if there are no
comments), "division by 3" (even if there is no division in the
program), and "Richard Nixon might be president" (even if there is
no Richard Nixon).) I think of the lines put out by some compilers
that start off "Copyright <year> ..." as warnings.

A compiler may generate errors only for programs that require a
diagnostic or that invoke undefined behavior (I think). Some argue
that a statement that generates undefined behavior may not generate
undefined behavior at the compilation stage if it is possible that
said statement is never executed. (On the other hand, I have seen
a compiler that aborted with a division by zero trap while attempting
to constant-fold a division by zero at compile time, even though
said statement was immediately after a return statement, and
therefore could never be executed. That bug did get fixed fairly
fast, though.)

Gordon L. Burditt

0 new messages