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 %0, i32* noalias %1)
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 %0, i32* noalias %1)
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 %0, i8* noalias %1)
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 %0, i8* noalias %1)
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 #pragma omp declare reduction(sssss : T : ssssss(omp_in)) initializer(omp_priv = 18 + omp_orig)
73   static void ssssss(T &x);
74 };
75 
76 SSS<int> d;
77 
78 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
79 // CHECK: [[XOR:%.+]] = xor i32
80 // CHECK-NEXT: store i32 [[XOR]], i32*
81 // CHECK-NEXT: ret void
82 // CHECK-NEXT: }
83 
84 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
85 // CHECK: [[ADD:%.+]] = add nsw i32 24,
86 // CHECK-NEXT: store i32 [[ADD]], i32*
87 // CHECK-NEXT: ret void
88 // CHECK-NEXT: }
89 
90 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
91 // CHECK: call void @_ZN3SSSIiE6ssssssERi(i32* nonnull align {{[0-9]+}} dereferenceable{{.*}})
92 // CHECK-NEXT: ret void
93 // CHECK-NEXT: }
94 
95 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
96 // CHECK: [[ADD:%.+]] = add nsw i32 18,
97 // CHECK-NEXT: store i32 [[ADD]], i32*
98 // CHECK-NEXT: ret void
99 // CHECK-NEXT: }
100 
101 template <typename T>
102 void init(T &lhs, T &rhs) {}
103 
104 #pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
105 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
106 // CHECK: call void @llvm.memcpy
107 // CHECK-NEXT: ret void
108 // CHECK-NEXT: }
109 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
110 // CHECK: call {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(
111 // CHECK-NEXT: ret void
112 // CHECK-NEXT: }
113 
114 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
115 // CHECK-LOAD: call void @llvm.memcpy
116 // CHECK-LOAD-NEXT: ret void
117 // CHECK-LOAD-NEXT: }
118 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias %0, [[SSS_INT]]* noalias %1)
119 // CHECK-LOAD: call {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(
120 // CHECK-LOAD-NEXT: ret void
121 // CHECK-LOAD-NEXT: }
122 
123 // CHECK: define {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(%struct.SSS* {{.+}}, %struct.SSS* {{.+}})
124 // CHECK-LOAD: define {{.*}}void @_Z4initI3SSSIiEEvRT_S3_(%struct.SSS* {{.+}}, %struct.SSS* {{.+}})
125 
126 template <typename T>
127 T foo(T a) {
128 #pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig)
129   {
130 #pragma omp declare reduction(fun : T : omp_out /= omp_in) initializer(omp_priv = 11 - omp_orig)
131   }
132   return a;
133 }
134 
135 struct Summary {
136   void merge(const Summary& other) {}
137 };
138 
139 template <typename K>
140 void work() {
141   Summary global_summary;
142 #pragma omp declare reduction(+ : Summary : omp_out.merge(omp_in))
143 #pragma omp parallel for reduction(+ : global_summary)
144   for (int k = 1; k <= 100; ++k) {
145   }
146 }
147 
148 struct A {};
149 
150 
151 // CHECK-LABEL: @main
152 int main() {
153   int i = 0;
154   SSS<int> sss;
155 #pragma omp parallel reduction(SSS < int > ::fun : i)
156   {
157     i += 1;
158   }
159 #pragma omp parallel reduction(::fun : sss)
160   {
161   }
162 #pragma omp declare reduction(fun : SSS < int > : init(omp_out, omp_in))
163 #pragma omp parallel reduction(fun : sss)
164   {
165   }
166   // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
167   // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(
168   // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call({{[^@]*}} @{{[^@]*}}[[REGION:@[^ ]+]]
169   // CHECK-LABEL: work
170   work<A>();
171   // CHECK-LABEL: foo
172   return foo(15);
173 }
174 
175 // CHECK: define internal {{.*}}void [[REGION]](
176 // CHECK: [[SSS_PRIV:%.+]] = alloca %struct.SSS,
177 // CHECK: invoke {{.*}} @_ZN3SSSIiEC1Ev(%struct.SSS* [[SSS_PRIV]])
178 // CHECK-NOT: {{call |invoke }}
179 // CHECK: call {{.*}}i32 @__kmpc_reduce_nowait(
180 
181 // CHECK-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
182 // CHECK-LOAD-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
183 
184 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
185 // CHECK-LOAD: [[XOR:%.+]] = xor i32
186 // CHECK-LOAD-NEXT: store i32 [[XOR]], i32*
187 // CHECK-LOAD-NEXT: ret void
188 // CHECK-LOAD-NEXT: }
189 
190 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
191 // CHECK-LOAD: [[ADD:%.+]] = add nsw i32 24,
192 // CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
193 // CHECK-LOAD-NEXT: ret void
194 // CHECK-LOAD-NEXT: }
195 
196 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
197 // CHECK: [[ADD:%.+]] = add nsw i32
198 // CHECK-NEXT: store i32 [[ADD]], i32*
199 // CHECK-NEXT: ret void
200 // CHECK-NEXT: }
201 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
202 // CHECK-LOAD: [[ADD:%.+]] = add nsw i32
203 // CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
204 // CHECK-LOAD-NEXT: ret void
205 // CHECK-LOAD-NEXT: }
206 
207 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
208 // CHECK: [[MUL:%.+]] = mul nsw i32 15,
209 // CHECK-NEXT: store i32 [[MUL]], i32*
210 // CHECK-NEXT: ret void
211 // CHECK-NEXT: }
212 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
213 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 15,
214 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
215 // CHECK-LOAD-NEXT: ret void
216 // CHECK-LOAD-NEXT: }
217 
218 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
219 // CHECK: [[DIV:%.+]] = sdiv i32
220 // CHECK-NEXT: store i32 [[DIV]], i32*
221 // CHECK-NEXT: ret void
222 // CHECK-NEXT: }
223 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
224 // CHECK-LOAD: [[DIV:%.+]] = sdiv i32
225 // CHECK-LOAD-NEXT: store i32 [[DIV]], i32*
226 // CHECK-LOAD-NEXT: ret void
227 // CHECK-LOAD-NEXT: }
228 
229 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
230 // CHECK: [[SUB:%.+]] = sub nsw i32 11,
231 // CHECK-NEXT: store i32 [[SUB]], i32*
232 // CHECK-NEXT: ret void
233 // CHECK-NEXT: }
234 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
235 // CHECK-LOAD: [[SUB:%.+]] = sub nsw i32 11,
236 // CHECK-LOAD-NEXT: store i32 [[SUB]], i32*
237 // CHECK-LOAD-NEXT: ret void
238 // CHECK-LOAD-NEXT: }
239 
240 #endif
241