Register keyword and "as if" rule...

S

Snis Pilbor

With the "as if" rule in play, doesn't that effectively render the
"register" keyword completely useless?

Example: I make a silly compiler which creates code that goes out of
its way to take a full 10 minutes every time a "register" declared
variable is read from or written to. Besides this lag, everything else
runs as expected. Then my compiler is still C compliant, aye?

If so, then it is unwise for any programmer to ever use the "register"
keyword if they want their code to run smoothly on all implementations:
their programs might get compiled by my silly compiler someday, and
then they'll be really blushing :*)

Or, more realistically, my compiler could simply ignore the "register"
keyword outright (except to issue diagnostics if it were used in a
syntactically bad way or its namespace violated).

Or does the standard actually make some assumption that the
implementation has things called "registers"?
 
R

Richard Heathfield

Snis Pilbor said:
With the "as if" rule in play, doesn't that effectively render the
"register" keyword completely useless?

Example: I make a silly compiler which creates code that goes out of
its way to take a full 10 minutes every time a "register" declared
variable is read from or written to. Besides this lag, everything else
runs as expected. Then my compiler is still C compliant, aye?

Yes. It would still be conforming if it went out of its way to take a full
10 minutes every time you read from or wrote to an object that was *not*
register-qualified. So the argument is spurious.
If so, then it is unwise for any programmer to ever use the "register"
keyword if they want their code to run smoothly on all implementations:

That isn't a reason not to bother with register. The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.
their programs might get compiled by my silly compiler someday, and
then they'll be really blushing :*)

More likely you will be. :)
Or, more realistically, my compiler could simply ignore the "register"
keyword outright (except to issue diagnostics if it were used in a
syntactically bad way or its namespace violated).

Many compilers behave in precisely this way.
Or does the standard actually make some assumption that the
implementation has things called "registers"?

No, it simply specifies the syntax, and leaves the decision up to the
implementor.
 
D

dcorbit

Snis said:
With the "as if" rule in play, doesn't that effectively render the
"register" keyword completely useless?

Example: I make a silly compiler which creates code that goes out of
its way to take a full 10 minutes every time a "register" declared
variable is read from or written to. Besides this lag, everything else
runs as expected. Then my compiler is still C compliant, aye?

If so, then it is unwise for any programmer to ever use the "register"
keyword if they want their code to run smoothly on all implementations:
their programs might get compiled by my silly compiler someday, and
then they'll be really blushing :*)

Or, more realistically, my compiler could simply ignore the "register"
keyword outright (except to issue diagnostics if it were used in a
syntactically bad way or its namespace violated).

Or does the standard actually make some assumption that the
implementation has things called "registers"?

For the past ten years, the register keyword has been useless anyway.

The compiler will choose what should be a register and what should not
better than you will (if the compiler is any good).

