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/TMS320F28377S: Code is incorrectly optimized to return zero always for O >= O2

Part Number: TMS320F28377S

Tool/software: TI C/C++ Compiler

When using optimizer levels 2 and above (O2, O3, O4) then the code for the strnlen_wtf() shown below gets incorrectly optimized to always return zero. For the similar but slightly different strnlen_ok() function this does not happen. Why?

Version info:

  • Compiler  v18.12.5LTS (and v18.12.4LTS)
  • CCS: 9.3
  • OS: Windows 10 1909 64bit

Here is the code.c example (fully self contained, no includes required):

typedef unsigned long size_t;  // taken from stdlib.h to avoid code bloat in example

// this gets optimized away for O2, O3, O4. (OK for O0, O1):
size_t strnlen_wtf( const char *s, size_t maxlen )
{
    size_t n = (size_t)-1;

    do n++; while ( (*s++)  &&  (n < maxlen) );
    return n;
}


// this works:
size_t strnlen_ok( char const* s, size_t maxlen )
{
    size_t n = 0;

    do
    {
    } while ( (*(s++)) && ++n < maxlen );

    return n;
}

When checking the object code with dis2000 we get:

/*
 Compiled with O2 or O3 or O4: strnlen_wtf() gets incorrectly optimized to always return 0
 "C:\\ti\\ccs930\\ccs\\tools\\compiler\\ti-cgt-c2000_18.12.5.LTS\\bin\\cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -O2 --opt_for_speed=0 --include_path=W:/compiler_error_optimized_away --include_path=C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c2000_18.12.5.LTS/include -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=coffabi "..\\code.c"
 "C:\\ti\\ccs930\\ccs\\tools\\compiler\\ti-cgt-c2000_18.12.5.LTS\\bin\\cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -O3 --opt_for_speed=0 --include_path=W:/compiler_error_optimized_away --include_path=C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c2000_18.12.5.LTS/include -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=coffabi "..\\code.c"
 "C:\\ti\\ccs930\\ccs\\tools\\compiler\\ti-cgt-c2000_18.12.5.LTS\\bin\\cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -O4 --opt_for_speed=0 --include_path=W:/compiler_error_optimized_away --include_path=C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c2000_18.12.5.LTS/include -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=coffabi "..\\code.c"

Disassembly of code.obj:

TEXT Section .text (Little Endian), 0x14 words at 0x00000000
00000000        _strnlen_wtf:
00000000   0200   MOVB         ACC, #0
00000001   0006   LRETR

00000002        _strnlen_ok:
00000002   ff58   TEST         ACC
00000003   6003   SB           3, NEQ
00000004   d501   MOVB         XAR5, #0x1
00000005   6f02   SB           2, UNC
00000006        $C$L1:
00000006   83a9   MOVL         XAR5, ACC
00000007        $C$L2:
00000007   dd81   SUBB         XAR5, #1
00000008   be00   MOVB         XAR6, #0x00
00000009        $C$L3:
00000009   92c4   MOV          AL, *+XAR4[0]
0000000a   6108   SB           8, EQ
0000000b   0200   MOVB         ACC, #0
0000000c   dd81   SUBB         XAR5, #1
0000000d   dc01   ADDB         XAR4, #1
0000000e   de01   ADDB         XAR6, #1
0000000f   1901   SUBB         ACC, #1
00000010   0fa5   CMPL         ACC, XAR5
00000011   60f8   SB           -8, NEQ
00000012        $C$L4:
00000012   06a6   MOVL         ACC, XAR6
00000013   0006   LRETR
*/


