Compiler code optimization: see code below

J

joshc

I'm writing some C to be used in an embedded environment and the code
needs to be optimized. I have a question about optimizing compilers in
general. I'm using GCC for the workstation and Diab compiler for the
embedded target.

My question is about how compilers optimize certain code sequences.

As an example, take the code below. Will the compiler eliminate the
actual function call to foo() in the object code generated and just
store the value '3' in temp(obviously somewhere on stack)? I think
based on my experiments with GCC the value '3' actually wont' be stored
at all since it's obviously not being used anywhere. My tests showed
that no function call is made in the object code and neither is any
value being stored in temp.

int main() {
int temp;

temp = foo(3);

return 0;
}

int foo(int x) {
return x;
}

Now as a general question, if I have function calls in my code in which
the arguments I am passing to the function are known at compile time,
will these function calls be eliminated by the compiler?

I guess since I don't have much of a background in compilers I'm not
sure what exactly a good optimizing compiler can optimize away. Please
point me to any references on this topic as well if you have some.
Thanks.
 
N

Neil Kurzman

joshc said:
I'm writing some C to be used in an embedded environment and the code
needs to be optimized. I have a question about optimizing compilers in
general. I'm using GCC for the workstation and Diab compiler for the
embedded target.

My question is about how compilers optimize certain code sequences.

As an example, take the code below. Will the compiler eliminate the
actual function call to foo() in the object code generated and just
store the value '3' in temp(obviously somewhere on stack)? I think
based on my experiments with GCC the value '3' actually wont' be stored
at all since it's obviously not being used anywhere. My tests showed
that no function call is made in the object code and neither is any
value being stored in temp.

int main() {
int temp;

temp = foo(3);

return 0;
}

int foo(int x) {
return x;
}

Now as a general question, if I have function calls in my code in which
the arguments I am passing to the function are known at compile time,
will these function calls be eliminated by the compiler?

I guess since I don't have much of a background in compilers I'm not
sure what exactly a good optimizing compiler can optimize away. Please
point me to any references on this topic as well if you have some.
Thanks.

The compiler can do whatever it wants as look as it generates a working
binary.
different compilers (or different versions) may do different things.
The compiler Docs should tell you what types of optimization it can do.
 
E

E. Robert Tisdale

joshc said:
I'm writing some C to be used in an embedded environment
and the code needs to be optimized.
I have a question about optimizing compilers in general.
I'm using GCC for the workstation
and Diab compiler for the embedded target.
My question is about how compilers optimize certain code sequences.
As an example, take the code below.
Will the compiler eliminate the actual function call to foo()
in the [emitted] object code
and just store the value '3' in temp(obviously somewhere on stack)?
I think [that], based on my experiments with GCC,
the value '3' actually won't be stored at all
since it's obviously not being used anywhere.
My tests showed that no function call is made in the object code
and neither is any value being stored in temp.
int main(int argc, char* argv[]) {
int temp = foo(3);
return 0;
}

int foo(int x) {
return x;
}

Now as a general question, if I have function calls in my code
in which the arguments I am passing to the function
are known at compile time,
will these function calls be eliminated by the compiler?

Yes, if the function definition is visible to the compiler.
To be safe, you should probably write

inline static
int foo(int x) {
return x;
}

int main(int argc, char* argv[]) {
int temp = foo(3);
// stuff
return 0;
}

It should also work for standard math functions:
> cat f.c
#include <math.h>

double f(double x) {
return sqrt(2.0);
}
> gcc -Wall -std=c99 -pedantic -O2 -S f.c
> cat f.s
.file "f.c"
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 1719614413
.long 1073127582
.text
.p2align 4,,15
.globl f
.type f, @function
f:
pushl %ebp // superfluous
movl %esp, %ebp // superfluous
popl %ebp // superfluous
fldl .LC0
ret
.size f, .-f
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.1"

The pair of long data words at LC0 represent sqrt(2.0).
I guess [that], since I don't have much of a background in compilers,
I'm not sure exactly what a good optimizing compiler can optimize away.

