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
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