This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Inline function structure vs. address passing
- To: gcc at gcc dot gnu dot org
- Subject: Inline function structure vs. address passing
- From: Dennis Ferguson <dennis at juniper dot net>
- Date: Tue, 19 Sep 2000 18:42:30 -0700
Hello,
For hysterical reasons, I have the misfortune to have a need to
write code that does a fair bit of complex math in C (not C++).
I've been compiling a couple of examples of this with a year-old
gcc 2.95.1, so please excuse me if this is of historical interest
only.
The examples compute (a + b) * (a - b) where a and b are complex
values. With the basic math operations coded as inline functions
which pass and return structures I get to write code that looks like
main()
{
complex a, b, c;
a = cmplx(1.0, 2.0);
b = cmplx(3.0, 4.0);
c = cmul(cadd(a, b), csub(a, b));
printf("%f %f\n", creal(c), cimag(c));
}
which is my preference.
If I instead write inline functions which pass pointers to arguments
and results, the code ends up looking like
main()
{
complex a, b, c;
complex temp1, temp2;
cmplx(&a, 1.0, 2.0);
cmplx(&b, 3.0, 4.0);
cadd(&temp1, &a, &b);
csub(&temp2, &b, &a);
cmul(&c, &temp1, &temp2);
printf("%f %f\n", creal(&c), cimag(&c));
}
which is a whole lot uglier to write and look at (I also rewrote the
math operations for this one as macros, but in this case the compiler
did the computation and only generated code to print the results).
Here are the results I got in terms of instructions and the amount of
stack space the routine allocated:
Instructions Stack Allocation
Address passing 52 328
Structure passing 136 780
Almost all of the extra code in the second case consists of doing
truly useless copies of data from one spot on the stack to another.
There is no reason which is apparent to me why these two programs
wouldn't compile to approximately the same code. I'm curious about
why they don't. The two programs are included below.
Thanks,
Dennis Ferguson
============= Structure passing =====================
#include <stdio.h>
typedef struct {
double r;
double i;
} complex;
static inline complex
cmplx (double r, double i)
{
complex res;
res.r = r;
res.i = i;
return (res);
}
static inline complex
cadd (complex a, complex b)
{
complex res;
res.r = a.r + b.r;
res.i = a.i + b.i;
return (res);
}
static inline complex
csub (complex a, complex b)
{
complex res;
res.r = a.r - b.r;
res.i = a.i - b.i;
return (res);
}
static inline complex
cmul (complex a, complex b)
{
complex res;
res.r = a.r * b.r - a.i * b.i;
res.i = a.i * b.r + a.r * b.i;
return (res);
}
static inline double
creal (complex a)
{
return (a.r);
}
static inline double
cimag (complex a)
{
return (a.i);
}
main()
{
complex a, b, c;
a = cmplx(1.0, 2.0);
b = cmplx(3.0, 4.0);
c = cmul(cadd(a, b), csub(a, b));
printf("%f %f\n", creal(c), cimag(c));
}
============== Address passing ======================
#include <stdio.h>
typedef struct {
double r;
double i;
} complex;
static inline void
cmplx (complex *res, double r, double i)
{
res->r = r;
res->i = i;
}
static inline void
cadd (complex *res, complex *a, complex *b)
{
res->r = a->r + b->r;
res->i = a->i + b->i;
}
static inline void
csub (complex *res, complex *a, complex *b)
{
res->r = a->r - b->r;
res->i = a->i - b->i;
}
static inline void
cmul (complex *res, complex *a, complex *b)
{
res->r = a->r * b->r - a->i * b->i;
res->i = a->i * b->r + a->r * b->i;
}
static inline double
creal (complex *a)
{
return (a->r);
}
static inline double
cimag (complex *a)
{
return (a->i);
}
main()
{
complex a, b, c;
complex t1, t2;
cmplx(&a, 1.0, 2.0);
cmplx(&b, 3.0, 4.0);
cadd(&t1, &a, &b);
csub(&t2, &a, &b);
cmul(&c, &t1, &t2);
printf("%f %f\n", creal(&c), cimag(&c));
}