1 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck %s 2 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck %s 3 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck %s 4 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG 5 6 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s 7 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s 8 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s 9 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s 10 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} 11 // expected-no-diagnostics 12 13 int a; 14 int b; 15 16 struct St { 17 unsigned long field; 18 St() {} 19 ~St() {} 20 int &get() { return a; } 21 }; 22 23 // CHECK-LABEL: parallel_atomic_ewc 24 void parallel_atomic_ewc() { 25 St s; 26 #pragma omp parallel 27 { 28 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR:%.+]]) 29 // CHECK: [[SCALAR_ADDR:%.+]] = invoke nonnull align 4 dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 30 // CHECK: [[SCALAR_VAL:%.+]] = load atomic i32, i32* [[SCALAR_ADDR]] monotonic, align 4 31 // CHECK: store i32 [[SCALAR_VAL]], i32* @b 32 // CHECK98: invoke void @_ZN2StD1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 33 // CHECK11: call void @_ZN2StD1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 34 #pragma omp atomic read 35 b = St().get(); 36 // CHECK-DAG: invoke void @_ZN2StC1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR:%.+]]) 37 // CHECK-DAG: [[SCALAR_ADDR:%.+]] = invoke nonnull align 4 dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 38 // CHECK-DAG: [[B_VAL:%.+]] = load i32, i32* @b 39 // CHECK: store atomic i32 [[B_VAL]], i32* [[SCALAR_ADDR]] monotonic, align 4 40 // CHECK: {{invoke|call}} void @_ZN2StD1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 41 #pragma omp atomic write 42 St().get() = b; 43 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR:%.+]]) 44 // CHECK: [[SCALAR_ADDR:%.+]] = invoke nonnull align 4 dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 45 // CHECK: [[B_VAL:%.+]] = load i32, i32* @b 46 // CHECK: [[OLD_VAL:%.+]] = load atomic i32, i32* [[SCALAR_ADDR]] monotonic, align 4 47 // CHECK: br label %[[OMP_UPDATE:.+]] 48 // CHECK: [[OMP_UPDATE]] 49 // CHECK: [[OLD_PHI_VAL:%.+]] = phi i32 [ [[OLD_VAL]], %{{.+}} ], [ [[NEW_OLD_VAL:%.+]], %[[OMP_UPDATE]] ] 50 // CHECK: [[NEW_VAL:%.+]] = srem i32 [[OLD_PHI_VAL]], [[B_VAL]] 51 // CHECK: store i32 [[NEW_VAL]], i32* [[TEMP:%.+]], 52 // CHECK: [[NEW_VAL:%.+]] = load i32, i32* [[TEMP]], 53 // CHECK: [[RES:%.+]] = cmpxchg i32* [[SCALAR_ADDR]], i32 [[OLD_PHI_VAL]], i32 [[NEW_VAL]] monotonic monotonic, align 4 54 // CHECK: [[NEW_OLD_VAL]] = extractvalue { i32, i1 } [[RES]], 0 55 // CHECK: [[COND:%.+]] = extractvalue { i32, i1 } [[RES]], 1 56 // CHECK: br i1 [[COND]], label %[[OMP_DONE:.+]], label %[[OMP_UPDATE]] 57 // CHECK: [[OMP_DONE]] 58 // CHECK: {{invoke|call}} void @_ZN2StD1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 59 #pragma omp atomic 60 St().get() %= b; 61 #pragma omp atomic hint(6) 62 s.field++; 63 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR:%.+]]) 64 // CHECK: [[SCALAR_ADDR:%.+]] = invoke nonnull align 4 dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 65 // CHECK: [[B_VAL:%.+]] = load i32, i32* @b 66 // CHECK: [[OLD_VAL:%.+]] = load atomic i32, i32* [[SCALAR_ADDR]] monotonic, align 4 67 // CHECK: br label %[[OMP_UPDATE:.+]] 68 // CHECK: [[OMP_UPDATE]] 69 // CHECK: [[OLD_PHI_VAL:%.+]] = phi i32 [ [[OLD_VAL]], %{{.+}} ], [ [[NEW_OLD_VAL:%.+]], %[[OMP_UPDATE]] ] 70 // CHECK: [[NEW_CALC_VAL:%.+]] = srem i32 [[OLD_PHI_VAL]], [[B_VAL]] 71 // CHECK: store i32 [[NEW_CALC_VAL]], i32* [[TEMP:%.+]], 72 // CHECK: [[NEW_VAL:%.+]] = load i32, i32* [[TEMP]], 73 // CHECK: [[RES:%.+]] = cmpxchg i32* [[SCALAR_ADDR]], i32 [[OLD_PHI_VAL]], i32 [[NEW_VAL]] monotonic monotonic, align 4 74 // CHECK: [[NEW_OLD_VAL]] = extractvalue { i32, i1 } [[RES]], 0 75 // CHECK: [[COND:%.+]] = extractvalue { i32, i1 } [[RES]], 1 76 // CHECK: br i1 [[COND]], label %[[OMP_DONE:.+]], label %[[OMP_UPDATE]] 77 // CHECK: [[OMP_DONE]] 78 // CHECK: store i32 [[NEW_CALC_VAL]], i32* @a, 79 // CHECK: {{invoke|call}} void @_ZN2StD1Ev(%struct.St* {{[^,]*}} [[TEMP_ST_ADDR]]) 80 #pragma omp atomic capture 81 a = St().get() %= b; 82 } 83 } 84 85 int &foo() { extern void mayThrow(); mayThrow(); return a; } 86 87 // TERM_DEBUG-LABEL: parallel_atomic 88 void parallel_atomic() { 89 #pragma omp parallel 90 { 91 #pragma omp atomic read 92 // TERM_DEBUG-NOT: __kmpc_global_thread_num 93 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 94 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 95 // TERM_DEBUG: load atomic i32, i32* @{{.+}} monotonic, align 4, !dbg [[READ_LOC:![0-9]+]] 96 foo() = a; 97 #pragma omp atomic write 98 // TERM_DEBUG-NOT: __kmpc_global_thread_num 99 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 100 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 101 // TERM_DEBUG-NOT: __kmpc_global_thread_num 102 // TERM_DEBUG: store atomic i32 {{%.+}}, i32* @{{.+}} monotonic, align 4, !dbg [[WRITE_LOC:![0-9]+]] 103 a = foo(); 104 #pragma omp atomic update 105 // TERM_DEBUG-NOT: __kmpc_global_thread_num 106 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 107 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 108 // TERM_DEBUG-NOT: __kmpc_global_thread_num 109 // TERM_DEBUG: atomicrmw add i32* @{{.+}}, i32 %{{.+}} monotonic, align 4, !dbg [[UPDATE_LOC:![0-9]+]] 110 a += foo(); 111 #pragma omp atomic capture 112 // TERM_DEBUG-NOT: __kmpc_global_thread_num 113 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 114 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 115 // TERM_DEBUG-NOT: __kmpc_global_thread_num 116 // TERM_DEBUG: [[OLD_VAL:%.+]] = atomicrmw add i32* @{{.+}}, i32 %{{.+}} monotonic, align 4, !dbg [[CAPTURE_LOC:![0-9]+]] 117 // TERM_DEBUG: store i32 [[OLD_VAL]], i32* @b, 118 {b = a; a += foo(); } 119 } 120 // TERM_DEBUG: [[TERM_LPAD]] 121 // TERM_DEBUG: call void @__clang_call_terminate 122 // TERM_DEBUG: unreachable 123 } 124 // TERM_DEBUG-DAG: [[READ_LOC]] = !DILocation(line: [[@LINE-28]], 125 // TERM_DEBUG-DAG: [[WRITE_LOC]] = !DILocation(line: [[@LINE-22]], 126 // TERM_DEBUG-DAG: [[UPDATE_LOC]] = !DILocation(line: [[@LINE-16]], 127 // TERM_DEBUG-DAG: [[CAPTURE_LOC]] = !DILocation(line: [[@LINE-9]], 128