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.

F29H859TU-Q1: TI F29 / C29 CLANG compiler: how to create a barrier in the code

Part Number: F29H859TU-Q1

Hello,

I am using the C29 Clang compiler and I am searching for the best way to create a barrier in the code instructing the compiler to not mix the code before the barrier with the code after the barrier.

This feature can be useful for example to be able to measure the duration of some code (to guarantee that we are measuring what we want).

I heard about different solutions but I am not sure about their robustness:

  • __builtin_instrumentation_label()
  • asm volatile ("")
  • asm volatile ("" : : : "memory")

So could you please provide which solution we shoud use and want are the limitations of this solution on the current version of the compiler (2.2.0 LTS) but also what could be the limitations in the future (globally, what is guaranteed and what is not).

Thank you

  • Hello,

    I've brought this thread to the attention of the compiler experts for further analysis. 

    Thanks

    ki

  • We do make a guarantee with both asm volatile and __builtin_instrumentation label. No volatile or memory operations will move around the given statement.

    However, non-memory operations such as common arithmetic, comparisons, bitwise operations, etc. Will still possibly move when optimization is turned on.

    You can achieve the most consistent numbers by placing the code you want to profile into a function marked with __attribute__((noinline)), and then call this function from a function which is marked with __attribute__((optnone)). The call to the profiled code should be surrounded by your timing functions of choice and instrumentation labels. The 'optnone' attribute on the profiling function ensures that your numbers will not vary due to changes in the profiling function itself when the optimization level (-On option) changes.

    __attribute__((noinline)) void profiled_code(int *out, int *in) {
        /* Profiled code goes here */
    }
    
    extern unsigned int read_timer();
    extern unsigned int calc_time(unsigned int start, unsigned int stop);
    __attribute((optnone)) void do_profile() {
        int *in_array; /*= ...*/;
        int *out_array; /* = ...*/;
        unsigned int start = 0, stop = 0;
    
    
        start = read_timer();
        __builtin_instrumentation_label("profile_start");
        profiled_code(out_array, in_array);
        __builtin_instrumentation_label("profile_stop");
        stop = read_timer();
    
        unsigned int total_time = calc_time(start, stop);
        /* Do something with total_time */
    }

  • Hello James,

    Thanks for the reply.

    And between __builtin_instrumentation_label(), asm volatile ("") and asm volatile ("" : : : "memory"), what would be the best candidate ? Or will they all behave the same ?

    And why creating __builtin_instrumentation_label() if asm volatile ("") has the same behavior ? Or does __builtin_instrumentation_label() have an additional functionality ?

    Thank you

  • For all intents and purposes, __builtin_instrumentation_label("name") is equivalent to asm volatile("name:\n").

    However, the compiler treats asm volatile("...") as potentially having any untraceable (aka non-register) effect in addition to being a barrier. The instrumentation label is known to just be a label outside of its barrier-like behavior, so it contributes nothing to size, pipeline behaviors, etc.

    For our ARM customers, I'd suggest asm volatile if writing portable code, and the instrumentation label otherwise. For C29, I would use the label, unless you have something to put into the assembly other than a label.

  • Thank you for the support