Quantcast
Channel: Intel Developer Zone Articles
Viewing all articles
Browse latest Browse all 3384

Diagnostic 15341: loop was not vectorized: nonstandard loop is not a vectorization candidate

$
0
0

Cause:

1. More than one exit point in the loop. A loop must have a single entry and a single exit point. Multiple exit points in a loop can generate this message.
2. This remark is also reported when C++ exception handling and OpenMP critical construct are used in a SIMD loop.
3. Third example demonstrates a case where compiler has no way to narrow down which function is passed as a function parameter. When this passed function is invoked inside the loop body, this vectorization diagnostic is generated.
4. Another case is documented which demonstrates how a loop body which is seen as a non-standard loop for vectorization can be made a suitable candidate for vectorization just by enabling the ANSI alias rule during compilation using compiler option -ansi-alias.

Below are examples for all the scenarios.


Examples:
 

void no_vec(float a[], float b[], float c[])
   {
        int i = 0.;
        while (i < 100) {
          a[i] = b[i] * c[i];
   //  this is a data-dependent exit condition:
          if (a[i] < 0.0)
             break;
          ++i;
        }
   }


>icl -c -Qvec-report2 example1.cpp
Intel® C++ Compiler for applications running on Intel® 64, Version 12.0.0.063 Build 20100721
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.

example1.cpp
example1.cpp(4) (col. 9): remark: loop was not vectorized: nonstandard loop is not a vectorization candidate.
 

#include <stdio.h>
#include <stdlib.h>

#define N 1000
int vecmsg_testcore001() {
#pragma omp simd
   for (int i=0; i<N; i++) {
      try {
           printf ( "throw exception 11n" );
           throw 11;
      } catch (int t) {
        printf ( "caught exception %dn", t );
        if ( t != 11 ) {
#pragma omp critical
            {  printf ( "TEST FAILEDn" );
               exit( 0);
            };
        };
      }
   };
   printf ( "TEST PASSEDn");
   exit(0);
}


>icl -c -Qvec-report2 example2.cpp -Qopenmp -EHsc

example2.cpp(7): (col. 4) remark: loop was not vectorized: nonstandard loop is not a vectorization candidate
example2.cpp(7): (col. 4) warning #13379: loop was not vectorized with "simd"

#include<iostream>

	int a[100];

	int b[100];

	int g(int i, int y){

	return b[i]+y;

	}

	__declspec(noinline) void doit1(int x(int,int), int y){

	int i;

	#pragma parallel

	for(i = 0; i < 100; i++)

	a[i] = x(i,y);

	}

	

$ icpc -c -vec-report2 example3.cc
example3.cc(12): (col. 1) remark: loop was not vectorized: nonstandard loop is not a vectorization candidate


	typedef struct  PREV_PR_o {

	        float           *px_l1;

	        float           *px_l2;

	        float           *px_r1;

	        float           *px_r2;

	        float           *pz_t1;

	        float           *pz_t2;

	        float           *pz_b1;

	        float           *pz_b2;

	        } PREV_PR_o;

typedef struct  PREV_PR_o  *PREV_PR_p;

typedef struct  PROPAG_PARMS {

	        int             nx;

	        int             nz;

	        float           dx;

	        float           dz;

	        float           dt;

	        float           dom_freq;

	        float           rec_length;

	        int             first_snap;

	        int             freq_snap;

	        int             nx_l;

	        int             nz_l;

	        int             nx_l_beg;

	        int             nz_l_beg;

	        int             nx_l_end;

	        int             nz_l_end;

	        int             output;

	        } PROPAG_PARMS;

typedef struct  PROPAG_PARMS    *PROPAG_PARMS_p;

int FD_Scheme( PROPAG_PARMS_p model, int t_step, float **p0,

	            PREV_PR_p prev )

	{

        int             return_value = 0;

	        int             ixm;

	        int             i;

        ixm = model->nx_l + 2;

        for( i=0 ; i<model->nz_l ; i++ ) {

	                prev->px_l1[i] = p0[3][i+2];

	                prev->px_l2[i] = p0[4][i+2];

	                prev->px_r1[i] = p0[ixm-2][i+2];

	                prev->px_r2[i] = p0[ixm-3][i+2];

	        }

	return return_value;

	}

	

$ icpc -c -vec-report2 example4.c
example4.c.c(45): (col. 2) remark: loop was not vectorized: nonstandard loop is not a vectorization candidate

Resolution Status:

1. For the first example, change the loop to have a single entry and a single exit point.
2. For the second example, change the loop not to have C++ exception handling and OpenMP criticial sections
3. No resolution unless we can let compiler know during compile time, which function will be called within the loop body
4. By using compiler option -ansi-alias and #pragma simd on the loop will vectorize this loop. By mentioning the compiler option -ansi-alias compiler option, the compiler will stick ISO C standard aliasing rules. Since this loop's bound is an integer and all the updates inside the loop body is on float data type, the compiler can be certain that the loop's bound is not changing inside the loop body (-ansi-alias assertion implies type-based disambiguation). Now with -ansi-alias option, the following vectorization report is generated which states there is a data dependency:

$ icpc test.c -c -vec-report2 -ansi-alias
rakesh1.c(45): (col. 2) remark: loop was not vectorized: existence of vector dependence

Since the developer is aware in this case that there is no data dependency in the loop across iterations, the developer can annotate the loop with #pragma simd (compiler neglects the heuristic information which suggest there is a data dependency) and the loop gets vectorized:

$ icpc test.c -c -vec-report2 -ansi-alias
test.c(45): (col. 2) remark: SIMD LOOP WAS VECTORIZED


Viewing all articles
Browse latest Browse all 3384

Trending Articles