[comp.lang.c] I forget what it was originally called.

tada@athena.mit.edu (Michael Zehr) (03/06/88)

Back a week or so ago, there was a discussion about code like:

array1[i] = array2[i] = array3[i++];

and all the problems it's caused.  Well, I got nailed by that today (well,
yesterday actually, but i found out what was wrong today) using:

array[j] = array[j -=h];

Now, the interesting part is, I pulled the subroutine out of a personal
library of useful things, and it had been tested beforehand.  For some
strange reason, when it's an array of int, it works, but on other types
of arrays it doesn't work.  (I guess I shouldn't say work, but rather
"has the effect I want", because work implies that it's defined :-)

Anyway, this brought up a curious question: do compliers typically produce
code with different order of evaluation when compiling the same statements
but using different data types?  Can anyone point me to a good book that
outlines the different things optimizers try to do? 

Thanks in advance.


-------
michael j zehr
"My opinions are my own ... as is my spelling."

mike@hpfclq.HP.COM (Mike McNelly) (03/08/88)

Not only do different types cause changes in the order of evaluation,
but different classes may also cause differences.  C compilers make
choices on the order of evaluation based on the "cost" of evaluating a
subexpression.  Pcc compilers typically evaluate a a subexpression with
a high cost in register resources first.

As a specific example, you may find your expression compiled differently
if "i" is declared to be a register variable than if it was an auto or a
static.

Frankly I have little sympathy with anyone writing code in this manner.
It's cute but it's also no more efficient than alternatives that do what
you really wanted to do in a much less ambiguous fashion.  If you
inherited this code you have my condolences.



Mike McNelly
hplabs!hpfcla!mike

tada@athena.mit.edu (Michael Zehr) (03/11/88)

In article <3850010@hpfclq.HP.COM> mike@hpfclq.HP.COM (Mike McNelly) writes:
> [commenting on "array[i] = array[i++]" style code:]
> Frankly I have little sympathy with anyone writing code in this manner.
> It's cute but it's also no more efficient than alternatives that do what
> you really wanted to do in a much less ambiguous fashion.  If you
> inherited this code you have my condolences.
>
>Mike McNelly

(start minor flame) You're right.  I have no sympathy for myself
either, and I hope I never make that mistake again.  One of the
reasons why I read this newsgroup is because I'm a fledgling C
programmer.  (I've taken no courses using the language, and I've only
been programming for about 1/2 year.  Also, so far the programs I've
written are of a nature that I'm far more concerned about speed than
maintainability.)  Until I discover for myself what's most efficient,
and what works and what doesn't, I'm going to make mistakes.  But if I
ask a more experienced person for help, I'd rather be given advice
than be told I'm doing something wrong.  (end minor flame)

Which brings me to another question:  How good are compilers these
day?  Can they optimize just as well as a programmer (without
resorting to assembly, that is) or not?  For example:

A)

temp = {expression}
a[temp] = 1;
b[temp] = 2;
c[temp] = 3;

B)

a[temp={expression}]=1;
b[temp]=2;
c[temp]=3;


C)

a[{expression}]=1;
b[{expression}]=2;
c[{expression}]=3;


A) is very readable.  B) may or may not be slightly faster.  Does
anyone know whether B) is typically faster than A)?  Would it probably
generate the same code?  C) is slower since {expression} is evaluated
three times, *unless* the compiler knows to evaluate it once and put
it in a register.  Which may be about the same thing as what A) and B)
are doing, *except* in A) and B) it might will write the value into a
variable, which is slower than storing it in a register.  Of course,
there's always:

D)

{
register temp;
temp = {expression};
.
.
.
}

But I find this harder to read, and furthermore, since C compilers can
ignore register declarations anyway, it might put it in as a normal
variable (just like A) ), but it will slow down because it's allocated
each time through the block of code.

