Compiler Advice (on TI Wiki)

Advice 27000: Use Optimization Options
Advice 27001: Increase Optimization Level
Advice 27002: Do not turn off software pipelining
Advice 27003: Avoid compiling with debug options
Advice 27004: No Performance Advice generated
Advice 30000: Prevent Loop Disqualification due to call
Advice 30001: Prevent Loop Disqualification due to rts-call
Advice 30002: Prevent Loop Disqualification due to asm statement
Advice 30003: Prevent Loop Disqualification due to complex condition
Advice 30004: Prevent Loop Disqualification due to switch statement
Advice 30005: Prevent Loop Disqualification due to arithmetic operation
Advice 30006: Prevent Loop Disqualification due to call(2)
Advice 30007: Prevent Loop Disqualification due to rts-call(2)
Advice 30008: Improve Loop; Qualify with restrict
Advice 30009: Improve Loop; Add MUST_ITERATE pragma
Advice 30010: Improve Loop; Add MUST_ITERATE pragma(2)
Advice 30011: Improve Loop; Add _nassert()

Typical Advice

 advice #30009: If you know that this loop will always execute at a
multiple of <2> and at least <2> times, try adding
"#pragma MUST_ITERATE(2, ,2)" just before the loop.

Why is the Compiler giving this Advice?

You may be able to get better loop performance by adding the "MUST_ITERATE" pragma. This Advice is issued to alert you to this potential performance improvement in your code.


What it means:

The C6000 architecture is partitioned into two nearly symmetric halves. The resource breakdown displayed in the software pipelining information, in the asm file, is computed after the compiler has partitioned instructions to either the A-side or the B-side. If the resources are imbalanced (i.e.; some resources on one side are used more than resources on the other) software pipelinging is resource-bound, and the loop cannot be efficiently scheduled. If the compiler has information about the trip-count for the loop, it can unroll the loop to balance resource usage, and get better pipelining.

You can give loop trip-count information to the compiler using the "MUST_ITERATE" pragma. The MUST_ITERATE pragma has the syntax:

   #pragma MUST_ITERATE(min, max, multiple)

The arguments min and max are programmer-guaranteed minimum and maximum trip counts. The trip count is the number of times a loop iterates. The trip count of the loop must be evenly divisible by multiple. All arguments are optional. For example, if the trip count could be 5 or greater, you can specify the argument list as follows:

   #pragma MUST_ITERATE(5);

However, if the trip count could be any nonzero multiple of 5, the pragma would look like this:

   #pragma MUST_ITERATE(5, , 5); /* Note the blank field for max */

It is sometimes necessary for you to provide min and multiple in order for the compiler to perform unrolling. This is especially the case when the compiler cannot easily determine how many iterations the loop will perform (that is, the loop has a complex exit condition). When specifying a multiple via the MUST_ITERATE pragma, results of the program are undefined if the trip count is not evenly divisible by multiple. Also, results of the program are undefined if the trip count is less than the minimum or greater than the maximum specified. If no min is specified, zero is used. If no max is specified, the largest possible number is used. If multiple MUST_ITERATE pragmas are specified for the same loop, the smallest max and largest min are used.

The MUST_ITERATE pragma specifies to the compiler certain properties of a loop. You guarantee that these properties are always true. Through the use of the MUST_ITERATE pragma, you can guarantee that a loop executes a specific number of times. For loops the MUST_ITERATE pragma's third argument, factor or multiple, is the most important and should always be specified. Furthermore, the MUST_ITERATE pragma should be applied to any other loops as often as possible. This is because the information provided via the pragma (especially the minimum number of iterations) aids the compiler in choosing the best loops and loop transformations (that is, software pipelining and nested loop transformations). It also helps the compiler reduce code size.

