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 // CHECK-DAG: [[SSS_INIT:@.+]] = private constant %struct.SSS zeroinitializer 21 // CHECK-DAG: [[INT_INIT:@.+]] = private constant i32 0 22 23 #pragma omp declare reduction(+ : int, char : omp_out *= omp_in) 24 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias noundef %0, i32* noalias noundef %1) 25 // CHECK: [[MUL:%.+]] = mul nsw i32 26 // CHECK-NEXT: store i32 [[MUL]], i32* 27 // CHECK-NEXT: ret void 28 // CHECK-NEXT: } 29 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias noundef %0, i32* noalias noundef %1) 30 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 31 // CHECK-LOAD-NEXT: store i32 [[MUL]], i32* 32 // CHECK-LOAD-NEXT: ret void 33 // CHECK-LOAD-NEXT: } 34 35 // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias noundef %0, i8* noalias noundef %1) 36 // CHECK: sext i8 37 // CHECK: sext i8 38 // CHECK: [[MUL:%.+]] = mul nsw i32 39 // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 40 // CHECK-NEXT: store i8 [[TRUNC]], i8* 41 // CHECK-NEXT: ret void 42 // CHECK-NEXT: } 43 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias noundef %0, i8* noalias noundef %1) 44 // CHECK-LOAD: sext i8 45 // CHECK-LOAD: sext i8 46 // CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 47 // CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 48 // CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8* 49 // CHECK-LOAD-NEXT: ret void 50 // CHECK-LOAD-NEXT: } 51 52 #pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = 15 + omp_orig) 53 // CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias noundef %0, float* noalias noundef %1) 54 // CHECK: [[ADD:%.+]] = fadd float 55 // CHECK-NEXT: store float [[ADD]], float* 56 // CHECK-NEXT: ret void 57 // CHECK-NEXT: } 58 // CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias noundef %0, float* noalias noundef %1) 59 // CHECK: [[ADD:%.+]] = fadd float 1.5 60 // CHECK-NEXT: store float [[ADD]], float* 61 // CHECK-NEXT: ret void 62 // CHECK-NEXT: } 63 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias noundef %0, float* noalias noundef %1) 64 // CHECK-LOAD: [[ADD:%.+]] = fadd float 65 // CHECK-LOAD-NEXT: store float [[ADD]], float* 66 // CHECK-LOAD-NEXT: ret void 67 // CHECK-LOAD-NEXT: } 68 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias noundef %0, float* noalias noundef %1) 69 // CHECK-LOAD: [[ADD:%.+]] = fadd float 1.5 70 // CHECK-LOAD-NEXT: store float [[ADD]], float* 71 // CHECK-LOAD-NEXT: ret void 72 // CHECK-LOAD-NEXT: } 73 74 struct SSS { 75 int field; 76 #pragma omp declare reduction(+ : int, char : omp_out *= omp_in) 77 // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias noundef %0, i32* noalias noundef %1) 78 // CHECK: [[MUL:%.+]] = mul nsw i32 79 // CHECK-NEXT: store i32 [[MUL]], i32* 80 // CHECK-NEXT: ret void 81 // CHECK-NEXT: } 82 83 // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias noundef %0, i8* noalias noundef %1) 84 // CHECK: sext i8 85 // CHECK: sext i8 86 // CHECK: [[MUL:%.+]] = mul nsw i32 87 // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 88 // CHECK-NEXT: store i8 [[TRUNC]], i8* 89 // CHECK-NEXT: ret void 90 // CHECK-NEXT: } 91 }; 92 93 void init(struct SSS *priv, struct SSS orig); 94 95 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) 96 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 97 // CHECK: call void @llvm.memcpy 98 // CHECK-NEXT: ret void 99 // CHECK-NEXT: } 100 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 101 // CHECK: call void @init( 102 // CHECK-NEXT: ret void 103 // CHECK-NEXT: } 104 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 105 // CHECK-LOAD: call void @llvm.memcpy 106 // CHECK-LOAD-NEXT: ret void 107 // CHECK-LOAD-NEXT: } 108 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 109 // CHECK-LOAD: call void @init( 110 // CHECK-LOAD-NEXT: ret void 111 // CHECK-LOAD-NEXT: } 112 113 // CHECK-LABEL: @main 114 // CHECK-LOAD-LABEL: @main 115 int main() { 116 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) 117 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 118 // CHECK: call void @llvm.memcpy 119 // CHECK-NEXT: ret void 120 // CHECK-NEXT: } 121 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 122 // CHECK: call void @init( 123 // CHECK-NEXT: ret void 124 // CHECK-NEXT: } 125 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 126 // CHECK-LOAD: call void @llvm.memcpy 127 // CHECK-LOAD-NEXT: ret void 128 // CHECK-LOAD-NEXT: } 129 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 130 // CHECK-LOAD: call void @init( 131 // CHECK-LOAD-NEXT: ret void 132 // CHECK-LOAD-NEXT: } 133 { 134 #pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) 135 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 136 // CHECK: call void @llvm.memcpy 137 // CHECK-NEXT: ret void 138 // CHECK-NEXT: } 139 // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 140 // CHECK: call void @init( 141 // CHECK-NEXT: ret void 142 // CHECK-NEXT: } 143 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 144 // CHECK-LOAD: call void @llvm.memcpy 145 // CHECK-LOAD-NEXT: ret void 146 // CHECK-LOAD-NEXT: } 147 // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias noundef %0, [[SSS_INT]]* noalias noundef %1) 148 // CHECK-LOAD: call void @init( 149 // CHECK-LOAD-NEXT: ret void 150 // CHECK-LOAD-NEXT: } 151 } 152 return 0; 153 } 154 155 // OMP45-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias noundef %0, i32* noalias noundef %1) 156 // OMP45-LOAD: [[MUL:%.+]] = mul nsw i32 157 // OMP45-LOAD-NEXT: store i32 [[MUL]], i32* 158 // OMP45-LOAD-NEXT: ret void 159 // OMP45-LOAD-NEXT: } 160 161 // OMP45-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias noundef %0, i8* noalias noundef %1) 162 // OMP45-LOAD: sext i8 163 // OMP45-LOAD: sext i8 164 // OMP45-LOAD: [[MUL:%.+]] = mul nsw i32 165 // OMP45-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 166 // OMP45-LOAD-NEXT: store i8 [[TRUNC]], i8* 167 // OMP45-LOAD-NEXT: ret void 168 // OMP45-LOAD-NEXT: } 169 170 // CHECK-LABEL: bar 171 struct SSS ss; 172 int in; 173 void bar() { 174 // CHECK: [[SS_PRIV:%.+]] = alloca %struct.SSS, 175 // CHECK: [[IN_PRIV:%.+]] = alloca i32, 176 // CHECK: [[BC:%.+]] = bitcast %struct.SSS* [[SS_PRIV]] to i8* 177 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{64|32}}(i8* {{.*}}[[BC]], i8* {{.*}}bitcast (%struct.SSS* [[SSS_INIT]] to i8*), i{{64|32}} 4, i1 false) 178 // CHECK: [[IN_VAL:%.+]] = load i32, i32* [[INT_INIT]], 179 // CHECK: store i32 [[IN_VAL]], i32* [[IN_PRIV]], 180 // CHECK: call void @__kmpc_for_static_init_4( 181 #pragma omp declare reduction(+ \ 182 : struct SSS \ 183 : omp_out = omp_in) 184 #pragma omp declare reduction(+ \ 185 : int \ 186 : omp_out = omp_in) 187 #pragma omp for reduction(+ \ 188 : ss, in) 189 for (int i = 0; i < 10; ++i) 190 ; 191 } 192 #endif 193