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 optimization bug?



I have a project that runs on a custom board that uses the Tiva TM4C129XNCADZ part. I have found what appears to be an optimization bug. If I set the optimization level to 1 (Local Optimizations) the issue appears. If I set the level to Off, the issue does not appear. I am using CCS 6.2.0.00050 with compiler version 15.12.3.LTS. (The issue also appeared on CCS version 6.1.1 with compiler 5.2.6). I have also reproduced this issue on the DK-TM4C129X.

The issue is that a variable that is passed to a function is corrupted by a call within the function before the passed variable is used. I have reduced my application to a minimal size that shows the bug. The project is attached and there are notes within the code as to where the problem is.

To see the issue:

  1. Grab a DK-TM4C129X.
  2. Create a workspace and load the attached project.
  3. Make sure TIVAWare 2.1.1.71 is installed (you may need to change the path within the project depending on where TivaWare is installed.
  4. Debug the project and run to the break point indicated in main and follow the comments.

Thanks,

Jeff

TPI-IIOptBug.zip

  • There is no error in the compiler generated code.  There are a few cycles where, in the debugger, it appears the argument to the function USB::Init is corrupted.  But that is not the case.

    The following is a few lines of compiler generated assembly for the source file TPIUSBInterface.cpp.  I added the option --src_interlist.  This causes the compiler to not delete the assembly output, and to interlist it with comments which make it easier to understand.  Then I ran the assembly file through the C++ name demangler utility armdem.  This de-mangles the function names, so they appear as they do in the C++ source.  Read more about armdem in the ARM compiler manual.  These lines show the call to the function TCPLogWrite, and a few instructions before and after that call.

            MOV       V2, A2                ; [DPU_3_PIPE] |23| 
            ADR       A1, $C$SL1            ; [DPU_3_PIPE] |27| 
            BL        TCPLogWrite(const char *, ...)   ; [DPU_3_PIPE] |27| 
            MOVS      A3, #0                ; [DPU_3_PIPE] |29| 
            MOV       A1, V1                ; [DPU_3_PIPE] |23| 
            MOV       A2, V2                ; [DPU_3_PIPE] |23|

    The argument to the function is named USBHIDMode, and it is passed to the function in the register A2.  On line 1, A2 is copied to the register V2.  On line 3, the function TCPLogWrite is called.  This causes A2 to be overwritten with a totally different value.  If you use CCS to watch the value USBHIDMode, this is the point where it seems that the argument is corrupted.  But it isn't.  On line 6, the register V2 is copied back to A2, thus restoring USBHIDMode.  This occurs before any reads of A2.

    This is the kind of thing which can occur when you debug optimized code.  This experience becomes more common with even higher levels optimization.  Please see this wiki article for more discussion of the trade-off between debug and optimization.

    Thanks and regards,

    -George

  • George,

    thanks for your detailed explanation. I am happy and relieved that you proved me wrong. After convincing myself that you were correct, I found my error elsewhere.

    Thanks,

    Jeff