1 // RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
2 // RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
3 // RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -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 %itanium_abi_triple -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
6 // RUN: %clang_cc1 -fopenmp-simd -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
7 // RUN: %clang_cc1 -fopenmp-simd -x c -triple %itanium_abi_triple -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 #pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
18 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
19 // CHECK: [[MUL:%.+]] = mul nsw i32
20 // CHECK-NEXT: store i32 [[MUL]], i32*
21 // CHECK-NEXT: ret void
22 // CHECK-NEXT: }
23 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
24 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
25 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
26 // CHECK-LOAD-NEXT: ret void
27 // CHECK-LOAD-NEXT: }
28 
29 // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
30 // CHECK: sext i8
31 // CHECK: sext i8
32 // CHECK: [[MUL:%.+]] = mul nsw i32
33 // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
34 // CHECK-NEXT: store i8 [[TRUNC]], i8*
35 // CHECK-NEXT: ret void
36 // CHECK-NEXT: }
37 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
38 // CHECK-LOAD: sext i8
39 // CHECK-LOAD: sext i8
40 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
41 // CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
42 // CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8*
43 // CHECK-LOAD-NEXT: ret void
44 // CHECK-LOAD-NEXT: }
45 
46 #pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = 15 + omp_orig)
47 // CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias)
48 // CHECK: [[ADD:%.+]] = fadd float
49 // CHECK-NEXT: store float [[ADD]], float*
50 // CHECK-NEXT: ret void
51 // CHECK-NEXT: }
52 // CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias)
53 // CHECK: [[ADD:%.+]] = fadd float 1.5
54 // CHECK-NEXT: store float [[ADD]], float*
55 // CHECK-NEXT: ret void
56 // CHECK-NEXT: }
57 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias)
58 // CHECK-LOAD: [[ADD:%.+]] = fadd float
59 // CHECK-LOAD-NEXT: store float [[ADD]], float*
60 // CHECK-LOAD-NEXT: ret void
61 // CHECK-LOAD-NEXT: }
62 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias)
63 // CHECK-LOAD: [[ADD:%.+]] = fadd float 1.5
64 // CHECK-LOAD-NEXT: store float [[ADD]], float*
65 // CHECK-LOAD-NEXT: ret void
66 // CHECK-LOAD-NEXT: }
67 
68 struct SSS {
69   int field;
70 #pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
71   // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
72   // CHECK: [[MUL:%.+]] = mul nsw i32
73   // CHECK-NEXT: store i32 [[MUL]], i32*
74   // CHECK-NEXT: ret void
75   // CHECK-NEXT: }
76 
77   // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
78   // CHECK: sext i8
79   // CHECK: sext i8
80   // CHECK: [[MUL:%.+]] = mul nsw i32
81   // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
82   // CHECK-NEXT: store i8 [[TRUNC]], i8*
83   // CHECK-NEXT: ret void
84   // CHECK-NEXT: }
85 };
86 
87 void init(struct SSS *priv, struct SSS orig);
88 
89 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig))
90 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
91 // CHECK: call void @llvm.memcpy
92 // CHECK-NEXT: ret void
93 // CHECK-NEXT: }
94 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
95 // CHECK: call void @init(
96 // CHECK-NEXT: ret void
97 // CHECK-NEXT: }
98 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
99 // CHECK-LOAD: call void @llvm.memcpy
100 // CHECK-LOAD-NEXT: ret void
101 // CHECK-LOAD-NEXT: }
102 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
103 // CHECK-LOAD: call void @init(
104 // CHECK-LOAD-NEXT: ret void
105 // CHECK-LOAD-NEXT: }
106 
107 // CHECK-LABEL: @main
108 // CHECK-LOAD-LABEL: @main
109 int main() {
110 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig))
111   // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
112   // CHECK: call void @llvm.memcpy
113   // CHECK-NEXT: ret void
114   // CHECK-NEXT: }
115   // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
116   // CHECK: call void @init(
117   // CHECK-NEXT: ret void
118   // CHECK-NEXT: }
119   // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
120   // CHECK-LOAD: call void @llvm.memcpy
121   // CHECK-LOAD-NEXT: ret void
122   // CHECK-LOAD-NEXT: }
123   // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
124   // CHECK-LOAD: call void @init(
125   // CHECK-LOAD-NEXT: ret void
126   // CHECK-LOAD-NEXT: }
127   {
128 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig))
129     // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
130     // CHECK: call void @llvm.memcpy
131     // CHECK-NEXT: ret void
132     // CHECK-NEXT: }
133     // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
134     // CHECK: call void @init(
135     // CHECK-NEXT: ret void
136     // CHECK-NEXT: }
137     // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
138     // CHECK-LOAD: call void @llvm.memcpy
139     // CHECK-LOAD-NEXT: ret void
140     // CHECK-LOAD-NEXT: }
141     // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias)
142     // CHECK-LOAD: call void @init(
143     // CHECK-LOAD-NEXT: ret void
144     // CHECK-LOAD-NEXT: }
145   }
146   return 0;
147 }
148 
149 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias)
150 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
151 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32*
152 // CHECK-LOAD-NEXT: ret void
153 // CHECK-LOAD-NEXT: }
154 
155 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias)
156 // CHECK-LOAD: sext i8
157 // CHECK-LOAD: sext i8
158 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32
159 // CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8
160 // CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8*
161 // CHECK-LOAD-NEXT: ret void
162 // CHECK-LOAD-NEXT: }
163 #endif
164