construct This patch adds lowering support for lastprivate privatization on unstructured construct. Generic lastprivate lowering on sections involves creating a if operation on the lexically last section block and updating the lastprivate variable inside it. However, this control flow is not needed if the section construct is lowered as an unstructured construct. Hence, this patch modifies the lowering control flow to not emit an unnecessary scf.if if the section block is lowered as an unstructured construct. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D143077
243 lines
10 KiB
Fortran
243 lines
10 KiB
Fortran
! This test checks the lowering of OpenMP sections construct with several clauses present
|
|
|
|
! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
|
|
|
|
!CHECK: func @_QQmain() attributes {fir.bindc_name = "sample"} {
|
|
!CHECK: %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref<i32>
|
|
!CHECK: %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"}
|
|
!CHECK: %[[CONST_1:.*]] = arith.constant 1 : i32
|
|
!CHECK: omp.sections allocate(%[[CONST_1]] : i32 -> %0 : !fir.ref<i32>) {
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"}
|
|
!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"}
|
|
!CHECK: %[[const:.*]] = arith.constant 5 : i32
|
|
!CHECK: fir.store %[[const]] to %[[COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[temp_count:.*]] = fir.load %[[COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[temp_double_count:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[result:.*]] = arith.muli %[[temp_count]], %[[temp_double_count]] : i32
|
|
!CHECK: {{.*}} = fir.convert %[[result]] : (i32) -> f32
|
|
!CHECK: fir.store {{.*}} to %[[PRIVATE_ETA]] : !fir.ref<f32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"}
|
|
!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[const:.*]] = arith.constant 1 : i32
|
|
!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[const]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"}
|
|
!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref<f32>
|
|
!CHECK: %[[const:.*]] = arith.constant 7.000000e+00 : f32
|
|
!CHECK: %[[result:.*]] = arith.subf %[[temp]], %[[const]] {{.*}}: f32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_ETA]] : !fir.ref<f32>
|
|
!CHECK: {{.*}} = fir.load %[[COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[temp_count:.*]] = fir.convert {{.*}} : (i32) -> f32
|
|
!CHECK: %[[temp_eta:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref<f32>
|
|
!CHECK: {{.*}} = arith.mulf %[[temp_count]], %[[temp_eta]] {{.*}}: f32
|
|
!CHECK: %[[result:.*]] = fir.convert {{.*}} : (f32) -> i32
|
|
!CHECK: fir.store %[[result]] to %[[COUNT]] : !fir.ref<i32>
|
|
!CHECK: {{.*}} = fir.load %[[COUNT]] : !fir.ref<i32>
|
|
!CHECK: %[[temp_count:.*]] = fir.convert {{.*}} : (i32) -> f32
|
|
!CHECK: %[[temp_eta:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref<f32>
|
|
!CHECK: {{.*}} = arith.subf %[[temp_count]], %[[temp_eta]] {{.*}}: f32
|
|
!CHECK: %[[result:.*]] = fir.convert {{.*}} : (f32) -> i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.sections nowait {
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: return
|
|
!CHECK: }
|
|
|
|
program sample
|
|
use omp_lib
|
|
integer :: count = 0, double_count = 1
|
|
!$omp sections private (eta, double_count) allocate(omp_high_bw_mem_alloc: count)
|
|
!$omp section
|
|
count = 1 + 4
|
|
eta = count * double_count
|
|
!$omp section
|
|
double_count = double_count + 1
|
|
!$omp section
|
|
eta = eta - 7
|
|
count = count * eta
|
|
double_count = count - eta
|
|
!$omp end sections
|
|
|
|
!$omp sections
|
|
!$omp end sections nowait
|
|
end program sample
|
|
|
|
!CHECK: func @_QPfirstprivate(%[[ARG:.*]]: !fir.ref<f32> {fir.bindc_name = "alpha"}) {
|
|
!CHECK: omp.sections {
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_ALPHA:.*]] = fir.alloca f32 {bindc_name = "alpha", pinned, uniq_name = "_QFfirstprivateEalpha"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[ARG]] : !fir.ref<f32>
|
|
!CHECK: fir.store %[[temp]] to %[[PRIVATE_ALPHA]] : !fir.ref<f32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.sections {
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_VAR:.*]] = fir.load %[[ARG]] : !fir.ref<f32>
|
|
!CHECK: %[[CONSTANT:.*]] = arith.constant 5.000000e+00 : f32
|
|
!CHECK: %[[PRIVATE_VAR_2:.*]] = arith.mulf %[[PRIVATE_VAR]], %[[CONSTANT]] {{.*}}: f32
|
|
!CHECK: fir.store %[[PRIVATE_VAR_2]] to %[[ARG]] : !fir.ref<f32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: return
|
|
!CHECK: }
|
|
|
|
subroutine firstprivate(alpha)
|
|
real :: alpha
|
|
!$omp sections firstprivate(alpha)
|
|
!$omp end sections
|
|
|
|
!$omp sections
|
|
alpha = alpha * 5
|
|
!$omp end sections
|
|
end subroutine
|
|
|
|
subroutine lastprivate()
|
|
integer :: x
|
|
!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: omp.sections {
|
|
!$omp sections lastprivate(x)
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[const:.*]] = arith.constant 10 : i32
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[result:.*]] = arith.muli %c10_i32, %[[temp]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x * 10
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[true:.*]] = arith.constant true
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[const:.*]] = arith.constant 1 : i32
|
|
!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[const]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.if %[[true]] {
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[X]] : !fir.ref<i32>
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x + 1
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp end sections
|
|
|
|
!CHECK: omp.sections {
|
|
!$omp sections firstprivate(x) lastprivate(x)
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.barrier
|
|
!CHECK: %[[const:.*]] = arith.constant 10 : i32
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[result:.*]] = arith.muli %c10_i32, %[[temp]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x * 10
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.barrier
|
|
!CHECK: %[[true:.*]] = arith.constant true
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[const:.*]] = arith.constant 1 : i32
|
|
!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[const]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.if %true {
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[X]] : !fir.ref<i32>
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x + 1
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp end sections
|
|
|
|
!CHECK: omp.sections nowait {
|
|
!$omp sections firstprivate(x) lastprivate(x)
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.barrier
|
|
!CHECK: %[[const:.*]] = arith.constant 10 : i32
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[result:.*]] = arith.muli %c10_i32, %[[temp]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x * 10
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: %[[temp:.*]] = fir.load %[[X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: omp.barrier
|
|
!CHECK: %[[true:.*]] = arith.constant true
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[const:.*]] = arith.constant 1 : i32
|
|
!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[const]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.if %true {
|
|
!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[temp]] to %[[X]] : !fir.ref<i32>
|
|
!CHECK: omp.barrier
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp section
|
|
x = x + 1
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!$omp end sections nowait
|
|
|
|
!CHECK: omp.sections {
|
|
!CHECK: omp.section {
|
|
!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
|
|
!CHECK: cf.br ^bb1
|
|
!CHECK: ^bb1: // pred: ^bb0
|
|
!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[const:.*]] = arith.constant 1 : i32
|
|
!CHECK: %[[result:.*]] = arith.addi %[[INNER_PRIVATE_X]], %[[const]] : i32
|
|
!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: %[[loaded_value:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref<i32>
|
|
!CHECK: fir.store %[[loaded_value]] to %[[X]] : !fir.ref<i32>
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
!CHECK: omp.terminator
|
|
!CHECK: }
|
|
|
|
!$omp sections lastprivate(x)
|
|
!$omp section
|
|
goto 30
|
|
30 x = x + 1
|
|
!$omp end sections
|
|
end subroutine
|