7.2. inbranch and notinbranch Clauses#

The following examples illustrate the use of the declare simd directive with the inbranch and notinbranch clauses. The notinbranch clause informs the compiler that the function foo is never called conditionally in the SIMD loop of the function myaddint . On the other hand, the inbranch clause for the function goo indicates that the function is always called conditionally in the SIMD loop inside the function myaddfloat .

//%compiler: clang
//%cflags: -fopenmp

/*
* name: SIMD.6
* type: C
* version: omp_4.0
*/
#pragma omp declare simd linear(p:1) notinbranch
int foo(int *p){
  *p = *p + 10;
  return *p;
}

int myaddint(int *a, int *b, int n)
{
#pragma omp simd
  for (int i=0; i<n; i++){
      a[i]  = foo(&b[i]);  /* foo is not called under a condition */
  }
  return a[n-1];
}

#pragma omp declare simd linear(p:1) inbranch
float goo(float *p){
  *p = *p + 18.5f;
  return *p;
}

int myaddfloat(float *x, float *y, int n)
{
#pragma omp simd
  for (int i=0; i<n; i++){
     x[i] = (x[i] > y[i]) ? goo(&y[i]) : y[i];
       /* goo is called under the condition (or within a branch) */
  }
  return x[n-1];
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: SIMD.6
! type: F-free
! version: omp_4.0
function foo(p) result(r)
  implicit none
!$omp declare simd(foo) notinbranch
  integer :: p, r
  p = p + 10
  r = p
end function foo

function myaddint(a, b,  n) result(r)
  implicit none
  integer :: a(*), b(*), n, r
  integer :: i
  integer, external :: foo

  !$omp simd
  do i=1, n
      a(i) = foo(b(i))  ! foo is not called under a condition
  end do
  r = a(n)

end function myaddint

function goo(p) result(r)
  implicit none
!$omp declare simd(goo) inbranch
  real :: p, r
  p = p + 18.5
  r = p
end function goo

function myaddfloat(x, y, n) result(r)
  implicit none
  real :: x(*), y(*), r
  integer :: n
  integer :: i
  real, external :: goo

  !$omp simd
  do i=1, n
     if (x(i) > y(i)) then
        x(i) = goo(y(i))
        ! goo is called under the condition (or within a branch)
     else
        x(i) = y(i)
     endif
  end do

  r = x(n)
end function myaddfloat

In the code below, the function fib() is called in the main program and also recursively called in the function fib() within an if condition. The compiler creates a masked vector version and a non-masked vector version for the function fib() while retaining the original scalar version of the fib() function.

//%compiler: clang
//%cflags: -fopenmp

/*
* name: SIMD.7
* type: C
* version: omp_4.0
*/
#include <stdio.h>
#include <stdlib.h>

#define N 45
int a[N], b[N], c[N];

#pragma omp declare simd inbranch
int fib( int n )
{
   if (n <= 1)
      return n;
   else {
      return fib(n-1) + fib(n-2);
   }
}

int main(void)
{
   int i;

   #pragma omp simd
   for (i=0; i < N; i++) b[i] = i;

   #pragma omp simd
   for (i=0; i < N; i++) {
      a[i] = fib(b[i]);
   }
   printf("Done a[%d] = %d\n", N-1, a[N-1]);
   return 0;
}
!!%compiler: gfortran
!!%cflags: -fopenmp

! name: SIMD.7
! type: F-free
! version: omp_4.0
program fibonacci
   implicit none
   integer,parameter :: N=45
   integer           :: a(0:N-1), b(0:N-1)
   integer           :: i
   integer, external :: fib

   !$omp simd
   do i = 0,N-1
      b(i) = i
   end do

   !$omp simd
   do i=0,N-1
      a(i) = fib(b(i))
   end do

   write(*,*) "Done a(", N-1, ") = ", a(N-1)
                        ! 44  701408733
end program

recursive function fib(n) result(r)
   implicit none
!$omp declare simd(fib) inbranch
   integer  :: n, r

   if (n <= 1) then
      r = n
   else
      r = fib(n-1) + fib(n-2)
   endif

end function fib