I'm not sure either.
Optimization is always at the cutting edge of compiler technology.
It is one of the ways that compiler developers compete with each other.
I always test for the optimizations that I think are important.
Sometimes, my compiler fails to perform the optimization that I expect
so I run benchmarks to determine whether or not my optimization
actually result in faster code -- they usually don't.
For example, in the above code,
there appear to be three superfluous instructions
but I doubt that the function f(double) would be any faster
if I removed them -- it might actually run slower.
Sometimes compilers leave superfluous instructions
in the code to serve as no-ops to prevent pipeline stalls
or to align the instruction stream properly,
Please point me to any references on this topic as well
if you have some.

I would be interested in any such references as well.
 
J

Jack Klein

I'm writing some C to be used in an embedded environment and the code
needs to be optimized. I have a question about optimizing compilers in
general. I'm using GCC for the workstation and Diab compiler for the
embedded target.

My question is about how compilers optimize certain code sequences.

The C standard does not define how compilers optimize certain code
sequences, nor does it require them to do so. It is entirely up to
the compiler and the options with which you invoke it.
As an example, take the code below. Will the compiler eliminate the
actual function call to foo() in the object code generated and just
store the value '3' in temp(obviously somewhere on stack)? I think
based on my experiments with GCC the value '3' actually wont' be stored
at all since it's obviously not being used anywhere. My tests showed
that no function call is made in the object code and neither is any
value being stored in temp.

int main() {
int temp;

temp = foo(3);

return 0;
}

int foo(int x) {
return x;
}

Now as a general question, if I have function calls in my code in which
the arguments I am passing to the function are known at compile time,
will these function calls be eliminated by the compiler?

I guess since I don't have much of a background in compilers I'm not
sure what exactly a good optimizing compiler can optimize away. Please
point me to any references on this topic as well if you have some.
Thanks.

would probably be a good reference to what "a good
optimizing compiler can optimize away", but that won't necessarily do
you any good at all. Note also that the issue is off-topic here, as
optimization is always an implementation issue, not a language issue.

The simple fact is that if it is important to you know what your
compiler does to your code, then compile your code with your compiler
and examine the generated object code or its assembly language
equivalent. That will give you exact answers, as opposed to
hypothetical indications of what a compiler might do.

Optimization with a specific compiler like gcc will vary greatly with
version, target architecture, and compiler options.

Neither optimization nor efficiency is defined by the C standard.
Only the observable output of a strictly conforming program. An
implementation that generated a Perl script from your source code and
invoked a Perl interpreter to execute the script could be a strictly
conforming C implementation if the observable output of the Perl
script was correct.
 
E

E. Robert Tisdale

Jack said:
The C standard does not define how compilers optimize certain code
sequences, nor does it require them to do so. It is entirely up to
the compiler and the options with which you invoke it.



would probably be a good reference to what "a good
optimizing compiler can optimize away", but that won't necessarily do
you any good at all. Note also that the issue is off-topic here, as
optimization is always an implementation issue, not a language issue.

The simple fact is that if it is important to you know what your
compiler does to your code, then compile your code with your compiler
and examine the generated object code or its assembly language
equivalent. That will give you exact answers, as opposed to
hypothetical indications of what a compiler might do.

Optimization with a specific compiler like gcc will vary greatly with
version, target architecture, and compiler options.

Neither optimization nor efficiency is defined by the C standard.
Only the observable output of a strictly conforming program. An
implementation that generated a Perl script from your source code and
invoked a Perl interpreter to execute the script could be a strictly
conforming C implementation if the observable output of the Perl
script was correct.

That is certainly all true but I don't think that's the issue here.
It isn't about any particular implementation
but implementations in general.

Too many C programmers write bad code
while attempting to out-wit their compilers
or appease deficient optimizing compilers.
The result is code that is unreliable,
hard to read, understand and maintain
and that frustrates optimizing C compilers
when C programmers attempt to port the code.

Perhaps it would have been better if Josh Curtz had asked,
"What optimizations do the ANSI/ISO standards allow?"