So -- other than not having any sympathy for me becuase I don't
already know the answer :-)  does anyone have any comments?



  
-------
michael j zehr
"My opinions are my own ... as is my spelling."

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (03/11/88)

> Which brings me to another question:  How good are compilers these
> day?  Can they optimize just as well as a programmer (without
> resorting to assembly, that is) or not?  For example:
		[common subexpress example deleted]

  All depends on the compiler.  ccp is generally a bad optimizing compiler.
Green Hill gcc and Tartan C compilers are suppose to produce lightening fast
executables.  If I could only get gcc to compile a copy of "man", I
might use it.
-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

mike@turing.UNM.EDU (Michael I. Bushnell) (03/11/88)

In article <3623@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes:
>Which brings me to another question:  How good are compilers these
>day?  Can they optimize just as well as a programmer (without
>resorting to assembly, that is) or not?  For example:

Actually, optimizing C and FORTRAN compilers nowadays do better than
programmers writing in assembly language.  There goes another old
misconception... 

>A)
>temp = {expression}
>a[temp] = 1;
>b[temp] = 2;
>c[temp] = 3;

>B)
>a[temp={expression}]=1;
>b[temp]=2;
>c[temp]=3;

>C)
>a[{expression}]=1;
>b[{expression}]=2;
>c[{expression}]=3;

>A) is very readable.  B) may or may not be slightly faster.  Does
>anyone know whether B) is typically faster than A)?  Would it probably
>generate the same code?  C) is slower since {expression} is evaluated
>three times, *unless* the compiler knows to evaluate it once and put
>it in a register.  Which may be about the same thing as what A) and B)
>are doing, *except* in A) and B) it might will write the value into a
>variable, which is slower than storing it in a register.  Of course,
>there's always:

Actaully, I find (B) to be more readable, but that isn't what you were
concerned about.  B is just as fast as A on any optimizing compiler.
C is also equal.  However, if the expression has a potential side
effect (like a function call), but you know there aren't any real side
effects, then C can't be optimized and will prove a little slower.
The Gnu C compiler will take (C) (assuming no potential side effects)
and calculate expression once, and store it in a register.  Pretty
neat, huh?

>D)
>{
>register temp;
>temp = {expression};
>.
>.
>.
>}
>But I find this harder to read, and furthermore, since C compilers can
>ignore register declarations anyway, it might put it in as a normal
>variable (just like A) ), but it will slow down because it's allocated
>each time through the block of code.

A compiler is allowed to ignore the decalaration, yes.  But if you
have a compiler that does, you are entitled to your money back.  It is
a little like the air IP link:  no packets transmitted, but, they did
say the protocol was nonreliable, right?
It is a little harder to read, and usually won't get you much.  If the
compiler ignores the register spec, however, you won't have any
problem with wasting time pushing and popping stack frames:  simple
peephole optimization will generate code equivalent to declaring it as
a variable specific to the function as a whole.  It is usually, I
think, a little slower to declare it static, but that is heavily
architecture dependent.


				Michael I. Bushnell
				mike@turing.unm.edu
				{ucbvax,gatech}!unmvax!turing!mike

				HASA -- "A" division

walter@hpcllz2.HP.COM (Walter Murray) (03/12/88)

> Which brings me to another question:  How good are compilers these
> day?  Can they optimize just as well as a programmer (without
> resorting to assembly, that is) or not?  For example:
> 
> A)
>    temp = {expression}
>    a[temp] = 1;
>    b[temp] = 2;
>    c[temp] = 3;
> B)
>    a[temp={expression}]=1;
>    b[temp]=2;
>    c[temp]=3;
> C)
>    a[{expression}]=1;
>    b[{expression}]=2;
>    c[{expression}]=3;
> D)
>    {
>    register temp;
>    temp = {expression};
>    .
>    .
>    .
>    }

I tried these on the HP C compiler on an HP 9000 Series 800
and (with optimization turned on) got the same code for all 
four approaches.

Walter Murray