blob: 90dbd47214df038a6b549343008bf85b863d368f [file] [log] [blame]
Chandler Carruth93786da2016-12-23 00:23:01 +00001// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
2// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
3// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix=CHECK-LOAD %s
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00004
5// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
6// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
7// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
8// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
Alexey Bataevc5b1d322016-03-04 09:22:22 +00009// expected-no-diagnostics
10
11#ifndef HEADER
12#define HEADER
13
14// CHECK: [[SSS_INT:.+]] = type { i32 }
15// CHECK-LOAD: [[SSS_INT:.+]] = type { i32 }
16
Alexey Bataeva7b19152017-10-12 20:03:39 +000017// CHECK: add
18void add(short &out, short &in) {}
19
20#pragma omp declare reduction(my_add : short : add(omp_out, omp_in))
21
22// CHECK: define internal void @.
23// CHECK: call void @{{.+}}add{{.+}}(
24// CHECK: ret void
25
26// CHECK: foo_reduction_array
27void foo_reduction_array() {
28 short y[1];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000029 // CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
Alexey Bataeva7b19152017-10-12 20:03:39 +000030#pragma omp parallel for reduction(my_add : y)
31 for (int i = 0; i < 1; i++) {
32 }
33}
34
35// CHECK: define internal void @
36
Alexey Bataevc5b1d322016-03-04 09:22:22 +000037#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
38// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
39// CHECK: [[MUL:%.+]] = mul nsw i32
40// CHECK-NEXT: store i32 [[MUL]], i32*
41// CHECK-NEXT: ret void
42// CHECK-NEXT: }
43// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
44// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
45// CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
46// CHECK-LOAD-NEXT: ret void
47// CHECK-LOAD-NEXT: }
48
49// CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
50// CHECK: sext i8
51// CHECK: sext i8
52// CHECK: [[MUL:%.+]] = mul nsw i32
53// CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
54// CHECK-NEXT: store i8 [[TRUNC]], i8*
55// CHECK-NEXT: ret void
56// CHECK-NEXT: }
57
58// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
59// CHECK-LOAD: sext i8
60// CHECK-LOAD: sext i8
61// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
62// CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
63// CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8*
64// CHECK-LOAD-NEXT: ret void
65// CHECK-LOAD-NEXT: }
66
67template <class T>
68struct SSS {
69 T a;
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000070 SSS() : a() {}
Alexey Bataevc5b1d322016-03-04 09:22:22 +000071#pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig)
72};
73
74SSS<int> d;
75
76// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
77// CHECK: [[XOR:%.+]] = xor i32
78// CHECK-NEXT: store i32 [[XOR]], i32*
79// CHECK-NEXT: ret void
80// CHECK-NEXT: }
81
82// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
83// CHECK: [[ADD:%.+]] = add nsw i32 24,
84// CHECK-NEXT: store i32 [[ADD]], i32*
85// CHECK-NEXT: ret void
86// CHECK-NEXT: }
87
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000088// CHECK: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
89// CHECK-LOAD: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
Alexey Bataevc5b1d322016-03-04 09:22:22 +000090void init(SSS<int> &lhs, SSS<int> &rhs) {}
91
92#pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
93// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
94// CHECK: call void @llvm.memcpy
95// CHECK-NEXT: ret void
96// CHECK-NEXT: }
97// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000098// CHECK: call {{.*}}void [[INIT]](
Alexey Bataevc5b1d322016-03-04 09:22:22 +000099// CHECK-NEXT: ret void
100// CHECK-NEXT: }
101
102// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
103// CHECK-LOAD: call void @llvm.memcpy
104// CHECK-LOAD-NEXT: ret void
105// CHECK-LOAD-NEXT: }
106// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000107// CHECK-LOAD: call {{.*}}void [[INIT]](
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000108// CHECK-LOAD-NEXT: ret void
109// CHECK-LOAD-NEXT: }
110
111template <typename T>
112T foo(T a) {
113#pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig)
114 {
115#pragma omp declare reduction(fun : T : omp_out /= omp_in) initializer(omp_priv = 11 - omp_orig)
116 }
117 return a;
118}
119
Alexey Bataevfdc20352017-08-25 15:43:55 +0000120struct Summary {
121 void merge(const Summary& other) {}
122};
123
124template <typename K>
125void work() {
126 Summary global_summary;
127#pragma omp declare reduction(+ : Summary : omp_out.merge(omp_in))
128#pragma omp parallel for reduction(+ : global_summary)
129 for (int k = 1; k <= 100; ++k) {
130 }
131}
132
133struct A {};
134
135
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000136// CHECK-LABEL: @main
137int main() {
138 int i = 0;
139 SSS<int> sss;
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000140#pragma omp parallel reduction(SSS < int > ::fun : i)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000141 {
142 i += 1;
143 }
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000144#pragma omp parallel reduction(::fun : sss)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000145 {
146 }
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000147#pragma omp declare reduction(fun : SSS < int > : init(omp_out, omp_in))
148#pragma omp parallel reduction(fun : sss)
149 {
150 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000151 // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
152 // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
153 // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call({{[^@]*}} @{{[^@]*}}[[REGION:@[^ ]+]]
Alexey Bataevfdc20352017-08-25 15:43:55 +0000154 // CHECK-LABEL: work
155 work<A>();
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000156 // CHECK-LABEL: foo
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000157 return foo(15);
158}
159
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000160// CHECK: define internal {{.*}}void [[REGION]](
161// CHECK: [[SSS_PRIV:%.+]] = alloca %struct.SSS,
Sean Fertiled900dd02018-10-15 15:43:00 +0000162// CHECK: invoke {{.*}} @_ZN3SSSIiEC1Ev(%struct.SSS* [[SSS_PRIV]])
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000163// CHECK-NOT: {{call |invoke }}
164// CHECK: call {{.*}}i32 @__kmpc_reduce_nowait(
165
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000166// CHECK-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
167// CHECK-LOAD-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
168
169// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
170// CHECK-LOAD: [[XOR:%.+]] = xor i32
171// CHECK-LOAD-NEXT: store i32 [[XOR]], i32*
172// CHECK-LOAD-NEXT: ret void
173// CHECK-LOAD-NEXT: }
174
175// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
176// CHECK-LOAD: [[ADD:%.+]] = add nsw i32 24,
177// CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
178// CHECK-LOAD-NEXT: ret void
179// CHECK-LOAD-NEXT: }
180
181// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
182// CHECK: [[ADD:%.+]] = add nsw i32
183// CHECK-NEXT: store i32 [[ADD]], i32*
184// CHECK-NEXT: ret void
185// CHECK-NEXT: }
186// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
187// CHECK-LOAD: [[ADD:%.+]] = add nsw i32
188// CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
189// CHECK-LOAD-NEXT: ret void
190// CHECK-LOAD-NEXT: }
191
192// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
193// CHECK: [[MUL:%.+]] = mul nsw i32 15,
194// CHECK-NEXT: store i32 [[MUL]], i32*
195// CHECK-NEXT: ret void
196// CHECK-NEXT: }
197// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
198// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 15,
199// CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
200// CHECK-LOAD-NEXT: ret void
201// CHECK-LOAD-NEXT: }
202
203// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
204// CHECK: [[DIV:%.+]] = sdiv i32
205// CHECK-NEXT: store i32 [[DIV]], i32*
206// CHECK-NEXT: ret void
207// CHECK-NEXT: }
208// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
209// CHECK-LOAD: [[DIV:%.+]] = sdiv i32
210// CHECK-LOAD-NEXT: store i32 [[DIV]], i32*
211// CHECK-LOAD-NEXT: ret void
212// CHECK-LOAD-NEXT: }
213
214// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
215// CHECK: [[SUB:%.+]] = sub nsw i32 11,
216// CHECK-NEXT: store i32 [[SUB]], i32*
217// CHECK-NEXT: ret void
218// CHECK-NEXT: }
219// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
220// CHECK-LOAD: [[SUB:%.+]] = sub nsw i32 11,
221// CHECK-LOAD-NEXT: store i32 [[SUB]], i32*
222// CHECK-LOAD-NEXT: ret void
223// CHECK-LOAD-NEXT: }
224
225#endif