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.

instruction reordering alters logic

Under rare circumstances, the compiler seems to reorder the instructions in a way that alters the logic. I suspect that this is related to inline functions returning a struct. In the example below, the global variable "DebugC" should be equal to 0x89abcdef, but instead gets the random value that was stored in a RAM address. That is because the variable "Cnr" got set before the field "parameters.C" was calculated. Please let me know how to avoid that issue.

Steps Needed to Recreate Problem: 

//1. Save this file to tiBug.c 
//2. With cgt 6.1.20, execute "cl6x.exe -g -o3 -mv6400+ -k tiBug.c" 
//3. Run the program 
//4. Set DebugNl to 0
//5. DebugC should be equal to 0x89abcdef, but instead gets the random value that was stored in a RAM address. 
//Using C6000 Code Generation Tools 6.1.20, the command 
//"cl6x.exe -g -o3 -mv6400+ -k tiBug.c" 
//generates the file tiBug.asm containing the 4 lines: 
//244 LDW .D2T2 *+B6(12),B4 RAM address x => B4 
//284 LDNDW .D2T2 *+B16(8),B9:B8 ; |20| parameters.C => B9 
//289 STNDW .D1T2 B9:B8,*+A3(8) ; |20| B9 => RAM address x 
//303 [ A0] STW .D2T2 B4,*+DP(_DebugC) ; |39| B4 => DebugC 
//The correct order should have been: parameters.C => B9 => RAM address x => B4 => DebugC
int DebugDisplay = 1; 
int DebugC = 0; 
int DebugNl = 1;  
typedef struct { int L; } Dpre_t;  
typedef struct { int Kp, Km, Cp, Cm, C; } Parameters_t;  

inline Parameters_t GetPrms(int B) 
{  
    Parameters_t parameters;  
    int table[2] = {40, 6144};  
    int b0 = 1;  
    if (B <= table[0]) 
        b0 = 0;  
    parameters.Kp = table[b0];  
    parameters.Km = table[0];  
    parameters.Cm = 0x01234567;  
    parameters.C = 0x89abcdef;  
    return parameters;  
}  

void main() 
{  
    Dpre_t dpre[1];  
    while (*(volatile int*)&DebugNl) 
        ; 
    {  
        int nCw = 2;  
        int q;  
        int tmpCh[128];  
        int *tmpPtr0 = &tmpCh[0];  
        for (q = 0; q < nCw; q++)  
        {  
            Parameters_t parameters = GetPrms(2560);  
            int Cm = parameters.Cm;  
            int Km = parameters.Km;  
            int Kp = parameters.Kp;  
            int Cnr = parameters.C;  
            int j;  
            if (DebugDisplay)  
            { 
                DebugDisplay = 0; 
                DebugC = Cnr; 
            }  
            for (j = 0; j < Cm; j++)  
                dpre[0].L += 0 <= Cnr ? Km : Kp; 
        } 
    }

[Edit: this post was badly mangled by the forum formatting. I've reformatted it so it can be viewed. Please let me know if I have not faithfully reproduced the text of your post.  --Archaeologist]

  • There are two problems with this test case

    1. dpre is not initialized before its value is read
    2. the loop count Cm is so large that the signed integer addition in the innermost loop will eventually overflow signed int, which is undefined behavior, which means the entire test case is not a conforming C program.

    However, when I reduce Cm to a small integer, there is still something fishy going on.  I'll have a look at it.

  • I am able to verify that there is a bug here; I've submitted SDSCM00043229 to track this issue.  However, I am unable to characterize the problem.  Someone in the support team will need to perform more analysis.