1 // 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
4 // 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 
12 // CHECK: add
13 void 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
22 void 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 
32 #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 
62 template <class T>
63 struct SSS {
64   T a;
65   SSS() : a() {}
66 #pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig)
67 };
68 
69 SSS<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 
83 // CHECK: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
84 // CHECK-LOAD: define {{.*}}void [[INIT:@[^(]+]]([[SSS_INT]]*
85 void 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)
93 // CHECK: call {{.*}}void [[INIT]](
94 // 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)
102 // CHECK-LOAD: call {{.*}}void [[INIT]](
103 // CHECK-LOAD-NEXT: ret void
104 // CHECK-LOAD-NEXT: }
105 
106 template <typename T>
107 T 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 
115 struct Summary {
116   void merge(const Summary& other) {}
117 };
118 
119 template <typename K>
120 void 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 
128 struct A {};
129 
130 
131 // CHECK-LABEL: @main
132 int main() {
133   int i = 0;
134   SSS<int> sss;
135 #pragma omp parallel reduction(SSS < int > ::fun : i)
136   {
137     i += 1;
138   }
139 #pragma omp parallel reduction(::fun : sss)
140   {
141   }
142 #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:@[^ ]+]]
149   // CHECK-LABEL: work
150   work<A>();
151   // CHECK-LABEL: foo
152   return foo(15);
153 }
154 
155 // 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 
161 // 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
221