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