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/TI-CGT: C6000-CGT UInt64 variable access not using LDDW

Part Number: TI-CGT
Other Parts Discussed in Thread: AM5729, AM5728

Tool/software: TI C/C++ Compiler

Hi All,

Using ti-cgt-c6000_8.3.6 on AM5729/C66x I looked into the generated asm listing of a simple 64-bit integer variable access and found that the loading/storing of the 64bit value is done using two LDW instructions instead of a single LDDW.

For example the following C code:

#include <xdc/std.h>

typedef unsigned long long u64;

u64 testVariable = 0;

u64 GetVar()
{
return testVariable;
}

void SetVar(u64 val)
{
testVariable = val;
}

Compiles into:

29 .global testVariable
30 00000000 .sect ".neardata", RW
31 .align 8
32 .elfsym testVariable,SYM_SIZE(8)
33 00000000 testVariable:
34 00000000 00000000 .bits 0,64

49 00000000 SetVar:
50 ;** --------------------------------------------------------------------------*
51 00000000 008c6362 RETNOP B3,3 ; [] |15|
52 00000004 0200007c! STW .D2T1 A4,*+DP(testVariable) ; [B_D64P] |14|
53 00000008 0280047c! STW .D2T1 A5,*+DP(testVariable+4) ; [B_D64P] |14|
54 ; BRANCH OCCURS {B3} ; [] |15|

66 0000000c GetVar:

69 0000000c 000c0363 RET .S2 B3 ; [B_Sb66] |10|
70 00000010 0200006c! || LDW .D2T1 *+DP(testVariable),A4 ; [B_D64P] |9|
71
72 00000014 0280046c! LDW .D2T1 *+DP(testVariable+4),A5 ; [B_D64P] |9|
73 00000018 00006000 NOP 4 ; [A_L66]
74 ; BRANCH OCCURS {B3} ; [] |10|

Here're my command line settings:

"/home/istvan/ti/ccs1000/ccs/tools/compiler/ti-cgt-c6000_8.3.6/bin/cl6x" -mv6600 -O3 --opt_for_speed=2 -ms0 --define=am5728 --define=core2 --define=SOC_AM572x --define=core2 --symdebug:none --c99 --c++14 --diag_suppress=2170 --diag_warning=225 --diag_wrap=off --display_error_number --auto_inline=0 --analyze_only -k --asm_listing --asm_cross_reference_listing --preproc_with_compile --preproc_dependency="test64.d_raw" --cmd_file="configPkg/compiler.opt" "../test64.c"

I'm wondering why the compilier is not using LDDW/STDW here?

Istvan

  • The problem is the LDDW and STDW instructions do not support the addressing mode *+DP(testVariable), but the LDW and STW instructions do.  If you add the storage class modifier far ...

    far u64 testVariable = 0;

    Then you'll see it.   However, that is not a clear win, because two additional instructions are required to load the address of testVariable into a register.  

    A different, but related, note ... Structure and array variables are, by default, accessed as far, and thus LDDW and STDW instructions may be used.

    Thanks and regards,

    -George

  • Thanks for the explanation George, that makes sense of course.

    From an instruction/cycle-count view this is clearly better with two LDW instructions, what I tried to achieve was to load the value in an uninterruptable way (so that the lower/upper part would be at least always consistent (with some limitations)).

    One other approach I played with was to use intrinsics to force LDDW access, and even if I tried loading the value using _amem8_const(&testVariable) the generated code will use two LDWs instead of one LDDW.

    This I find somewhat counter-intuitive, as the compiler user guide states:

    "long long & _amem8 (void *ptr);

    LDDW STDW

    Allows aligned loads and stores of 8 bytes to memory. The pointer must be aligned to an eight-byte boundary. An LDDW or STDW instruction will be used"

    IMO the compiler should have sticked to LDDW based on that, what do you think?

    Istvan

  • The intended use case for _amem8 is closer to ...

    _amem8(ptr_to_long_long);
    _amem8(&array_of_long_long[i]);

    That applying it to a single global variable does not generate a LDDW or STDW was overlooked.

    Thanks and regards,

    -George

  • Thanks George, this is really interesting, when using a pointer variable, that really works:

    u64 testVariable;
    u64 *ptest = &testVariable;

    u64 GetVar()
    {
    return _amem8_const(ptest) >> 1;
    }

    Produces 

    69 0000000c 0200006e! LDW .D2T2 *+DP(ptest),B4 ; [B_D64P] |11|
    70 00000010 6c6e NOP 4 ; [A_L66]
    71 00000012 100d LDDW .D2T2 *B4(0),B1:B0 ; [B_D64P] |11|
    72 00000014 2c6e NOP 2 ; [A_L66]
    ....

    Although I think it should work in both cases, even when not explicitly using a pointer variable, but just taking the address of a variable, as it is defined in the UG, would be nice to get this fixed once :)

    Thanks again!

    Istvan