By naming something as a register, certain operations become impossible
(e.g. you can't take the address of a register).

The same thing goes for 'inline' which was obsolete before it was
formally introduced.

Optimization hints in general are not nearly so important as they were
20 years ago.
 
P

pete

Snis said:
is unwise for any programmer to ever use the "register"
keyword if they want their code to run smoothly on all
mplementations

The register keyword tells the compiler
that you think that you know more about optimization
than the compiler does.

The only way to use "register" effectively,
is on a per implementation basis with timed tests.
 
T

Thad Smith

Richard said:
That isn't a reason not to bother with register. The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.

I have read that claim many times. While it may be true, I would rather
the compiler honor the request when made so that the careful programmer
has the opportunity to improve his generated code. I don't care that a
careless programmer can easily make it worse. Unfortunately (in my
opinion), most modern compilers ignore that hint.

The one thing that the programmer can know that the compiler doesn't is
the relative frequency of execution paths, which may be important for
choosing the proper register allocation.
 
J

Jean-Marc Bourguet

Thad Smith said:
I have read that claim many times. While it may be true, I would rather
the compiler honor the request when made so that the careful programmer has
the opportunity to improve his generated code. I don't care that a
careless programmer can easily make it worse. Unfortunately (in my
opinion), most modern compilers ignore that hint.

The carefull programmer of yesterday make it impossible to get correct
performance from his code in today's implementation if the implementation
were to honor his request.

Yours,
 
M

Malcolm

Richard Heathfield said:
That isn't a reason not to bother with register. The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.
If you were writing a compiler, how would you use the keyword? Given that
we've got a spare word that won't break old programs.
 
K

Keith Thompson

Malcolm said:
If you were writing a compiler, how would you use the keyword? Given that
we've got a spare word that won't break old programs.

For starters, the guarantee that the object's address will never be
taken could introduce some opportunities for optimizations (though for
local variables the compiler can probably figure that out for itself).

I might ignore it by default, or perhaps give it some small weight in
deciding whether to assign a variable to a register, but provide a
command-line option to assign a higher weight.

This assumes, of course, that my optimizer really is better at
register allocation than most programmers; I'd want to test that
assumption on some real code before making a final decision on what
the default behavior should be.
 
E

Eric Sosman

Thad said:
I have read that claim many times. While it may be true, I would rather
the compiler honor the request when made so that the careful programmer
has the opportunity to improve his generated code. I don't care that a
careless programmer can easily make it worse. Unfortunately (in my
opinion), most modern compilers ignore that hint.

As a careful programmer, you no doubt made a careful series
of measurements to figure out which variables merit `register'
and which do not. You may even have discovered some variables
for which adding `register' slows down the code -- for example,
by forcing a save/restore the compiler would not otherwise have
generated, or by depriving the compiler of scratch registers it
could have used for other purposes. (I have seen this happen,
back in the Bad Old Days when `register' was the C programmer's
"abracadabra.")

But all your measurements are inextricably tied to just one
version of one compiler on one machine. As a careful programmer,
then, you need to repeat your measurements on the other platforms
of interest, and use #if magic so that you'll get optimal code
from gcc and Visual C++ and Frobozz Magic C, on Xeon and Opteron
and PowerPC and DS9000. And you'll need to do the whole job over
again when you patch or upgrade a compiler, or when a faster model
of a processor chip changes the relative costs of register- and
memory-resident data ...

A question: If the last smidgen of speed is so important to
you that you're willing to become the slave of the machine instead
of 'tother way about, why are you messing around with compiled
languages in the first place? Shouldn't you be writing machine
code, or at the very least assembly code?

I am not claiming that micro-optimization in general and
`register' in particular are always bad ideas, but I do claim
that they are seldom good ideas. The techniques developed
thirty years ago have been largely overtaken by the economics
of progress: CPU cycles used to be costlier than programmer
cycles, but the balance is now reversed. Corner cases will
always be with us, but the corners have been shrinking.
The one thing that the programmer can know that the compiler doesn't is
the relative frequency of execution paths, which may be important for
choosing the proper register allocation.

Compilers *can* know this, and with more accuracy than the
programmer is usually able to provide. The compiler instruments
the compiled code, you run the program over your universe of test
cases to generate counts and stuff, and finally you recompile
using both the source and the "feedback" data. This was cutting-
edge stuff fifteen years ago, and commercial compilers have been
using the technique for at least a decade.
 
A

Ancient_Hacker

Richard said:
That isn't a reason not to bother with register. The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.


Well, generally yes, but sometimes, NO.

The glitch in the ointment is that optimizing compilers try to minimize
the overall run time.

That's really keen and swell if you care about the time from engine
start to hitting the pub.

But there are many real-world situations where certain snippets of
code HAVE to run as fast as possible, in order to keep screens from
flickering, while maybe 95% of the code, being background or keypress
handling code, could be running at interpreted COBOL speeds. A
flight-control computer is a good example-- the keypresses come in very
rarely, but managing the rudder position had better happen every
millisecond.

But your typical compiler will try to speedup ALL the code, which in a
register-tight environment, such as the x86, means every register the
compiler allocates to a keyboard key handling loop, is a register that
won't be available for the rudder-damping code (assuming there's a
minimum of slow register save/restores being done).

So in those cases where pinpoint optimization is really needed, hints
like "register" might be appropriate.
 
M

Malcolm

Keith Thompson said:
For starters, the guarantee that the object's address will never be
taken could introduce some opportunities for optimizations (though for
local variables the compiler can probably figure that out for itself).

I might ignore it by default, or perhaps give it some small weight in
deciding whether to assign a variable to a register, but provide a
command-line option to assign a higher weight.

This assumes, of course, that my optimizer really is better at
register allocation than most programmers; I'd want to test that
assumption on some real code before making a final decision on what
the default behavior should be.
I meant, how wouold you extend the keyword.
For instnace, we could use "register" to register a pointer for bounds
checking. It would be perfectly compliant, but extend the language in a
useful way.
 
K

Keith Thompson

Malcolm said:
I meant, how wouold you extend the keyword.
For instnace, we could use "register" to register a pointer for bounds
checking. It would be perfectly compliant, but extend the language in a
useful way.

Oh, I see.

I wouldn't re-use "register". If I wanted to implement an extension,
I'd use some reserved identifier like __foobar__.

Or, if I were trying to create a new version of the standard, I'd
provide another meaning for "static". :cool:}
 
