1 | // RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple x86_64-linux -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s |
2 | // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes |
3 | // RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-linux -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 |
4 | |
5 | // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -emit-llvm %s -triple x86_64-linux -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 x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes |
7 | // RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-linux -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}} |
9 | // 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 | |
17 | // CHECK: add |
18 | void 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 |
27 | void foo_reduction_array() { |
28 | short y[1]; |
29 | // CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call( |
30 | #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 | |
37 | #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 | |
67 | template <class T> |
68 | struct SSS { |
69 | T a; |
70 | SSS() : a() {} |
71 | #pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig) |
72 | }; |
73 | |
74 | SSS<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 | |
88 | // CHECK: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]* |
89 | // CHECK-LOAD: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]* |
90 | void 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) |
98 | // CHECK: call {{.*}}void [[INIT]]( |
99 | // 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) |
107 | // CHECK-LOAD: call {{.*}}void [[INIT]]( |
108 | // CHECK-LOAD-NEXT: ret void |
109 | // CHECK-LOAD-NEXT: } |
110 | |
111 | template <typename T> |
112 | T 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 | |
120 | struct Summary { |
121 | void merge(const Summary& other) {} |
122 | }; |
123 | |
124 | template <typename K> |
125 | void 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 | |
133 | struct A {}; |
134 | |
135 | |
136 | // CHECK-LABEL: @main |
137 | int main() { |
138 | int i = 0; |
139 | SSS<int> sss; |
140 | #pragma omp parallel reduction(SSS < int > ::fun : i) |
141 | { |
142 | i += 1; |
143 | } |
144 | #pragma omp parallel reduction(::fun : sss) |
145 | { |
146 | } |
147 | #pragma omp declare reduction(fun : SSS < int > : init(omp_out, omp_in)) |
148 | #pragma omp parallel reduction(fun : sss) |
149 | { |
150 | } |
151 | // 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:@[^ ]+]] |
154 | // CHECK-LABEL: work |
155 | work<A>(); |
156 | // CHECK-LABEL: foo |
157 | return foo(15); |
158 | } |
159 | |
160 | // CHECK: define internal {{.*}}void [[REGION]]( |
161 | // CHECK: [[SSS_PRIV:%.+]] = alloca %struct.SSS, |
162 | // CHECK: invoke {{.*}} @_ZN3SSSIiEC1Ev(%struct.SSS* [[SSS_PRIV]]) |
163 | // CHECK-NOT: {{call |invoke }} |
164 | // CHECK: call {{.*}}i32 @__kmpc_reduce_nowait( |
165 | |
166 | // 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 |
226 | |