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