Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 3/22/2024
Public
Document Table of Contents

UNROLL Directive for OpenMP

OpenMP* Fortran Compiler Directive: Partially or fully unrolls a DO loop. This feature is only available for ifx.

Syntax

!$OMP UNROLL [clause]

   loop-nest

[!$OMP END UNROLL]

clause

Is FULL or PARTIAL [ (count) ], where count is a compile-time integer constant expression.

If FULL is specified, and n is the iteration count of the outermost DO loop, the outermost loop is replaced by n copies of the loop body.

If PARTIAL is specified, the outermost loop is first tiled with a tile size of count, and then the tiled loop is fully unrolled. If PARTIAL is specified without count, the compiler determines the count.

If clause is omitted, the compiler determines if and how the loop is transformed.

loop-nest

Is a nest of DO loops in canonical form.

Description

The UNROLL construct applies to the outermost loop of the loop nest. It is a pure directive, so it can appear in a Fortran PURE procedure.

The transformed loop will be in canonical form only when PARTIAL is specified.

The iteration count of the outermost DO loop must be constant if FULL is specified.

Examples

In the following example, the FULL clause is specified in the UNROLL directive, so the loop iteration count must be a compile-time constant. In this case, a worksharing loop construct cannot be used because there is no loop to apply it to after the loop is unrolled.

  INTEGER,DIMENSION (5) :: arr
  INTEGER               :: i
  !$OMP UNROLL FULL
  DO i = 1, 5
    arr(i) = 100
  END DO 

Unrolling the above DO loops produces the following transformed code:

  INTEGER,DIMENSION (5) :: arr
  INTEGER               :: i
  arr(1) = 100
  arr(2) = 100
  arr(3) = 100
  arr(4) = 100
  arr(5) = 100

In the following example, the loop is partially unrolled. The trip count is a multiple of count specified in the PARTIAL clause:

  INTEGER,DIMENSION (64) :: arr
  INTEGER                :: i
  !$OMP PARALLEL DO
  !$OMP UNROLL PARTIAL(4)
  DO i = 1, 64
    arr(i) = arr(i) * 10
  END DO 

Unrolling the above DO loops 4 times produces the following result:

  INTEGER,DIMENSION (64) :: arr
  INTEGER                :: i
  !$OMP PARALLEL DO
  DO i = 0, 15
    arr(i*4 + 1) = arr(i*4 + 1) * 10
    arr(i*4 + 2) = arr(i*4 + 2) * 10
    arr(i*4 + 3) = arr(i*4 + 3) * 10
    arr(i*4 + 4) = arr(i*4 + 4) * 10
  END DO 

The following example shows how a loop with an unknown trip count that is partially unrolled may be transformed:

  SUBROUTINE FOO (arr, n)
  INTEGER               :: i,n
  INTEGER,DIMENSION (n) :: arr
  !$OMP PARALLEL DO
  !$OMP UNROLL PARTIAL(4)
  DO i = 1, n
    arr(i) = arr(i) * 10
  END DO 
  END SUBROUTINE

Unrolling the above DO loop 4 times produces code equivalent to the following:

  SUBROUTINE FOO (arr, n)
  INTEGER               :: i,n
  INTEGER,DIMENSION (n) :: arr
  !$OMP PARALLEL DO
  DO i = 0, (n+3)/4 - 1
    arr(i*4 + 1) = arr(i*4 + 1) * 10
    if ((i*4 + 2) < n) arr(i*4 + 2) = arr(i*4 + 2) * 10
    if ((i*4 + 3) < n) arr(i*4 + 3) = arr(i*4 + 3) * 10
    if ((i*4 + 4) < n) arr(i*4 + 4) = arr(i*4 + 4) * 10
  END DO 
  END SUBROUTINE