1 // RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-optzns | 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-optzns
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-optzns | 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 #pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
13 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
14 // CHECK: [[MUL:%.+]] = mul nsw i32
15 // CHECK-NEXT: store i32 [[MUL]], i32*
16 // CHECK-NEXT: ret void
17 // CHECK-NEXT: }
18 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
19 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
20 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
21 // CHECK-LOAD-NEXT: ret void
22 // CHECK-LOAD-NEXT: }
23 
24 // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
25 // CHECK: sext i8
26 // CHECK: sext i8
27 // CHECK: [[MUL:%.+]] = mul nsw i32
28 // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
29 // CHECK-NEXT: store i8 [[TRUNC]], i8*
30 // CHECK-NEXT: ret void
31 // CHECK-NEXT: }
32 
33 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
34 // CHECK-LOAD: sext i8
35 // CHECK-LOAD: sext i8
36 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
37 // CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
38 // CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8*
39 // CHECK-LOAD-NEXT: ret void
40 // CHECK-LOAD-NEXT: }
41 
42 template <class T>
43 struct SSS {
44   T a;
45 #pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig)
46 };
47 
48 SSS<int> d;
49 
50 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
51 // CHECK: [[XOR:%.+]] = xor i32
52 // CHECK-NEXT: store i32 [[XOR]], i32*
53 // CHECK-NEXT: ret void
54 // CHECK-NEXT: }
55 
56 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
57 // CHECK: [[ADD:%.+]] = add nsw i32 24,
58 // CHECK-NEXT: store i32 [[ADD]], i32*
59 // CHECK-NEXT: ret void
60 // CHECK-NEXT: }
61 
62 // CHECK: define void [[INIT:@[^(]+]]([[SSS_INT]]*
63 // CHECK-LOAD: define void [[INIT:@[^(]+]]([[SSS_INT]]*
64 void init(SSS<int> &lhs, SSS<int> &rhs) {}
65 
66 #pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
67 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
68 // CHECK: call void @llvm.memcpy
69 // CHECK-NEXT: ret void
70 // CHECK-NEXT: }
71 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
72 // CHECK: call void [[INIT]](
73 // CHECK-NEXT: ret void
74 // CHECK-NEXT: }
75 
76 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
77 // CHECK-LOAD: call void @llvm.memcpy
78 // CHECK-LOAD-NEXT: ret void
79 // CHECK-LOAD-NEXT: }
80 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
81 // CHECK-LOAD: call void [[INIT]](
82 // CHECK-LOAD-NEXT: ret void
83 // CHECK-LOAD-NEXT: }
84 
85 template <typename T>
86 T foo(T a) {
87 #pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig)
88   {
89 #pragma omp declare reduction(fun : T : omp_out /= omp_in) initializer(omp_priv = 11 - omp_orig)
90   }
91   return a;
92 }
93 
94 // CHECK-LABEL: @main
95 int main() {
96   int i = 0;
97   SSS<int> sss;
98   // TODO: Add support for scoped reduction identifiers
99   //  #pragma omp parallel reduction(SSS<int>::fun : i)
100   // TODO-CHECK: #pragma omp parallel reduction(SSS<int>::fun: i)
101   {
102     i += 1;
103   }
104   // #pragma omp parallel reduction(::fun:sss)
105   // TODO-CHECK: #pragma omp parallel reduction(::fun: sss)
106   {
107   }
108   return foo(15);
109 }
110 
111 // CHECK-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
112 // CHECK-LOAD-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32
113 
114 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
115 // CHECK-LOAD: [[XOR:%.+]] = xor i32
116 // CHECK-LOAD-NEXT: store i32 [[XOR]], i32*
117 // CHECK-LOAD-NEXT: ret void
118 // CHECK-LOAD-NEXT: }
119 
120 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
121 // CHECK-LOAD: [[ADD:%.+]] = add nsw i32 24,
122 // CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
123 // CHECK-LOAD-NEXT: ret void
124 // CHECK-LOAD-NEXT: }
125 
126 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
127 // CHECK: [[ADD:%.+]] = add nsw i32
128 // CHECK-NEXT: store i32 [[ADD]], i32*
129 // CHECK-NEXT: ret void
130 // CHECK-NEXT: }
131 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
132 // CHECK-LOAD: [[ADD:%.+]] = add nsw i32
133 // CHECK-LOAD-NEXT: store i32 [[ADD]], i32*
134 // CHECK-LOAD-NEXT: ret void
135 // CHECK-LOAD-NEXT: }
136 
137 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
138 // CHECK: [[MUL:%.+]] = mul nsw i32 15,
139 // CHECK-NEXT: store i32 [[MUL]], i32*
140 // CHECK-NEXT: ret void
141 // CHECK-NEXT: }
142 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
143 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 15,
144 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
145 // CHECK-LOAD-NEXT: ret void
146 // CHECK-LOAD-NEXT: }
147 
148 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
149 // CHECK: [[DIV:%.+]] = sdiv i32
150 // CHECK-NEXT: store i32 [[DIV]], i32*
151 // CHECK-NEXT: ret void
152 // CHECK-NEXT: }
153 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
154 // CHECK-LOAD: [[DIV:%.+]] = sdiv i32
155 // CHECK-LOAD-NEXT: store i32 [[DIV]], i32*
156 // CHECK-LOAD-NEXT: ret void
157 // CHECK-LOAD-NEXT: }
158 
159 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
160 // CHECK: [[SUB:%.+]] = sub nsw i32 11,
161 // CHECK-NEXT: store i32 [[SUB]], i32*
162 // CHECK-NEXT: ret void
163 // CHECK-NEXT: }
164 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
165 // CHECK-LOAD: [[SUB:%.+]] = sub nsw i32 11,
166 // CHECK-LOAD-NEXT: store i32 [[SUB]], i32*
167 // CHECK-LOAD-NEXT: ret void
168 // CHECK-LOAD-NEXT: }
169 
170 #endif
171