My personal approach is to write code assuming that
my C compiler or some C compiler for my target platform(s)
will [eventually] perform *all* of the optimizations
that the ANSI/ISO C standards allow.
That is to say that, "I avoid premature optimization."
 
T

Taran

I am not sure about gcc compiler. All that I say is regarding the diab
5.1.2 compiler.

Also compiler can do anything, what I say is based on my observation.

The dcc did not generate any code for foo except for blr. The main
doesn't have call to foo and it just returns. BUT I had maximum
optimization switch on. So this does make sense. If you set the
optimization switch to least or no optimization the results would be as
expected.

As of what I have seen, knowing the arguments to be passed doesn't say
anything. Its whether your processing something and returning it.

If I have say
/**/ void some(int temp)
/**/ {
/**/ int local=temp;
/**/ return local; /* or return temp*/
/**/ }

/**/ int main(void)
/**/ {
/**/ some(9);
/**/ }

The _some would be optimized as it doesn't makes sense there.
Parameters passed by value, do something but not return. The function
as such doesn't do anything. Remove it. And that's what the compiler
does.

But if I have
/**/ int some(int temp)
/**/ {
/**/ return temp*2;
/**/ }

The some would not be optimized and instructions will be there for it.
To force the compiler to not optimize the code use volatile.

For simple C instructions like implicit cast:
int ia;
int fa=25.27;
/*some code*/
ia=fa;
/*some more code*/

For same compiler options the compiler can either
A) addi rx,r0,25; where rx holds ia
B) or else have a set of instructions to cast fa to it.


For diab read the dcc user manual chapter on optimization.

I would again reiterate that what a compiler can do anything it deems
necessary to optimize the code and also it depends heavily on the
values of optimizations switches given when compiling.
HTH
Regards,
Taran
 
T

Taran

One more thing:

Passing pointers to functions, the compilers understands it differently
as against passing params by value and it doesn't optimize and remove
the function or some of its C source (all or some).

Declaring varaibles as volatile doesn't optimize the function. the
function call is still there and all the C level code translates to
identifiable assembly level instruction. But this particular to dcc.
Diab removed the call to the function.

Regards,
Taran
 
L

Lawrence Kirby

On Wed, 12 Jan 2005 22:10:34 -0800, E. Robert Tisdale wrote:

....
Perhaps it would have been better if Josh Curtz had asked,
"What optimizations do the ANSI/ISO standards allow?"

Th answer to that is anything at all as lon as the program produces
correct output. At that point it is a case of understanding what behaviour
the standard does and doesn't require for particular constructs.

Lawrence
 
C

Chris Croughton

On Wed, 12 Jan 2005 22:10:34 -0800, E. Robert Tisdale wrote:

...


Th answer to that is anything at all as lon as the program produces
correct output. At that point it is a case of understanding what behaviour
the standard does and doesn't require for particular constructs.

Including, if the compiler knows all the information it needs, producing
a program which doesn't do anything. This can be a problem if the
optimisation has bugs, on the first system I used professionally when I
looked at the assembler output to try to issue a patch (in those days it
was a lot cheaper to patch machine instructions than to send out a tape
with the complete binary) I found that the optimiser had deleted a whole
function because it thought that it wasn't used...

Chris C
 
J

joshc

Hey guys,

THanks for all your replies. Yes, I realized this was probably better
suited for comp.compilers and that's why minutes after I posted I tried
to use the "remove" option but I guess somehow my message was still
posted to the group. The reason I posted in this forum was casue I saw
a similar question on comp.lang.c from a few days ago and no one seemed
to complain.

I realize that the optimizations that I asked about have nothing to do
with the standard. I simply wanted to see whether or not any compilers
out there do what I was asking about more as a question to educate
myself about compilers. I definitely will end up looking at my compiler
manual.

Just in case anyone is interested, the reason I asked the question
initially was because when I was reading the GCC manual regarding the
inline keyword it said that if I had something like:

inline static int foo(int x) {
if (x > THRESHOLD)
return foo1(x);
else
return foo2(x);
}

