1 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp=libiomp5 -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck %s 2 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp=libiomp5 -fexceptions -fcxx-exceptions -gline-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG 3 // expected-no-diagnostics 4 5 int a; 6 int b; 7 8 struct St { 9 St() {} 10 ~St() {} 11 int &get() { return a; } 12 }; 13 14 // CHECK-LABEL: parallel_atomic_ewc 15 void parallel_atomic_ewc() { 16 #pragma omp parallel 17 { 18 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* [[TEMP_ST_ADDR:%.+]]) 19 // CHECK: [[SCALAR_ADDR:%.+]] = invoke dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* [[TEMP_ST_ADDR]]) 20 // CHECK: [[SCALAR_VAL:%.+]] = load atomic i32, i32* [[SCALAR_ADDR]] monotonic 21 // CHECK: store i32 [[SCALAR_VAL]], i32* @b 22 // CHECK: invoke void @_ZN2StD1Ev(%struct.St* [[TEMP_ST_ADDR]]) 23 #pragma omp atomic read 24 b = St().get(); 25 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* [[TEMP_ST_ADDR:%.+]]) 26 // CHECK: [[SCALAR_ADDR:%.+]] = invoke dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* [[TEMP_ST_ADDR]]) 27 // CHECK: [[B_VAL:%.+]] = load i32, i32* @b 28 // CHECK: store atomic i32 [[B_VAL]], i32* [[SCALAR_ADDR]] monotonic 29 // CHECK: invoke void @_ZN2StD1Ev(%struct.St* [[TEMP_ST_ADDR]]) 30 #pragma omp atomic write 31 St().get() = b; 32 // CHECK: invoke void @_ZN2StC1Ev(%struct.St* [[TEMP_ST_ADDR:%.+]]) 33 // CHECK: [[SCALAR_ADDR:%.+]] = invoke dereferenceable(4) i32* @_ZN2St3getEv(%struct.St* [[TEMP_ST_ADDR]]) 34 // CHECK: [[B_VAL:%.+]] = load i32, i32* @b 35 // CHECK: [[OLD_VAL:%.+]] = load atomic i32, i32* [[SCALAR_ADDR]] monotonic, 36 // CHECK: br label %[[OMP_UPDATE:.+]] 37 // CHECK: [[OMP_UPDATE]] 38 // CHECK: [[OLD_PHI_VAL:%.+]] = phi i32 [ [[OLD_VAL]], %{{.+}} ], [ [[NEW_OLD_VAL:%.+]], %[[OMP_UPDATE]] ] 39 // CHECK: [[NEW_VAL:%.+]] = srem i32 [[OLD_PHI_VAL]], [[B_VAL]] 40 // CHECK: [[RES:%.+]] = cmpxchg i32* [[SCALAR_ADDR]], i32 [[OLD_PHI_VAL]], i32 [[NEW_VAL]] monotonic monotonic 41 // CHECK: [[NEW_OLD_VAL]] = extractvalue { i32, i1 } [[RES]], 0 42 // CHECK: [[COND:%.+]] = extractvalue { i32, i1 } [[RES]], 1 43 // CHECK: br i1 [[COND]], label %[[OMP_DONE:.+]], label %[[OMP_UPDATE]] 44 // CHECK: [[OMP_DONE]] 45 // CHECK: invoke void @_ZN2StD1Ev(%struct.St* [[TEMP_ST_ADDR]]) 46 #pragma omp atomic 47 St().get() %= b; 48 } 49 } 50 51 int &foo() { return a; } 52 53 // TERM_DEBUG-LABEL: parallel_atomic 54 void parallel_atomic() { 55 #pragma omp parallel 56 { 57 #pragma omp atomic read 58 // TERM_DEBUG-NOT: __kmpc_global_thread_num 59 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 60 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 61 // TERM_DEBUG: load atomic i32, i32* @{{.+}} monotonic, {{.*}}!dbg [[READ_LOC:![0-9]+]] 62 foo() = a; 63 #pragma omp atomic write 64 // TERM_DEBUG-NOT: __kmpc_global_thread_num 65 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 66 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 67 // TERM_DEBUG-NOT: __kmpc_global_thread_num 68 // TERM_DEBUG: store atomic i32 {{%.+}}, i32* @{{.+}} monotonic, {{.*}}!dbg [[WRITE_LOC:![0-9]+]] 69 a = foo(); 70 #pragma omp atomic update 71 // TERM_DEBUG-NOT: __kmpc_global_thread_num 72 // TERM_DEBUG: invoke {{.*}}foo{{.*}}() 73 // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], 74 // TERM_DEBUG-NOT: __kmpc_global_thread_num 75 // TERM_DEBUG: atomicrmw add i32* @{{.+}}, i32 %{{.+}} monotonic, {{.*}}!dbg [[UPDATE_LOC:![0-9]+]] 76 a += foo(); 77 } 78 // TERM_DEBUG: [[TERM_LPAD]] 79 // TERM_DEBUG: call void @__clang_call_terminate 80 // TERM_DEBUG: unreachable 81 } 82 // TERM_DEBUG-DAG: [[READ_LOC]] = !MDLocation(line: [[@LINE-25]], 83 // TERM_DEBUG-DAG: [[WRITE_LOC]] = !MDLocation(line: [[@LINE-20]], 84 // TERM_DEBUG-DAG: [[UPDATE_LOC]] = !MDLocation(line: [[@LINE-14]], 85