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