then it said that GCC could optmize foo() if the argument 'x' was known
at compile time and you would end up with just a function call foo1()
or foo2() without the if-else conditional. It seemed to imply that
this happened because of using the 'inline' keyword so I was wondering
if I picked up on that correctly or if that kind of optimization also
happened in functions that are _not_ inlined.

THanks.
 
C

Chris Torek

... I realized this was probably better suited for comp.compilers
and that's why minutes after I posted I tried to use the "remove"
option but I guess somehow my message was still posted to the group.

(Newsgroup postings are generally not cancel-able at all anymore,
because vandals used to use the feature to remove everything from
some or all newsgroups.)
I realize that the optimizations that I asked about have nothing to do
with the standard. I simply wanted to see whether or not any compilers
out there do what I was asking about more as a question to educate
myself about compilers.

Many compilers do various kinds of optimizations. :)
... when I was reading the GCC manual regarding the inline keyword
it [noted aspects of optimizing inline-expanded functions]. ... It
seemed to imply that this happened because of using the 'inline'
keyword so I was wondering if I picked up on that correctly or if
that kind of optimization also happened in functions that are _not_
inlined.

In general, this kind of optimization can only happen if the
body of the function is expanded in line in the caller (because
the constraints on the operands are not known at compile time
in the other case). But gcc will sometimes do in-line expansion
of functions even when they are *not* declared "inline"; and as
it happens, Diab does even-more-aggressive function inlining than
gcc, in general.

Even in C90 (which has no "inline" keyword), you can "encourage"
a compiler to in-line-expand a short function by defining it before
calling it:

/* the "static" here is optional but generally good */
static int f(int x) {
return x + 1;
}
...
void g(args) {
...
result = f(1);
...
}

A practical C compiler *has* to read source code "top to bottom", as
it were, starting at the beginning of the source file and ending at
the end. Because of this, it will have "seen" all of f() by the time
it gets to compiling g(). If f() is small (as here), and the compiler
does this kind of optimization at all, there is a good chance it will
remove the call and, in this case, just do "result = 2".

Note that by making f() static, f() becomes invisible to other
translation units (roughly, "source files"), so not only can the
compiler expand calls to f() in line, it can also not bother
generating any actual function f() in the first place. This also
allows you to violate the usual rules about C code, and put the
entire function f() in a header file that gets included in multiple
translation units. (If the compiler does *not* do inline expansion
and optimizations, this will waste code space in the final executable,
but still *work* OK.)
 
J

joshc

Chris,

Thanks for your reply. Yeah, I know about the inlining details since I
investigated that a while back as I noticed the object code for the
inline function was emited even though I had my compiler options set to
force inlining. Obviously it turned out it had to be declared as inline
static and defined before it's use.
 
J

joshc

Chris,

Thanks for your reply. Yeah, I know about the inlining details since I
investigated that a while back as I noticed the object code for the
inline function was emited even though I had my compiler options set to
force inlining. Obviously it turned out it had to be declared as inline
static and defined before it's use.
 
J

joshc

Chris,

Thanks for your reply. Yeah, I know about the inlining details since I
investigated that a while back as I noticed the object code for the
inline function was emited even though I had my compiler options set to
force inlining. Obviously it turned out it had to be declared as inline
static and defined before it's use.
 
K

Keith Thompson

joshc said:
Chris,

Thanks for your reply. Yeah, I know about the inlining details since I
investigated that a while back as I noticed the object code for the
inline function was emited even though I had my compiler options set to
force inlining. Obviously it turned out it had to be declared as inline
static and defined before it's use.

Josh, you're obviously being bitten by the flawed groups.google.com
posting interface. I presume you didn't mean to post that same
article 3 times. We see a lot of Google users doing that kind of
thing; I'm not quite sure why. You also didn't provide any context or
attribution. Don't use the "Reply" link at the bottom of the article;
instead, click on "show options" and then on the "Reply" link just
under the article's headers.

For more information, search for my article in comp.lang.c, subject
"groups.google.com indentation bugs [semi-OT]" (that's one thing that
Google is still reasonably good at).

And you might want to complain to Google if you're so inclined.
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top