1// RUN: mlir-opt -convert-scf-to-openmp -split-input-file %s | FileCheck %s
2
3// CHECK: omp.reduction.declare @[[$REDF:.*]] : f32
4
5// CHECK: init
6// CHECK: %[[INIT:.*]] = llvm.mlir.constant(0.000000e+00 : f32)
7// CHECK: omp.yield(%[[INIT]] : f32)
8
9// CHECK: combiner
10// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32)
11// CHECK: %[[RES:.*]] = arith.addf %[[ARG0]], %[[ARG1]]
12// CHECK: omp.yield(%[[RES]] : f32)
13
14// CHECK: atomic
15// CHECK: ^{{.*}}(%[[ARG0:.*]]: !llvm.ptr<f32>, %[[ARG1:.*]]: !llvm.ptr<f32>):
16// CHECK: %[[RHS:.*]] = llvm.load %[[ARG1]]
17// CHECK: llvm.atomicrmw fadd %[[ARG0]], %[[RHS]] monotonic
18
19// CHECK-LABEL: @reduction1
20func.func @reduction1(%arg0 : index, %arg1 : index, %arg2 : index,
21                 %arg3 : index, %arg4 : index) {
22  // CHECK: %[[CST:.*]] = arith.constant 0.0
23  // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1
24  // CHECK: %[[BUF:.*]] = llvm.alloca %[[ONE]] x f32
25  // CHECK: llvm.store %[[CST]], %[[BUF]]
26  %step = arith.constant 1 : index
27  %zero = arith.constant 0.0 : f32
28  // CHECK: omp.parallel
29  // CHECK: omp.wsloop
30  // CHECK-SAME: reduction(@[[$REDF]] -> %[[BUF]]
31  // CHECK: memref.alloca_scope
32  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3)
33                            step (%arg4, %step) init (%zero) -> (f32) {
34    // CHECK: %[[CST_INNER:.*]] = arith.constant 1.0
35    %one = arith.constant 1.0 : f32
36    // CHECK: omp.reduction %[[CST_INNER]], %[[BUF]]
37    scf.reduce(%one) : f32 {
38    ^bb0(%lhs : f32, %rhs: f32):
39      %res = arith.addf %lhs, %rhs : f32
40      scf.reduce.return %res : f32
41    }
42    // CHECK: omp.yield
43  }
44  // CHECK: omp.terminator
45  // CHECK: llvm.load %[[BUF]]
46  return
47}
48
49// -----
50
51// Only check the declaration here, the rest is same as above.
52// CHECK: omp.reduction.declare @{{.*}} : f32
53
54// CHECK: init
55// CHECK: %[[INIT:.*]] = llvm.mlir.constant(1.000000e+00 : f32)
56// CHECK: omp.yield(%[[INIT]] : f32)
57
58// CHECK: combiner
59// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32)
60// CHECK: %[[RES:.*]] = arith.mulf %[[ARG0]], %[[ARG1]]
61// CHECK: omp.yield(%[[RES]] : f32)
62
63// CHECK-NOT: atomic
64
65// CHECK-LABEL: @reduction2
66func.func @reduction2(%arg0 : index, %arg1 : index, %arg2 : index,
67                 %arg3 : index, %arg4 : index) {
68  %step = arith.constant 1 : index
69  %zero = arith.constant 0.0 : f32
70  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3)
71                            step (%arg4, %step) init (%zero) -> (f32) {
72    %one = arith.constant 1.0 : f32
73    scf.reduce(%one) : f32 {
74    ^bb0(%lhs : f32, %rhs: f32):
75      %res = arith.mulf %lhs, %rhs : f32
76      scf.reduce.return %res : f32
77    }
78  }
79  return
80}
81
82// -----
83
84// Only check the declaration here, the rest is same as above.
85// CHECK: omp.reduction.declare @{{.*}} : f32
86
87// CHECK: init
88// CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4
89// CHECK: omp.yield(%[[INIT]] : f32)
90
91// CHECK: combiner
92// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32)
93// CHECK: %[[CMP:.*]] = arith.cmpf oge, %[[ARG0]], %[[ARG1]]
94// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]]
95// CHECK: omp.yield(%[[RES]] : f32)
96
97// CHECK-NOT: atomic
98
99// CHECK-LABEL: @reduction3
100func.func @reduction3(%arg0 : index, %arg1 : index, %arg2 : index,
101                 %arg3 : index, %arg4 : index) {
102  %step = arith.constant 1 : index
103  %zero = arith.constant 0.0 : f32
104  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3)
105                            step (%arg4, %step) init (%zero) -> (f32) {
106    %one = arith.constant 1.0 : f32
107    scf.reduce(%one) : f32 {
108    ^bb0(%lhs : f32, %rhs: f32):
109      %cmp = arith.cmpf oge, %lhs, %rhs : f32
110      %res = arith.select %cmp, %lhs, %rhs : f32
111      scf.reduce.return %res : f32
112    }
113  }
114  return
115}
116
117// -----
118
119// CHECK: omp.reduction.declare @[[$REDF1:.*]] : f32
120
121// CHECK: init
122// CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4
123// CHECK: omp.yield(%[[INIT]] : f32)
124
125// CHECK: combiner
126// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32)
127// CHECK: %[[CMP:.*]] = arith.cmpf oge, %[[ARG0]], %[[ARG1]]
128// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]]
129// CHECK: omp.yield(%[[RES]] : f32)
130
131// CHECK-NOT: atomic
132
133// CHECK: omp.reduction.declare @[[$REDF2:.*]] : i64
134
135// CHECK: init
136// CHECK: %[[INIT:.*]] = llvm.mlir.constant
137// CHECK: omp.yield(%[[INIT]] : i64)
138
139// CHECK: combiner
140// CHECK: ^{{.*}}(%[[ARG0:.*]]: i64, %[[ARG1:.*]]: i64)
141// CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[ARG0]], %[[ARG1]]
142// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG1]], %[[ARG0]]
143// CHECK: omp.yield(%[[RES]] : i64)
144
145// CHECK: atomic
146// CHECK: ^{{.*}}(%[[ARG0:.*]]: !llvm.ptr<i64>, %[[ARG1:.*]]: !llvm.ptr<i64>):
147// CHECK: %[[RHS:.*]] = llvm.load %[[ARG1]]
148// CHECK: llvm.atomicrmw max %[[ARG0]], %[[RHS]] monotonic
149
150// CHECK-LABEL: @reduction4
151func.func @reduction4(%arg0 : index, %arg1 : index, %arg2 : index,
152                 %arg3 : index, %arg4 : index) -> (f32, i64) {
153  %step = arith.constant 1 : index
154  // CHECK: %[[ZERO:.*]] = arith.constant 0.0
155  %zero = arith.constant 0.0 : f32
156  // CHECK: %[[IONE:.*]] = arith.constant 1
157  %ione = arith.constant 1 : i64
158  // CHECK: %[[BUF1:.*]] = llvm.alloca %{{.*}} x f32
159  // CHECK: llvm.store %[[ZERO]], %[[BUF1]]
160  // CHECK: %[[BUF2:.*]] = llvm.alloca %{{.*}} x i64
161  // CHECK: llvm.store %[[IONE]], %[[BUF2]]
162
163  // CHECK: omp.parallel
164  // CHECK: omp.wsloop
165  // CHECK-SAME: reduction(@[[$REDF1]] -> %[[BUF1]]
166  // CHECK-SAME:           @[[$REDF2]] -> %[[BUF2]]
167  // CHECK: memref.alloca_scope
168  %res:2 = scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3)
169                        step (%arg4, %step) init (%zero, %ione) -> (f32, i64) {
170    %one = arith.constant 1.0 : f32
171    // CHECK: omp.reduction %{{.*}}, %[[BUF1]]
172    scf.reduce(%one) : f32 {
173    ^bb0(%lhs : f32, %rhs: f32):
174      %cmp = arith.cmpf oge, %lhs, %rhs : f32
175      %res = arith.select %cmp, %lhs, %rhs : f32
176      scf.reduce.return %res : f32
177    }
178    // CHECK: arith.fptosi
179    %1 = arith.fptosi %one : f32 to i64
180    // CHECK: omp.reduction %{{.*}}, %[[BUF2]]
181    scf.reduce(%1) : i64 {
182    ^bb1(%lhs: i64, %rhs: i64):
183      %cmp = arith.cmpi slt, %lhs, %rhs : i64
184      %res = arith.select %cmp, %rhs, %lhs : i64
185      scf.reduce.return %res : i64
186    }
187    // CHECK: omp.yield
188  }
189  // CHECK: omp.terminator
190  // CHECK: %[[RES1:.*]] = llvm.load %[[BUF1]]
191  // CHECK: %[[RES2:.*]] = llvm.load %[[BUF2]]
192  // CHECK: return %[[RES1]], %[[RES2]]
193  return %res#0, %res#1 : f32, i64
194}
195