blob: ae6e047d94836f954492cf424f63f6b183418037 [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 Bataevc5b1d322016-03-04 09:22:22 +00004// expected-no-diagnostics
5
6#ifndef HEADER
7#define HEADER
8
9// CHECK: [[SSS_INT:.+]] = type { i32 }
10// CHECK-LOAD: [[SSS_INT:.+]] = type { i32 }
11
Alexey Bataeva7b19152017-10-12 20:03:39 +000012// CHECK: add
13void add(short &out, short &in) {}
14
15#pragma omp declare reduction(my_add : short : add(omp_out, omp_in))
16
17// CHECK: define internal void @.
18// CHECK: call void @{{.+}}add{{.+}}(
19// CHECK: ret void
20
21// CHECK: foo_reduction_array
22void foo_reduction_array() {
23 short y[1];
24 // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
25#pragma omp parallel for reduction(my_add : y)
26 for (int i = 0; i < 1; i++) {
27 }
28}
29
30// CHECK: define internal void @
31
Alexey Bataevc5b1d322016-03-04 09:22:22 +000032#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
33// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
34// CHECK: [[MUL:%.+]] = mul nsw i32
35// CHECK-NEXT: store i32 [[MUL]], i32*
36// CHECK-NEXT: ret void
37// CHECK-NEXT: }
38// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
39// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
40// CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
41// CHECK-LOAD-NEXT: ret void
42// CHECK-LOAD-NEXT: }
43
44// CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
45// CHECK: sext i8
46// CHECK: sext i8
47// CHECK: [[MUL:%.+]] = mul nsw i32
48// CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
49// CHECK-NEXT: store i8 [[TRUNC]], i8*
50// CHECK-NEXT: ret void
51// CHECK-NEXT: }
52
53// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
54// CHECK-LOAD: sext i8
55// CHECK-LOAD: sext i8
56// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
57// CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
58// CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8*
59// CHECK-LOAD-NEXT: ret void
60// CHECK-LOAD-NEXT: }
61
62template <class T>
63struct SSS {
64 T a;
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000065 SSS() : a() {}
Alexey Bataevc5b1d322016-03-04 09:22:22 +000066#pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig)
67};
68
69SSS<int> d;
70
71// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
72// CHECK: [[XOR:%.+]] = xor i32
73// CHECK-NEXT: store i32 [[XOR]], i32*
74// CHECK-NEXT: ret void
75// CHECK-NEXT: }
76
77// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
78// CHECK: [[ADD:%.+]] = add nsw i32 24,
79// CHECK-NEXT: store i32 [[ADD]], i32*
80// CHECK-NEXT: ret void
81// CHECK-NEXT: }
82
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000083// CHECK: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
84// CHECK-LOAD: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
Alexey Bataevc5b1d322016-03-04 09:22:22 +000085void init(SSS<int> &lhs, SSS<int> &rhs) {}
86
87#pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
88// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
89// CHECK: call void @llvm.memcpy
90// CHECK-NEXT: ret void
91// CHECK-NEXT: }
92// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +000093// CHECK: call {{.*}}void [[INIT]](
Alexey Bataevc5b1d322016-03-04 09:22:22 +000094// CHECK-NEXT: ret void
95// CHECK-NEXT: }
96
97// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
98// CHECK-LOAD: call void @llvm.memcpy
99// CHECK-LOAD-NEXT: ret void
100// CHECK-LOAD-NEXT: }
101// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000102// CHECK-LOAD: call {{.*}}void [[INIT]](
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000103// CHECK-LOAD-NEXT: ret void
104// CHECK-LOAD-NEXT: }
105
106template <typename T>
107T foo(T a) {
108#pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig)
109 {
110#pragma omp declare reduction(fun : T : omp_out /= omp_in) initializer(omp_priv = 11 - omp_orig)
111 }
112 return a;
113}
114
Alexey Bataevfdc20352017-08-25 15:43:55 +0000115struct Summary {
116 void merge(const Summary& other) {}
117};
118
119template <typename K>
120void work() {
121 Summary global_summary;
122#pragma omp declare reduction(+ : Summary : omp_out.merge(omp_in))
123#pragma omp parallel for reduction(+ : global_summary)
124 for (int k = 1; k <= 100; ++k) {
125 }
126}
127
128struct A {};
129
130
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000131// CHECK-LABEL: @main
132int main() {
133 int i = 0;
134 SSS<int> sss;
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000135#pragma omp parallel reduction(SSS < int > ::fun : i)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000136 {
137 i += 1;
138 }
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000139#pragma omp parallel reduction(::fun : sss)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000140 {
141 }
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000142#pragma omp declare reduction(fun : SSS < int > : init(omp_out, omp_in))
143#pragma omp parallel reduction(fun : sss)
144 {
145 }
146 // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
147 // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
148 // CHECK: call {{.*}}void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call({{[^@]*}} @{{[^@]*}}[[REGION:@[^ ]+]]
Alexey Bataevfdc20352017-08-25 15:43:55 +0000149 // CHECK-LABEL: work
150 work<A>();
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000151 // CHECK-LABEL: foo
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000152 return foo(15);
153}
154
Alexey Bataev8fbae8cf2016-04-27 11:38:05 +0000155// CHECK: define internal {{.*}}void [[REGION]](
156// CHECK: [[SSS_PRIV:%.+]] = alloca %struct.SSS,
157// CHECK: invoke {{.*}} @_ZN3SSSIiEC1Ev(%struct.SSS* [[SSS_PRIV]])
158// CHECK-NOT: {{call |invoke }}
159// CHECK: call {{.*}}i32 @__kmpc_reduce_nowait(
160
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000161// CHECK-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
162// CHECK-LOAD-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
163
164// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
165// CHECK-LOAD: [[XOR:%.+]] = xor i32
166// CHECK-LOAD-NEXT: store i32 [[XOR]], i32*
167// CHECK-LOAD-NEXT: ret void
168// CHECK-LOAD-NEXT: }
169
170// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
171// CHECK-LOAD: [[ADD:%.+]] = add nsw i32 24,
172// CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
173// CHECK-LOAD-NEXT: ret void
174// CHECK-LOAD-NEXT: }
175
176// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
177// CHECK: [[ADD:%.+]] = add nsw i32
178// CHECK-NEXT: store i32 [[ADD]], i32*
179// CHECK-NEXT: ret void
180// CHECK-NEXT: }
181// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
182// CHECK-LOAD: [[ADD:%.+]] = add nsw i32
183// CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
184// CHECK-LOAD-NEXT: ret void
185// CHECK-LOAD-NEXT: }
186
187// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
188// CHECK: [[MUL:%.+]] = mul nsw i32 15,
189// CHECK-NEXT: store i32 [[MUL]], i32*
190// CHECK-NEXT: ret void
191// CHECK-NEXT: }
192// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
193// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 15,
194// CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
195// CHECK-LOAD-NEXT: ret void
196// CHECK-LOAD-NEXT: }
197
198// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
199// CHECK: [[DIV:%.+]] = sdiv i32
200// CHECK-NEXT: store i32 [[DIV]], i32*
201// CHECK-NEXT: ret void
202// CHECK-NEXT: }
203// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
204// CHECK-LOAD: [[DIV:%.+]] = sdiv i32
205// CHECK-LOAD-NEXT: store i32 [[DIV]], i32*
206// CHECK-LOAD-NEXT: ret void
207// CHECK-LOAD-NEXT: }
208
209// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
210// CHECK: [[SUB:%.+]] = sub nsw i32 11,
211// CHECK-NEXT: store i32 [[SUB]], i32*
212// CHECK-NEXT: ret void
213// CHECK-NEXT: }
214// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
215// CHECK-LOAD: [[SUB:%.+]] = sub nsw i32 11,
216// CHECK-LOAD-NEXT: store i32 [[SUB]], i32*
217// CHECK-LOAD-NEXT: ret void
218// CHECK-LOAD-NEXT: }
219
220#endif