function call optimization question

S

Szabolcs Nagy

in the code below i thought the function call in g() could be easily
optimized out so that g() becomes the same as h() (which becomes
{return 0;})

executing 'gcc -O3 -S' i found that gcc does not do this

now i'm wondering: is there something in the standard (eg c99) that
prevents this optimization (theoretically)


#include <stdio.h>
#include <stdlib.h>

static inline int c(int a, int b) {
return a == b;
}

static int f(int a, int b, int(*c)(int, int)) {
return c(a, b) - c(b, a);
}

int g(int a, int b) {
return f(a, b, c);
}

int h(int a, int b) {
return c(a, b) - c(b, a);
}


int main(int argc, char *argv[]) {
int a, b;

if (argc < 3)
return printf("usage: %s a b\n", argv[0]);
a = atoi(argv[1]);
b = atoi(argv[2]);
printf("f: %d\n", f(a, b, c));
printf("g: %d\n", g(a, b));
printf("h: %d\n", h(a, b));
return 0;
}
 
A

Army1987

in the code below i thought the function call in g() could be easily
optimized out so that g() becomes the same as h() (which becomes
{return 0;})

executing 'gcc -O3 -S' i found that gcc does not do this

now i'm wondering: is there something in the standard (eg c99) that
prevents this optimization (theoretically)

The standard only requires that files and volatile objects are
written/read in the right order. But I won't expect a program to
compute the 100008th prime number to generate the same machine
code as
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
return (fwrite("1299827\n", 1, 8, stdout) < 8) * EXIT_FAILURE;
}

IOW, while you shouldn't do micro-optimizations yourself, you
shouldn't write silly code hoping that the compiler will make it
decent.
 
M

Michal Nazarewicz

Szabolcs Nagy said:
in the code below i thought the function call in g() could be easily
optimized out so that g() becomes the same as h() (which becomes
{return 0;})

executing 'gcc -O3 -S' i found that gcc does not do this

Well... You can go complain to GCC developers if you like. ;)
now i'm wondering: is there something in the standard (eg c99) that
prevents this optimization (theoretically)

No. Standard doesn't prevents optimisation.
 
S

Szabolcs Nagy

Michal said:
No. Standard doesn't prevents optimisation.

thanks for your answers

actually what i was thinking about is the situations like sorting int
arrays

static inline int intcmp(int *a, int *b) {
return *a < *b ? -1: *a > *b;
}

void intqsort(int *arr, size_t n) {
qsort(arr, n, sizeof(int), intcmp);
}

imho this is not a silly thing to optimize out, since many algorithms
can be done in a (type) generic way with a couple of function
arguments and most of these algorithms are performance critical (eg
when we cannot allow an additional function call for each int
comparison)

other possible examples:
int find_if(int *arr, size_t n, int (*pred)(int));
int hash_get(const hashtable_t *ht, const key_t *key, int (*hash)
(key_t *), int (*isempty)(item_t *), int (*isdeleted)(item_t *));
....
 
R

Richard Tobin

Szabolcs Nagy said:
actually what i was thinking about is the situations like sorting int
arrays

static inline int intcmp(int *a, int *b) {
return *a < *b ? -1: *a > *b;
}

void intqsort(int *arr, size_t n) {
qsort(arr, n, sizeof(int), intcmp);

This is unlikely to be useful, because

(a) intcmp is an argument to qsort(), and will be different for different
calls;
(b) even if it wasn't an argument, to inline the calls to intcmp()
its source would have to be available when qsort was compiled,
and typically qsort() is in a pre-compiled library.

One possibility would be for qsort itself to be inline, with its definition
in the header.

If you really need this efficiency, you could take one of the many free
implementations of qsort() and produce a specialised version yourself.

-- Richard
 
S

Szabolcs Nagy

Richard said:
This is unlikely to be useful, because

(a) intcmp is an argument to qsort(), and will be different for different
calls;
(b) even if it wasn't an argument, to inline the calls to intcmp()
its source would have to be available when qsort was compiled,
and typically qsort() is in a pre-compiled library.
true
you are right

well i'm writing an algorithm lib for my own amusement and i thought
it would make things easy if i could write

static void sort_internal(int *arr, size_t len, int (*less)(int, int))
{..}
static inline intless(int a, int b) {return a < b;}

void sort_f(int *arr, int len, int (*less)(int, int)) {
return sort_internal(arr, len, less);
}

void sort(int *arr, int len) {
return sort_internal(arr, len, intless);
}

so i don't need to write down the algorithm 2 times for sort() and
sort_f().
also type generic code can be written in this way so i can make my own
c++ stl like thing.
 
M

Malcolm McLean

Army1987 said:
On Wed, 12 Sep 2007 03:01:26 -0700, Szabolcs Nagy wrote:

The standard only requires that files and volatile objects are
written/read in the right order. But I won't expect a program to
compute the 100008th prime number to generate the same machine
code as
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
return (fwrite("1299827\n", 1, 8, stdout) < 8) * EXIT_FAILURE;
}
I'd expect a Fortran 77 compiler to do this.
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top