views:

256

answers:

4

Hi,

I work in project in which I have the following code:

file1.c

extern const int z;
int x;
do_some_stuff_to_calculate_x();
y = x / z;
do_some_stuff_with_y();

file2.c

const int z = Z_INIT_VALUE; // some value defined in some .h file.

The point of interest is the division in file1.c . Since z is extern, so it is not known in compile time [it will be defined in linking time]. So, the compiler can't optimize the division.

I know that if value of z is known at compile time the compiler will convert the division to multiplication and some other manipulations.

Note that file1.c will be delivered as a library, so re-compiling file1.c with file2.c is not an option.

Do any one know away to make the linker optimize such things? Or any other trick to avoid this EXPENSIVE division?

Thx :)

Update:

Well, after I saw some answers I noticed that some more details are required to make this question more informative.

  • I use a microcontroller from company called renesas (Family SH725).
  • This division is found in MANY places in the code, with many variants.
  • Most of the other stuff in the code is directly reading and writing to registers and ports (no overhead, i.e: *0x0ABCDEFF = 15).

The functions which include division are normally looks like this.

extern const int common_divisor;
extern const int common_addition;

void handleTheDamnInterrupt(void)
{
    int x = *(REG_FOO_1);
    int y = x / common_divisor;
    y += common_addition;
    if( x > some_value )
    {
       y += blah_blah;
    }
    else
    {
       y += foo_bar;
    }

    *(REG_BAR_1) = y;
}

This function is the typical function form in all the program. Can't know exactly how much division is affecting the program because I have many of these functions with different periodicity.
But when I tried to remove the extern from the const and gave it arbitrary value, it was better.

+2  A: 

The Microsoft linker, for one, will optimize this. It's called "link-time code generation". Here's an article about it (dated, but still useful). It's turned on with the /LTCG flag.

Thomas
although I am not using microsoft compilers, but it is good to know about this LTCG. :)
Yousf
I believe GCC can do link-time optimization as well, if you're using that.
Chris Lutz
+3  A: 

This is microoptimization if I ever saw it. You should profile, and probably edit your question with some results indicating why it's so important to optimize this single integer operation.

If z really is constant and initialized from a preprocessor symbol, just put that symbol in the library's header, and stop introducing it as a run-time variable at all.

unwind
`z` is really const, but it will be defined in linking stage. I will compile file1.c to get file1.o and send it to other team.This other team shouldn't see file1.c. This team also will but some value in this header file and compile his files then link every thing to get executable.
Yousf
This is a micro optimization UNLESS you are working on some very slow embedded platform where divisions are not optimized in the processor(as they are in most desktop processors)
Earlz
A: 

Your calls to do_some_stuff will far outweigh the integer division.

Mike Dunlavey
no :)Actually do_some_stuff_to_calculate_x() will read some values from some registers in the microcontroller and do_some_stuff_with_y() will write the value in another register..both operations are very trivial..
Yousf
@Yousf: Let me put it another way. That division should take maybe 10-50 nanoseconds, or maybe a microsecond at most if the CPU is slow. Are you executing it more than 100,000 times a second? If not, you probably have bigger "fish to fry".
Mike Dunlavey
@Mike: Depends on what you're working on. This could well be significant on a low-end embedded processor, which some company might be doing to save a few bucks on the mass production of something. Yousf mentioned "microcontroller" in his comment, after all.
David Thornley
@David: You're right. The slowness of the processor is not stated here, so maybe I didn't make it clear is that what matters is the overall percent of time spent in that division. In general, I don't recommend fixing something until it's known that it's the most time-consuming problem that one *can* fix. Usually, if there's a problem at all, it's not what one detects by eyeballing the code.
Mike Dunlavey
+3  A: 

You can do the same optimization yourself, performing some setup calculation at initialization time. The algorithm invented by Terje Mathisen to convert integer division to a multiply is described here: http://www.asdf.org/~fatphil/x86/pentopt/27.html

Ants Aasma
++ That is *nifty*.
Mike Dunlavey