Replace call(s) to virtual method with direct call(s)

Calls to virtual methods are always indirect because the function address is calculated during runtime. Do the following to fix:

Example (original code)

...
virtual double foo(double x) { return x+1; }
...
// virtual indirect call
sum += obj->foo(a[k]);
...
struct A {
    virtual double foo(double x) { return x+1; }
};

struct B : public A {
    double foo(double x) override { return x-1; }
};

 ...

A* obj = new B();

double sum = 0.0;
#pragma omp simd reduction(+:sum)
for (int k = 0; k < N; ++k) {
    // virtual indirect call
    sum += obj->foo(a[k]);
}
...

Example (revised code)

...
#pragma omp declare simd
virtual double foo(double x) { return x+1; }
...
sum += ((B*)obj)->B::foo(a[k]);
...
struct A {
    // Intel Compiler 17.x or higher could vectorize call to virtual method
    #pragma omp declare simd
    virtual double foo(double x) { return x+1; }
};

 ...

sum = 0.0;
#pragma omp simd reduction(+:sum)
for (int k = 0; k < N; ++k) {
    // step for Intel Compiler 16.x or lower:
    // if you know the method to be called,
    // replace virtual call with direct one
    sum += ((B*)obj)->B::foo(a[k]);
}
...

Read More