/*
 Compiled with O1 (OK):
 ""C:\\ti\\ccs930\\ccs\\tools\\compiler\\ti-cgt-c2000_18.12.5.LTS\\bin\\cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -O1 --opt_for_speed=0 --include_path=W:/compiler_error_optimized_away --include_path=C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c2000_18.12.5.LTS/include -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=coffabi "..\\code.c"

Disassembly of code.obj:

TEXT Section .text (Little Endian), 0x16 words at 0x00000000
00000000        _strnlen_wtf:
00000000   1ea7   MOVL         XAR7, ACC
00000001   0200   MOVB         ACC, #0
00000002   1901   SUBB         ACC, #1
00000003   1ea6   MOVL         XAR6, ACC
00000004        $C$L1:
00000004   9284   MOV          AL, *XAR4++
00000005   de01   ADDB         XAR6, #1
00000006   6104   SB           4, EQ
00000007   06a7   MOVL         ACC, XAR7
00000008   0fa6   CMPL         ACC, XAR6
00000009   66fb   SB           -5, HI
0000000a        $C$L2:
0000000a   06a6   MOVL         ACC, XAR6
0000000b   0006   LRETR

0000000c        _strnlen_ok:
0000000c   d500   MOVB         XAR5, #0x0
0000000d   1ea6   MOVL         XAR6, ACC
0000000e        $C$L3:
0000000e   9284   MOV          AL, *XAR4++
0000000f   6105   SB           5, EQ
00000010   dd01   ADDB         XAR5, #1
00000011   06a6   MOVL         ACC, XAR6
00000012   0fa5   CMPL         ACC, XAR5
00000013   66fb   SB           -5, HI
00000014        $C$L4:
00000014   a0a9   MOVL         ACC, XAR5
00000015   0006   LRETR

 */
/*
 Compiled with O0 (OK):
 "C:\\ti\\ccs930\\ccs\\tools\\compiler\\ti-cgt-c2000_18.12.5.LTS\\bin\\cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -O0 --opt_for_speed=0 --include_path=W:/compiler_error_optimized_away --include_path=C:/ti/ccs930/ccs/tools/compiler/ti-cgt-c2000_18.12.5.LTS/include -g --diag_warning=225 --diag_wrap=off --display_error_number --abi=coffabi "..\\code.c"

Disassembly of code.obj:

TEXT Section .text (Little Endian), 0x16 words at 0x00000000
00000000        _strnlen_wtf:
00000000   1ea7   MOVL         XAR7, ACC
00000001   0200   MOVB         ACC, #0
00000002   1901   SUBB         ACC, #1
00000003   1ea6   MOVL         XAR6, ACC
00000004        $C$L1:
00000004   de01   ADDB         XAR6, #1
00000005   9284   MOV          AL, *XAR4++
00000006   6104   SB           4, EQ
00000007   06a7   MOVL         ACC, XAR7
00000008   0fa6   CMPL         ACC, XAR6
00000009   66fb   SB           -5, HI
0000000a        $C$L2:
0000000a   06a6   MOVL         ACC, XAR6
0000000b   0006   LRETR

0000000c        _strnlen_ok:
0000000c   1ea6   MOVL         XAR6, ACC
0000000d   d500   MOVB         XAR5, #0x0
0000000e        $C$L3:
0000000e   9284   MOV          AL, *XAR4++
0000000f   6105   SB           5, EQ
00000010   dd01   ADDB         XAR5, #1
00000011   06a6   MOVL         ACC, XAR6
00000012   0fa5   CMPL         ACC, XAR5
00000013   66fb   SB           -5, HI
00000014        $C$L4:
00000014   a0a9   MOVL         ACC, XAR5
00000015   0006   LRETR
*/

  • Thank you for reporting this problem, and providing a concise test case.  I can reproduce the same result.  I filed the entry EXT_EP-9681 to have this problem investigated.  You are welcome to follow it using the link below in my signature.

    Thanks and regards,

    -George

  • A possible interpretation, which hinges on a detail of sequence points that I haven't double-checked:

      size_t n = (size_t)-1;

      do n++; while ( (*s++)  &&  (n < maxlen) );

    n is initially 0xffffffff, because size_t is an unsigned type.  If the "++" part of "n++" doesn't happen till after the while-test, then "n < maxlen" will be false, terminating the loop.  (And then the "++" happens, making n 0 for the return.)

    Have you tried "++n"?

  • I've been informed that there is actually a sequence point after the "n++" in the do-while loop.  Thus my explanation might cover what the compiler is doing, but that's not what it's *supposed* to do, and we're treating it as a compiler bug.

  • Thank you for looking into this.

    I just tried your suggestion using "++n" instead of "n++" in the loop. Same result: the function gets 'optimized' to always return zero.