1! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s
2! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
3
4!CHECK-LABEL: omp.reduction.declare
5!CHECK-SAME: @[[RED_I64_NAME:.*]] : i64 init {
6!CHECK: ^bb0(%{{.*}}: i64):
7!CHECK:  %[[C0_1:.*]] = arith.constant 0 : i64
8!CHECK:  omp.yield(%[[C0_1]] : i64)
9!CHECK: } combiner {
10!CHECK: ^bb0(%[[ARG0:.*]]: i64, %[[ARG1:.*]]: i64):
11!CHECK:  %[[RES:.*]] = arith.addi %[[ARG0]], %[[ARG1]] : i64
12!CHECK:  omp.yield(%[[RES]] : i64)
13!CHECK: }
14
15!CHECK-LABEL: omp.reduction.declare
16!CHECK-SAME: @[[RED_I32_NAME:.*]] : i32 init {
17!CHECK: ^bb0(%{{.*}}: i32):
18!CHECK:  %[[C0_1:.*]] = arith.constant 0 : i32
19!CHECK:  omp.yield(%[[C0_1]] : i32)
20!CHECK: } combiner {
21!CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32):
22!CHECK:  %[[RES:.*]] = arith.addi %[[ARG0]], %[[ARG1]] : i32
23!CHECK:  omp.yield(%[[RES]] : i32)
24!CHECK: }
25
26!CHECK-LABEL: func.func @_QPsimple_reduction
27!CHECK:  %[[XREF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"}
28!CHECK:  %[[C0_2:.*]] = arith.constant 0 : i32
29!CHECK:  fir.store %[[C0_2]] to %[[XREF]] : !fir.ref<i32>
30!CHECK:  omp.parallel
31!CHECK:    %[[I_PVT_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
32!CHECK:    %[[C1_1:.*]] = arith.constant 1 : i32
33!CHECK:    %[[C100:.*]] = arith.constant 100 : i32
34!CHECK:    %[[C1_2:.*]] = arith.constant 1 : i32
35!CHECK:    omp.wsloop   reduction(@[[RED_I32_NAME]] -> %[[XREF]] : !fir.ref<i32>) for  (%[[IVAL:.*]]) : i32 = (%[[C1_1]]) to (%[[C100]]) inclusive step (%[[C1_2]])
36!CHECK:      fir.store %[[IVAL]] to %[[I_PVT_REF]] : !fir.ref<i32>
37!CHECK:      %[[I_PVT_VAL:.*]] = fir.load %[[I_PVT_REF]] : !fir.ref<i32>
38!CHECK:      omp.reduction %[[I_PVT_VAL]], %[[XREF]] : !fir.ref<i32>
39!CHECK:      omp.yield
40!CHECK:    omp.terminator
41!CHECK:  return
42
43subroutine simple_reduction
44  integer :: x
45  x = 0
46  !$omp parallel
47  !$omp do reduction(+:x)
48  do i=1, 100
49    x = x + i
50  end do
51  !$omp end do
52  !$omp end parallel
53end subroutine
54
55!CHECK-LABEL: func.func @_QPsimple_reduction_switch_order
56!CHECK:  %[[XREF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"}
57!CHECK:  %[[C0_2:.*]] = arith.constant 0 : i32
58!CHECK:  fir.store %[[C0_2]] to %[[XREF]] : !fir.ref<i32>
59!CHECK:  omp.parallel
60!CHECK:    %[[I_PVT_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
61!CHECK:    %[[C1_1:.*]] = arith.constant 1 : i32
62!CHECK:    %[[C100:.*]] = arith.constant 100 : i32
63!CHECK:    %[[C1_2:.*]] = arith.constant 1 : i32
64!CHECK:    omp.wsloop   reduction(@[[RED_I32_NAME]] -> %[[XREF]] : !fir.ref<i32>) for  (%[[IVAL:.*]]) : i32 = (%[[C1_1]]) to (%[[C100]]) inclusive step (%[[C1_2]])
65!CHECK:      fir.store %[[IVAL]] to %[[I_PVT_REF]] : !fir.ref<i32>
66!CHECK:      %[[I_PVT_VAL:.*]] = fir.load %[[I_PVT_REF]] : !fir.ref<i32>
67!CHECK:      omp.reduction %[[I_PVT_VAL]], %[[XREF]] : !fir.ref<i32>
68!CHECK:      omp.yield
69!CHECK:    omp.terminator
70!CHECK:  return
71
72subroutine simple_reduction_switch_order
73  integer :: x
74  x = 0
75  !$omp parallel
76  !$omp do reduction(+:x)
77  do i=1, 100
78    x = i + x
79  end do
80  !$omp end do
81  !$omp end parallel
82end subroutine
83
84!CHECK-LABEL: func.func @_QPmultiple_reductions_same_type
85!CHECK:  %[[XREF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_same_typeEx"}
86!CHECK:  %[[YREF:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_same_typeEy"}
87!CHECK:  %[[ZREF:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_same_typeEz"}
88!CHECK:  omp.parallel
89!CHECK:    %[[I_PVT_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
90!CHECK:    omp.wsloop   reduction(@[[RED_I32_NAME]] -> %[[XREF]] : !fir.ref<i32>, @[[RED_I32_NAME]] -> %[[YREF]] : !fir.ref<i32>, @[[RED_I32_NAME]] -> %[[ZREF]] : !fir.ref<i32>) for  (%[[IVAL]]) : i32
91!CHECK:      fir.store %[[IVAL]] to %[[I_PVT_REF]] : !fir.ref<i32>
92!CHECK:      %[[I_PVT_VAL1:.*]] = fir.load %[[I_PVT_REF]] : !fir.ref<i32>
93!CHECK:      omp.reduction %[[I_PVT_VAL1]], %[[XREF]] : !fir.ref<i32>
94!CHECK:      %[[I_PVT_VAL2:.*]] = fir.load %[[I_PVT_REF]] : !fir.ref<i32>
95!CHECK:      omp.reduction %[[I_PVT_VAL2]], %[[YREF]] : !fir.ref<i32>
96!CHECK:      %[[I_PVT_VAL3:.*]] = fir.load %[[I_PVT_REF]] : !fir.ref<i32>
97!CHECK:      omp.reduction %[[I_PVT_VAL3]], %[[ZREF]] : !fir.ref<i32>
98!CHECK:      omp.yield
99!CHECK:    omp.terminator
100!CHECK:  return
101
102subroutine multiple_reductions_same_type
103  integer :: x,y,z
104  x = 0
105  y = 0
106  z = 0
107  !$omp parallel
108  !$omp do reduction(+:x,y,z)
109  do i=1, 100
110    x = x + i
111    y = y + i
112    z = z + i
113  end do
114  !$omp end do
115  !$omp end parallel
116end subroutine
117
118!CHECK-LABEL: func.func @_QPmultiple_reductions_different_type
119!CHECK:  %[[XREF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"}
120!CHECK:  %[[YREF:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"}
121!CHECK:  omp.parallel
122!CHECK:    %[[I_PVT_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
123!CHECK:    omp.wsloop   reduction(@[[RED_I32_NAME]] -> %[[XREF]] : !fir.ref<i32>, @[[RED_I64_NAME]] -> %[[YREF]] : !fir.ref<i64>) for  (%[[IVAL:.*]]) : i32
124!CHECK:      fir.store %[[IVAL]] to %[[I_PVT_REF]] : !fir.ref<i32>
125!CHECK:      %[[C1_32:.*]] = arith.constant 1 : i32
126!CHECK:      omp.reduction %[[C1_32]], %[[XREF]] : !fir.ref<i32>
127!CHECK:      %[[C1_64:.*]] = arith.constant 1 : i64
128!CHECK:      omp.reduction %[[C1_64]], %[[YREF]] : !fir.ref<i64>
129!CHECK:      omp.yield
130!CHECK:    omp.terminator
131!CHECK:  return
132
133subroutine multiple_reductions_different_type
134  integer :: x
135  integer(kind=8) :: y
136  !$omp parallel
137  !$omp do reduction(+:x,y)
138  do i=1, 100
139    x = x + 1_4
140    y = y + 1_8
141  end do
142  !$omp end do
143  !$omp end parallel
144end subroutine
145