This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Inline function structure vs. address passing


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));
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]