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/MSP430FR5739: Bug in TI MSP430 Optimizing Compiler v18.1.3.LTS

Part Number: MSP430FR5739


Tool/software: TI C/C++ Compiler

/* TI MSP430 compiler bug discovered by Greg Fundyler on August 15, 2018.
 *
 * Tested primarily with -O2 --opt-for-speed=5
 * Speed vs size setting appears not to matter.
 * Bug manifests with -O2 and higher.
 *
 * Each for-loop executes only once, but this structure is required to
 * demonstrate the bug.
 *
 * Tested with ti-cgt-msp430_16.9.1.LTS and ti-cgt-msp430_18.1.3.LTS
 *
 * Compiler invocation:
 * "C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/bin/cl430" -vmspx -O2 --opt_for_speed=5 --include_path="C:/apps/ti/ccsv7/ccs_base/msp430/include" --include_path="C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/include" --advice:power="all" --define=__MSP430FR5739__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 -k --asm_listing --cross_reference --output_all_syms --gen_acp_raw --preproc_with_compile --preproc_dependency="main.d"  "../main.c"
 *
 * Linker invocation:
 * "C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/bin/cl430" -vmspx -O2 --opt_for_speed=5 --advice:power="all" --define=__MSP430FR5739__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 -k --asm_listing --cross_reference --output_all_syms --gen_acp_raw -z -m"bug.map" --heap_size=160 --stack_size=160 --cinit_hold_wdt=on -i"C:/apps/ti/ccsv7/ccs_base/msp430/include" -i"C:/apps/ti/ccsv7/ccs_base/msp430/lib/5xx_6xx_FRxx" -i"C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/lib" -i"C:/apps/ti/ccsv7/tools/compiler/ti-cgt-msp430_18.1.3.LTS/include" --reread_libs --define=_MPU_ENABLE --diag_wrap=off --display_error_number --warn_sections --xml_link_info="linkInfo.xml" --rom_model -o "bug.out" "./main.obj" "C:/apps/ti/ccsv7/ccs_base/msp430/include/lnk_msp430fr5739.cmd"  -llibmath.a -llibc.a
 */

#include <msp430fr5739.h>
#include <stdint.h>

uint32_t y;
int32_t signed_y;
int16_t z;
int32_t big_z;

volatile int32_t outa, outb, outc, outd;    // optimized out if missing 'volatile' at -O3 and higher
// volatile int16_t outa, outb, outc, outd;    // changes behavior slightly

static inline int16_t foo(int32_t x) {
    return x >> 16;
}

void test1(void) {
    for(y = 33345; y < 34000; y += 1000) {
        signed_y = (int16_t)y;

        outa = (5368UL * (uint16_t)y) >> 16;
        outb = foo(signed_y);                       // outb =  0 (incorrect: should be -1)
        outc = signed_y >> 16;                      // outc = -1 (correct)
    }
}

void test2(void) {
    for(y = 33345; y < 34000; y += 1000) {
        signed_y = (int16_t)y;

        outa = (5368UL * y) >> 16;
        outb = foo(signed_y);                       // outb =  0 (incorrect: should be -1)
        outc = signed_y >> 16;                      // outc =  0 (incorrect: should be -1)
    }
}

void test3(void) {
    for(y = 33345; y < 34000; y += 1000) {
        signed_y = (int16_t)y;

        outb = foo(signed_y);                       // outb =  0 (incorrect: should be -1)
        outc = signed_y >> 16;                      // outc =  0 (incorrect: should be -1)
    }
}

void test4(void) {
    for(y = 33345; y < 34000; y += 1000) {
        signed_y = (int16_t)y;

        outb = foo(signed_y);                       // outb = -1 (correct)
        outc = signed_y >> 16;                      // outc = 65535 (incorrect: should be -1)
        outd = signed_y >> 17;                      // outd = -1 (correct)
    }
}

void test5(void) {
    for(y = 33345; y < 34000; y += 1000) {
        signed_y = (int16_t)y;

        outc = signed_y >> 16;                      // outc = -1 (correct)
        outb = foo(signed_y);                       // outb = -1 (correct)
    }
}

void test6(void) {
    for(z = -20000; z < -19500; z += 1000) {
        big_z = z;

        outb = foo(big_z);                          // outb = -1 (correct)
        outc = big_z >> 16;                         // outc = 65535 @ -O2 optimization, -1 @ all other optimizations
    }
}

void test7(void) {
    for(z = -20000; z < -19500; z += 1000) {
        big_z = z;

        outc = big_z >> 16;                         // outc = -1 (correct)
        outb = foo(big_z);                          // outb = -1 (correct)
    }
}

void main(void) {
    WDTCTL = WDTPW + WDTHOLD;   // stop WDT

    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();

    while(1) {}
}