Compiling with /O2 (Max-Speed) - a needed routine was eliminated ..


  • Hi,
    I;m using Visual C++2008 and trying to compile my code with /O2 optimization flag for max speed.
    I've noticed that at least one routine, which is reachible isn't called by my new application. When the same code is compiled without optimization the routine is called.
    This routine change a parameter which is used by other routines. I tried to add a print in it but the result was the same (the routine was taken out of my optimized code).
    Compiling the same code with Max Speed optimization in eMbedded Visual C++ 4.0 works fine.

    How can I know why it happened? How can I avoid that? and last - how can I find out if there are othere routines that maybe were removed by the compiler after add the optimization flag?

    Thanks in advance
    Tuesday, July 21, 2009 1:29 PM

All replies

  • seems like there is some information missing, but I suspect that you have not looked at the disassembly.

    So, I'm going to guess that your function was optimized out by being replaced with an inline version...that apparently does not work as expected. You can turn off inline expansion of functions directly with the /Ob0 or /Ob1 compiler switch.
    Tuesday, July 21, 2009 2:29 PM
  • you're right - I haven't look at the disassembly ..
    I'll check out the inline configuration later (not at my desk right now) but I wonder how come I didn't even see the prints I added to my routine? can it be that different?
    Tuesday, July 21, 2009 2:50 PM
  • ...not that the disassembly will make a whole lot of sense, but you would be able to spot inline code in there pretty quickly when comparing it to the version that makes a function call.

    When you say the you mean some form of debug output that prints (printf, sprintf, etc) into strings? Are they at least printed to the screen? (Is this a console app?)

    You can also use pragma to turn optimization on and off, which helps.

    The only times I have used optimization (By compiler switch, that is.), it was an iterative process. In other words, I found places where I apparently was not clear enough in my intent that the compiler could write it better. [or at all sometimes!]

    I think that perhaps your prints are local to a function, and the compiler sees no use for them, because their output never leaves the routine, nor is it used in a way that the compiler can make sense of, so it optimizes them away because they are inefficient in its 'mind'.

    As an example, I am debugging an ASP.NET project, and I am not currently connected to the logging facility, so in my catch blocks, I put a 'dummy line' [ VB : dim i as integer = 0], and put a break point on it. There are other ways to set a break point at this type of place, but that requires only the line and the break, it is easy enough to put all over. (So the code runs normally, but when an exception fires, I can look at the message before ASP loses its mind and take the IDE with it.)
    Tuesday, July 21, 2009 3:14 PM
  • While there's always the possibility of a bug in the optimizer, are you sure your routine is doing what you think it's doing? If the optimizer removed the routine, it's probably because the code isn't doing anything significant. Or perhaps the return value is never used, etc. Try to narrow down the issue to a small reproducible example. Either you'll find the bug, or open a bug report on connect (or take a look there first and see if you find a similar issue).
    Don Caton - Shoreline Software
    NewsHound - Offline Reader for Newsgroups and Microsoft Forums
    Tuesday, July 21, 2009 4:13 PM
  • OK .. after compiling the code with /Ob1 the routine was called but as you suspected - it doesn't do nothing - the reason for that in I call to a another routine there that should add 2 numbers (I save the time in a specific format and add a few MS to it - the routine just add it and need to fix wraparound) - and this TimeAdd routine does nothing at all! ( the time stays the same).

    I print the data sent to this TimeAdd routine and it's all good. The only issue is that I send the time in double (0.512 for 512ms) - when I call another routine that does the TimeAdd in ms and gets U32 instead of double - it works fine.

    The TimeAdd double routine works fine, of-course, with no optimization.

    I have the asm code of the AddTime routine - with and without the optimization - I don't understand from it what is the problem - will it help if I'll send it over?

    Thanks a lot!


    I found the line that is taken out.
    The code is below - the problematic line is bolded - somehow the compiler ignores it in case any kind of optimization is enabled.
    I found several ways to make it works but I would like to understand the root of the problem in order to make sure I don't have it elsewhere in the code.

    The ways to make it works are (each one works seperately):
    1. define the local variables as volatile
    2. If I define deltaFrac as DOUBLE and do the cast to U32 only when adding it to secondFrac .
    3. If I just print deltaFrac.

    I tried many other ways such as changing the casting, adding () etc .. and nothing works.

    Please advise .. why the compiler ignores the line bolded below ..


    btw - when aDeltaTime is 2.5 - the routine just add the 2 but ignores the 0.5 ..




    MAX_FRAC_SEC 1000000000

    void TimeAdd(CTime *pTime, DOUBLE aDeltaTime)





    U32 deltaFrac = 0;


    U32 deltaSec = 0;

    (aDeltaTime >= 0){

    deltaFrac = (U32)(((aDeltaTime - (U32)aDeltaTime) * MAX_FRAC_SEC));

    pTime->second += aDeltaTime;

    pTime->secondFrac += deltaFrac;

    while (pTime->secondFrac >= MAX_FRAC_SEC) {


    pTime->secondFrac -= MAX_FRAC_SEC;



    while (pTime->second >= SECONDS_IN_WEEK) {


    pTime->second -= SECONDS_IN_WEEK;



    imeAdd(CTime *pTime, DOUBLE aDeltaTime) U32 deltaFrac = 0;


    U32 deltaSec = 0;
    • Edited by mnilsm Wednesday, July 22, 2009 12:43 PM
    Wednesday, July 22, 2009 6:27 AM