Example 1 : The example below tells the compiler that the loop is guaranteed to run exactly 10 times:

   #pragma MUST_ITERATE(10,10);
   for(i = 0; i < trip_count; i++) { ...

In this example, the compiler attempts to generate a software pipelined loop even without the pragma. However, if MUST_ITERATE is not specified for a loop such as this, the compiler generates code to bypass the loop, to account for the possibility of 0 iterations. With the pragma specification, the compiler knows that the loop iterates at least once and can eliminate the loop-bypassing code. MUST_ITERATE can specify a range for the trip count as well as a factor of the trip count.

Example 2 : This example tells the compiler that the loop executes between 8 and 48 times and that the trip_count variable is a multiple of 8 (8, 16, 24, 32, 40, 48). The multiple argument allows the compiler to unroll the loop.

   #pragma MUST_ITERATE(8, 48, 8);
   for(i = 0; i < trip_count; i++) { ...

Example 3 : You should also consider using MUST_ITERATE for loops with complicated bounds. In the following example, the compiler would have to generate a divide function call to determine, at run time, the exact number of iterations performed. The compiler will not do this. In this case, using MUST_ITERATE to specify that the loop always executes eight times allows the compiler to attempt to generate a software pipelined loop:

   #pragma MUST_ITERATE(8, 8);
   for(i2 = ipos[2]; i2 < 40; i2 += 5) { ...

For further information on conveying information to the compiler to improve performance, see Tuning Software Pipelined Loops and Optimization Lab.


Risks, Severity

When you use mechanisms such as restrict, MUST_ITERATE, or _nassert, you are conveying extra information to the compiler. Always verify all such information is correct for every call.

Also, while the "MUST_ITERATE" pragma can help you get better performance, you must make sure that the syntax is correctly followed. Results of the program are undefined if the trip count is not evenly divisible by the specified multiple. Also, results of the program are undefined if the trip count is less than the minimum or greater than the maximum specified. If no min is specified, zero is used. If no max is specified, the largest possible number is used. If multiple MUST_ITERATE pragmas are specified for the same loop, the smallest max and largest min are used.

In certain cases, when a function is inlined, the compiler can emit multiple advice advice for a particular loop. For example, consider function test() defined in "test.h"

static inline void test (int n)
{
   int i;
 
   for (i = 0; i < n i++)
   {
      // other statements
   }
 
   return;
}

If function test() is called from multiple locations and from different functions, as (and note that this example is a simplified version) :

test(a);

test(b);

test(c);

the compiler can generate multiple Advice for each invocation of the call :

"test.h", line 149: advice #30009: If you know that this loop will always
execute at a multiple of <20> and at least <20> times, try adding "#pragma
MUST_ITERATE(20, ,20)" just before the loop.
"test.h", line 149: advice #30009: If you know that this loop will always
execute at a multiple of <10> and at least <10> times, try adding "#pragma
MUST_ITERATE(10, ,10)" just before the loop.
"test.h", line 149: advice #30009: If you know that this loop will always
execute at a multiple of <28> and at least <28> times, try adding "#pragma
MUST_ITERATE(28, ,28)" just before the loop.

This can happen if the function containing this loop, test(), is inlined. Then, the compiler emits the best advice it can for each inlining case. In such a case, any MUST_ITERATE advice added will have to be true for ALL invocations of function test(). From these three Advice, we can infer that the loop will iterate for atleast 10 counts, and will be a multiple of 2, since:


Minimum(10, 20,28) = 10

Greatest Common Divisor(10, 20, 28) = 2


Thus the best way to specify this would be to add before the loop :

   #pragma MUST_ITERATE(10, ,2);

If however test() in invoked in another location as


test(g(x)); //g() being another function


If the value of g(x) is not known until runtime, the above pragma may not be true anymore, since g(x) might be less than 10, and a non-multiple of 2. So, ensure that such pragmas convey correct information.


Suggested Action

Use pragma "MUST_ITERATE".

More Resources

Want to squeeze a few more Performance Cycles out of your application? Leverage the e2e (Engineer-to-Engineer) online community to get all of your Advice questions answered! Or, give back to the community with your expertise.

Go to the TI Compiler's e2e online forum! 

E2e.jpg For technical support please post your questions at http://e2e.ti.com.