O

Old Wolf

Keith said:
For starters, the guarantee that the object's address will never be
taken could introduce some opportunities for optimizations (though for
local variables the compiler can probably figure that out for itself).

All register variables are local variables.
 
J

Jack Klein

Snis Pilbor said:


Yes. It would still be conforming if it went out of its way to take a full
10 minutes every time you read from or wrote to an object that was *not*
register-qualified. So the argument is spurious.


That isn't a reason not to bother with register. The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.

[snip]

Can you point to any actual tests that back up this often made and, in
my experience, totally incorrect truism?

In fact, it is relatively easily to concoct sample code that the best
optimizing compiler in the world cannot do as good a job of deciding
which local objects to keep in registers, as can a programmer who
knows the range of the data passed to the function.

Think loops whose counts depend on the value of parameters.
 
J

Jack Klein

As a careful programmer, you no doubt made a careful series
of measurements to figure out which variables merit `register'
and which do not. You may even have discovered some variables
for which adding `register' slows down the code -- for example,
by forcing a save/restore the compiler would not otherwise have
generated, or by depriving the compiler of scratch registers it
could have used for other purposes. (I have seen this happen,
back in the Bad Old Days when `register' was the C programmer's
"abracadabra.")

It still is, in come cases. Perhaps not in writing tiered middleware
under a desktop GUI, but C has more uses than that.
But all your measurements are inextricably tied to just one
version of one compiler on one machine. As a careful programmer,
then, you need to repeat your measurements on the other platforms
of interest, and use #if magic so that you'll get optimal code
from gcc and Visual C++ and Frobozz Magic C, on Xeon and Opteron
and PowerPC and DS9000. And you'll need to do the whole job over
again when you patch or upgrade a compiler, or when a faster model
of a processor chip changes the relative costs of register- and
memory-resident data ...

Dann straight its tied to just one compiler on one processor. Quite
often, when writing code to be run during interrupts on systems with
hard real time requirements, that is all that matters. Once such a
system ships, the compiler version will not be changed, no matter what
new version the vendor ships.
A question: If the last smidgen of speed is so important to
you that you're willing to become the slave of the machine instead
of 'tother way about, why are you messing around with compiled
languages in the first place? Shouldn't you be writing machine
code, or at the very least assembly code?

How many times have you written interrupt service routines in C that
are executed 20,000 times per second?
I am not claiming that micro-optimization in general and
`register' in particular are always bad ideas, but I do claim
that they are seldom good ideas. The techniques developed
thirty years ago have been largely overtaken by the economics
of progress: CPU cycles used to be costlier than programmer
cycles, but the balance is now reversed. Corner cases will
always be with us, but the corners have been shrinking.

There still are, and always will be, cases where CPU cycles are the
costliest resource of all, although very few of these are appear on
the typical desktop.
Compilers *can* know this, and with more accuracy than the
programmer is usually able to provide. The compiler instruments
the compiled code, you run the program over your universe of test
cases to generate counts and stuff, and finally you recompile
using both the source and the "feedback" data. This was cutting-
edge stuff fifteen years ago, and commercial compilers have been
using the technique for at least a decade.

Sadly, you are quite wrong about the state of many commercial
compilers, especially those for the embedded market where it is often
required to extract the maximum performance out of the minimum number
of clock cycles.
 
J

Jack Klein

For the past ten years, the register keyword has been useless anyway.

Interesting assertion. Can you point to any measured test data to
back it up?
The compiler will choose what should be a register and what should not
better than you will (if the compiler is any good).

The compiler? Is there only one? What about all the others? Perhaps
you really mean "most compilers" (doubtful), "some compilers", "the
compilers I use most", or "my favorite compiler"?
By naming something as a register, certain operations become impossible
(e.g. you can't take the address of a register).

Anyone who uses the "register" keyword without knowing how the
particular compiler in use generates code for the underlying processor
platform in use is a fool, as is any user of premature optimizations.
Still a fool, but less so, if he/she does not actually measure and
verify that the optimization, be it the use of the register keyword,
the inline keyword, or various other tricks, actually improves the
executable in the desired fashion.
The same thing goes for 'inline' which was obsolete before it was
formally introduced.

Optimization hints in general are not nearly so important as they were
20 years ago.

Again, I have not seen anyone produce a link to any studies that prove
this. And like anything else about the C language, evidence that
"most compilers", or even "all compilers except one", do better than
the programmer can is not a general proof.

The register keyword, and the inline keyword, now that we have it, are
tools that can be used effectively by someone who knows (and verifies)
what they do in a particular situation. And, like virtually all
optimization techniques, they can be misused much more easily by those
who do not know what they are doing.
 
R

Richard Heathfield

Jack Klein said:
On Fri, 13 Oct 2006 20:40:20 +0000, Richard Heathfield

The best reason not to
bother with register is that modern compilers are far better at deciding
what to put into registers than the vast majority of programmers.

[snip]

Can you point to any actual tests that back up this often made and, in
my experience, totally incorrect truism?

I'd put the boot on the other foot, and ask the programmer who wishes to use
'register' to show that it reduces the runtime significantly[1]. If it
does, fine, let him use it.

[1] Which leads to the question "when is a runtime reduction 'significant'?"
But that's another story.
 
K

Keith Thompson

Jack Klein said:
On 13 Oct 2006 17:07:04 -0700, (e-mail address removed) wrote in comp.lang.c: [...]
For the past ten years, the register keyword has been useless anyway.

Interesting assertion. Can you point to any measured test data to
back it up?

Do you have any measured test data to refute it?

(The question is not meant to imply that you don't have such data.)
 
T

Thad Smith

Yes, I do make such tests and measurements when it matters.
It still is, in come cases. Perhaps not in writing tiered middleware
under a desktop GUI, but C has more uses than that.


Dann straight its tied to just one compiler on one processor. Quite
often, when writing code to be run during interrupts on systems with
hard real time requirements, that is all that matters. Once such a
system ships, the compiler version will not be changed, no matter what
new version the vendor ships.

Jack is right on. As an embedded programmer, I have a choice of
dropping to assembly or tweaking the C code to meet constraints. If I
switch compilers or processors it changes. It still can be the best
option for my product.
How many times have you written interrupt service routines in C that
are executed 20,000 times per second?

That's the sort of scenario I sometimes work with, as well.
There still are, and always will be, cases where CPU cycles are the
costliest resource of all, although very few of these are appear on
the typical desktop.


Sadly, you are quite wrong about the state of many commercial
compilers, especially those for the embedded market where it is often
required to extract the maximum performance out of the minimum number
of clock cycles.

Right again. Also, there are times to minimize the maximum execution
path or only a particular portion of code, not just the overall average.
I am not aware of any such automated tools for low-end embedded
market, where execution speed may be critical.

A product developer uses a range of techniques, when needed, to achieve
project goals, including algorithm choice, selecting data precision,
changing the processor clock, dropping to assembly, changing processor
model, etc. Having the compiler do something potentially useful with
the register keyword beats ignoring it. A programmer can always abstain
from using the feature and let the compiler do its best, which is the
probably best in most, but not all, cases.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top