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.

How to allocate variables to a common data page for minimizing dp loads?

Other Parts Discussed in Thread: TMS320F28335

I have a TMS320F28335 application with many floating point variables, and time is critical. It's really frustrating when the compiler doesn't optimize out redundant dp loads. There is supposed to be a post-link optimizer to do this, but it appears to be disabled for FPU targets (like the 28335). This makes no sense to me, since I can't see why FPU or not affects DP loads. There is a plink2000.exe tool, but it seems to be completely undocumented. It seems to want to read assembler files, but I can't get it to do anything useful.


I have used #pragma DATA_SECTION directives to keep my critical data in one page. This works, in the sense that the variables get allocated to the same page, but infuriatingly, it seems to make the compiler throw away any DP load optimizations that it might have done.


Example code:

#if 1
#pragma DATA_SECTION(fVtra, "critical_data");
#pragma DATA_SECTION(fVtrb, "critical_data");
#pragma DATA_SECTION(fVtrc, "critical_data");
#pragma DATA_SECTION(fIora, "critical_data");
#pragma DATA_SECTION(fIorb, "critical_data");
#pragma DATA_SECTION(fIorc, "critical_data");
#endif

    float fQs, fVtra, fVtrb,fVtrc, fIora, fIorb, fIorc;
void main(void)
{
    fVtra = 1; fVtrb = 2; fVtrc = 3; fIora = 4; fIorb = 5; fIorc = 6;
    fQs = (1./1.73208) * ((fVtrb - fVtrc) * fIora + (fVtrc - fVtra) * fIorb + (fVtra - fVtrb) * fIorc);

This generates code like this:

003004f5   e801       MOVIZ        R0, #0x3f80
003004f6   fc00
003004f7   761f       MOVW         DP, #0x300
003004f8   0300
003004f9   e203       MOV32        @0xa, R0H
003004fa   000a
003004fb   761f       MOVW         DP, #0x300
003004fc   0300
003004fd   e802       MOVIZ        R0, #0x4000
003004fe   0000
003004ff   e203       MOV32        @0x2, R0H
00300500   0002
00300501   761f       MOVW         DP, #0x300
00300502   0300
00300503   e802       MOVIZ        R0, #0x4040
00300504   0200
00300505   e203       MOV32        @0x0, R0H
00300506   0000
00300507   761f       MOVW         DP, #0x300
00300508   0300
00300509   e802       MOVIZ        R0, #0x4080
0030050a   0400
0030050b   e203       MOV32        @0x6, R0H
0030050c   0006
0030050d   761f       MOVW         DP, #0x300
0030050e   0300
0030050f   e802       MOVIZ        R0, #0x40a0

Note the underlined redundant DP load instructions. If I take away the #pragma DATA_SECTIONs (using #if 0 instead of #if 1), it optimized them out:

003004f5   e801       MOVIZ        R0, #0x3f80
003004f6   fc00
003004f7   761f       MOVW         DP, #0x30d
003004f8   030d
003004f9   e203       MOV32        @0x2e, R0H
003004fa   002e
003004fb   e802       MOVIZ        R0, #0x4000
003004fc   0000
003004fd   e203       MOV32        @0x24, R0H
003004fe   0024
003004ff   e802       MOVIZ        R0, #0x4040
00300500   0200
00300501   e203       MOV32        @0x22, R0H
00300502   0022
00300503   e802       MOVIZ        R0, #0x4080

This is what I want. But with a more complex real-world program with many more global variables, I can't control where the variables "land", and there will usually be a page boundary between one half and the others, generating more unnecessary DP loads.


It seems to me that most of the point of the DATA_SECTION pragma is to give the user the ability to control where variables are allocated. So why does the compiler go crazy and stop optimizing the DP loads?

Is there some way to make the compiler stop doing this, or some other way to force variables to the same data page?

Maybe I need to put these variables into a struct, and use x.foo instead of bare foo? That's ugly, but I suppose it's doable.


Thanks in advance for any suggestions.

  • I forgot to post how I defined the critical_data section, in case that's significant:

      L4SARAMa   : origin = 0x00C000, length = 0x000040 /* Testing */

      L4SARAM         : origin = 0x00C040, length = 0x000FC0     /* 4Kw L4 SARAM, DMA accessible */

     ...

      critical_data : > L4SARAMa, PAGE = 1 /* Data used by the critical code, keep together for speed */

    This is in the F28335_nonBios_flash.cmd file.

  • Moving this post to the compiler forum where you should get more helpful responses.


    Thank you,
    Brett
  • I don't have an answer for your question about DATA_SECTION, but if you put those global variables into a single struct, you will minimize the DP loads.
  • Thanks. The common struct is a little clunky, but it works and it gives me the bare minimum control that I need, so for now that's what I'll do.

  • Currently the DP load optimization is only performed on compiler-generated sections. 

    The additional post-link optimization pass works by eliminating DP load instructions after they have already been issued in the assembly/object file.  We can do this when FPU is not enabled because the regular C28x pipeline is protected, meaning there are no delay slots to maintain.  The FPU pipeline is not protected.  Certain instructions have delays before their output can be consumed, and after the code generation phase is complete and the instructions are issued, we no longer have that information.  If we removed any instructions after linking, we would run the risk of eliminating necessary delay slots and producing incorrect code.  There is an option to run the pass and issue advice only when FPU is enabled.

    As of compiler version 6.2, the separate post link tool was eliminated and this pass is now handled by the regular tool chain through linker options.  However, there is no CCS option for it so the linker options have to be inserted manually.

    See section 5.6.5-5.7 in the compiler guide and Table 2-28 p.26 Link-time Optimization Options.

    www.ti.com/.../spru514h.pdf

  • Ah! Delay slots; I didn't think of that. It just seemed arbitrary that the DP optimisation was not available when using a processor with a floating point unit. Thanks for explaining that.