1 // RUN: %clang_cc1 -no-opaque-pointers -verify -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s 2 // RUN: %clang_cc1 -no-opaque-pointers -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-pch -o %t %s 3 // RUN: %clang_cc1 -no-opaque-pointers -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s 4 5 // RUN: %clang_cc1 -no-opaque-pointers -verify -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s 6 // RUN: %clang_cc1 -no-opaque-pointers -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-pch -o %t %s 7 // RUN: %clang_cc1 -no-opaque-pointers -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s 8 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} 9 // 10 // expected-no-diagnostics 11 #ifndef HEADER 12 #define HEADER 13 void foo(); 14 void bar(); 15 16 // CHECK-LABEL: baz 17 void baz() { 18 int a = 0; 19 20 // CHECK: store i32 0, i32* [[A_ADDR:%.+]], 21 // CHECK: store i32 0, i32* [[OMP_CNT:%.+]], 22 // CHECK: br label %[[OMP_HEADER:.+]] 23 24 // CHECK: [[OMP_HEADER]]: 25 // CHECK: [[CNT_VAL:%.+]] = load i32, i32* [[OMP_CNT]], 26 // CHECK: [[CMP:%.+]] = icmp slt i32 [[CNT_VAL]], 10 27 // CHECK: br i1 [[CMP]], label %[[OMP_BODY:.+]], label %[[OMP_END:.+]] 28 #pragma omp simd reduction(inscan, + : a) 29 for (int i = 0; i < 10; ++i) { 30 // CHECK: [[OMP_BODY]]: 31 32 // i = OMP_CNT*1 + 0; 33 // CHECK: [[CNT_VAL:%.+]] = load i32, i32* [[OMP_CNT]], 34 // CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT_VAL]], 1 35 // CHECK: [[ADD:%.+]] = add nsw i32 0, [[MUL]] 36 // CHECK: store i32 [[ADD]], i32* [[I_ADDR:%.+]], 37 38 // A_PRIV = 0; 39 // CHECK: store i32 0, i32* [[A_PRIV_ADDR:%.+]], 40 41 // goto DISPATCH; 42 // CHECK: br label %[[DISPATCH:[^,]+]] 43 44 // INPUT_PHASE: 45 // foo(); 46 // goto REDUCE; 47 // CHECK: [[INPUT_PHASE:.+]]: 48 // CHECK: call void @{{.*}}foo{{.*}}() 49 // CHECK: br label %[[REDUCE:[^,]+]] 50 foo(); 51 52 // DISPATCH: 53 // goto INPUT_PHASE; 54 // CHECK: [[DISPATCH]]: 55 // CHECK: br label %[[INPUT_PHASE]] 56 57 // REDUCE: 58 // A = A_PRIV + A; 59 // A_PRIV = A; 60 // goto SCAN_PHASE; 61 // CHECK: [[REDUCE]]: 62 // CHECK: [[A:%.+]] = load i32, i32* [[A_ADDR]], 63 // CHECK: [[A_PRIV:%.+]] = load i32, i32* [[A_PRIV_ADDR]], 64 // CHECK: [[SUM:%.+]] = add nsw i32 [[A]], [[A_PRIV]] 65 // CHECK: store i32 [[SUM]], i32* [[A_ADDR]], 66 // CHECK: [[A:%.+]] = load i32, i32* [[A_ADDR]], 67 // CHECK: store i32 [[A]], i32* [[A_PRIV_ADDR]], 68 // CHECK: br label %[[SCAN_PHASE:[^,]+]] 69 #pragma omp scan inclusive(a) 70 71 // SCAN_PHASE: 72 // bar(); 73 // goto CONTINUE; 74 // CHECK: [[SCAN_PHASE]]: 75 // CHECK: call void @{{.*}}bar{{.*}}() 76 // CHECK: br label %[[CONTINUE:[^,]+]] 77 bar(); 78 79 // CHECK: [[CONTINUE]]: 80 // CHECK: br label %[[INC_BLOCK:[^,]+]] 81 82 // ++OMP_CNT; 83 // CHECK: [[INC_BLOCK]]: 84 // CHECK: [[CNT:%.+]] = load i32, i32* [[OMP_CNT]], 85 // CHECK: [[INC:%.+]] = add nsw i32 [[CNT]], 1 86 // CHECK: store i32 [[INC]], i32* [[OMP_CNT]], 87 // CHECK: br label %[[OMP_HEADER]] 88 } 89 // CHECK: [[OMP_END]]: 90 } 91 92 struct S { 93 int a; 94 S() {} 95 ~S() {} 96 S& operator+(const S&); 97 S& operator=(const S&); 98 }; 99 100 // CHECK-LABEL: xyz 101 void xyz() { 102 S s[2]; 103 104 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[S_ADDR:%.+]], i{{.+}} 0, i{{.+}} 0 105 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, %struct.S* [[S_BEGIN]], i{{.+}} 2 106 // CHECK: br label %[[ARRAY_INIT:.+]] 107 // CHECK: [[ARRAY_INIT]]: 108 // CHECK: [[S_CUR:%.+]] = phi %struct.S* [ [[S_BEGIN]], %{{.+}} ], [ [[S_NEXT:%.+]], %[[ARRAY_INIT]] ] 109 // CHECK: call void [[CONSTR:@.+]](%struct.S* {{[^,]*}} [[S_CUR]]) 110 // CHECK: [[S_NEXT]] = getelementptr inbounds %struct.S, %struct.S* [[S_CUR]], i{{.+}} 1 111 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[S_NEXT]], [[S_END]] 112 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT]] 113 // CHECK: [[DONE]]: 114 // CHECK: store i32 0, i32* [[OMP_CNT:%.+]], 115 // CHECK: br label %[[OMP_HEADER:.+]] 116 117 // CHECK: [[OMP_HEADER]]: 118 // CHECK: [[CNT_VAL:%.+]] = load i32, i32* [[OMP_CNT]], 119 // CHECK: [[CMP:%.+]] = icmp slt i32 [[CNT_VAL]], 10 120 // CHECK: br i1 [[CMP]], label %[[OMP_BODY:.+]], label %[[OMP_END:.+]] 121 #pragma omp simd reduction(inscan, + : s) 122 for (int i = 0; i < 10; ++i) { 123 // CHECK: [[OMP_BODY]]: 124 125 // i = OMP_CNT*1 + 0; 126 // CHECK: [[CNT_VAL:%.+]] = load i32, i32* [[OMP_CNT]], 127 // CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT_VAL]], 1 128 // CHECK: [[ADD:%.+]] = add nsw i32 0, [[MUL]] 129 // CHECK: store i32 [[ADD]], i32* [[I_ADDR:%.+]], 130 131 // S S_PRIV[2]; 132 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[S_PRIV_ADDR:%.+]], i{{.+}} 0, i{{.+}} 0 133 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, %struct.S* [[S_BEGIN]], i{{.+}} 2 134 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[S_BEGIN]], [[S_END]] 135 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT:[^,]+]] 136 // CHECK: [[ARRAY_INIT]]: 137 // CHECK: [[S_CUR:%.+]] = phi %struct.S* [ [[S_BEGIN]], %[[OMP_BODY]] ], [ [[S_NEXT:%.+]], %[[ARRAY_INIT]] ] 138 // CHECK: call void [[CONSTR]](%struct.S* {{[^,]*}} [[S_CUR]]) 139 // CHECK: [[S_NEXT]] = getelementptr {{.*}}%struct.S, %struct.S* [[S_CUR]], i{{.+}} 1 140 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[S_NEXT]], [[S_END]] 141 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT]] 142 // CHECK: [[DONE]]: 143 // CHECK: [[LHS_BEGIN:%.+]] = bitcast [2 x %struct.S]* [[S_ADDR]] to %struct.S* 144 // CHECK: [[RHS_BEGIN:%.+]] = bitcast [2 x %struct.S]* [[S_PRIV_ADDR]] to %struct.S* 145 146 // goto DISPATCH; 147 // CHECK: br label %[[DISPATCH:[^,]+]] 148 149 // SCAN_PHASE: 150 // foo(); 151 // goto CONTINUE; 152 // CHECK: [[SCAN_PHASE:.+]]: 153 // CHECK: call void @{{.*}}foo{{.*}}() 154 // CHECK: br label %[[CONTINUE:[^,]+]] 155 foo(); 156 157 // DISPATCH: 158 // goto INPUT_PHASE; 159 // CHECK: [[DISPATCH]]: 160 // CHECK: br label %[[INPUT_PHASE:[^,]+]] 161 162 // REDUCE: 163 // TEMP = S; 164 // S = S_PRIV + S; 165 // S_PRIV = TEMP; 166 // goto SCAN_PHASE; 167 // CHECK: [[REDUCE:.+]]: 168 169 // S TEMP[2]; 170 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[TEMP_ARR:%.+]], i32 0, i32 0 171 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr inbounds %struct.S, %struct.S* [[TEMP_ARR_BEG]], i64 2 172 // CHECK: br label %[[BODY:[^,]+]] 173 // CHECK: [[BODY]]: 174 // CHECK: [[CUR:%.+]] = phi %struct.S* [ [[TEMP_ARR_BEG]], %[[REDUCE]] ], [ [[NEXT:%.+]], %[[BODY]] ] 175 // CHECK: call void [[CONSTR]](%struct.S* {{[^,]*}} [[CUR]]) 176 // CHECK: [[NEXT]] = getelementptr inbounds %struct.S, %struct.S* [[CUR]], i64 1 177 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[NEXT]], [[TEMP_ARR_END]] 178 // CHECK: br i1 [[IS_DONE]], label %[[EXIT:[^,]+]], label %[[BODY]] 179 // CHECK: [[EXIT]]: 180 181 // TEMP = S; 182 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[TEMP_ARR]], i32 0, i32 0 183 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr %struct.S, %struct.S* [[TEMP_ARR_BEG]], i64 2 184 // CHECK: [[IS_EMPTY:%.+]] = icmp eq %struct.S* [[TEMP_ARR_BEG]], [[TEMP_ARR_END]] 185 // CHECK: br i1 [[IS_EMPTY]], label %[[EXIT:[^,]+]], label %[[BODY:[^,]+]] 186 // CHECK: [[BODY]]: 187 // CHECK: [[CUR_SRC:%.+]] = phi %struct.S* [ [[LHS_BEGIN]], %{{.+}} ], [ [[SRC_NEXT:%.+]], %[[BODY]] ] 188 // CHECK: [[CUR_DEST:%.+]] = phi %struct.S* [ [[TEMP_ARR_BEG]], %{{.+}} ], [ [[DEST_NEXT:%.+]], %[[BODY]] ] 189 // CHECK: call {{.*}}%struct.S* [[S_COPY:@.+]](%struct.S* {{[^,]*}} [[CUR_DEST]], %struct.S* {{.*}}[[CUR_SRC]]) 190 // CHECK: [[DEST_NEXT:%.+]] = getelementptr %struct.S, %struct.S* [[CUR_DEST]], i32 1 191 // CHECK: [[SRC_NEXT:%.+]] = getelementptr %struct.S, %struct.S* [[CUR_SRC]], i32 1 192 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[DEST_NEXT]], [[TEMP_ARR_END]] 193 // CHECK: br i1 [[IS_DONE]], label %[[EXIT]], label %[[BODY]] 194 // CHECK: [[EXIT]]: 195 196 // S = S_PRIV + S; 197 // CHECK: [[LHS_END:%.+]] = getelementptr {{.*}}%struct.S, %struct.S* [[LHS_BEGIN]], i{{.+}} 2 198 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[LHS_BEGIN]], [[LHS_END]] 199 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_REDUCE_COPY:[^,]+]] 200 // CHECK: [[ARRAY_REDUCE_COPY]]: 201 // CHECK: [[SRC_CUR:%.+]] = phi %struct.S* [ [[RHS_BEGIN]], %[[EXIT]] ], [ [[SRC_NEXT:%.+]], %[[ARRAY_REDUCE_COPY]] ] 202 // CHECK: [[DEST_CUR:%.+]] = phi %struct.S* [ [[LHS_BEGIN]], %[[EXIT]] ], [ [[DEST_NEXT:%.+]], %[[ARRAY_REDUCE_COPY]] ] 203 // CHECK: [[SUM:%.+]] = call {{.*}}%struct.S* @{{.+}}(%struct.S* {{[^,]*}} [[DEST_CUR]], %struct.S* {{.*}}[[SRC_CUR]]) 204 // CHECK: call {{.*}}%struct.S* [[S_COPY]](%struct.S* {{[^,]*}} [[DEST_CUR]], %struct.S* {{.*}}[[SUM]]) 205 // CHECK: [[DEST_NEXT]] = getelementptr {{.*}}%struct.S, %struct.S* [[DEST_CUR]], i{{.+}} 1 206 // CHECK: [[SRC_NEXT]] = getelementptr {{.*}}%struct.S, %struct.S* [[SRC_CUR]], i{{.+}} 1 207 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[DEST_NEXT]], [[LHS_END]] 208 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_REDUCE_COPY]] 209 // CHECK: [[DONE]]: 210 211 // S_PRIV = TEMP; 212 // CHECK: [[TEMP_ARR_BEG:%.+]] = bitcast [2 x %struct.S]* [[TEMP_ARR]] to %struct.S* 213 // CHECK: [[RHS_END:%.+]] = getelementptr %struct.S, %struct.S* [[RHS_BEGIN]], i64 2 214 // CHECK: [[IS_EMPTY:%.+]] = icmp eq %struct.S* [[RHS_BEGIN]], [[RHS_END]] 215 // CHECK: br i1 [[IS_EMPTY]], label %[[EXIT:[^,]+]], label %[[BODY:[^,]+]] 216 // CHECK: [[BODY]]: 217 // CHECK: [[CUR_SRC:%.+]] = phi %struct.S* [ [[TEMP_ARR_BEG]], %[[DONE]] ], [ [[SRC_NEXT:%.+]], %[[BODY]] ] 218 // CHECK: [[CUR_DEST:%.+]] = phi %struct.S* [ [[RHS_BEGIN]], %[[DONE]] ], [ [[DEST_NEXT:%.+]], %[[BODY]] ] 219 // CHECK: call {{.*}}%struct.S* [[S_COPY]](%struct.S* {{[^,]*}} [[CUR_DEST]], %struct.S* {{.*}}[[CUR_SRC]]) 220 // CHECK: [[DEST_NEXT]] = getelementptr %struct.S, %struct.S* [[CUR_DEST]], i32 1 221 // CHECK: [[SRC_NEXT]] = getelementptr %struct.S, %struct.S* [[CUR_SRC]], i32 1 222 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[DEST_NEXT]], [[RHS_END]] 223 // CHECK: br i1 [[IS_DONE]], label %[[DONE:[^,]+]], label %[[BODY]] 224 // CHECK: [[DONE]]: 225 226 // TEMP.~S() 227 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[TEMP_ARR]], i32 0, i32 0 228 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr inbounds %struct.S, %struct.S* [[TEMP_ARR_BEG]], i64 2 229 // CHECK: br label %[[BODY:[^,]+]] 230 // CHECK: [[BODY]]: 231 // CHECK: [[CUR:%.+]] = phi %struct.S* [ [[TEMP_ARR_END]], %[[DONE]] ], [ [[PREV:%.+]], %[[BODY]] ] 232 // CHECK: [[PREV]] = getelementptr inbounds %struct.S, %struct.S* [[CUR]], i64 -1 233 // CHECK: call void [[DESTR:@.+]](%struct.S* {{[^,]*}} [[PREV]]) 234 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[PREV]], [[TEMP_ARR_BEG]] 235 // CHECK: br i1 [[IS_DONE]], label %[[EXIT:[^,]+]], label %[[BODY]] 236 // CHECK: [[EXIT]]: 237 238 // goto SCAN_PHASE; 239 // CHECK: br label %[[SCAN_PHASE]] 240 #pragma omp scan exclusive(s) 241 242 // INPUT_PHASE: 243 // bar(); 244 // goto REDUCE; 245 // CHECK: [[INPUT_PHASE]]: 246 // CHECK: call void @{{.*}}bar{{.*}}() 247 // CHECK: br label %[[REDUCE]] 248 bar(); 249 250 // CHECK: [[CONTINUE]]: 251 252 // S_PRIV[2].~S(); 253 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], [2 x %struct.S]* [[S_PRIV_ADDR]], i{{.+}} 0, i{{.+}} 0 254 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, %struct.S* [[S_BEGIN]], i{{.+}} 2 255 // CHECK: br label %[[ARRAY_DESTR:[^,]+]] 256 // CHECK: [[ARRAY_DESTR]]: 257 // CHECK: [[S_CUR:%.+]] = phi %struct.S* [ [[S_END]], %[[CONTINUE]] ], [ [[S_PREV:%.+]], %[[ARRAY_DESTR]] ] 258 // CHECK: [[S_PREV]] = getelementptr {{.*}}%struct.S, %struct.S* [[S_CUR]], i{{.+}} -1 259 // CHECK: call void [[DESTR]](%struct.S* {{[^,]*}} [[S_PREV]]) 260 // CHECK: [[IS_DONE:%.+]] = icmp eq %struct.S* [[S_PREV]], [[S_BEGIN]] 261 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_DESTR]] 262 // CHECK: [[DONE]]: 263 // CHECK: br label %[[INC_BLOCK:[^,]+]] 264 265 // ++OMP_CNT; 266 // CHECK: [[INC_BLOCK]]: 267 // CHECK: [[CNT:%.+]] = load i32, i32* [[OMP_CNT]], 268 // CHECK: [[INC:%.+]] = add nsw i32 [[CNT]], 1 269 // CHECK: store i32 [[INC]], i32* [[OMP_CNT]], 270 // CHECK: br label %[[OMP_HEADER]] 271 } 272 // CHECK: [[OMP_END]]: 273 } 274 275 // CHECK-NOT: !{!"llvm.loop.parallel_accesses" 276 277 #endif // HEADER 278