This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler: Negative number comparison does not generate code

Other Parts Discussed in Thread: MSP430FR5969

Tool/software: TI C/C++ Compiler

Consider this short test code. The trouble is that that signed 32bit number comparison 

if(foo<tempmin){
return total;
}

does not produce any assembler code, it always skips to the return. Why?

#include <msp430.h>
#include <stdint.h>

#define SHORT int16_t
#define LONG int32_t
#define USHORT uint16_t

SHORT Temp_Integral(SHORT total, USHORT value, USHORT setpoint, USHORT max);

/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    Temp_Integral(0, 4096, 4100,32);
	return 0;
}

#pragma FUNC_CANNOT_INLINE(Temp_Integral)

SHORT Temp_Integral(SHORT total, USHORT value, USHORT setpoint, USHORT max){
    LONG volatile tempmin=-0x7FFE;
    LONG volatile foo;
    LONG volatile diff=0;
    /*
     * Negative roll-over-check
     */
    if(((LONG) value-setpoint)<tempmin){
        return total;
    }
    diff=(LONG) value-(LONG) setpoint;
    foo=total+diff;
    if(foo<tempmin){
        return total;
    }

    /*
     * Wind-up limit
     */
    if((total+diff)>max){
        return max;
    }
    return total+diff;
}

  • Please show the compiler version (not CCS), and the build options exactly as the compiler sees them.

    Thanks and regards,

    -George

  • Pfft, forgot the attachment..

    -vmspx --data_model=restricted --use_hw_mpy=F5 --include_path="C:/ti/ccsv7/ccs_base/msp430/include" --include_path="C:/Users/olli.mannisto/workspace_v7/testi" --include_path="C:/ti/ccsv7/tools/compiler/ti-cgt-msp430_17.9.0.STS/include" --advice:power=all --advice:hw_config=all --define=__MSP430FR5969__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40

    17.9.0.STS it says. 

    main.zip

  • In this snippet the if comparison is being trimmed because of integer literals. However I have sent you code for (trimmed) actual application which uses variables. It suffers from the same issue however.

    I tried changing the USHORT value parameter to the function to USHORT volatile value as the ADC sensor reading is in fact volatile. No effect. 

    On further testing I found out that bumping optimization to level 1 makes the comparison work while level 0 does not generate any code. This is very funky. Unfortunately the follow-up Wind-up limit comparison does not generate code either with level 1 comparison. A clearcut case of a bug, won't you agree? 

    Here's the latest version of the code where I've tried to eliminate any unwanted signed to unsigned conversions. If the 

            if(((LONG) value-setpoint)<tempmin){
                return total;
            }

    comparison is commented out (it's redundant) the follow-up 

        if(foo<tempmin){
            return total;
        }

    stops working. 

    /*
     * Calculate the temperature integral, max defines maximum positive value so we don't have
     * wind-up problems during warm-up
     */
    
    SHORT Temp_Integral(SHORT volatile total, SHORT volatile value, SHORT setpoint, SHORT max){
        LONG volatile tempmin=-0x7FFE;
        LONG volatile foo;
        LONG volatile diff=0;
        /*
         * Negative roll-over-check
         */
    /* if(((LONG) value-setpoint)<tempmin){ return total; }
    */ diff=(LONG) value- (LONG) setpoint; foo=(LONG) total+ (LONG) diff; if(foo<tempmin){ return total; } /* * Wind-up limit */ if(foo>(LONG) max){ return max; } return total+diff; }

    I also realized the 

    #pragma FUNC_CANNOT_INLINE(Temp_Integral)

    line needs to be before DECLARATION of the function so it had no effect as it was before the actual function. However it has no effect either way on the --opt_level 0 or 1. 

  • Setting optimization to 0 fixes the problem but the firmware is pretty unusable with that..

    After some digging I found out about #pragma FUNCTION_OPTIONS, however this line does apparently nothing:

    #pragma FUNCTION_OPTIONS(Temp_Integral, "--opt_level=off")
    

    That *did* however give me an idea, I split the Temp_Integral function into it's own file which let me disable optimizations for that function only. This way the code works without crippling the whole firmware. Kludge if I seen one. To enable a single "if" statement in the code.

  • You have conducted several experiments with changing the build options and the source.  I decided to investigate at this point ...

    Olli Mannisto said:
    In this snippet the if comparison is being trimmed because of integer literals. However I have sent you code for (trimmed) actual application which uses variables. It suffers from the same issue however.

    I received that code by private message.  Thank you.  I used the build options you sent in that message.  Among those options is setting optimization to level 0.  Then, in a later post, you state that using optimization level 0 avoids the problem.  So I changed the optimization level to 3.  

    I cannot run the code, but I looked at the assembly output carefully.  To do that, I add the option --src_interlist to the build, then inspect the resulting .asm file.  In this particular case, it is useful to inspect just the optimizer generated comments that you get with --src_interlist.  There are a few ways to do that. I did this ...

    % type file.asm | perl -ne "print if m/^;\*[\* ]/;" > cmts.txt

    This uses a Perl regular expression to capture just the optimizer generated comments in the file cmts.txt.  Inspecting that file I see this ...

    ;* 18223	-----------------------    if ( foo >= tempmin ) goto g4;
    ;* --------------------------------------------------------------------------*
    ;* --------------------------------------------------------------------------*
    ;* --------------------------------------------------------------------------*
    ;**	-----------------------g3:
    ;* 18224	-----------------------    return total;
    ;* --------------------------------------------------------------------------*
    ;**	-----------------------g4:
    

    And the assembly code under looks right.  Though I have to admit my knowledge of MSP430 assembly is less than expert.  But there is enough there to be very confident this comparison is carried out.  As comparisons go, it is straightforward.  It is very unlikely the compiler could pass its own tests and get this wrong.

    So, here is my guess.  The generated assembly is correct.  If you run through the function to completion, it does the right thing.  However, if you single step through it in CCS, it may appear things have gone wrong.  This kind of thing is to be expected when debugging optimized code.  Does this make sense?

    Thanks and regards,

    -George

  • It's been indeed a bit convoluted report. To summarize what I've found:
    Optimization=off => works as expected
    Optimization=0 => if comparison is optimized away but result seems indeed to work as expected
    Optimization=1 => Same as 0 but there is MORE code being apparently executed
    Optimization=3 => Same behavior as 1

    I would expect the 0 level optimizations not go around dropping code outright. Also it seems #pragma FUNCTION_OPTIONS(Temp_Integral, "--opt_level=off") has no effect, which is why I split the integral function to it's own source file. For a good measure I included #pragma FUNC_CANNOT_INLINE (Temp_Integral) as well, but that also didn't change anything.

    Why cannot you run the code? It should execute fine with MSP430FR5969 evaluation board?

    I could give you the latest code so we're not comparing different things. I have fixed some bugs meanwhile but they shouldn't really have a bearing here.

    I have had similar problems before with my firmware heartbeat led blink routines on higher optimization levels, which is why the optimization level for "Release" is 2, not 3. In that case you can definitely verify code is being skipped.

  • Regarding things you say like the "if comparison is optimized away", or "dropping code outright", or "code is being skipped", please give a detailed description of what you do to see that.  

    Thanks and regards,

    -George

  • Well, all of that means that what you see in source code is not what you get. In 0 level optimizations the line by line debugging jumps over the comparisons and you cannot set breakpoint to them. I don't think this should happen with "register optimizations"?

    With regards to code being outright skipped on optimization 3, it means just what it says on the tin. My heartbeat LED would not blink at level 3 at all because the code was simply not executed. No inlining pragma restored the function in this case. 

  • Olli Mannisto said:
    In 0 level optimizations the line by line debugging jumps over the comparisons and you cannot set breakpoint to them.

    For --opt_level=0, this is unusual, but not a total surprise.

    Olli Mannisto said:
    My heartbeat LED would not blink at level 3 at all because the code was simply not executed.

    I'd like to take a closer look at that.  I may already have the code.  But keep in mind I handle multiple issues every day.  So, please show me a bit of patience, and tell me which file(s) I need to build with which options to see this problem.  I also need guidance on what function in the code to inspect.  

    As for running code ... You probably are not aware that I support all of TI's compilers.  It is simply impractical for me to even have all the hardware I need to run every test case.  And that ignores the fact that most code presumes the rest of the system hardware is present, supplying their input, receiving the output, etc.  On rare occasions, I do run customer code.  But that is far from typical.  The default presumption is that I will have to work out the problem without running anything.

    Thanks and regards,

    -George

  • Sounds like you need some assistants/teammates. Perhaps TI makes some recruiting in the spirit of Xmas.

    The source I sent you is actually trimmed of external inputs and should run adequately as is. I'll check that LED glitch when I have a bit of spare time, right now I'm working on fine tuning the temperature control bit. The code is relatively extensive so it wouldn't surprise me if the problem has gone away in the meantime. Firmware certainly doesn't work properly on OPT=3 but it can take a bit to drill down where it fails specifically. The code is now sitting at 25kB mark, I don't know if that's "large" by embedded standards but it's a fair amount of functionality with simple cooperative multitasking et cetera.