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

ID 767251
Date 3/22/2024
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Nested DO Constructs

A DO construct can contain one or more complete DO constructs (loops). The range of an inner nested DO construct must lie completely within the range of the next outer DO construct. Nested nonblock DO constructs can share a labeled terminal statement.

The following figure shows correctly and incorrectly nested DO constructs:

In a nested DO construct, you can transfer control from an inner construct to an outer construct. However, you cannot transfer control from an outer construct to an inner construct.

If two or more nested DO constructs share the same terminal statement, you can transfer control to that statement only from within the range of the innermost construct. Any other transfer to that statement constitutes a transfer from an outer construct to an inner construct, because the shared statement is part of the range of the innermost construct.

When the nested DO constructs contain no statements between the DO statements in the nest of DO constructs, the nest is called “perfectly nested”. When perfectly nested DO constructs are modified by a COLLAPSE clause in any of these OpenMP* directives:

  • !$OMP DISTRIBUTE
  • !$OMP DO
  • !$OMP SIMD

There are restrictions on which general compiler directives (see General Compiler Directives) and OpenMP Fortran compiler directives (see OpenMP Fortran Compiler Directives) can appear before the DO statements in the nested DO construct:

  • Any OpenMP or general directives that are allowed to affect DO loops are allowed prior to the first DO loop of the "perfectly nested" DO construct.
  • It is an error if any of these directives are between any of the perfectly nested DO loop statements for the loops affected by the COLLAPSE clause.

Examples

In the following example, COLLAPSE (1) on affects the DO I loop. Therefore general directives before the DO J loop, which is at level 2, are allowed:

!$OMP SIMD collapse (1)
!dir$ prefetch  …          ! this is allowed since it is before the start
                           !    of the perfectly nested DO construct

 do i = …
     !dir$ loop count …    ! this is allowed since collapse only applies
                           !    to the i-loop, not the j-loop
      do j = …
      enddo                ! end for j-loop
 enddo                     ! end for i-loop

In the following example, COLLAPSE (2) affects the DO I loop and the DO J loop but not the DO k loop.

!$OMP SIMD collapse (2)
!dir$ prefetch  …          ! this is allowed since it is before the start
                           !    of the perfectly nested DO construct
 do i = … 
    do j = …
       !dir$ loop count …  ! this is allowed since collapse only applies to
                           !   the i-loop and the j-loop, not the k-loop
        do k= ….
        enddo              ! end for k-loop
     enddo                 ! end for j-loop
 enddo                     ! end for i-loop

In the following example, COLLAPSE (2) affects the DO I loop and the DO J loop so there can be no directives before the DO J loop.

!$OMP SIMD collapse (2)
!dir$ prefetch  …          ! this is allowed since it is before the start
                           !    of the perfectly nested DO construct
 do i = …
    !dir$ loop count …     ! this is not allowed: it is breaks the perfectness
                           !    of the  i-loop and the nj-loop collapsing
    do j = …
    enddo                  ! end for j-loop
 enddo                     ! end for i-loop