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