inbranch and notinbranch Clauses
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