// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++98 %s -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -x c++ -emit-llvm -std=c++11 %s -o - | FileCheck %s
// 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
// 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
// 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
// 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
// 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
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
int a;
int b;
struct St {
unsigned long field;
St() {}
~St() {}
int &get() { return a; }
};
// CHECK-LABEL: parallel_atomic_ewc
void parallel_atomic_ewc() {
St s;
#pragma omp parallel
{
// CHECK: invoke void @_ZN2StC1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR:%.+]])
// CHECK: [[SCALAR_ADDR:%.+]] = invoke noundef nonnull align 4 dereferenceable(4) ptr @_ZN2St3getEv(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
// CHECK: [[SCALAR_VAL:%.+]] = load atomic i32, ptr [[SCALAR_ADDR]] monotonic, align 4
// CHECK: store i32 [[SCALAR_VAL]], ptr @b
// CHECK98: invoke void @_ZN2StD1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
// CHECK11: call void @_ZN2StD1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
#pragma omp atomic read
b = St().get();
// CHECK-DAG: invoke void @_ZN2StC1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR:%.+]])
// CHECK-DAG: [[SCALAR_ADDR:%.+]] = invoke noundef nonnull align 4 dereferenceable(4) ptr @_ZN2St3getEv(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
// CHECK-DAG: [[B_VAL:%.+]] = load i32, ptr @b
// CHECK: store atomic i32 [[B_VAL]], ptr [[SCALAR_ADDR]] monotonic, align 4
// CHECK: {{invoke|call}} void @_ZN2StD1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
#pragma omp atomic write
St().get() = b;
// CHECK: invoke void @_ZN2StC1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR:%.+]])
// CHECK: [[SCALAR_ADDR:%.+]] = invoke noundef nonnull align 4 dereferenceable(4) ptr @_ZN2St3getEv(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
// CHECK: [[B_VAL:%.+]] = load i32, ptr @b
// CHECK: [[OLD_VAL:%.+]] = load atomic i32, ptr [[SCALAR_ADDR]] monotonic, align 4
// CHECK: br label %[[OMP_UPDATE:.+]]
// CHECK: [[OMP_UPDATE]]
// CHECK: [[OLD_PHI_VAL:%.+]] = phi i32 [ [[OLD_VAL]], %{{.+}} ], [ [[NEW_OLD_VAL:%.+]], %[[OMP_UPDATE]] ]
// CHECK: [[NEW_VAL:%.+]] = srem i32 [[OLD_PHI_VAL]], [[B_VAL]]
// CHECK: store i32 [[NEW_VAL]], ptr [[TEMP:%.+]],
// CHECK: [[NEW_VAL:%.+]] = load i32, ptr [[TEMP]],
// CHECK: [[RES:%.+]] = cmpxchg ptr [[SCALAR_ADDR]], i32 [[OLD_PHI_VAL]], i32 [[NEW_VAL]] monotonic monotonic, align 4
// CHECK: [[NEW_OLD_VAL]] = extractvalue { i32, i1 } [[RES]], 0
// CHECK: [[COND:%.+]] = extractvalue { i32, i1 } [[RES]], 1
// CHECK: br i1 [[COND]], label %[[OMP_DONE:.+]], label %[[OMP_UPDATE]]
// CHECK: [[OMP_DONE]]
// CHECK: {{invoke|call}} void @_ZN2StD1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
#pragma omp atomic
St().get() %= b;
#pragma omp atomic hint(6)
s.field++;
// CHECK: invoke void @_ZN2StC1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR:%.+]])
// CHECK: [[SCALAR_ADDR:%.+]] = invoke noundef nonnull align 4 dereferenceable(4) ptr @_ZN2St3getEv(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
// CHECK: [[B_VAL:%.+]] = load i32, ptr @b
// CHECK: [[OLD_VAL:%.+]] = load atomic i32, ptr [[SCALAR_ADDR]] monotonic, align 4
// CHECK: br label %[[OMP_UPDATE:.+]]
// CHECK: [[OMP_UPDATE]]
// CHECK: [[OLD_PHI_VAL:%.+]] = phi i32 [ [[OLD_VAL]], %{{.+}} ], [ [[NEW_OLD_VAL:%.+]], %[[OMP_UPDATE]] ]
// CHECK: [[NEW_CALC_VAL:%.+]] = srem i32 [[OLD_PHI_VAL]], [[B_VAL]]
// CHECK: store i32 [[NEW_CALC_VAL]], ptr [[TEMP:%.+]],
// CHECK: [[NEW_VAL:%.+]] = load i32, ptr [[TEMP]],
// CHECK: [[RES:%.+]] = cmpxchg ptr [[SCALAR_ADDR]], i32 [[OLD_PHI_VAL]], i32 [[NEW_VAL]] monotonic monotonic, align 4
// CHECK: [[NEW_OLD_VAL]] = extractvalue { i32, i1 } [[RES]], 0
// CHECK: [[COND:%.+]] = extractvalue { i32, i1 } [[RES]], 1
// CHECK: br i1 [[COND]], label %[[OMP_DONE:.+]], label %[[OMP_UPDATE]]
// CHECK: [[OMP_DONE]]
// CHECK: store i32 [[NEW_CALC_VAL]], ptr @a,
// CHECK: {{invoke|call}} void @_ZN2StD1Ev(ptr {{[^,]*}} [[TEMP_ST_ADDR]])
#pragma omp atomic capture
a = St().get() %= b;
}
}
int &foo() { extern void mayThrow(); mayThrow(); return a; }
// TERM_DEBUG-LABEL: parallel_atomic
void parallel_atomic() {
#pragma omp parallel
{
#pragma omp atomic read
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: invoke {{.*}}foo{{.*}}()
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG: load atomic i32, ptr @{{.+}} monotonic, align 4, !dbg [[READ_LOC:![0-9]+]]
foo() = a;
#pragma omp atomic write
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: invoke {{.*}}foo{{.*}}()
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: store atomic i32 {{%.+}}, ptr @{{.+}} monotonic, align 4, !dbg [[WRITE_LOC:![0-9]+]]
a = foo();
#pragma omp atomic update
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: invoke {{.*}}foo{{.*}}()
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: atomicrmw add ptr @{{.+}}, i32 %{{.+}} monotonic, align 4, !dbg [[UPDATE_LOC:![0-9]+]]
a += foo();
#pragma omp atomic capture
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: invoke {{.*}}foo{{.*}}()
// TERM_DEBUG: unwind label %[[TERM_LPAD:.+]],
// TERM_DEBUG-NOT: __kmpc_global_thread_num
// TERM_DEBUG: [[OLD_VAL:%.+]] = atomicrmw add ptr @{{.+}}, i32 %{{.+}} monotonic, align 4, !dbg [[CAPTURE_LOC:![0-9]+]]
// TERM_DEBUG: store i32 [[OLD_VAL]], ptr @b,
{b = a; a += foo(); }
}
// TERM_DEBUG: [[TERM_LPAD]]
// TERM_DEBUG: call void @__clang_call_terminate
// TERM_DEBUG: unreachable
}
// TERM_DEBUG-DAG: [[READ_LOC]] = !DILocation(line: [[@LINE-28]],
// TERM_DEBUG-DAG: [[WRITE_LOC]] = !DILocation(line: [[@LINE-22]],
// TERM_DEBUG-DAG: [[UPDATE_LOC]] = !DILocation(line: [[@LINE-16]],
// TERM_DEBUG-DAG: [[CAPTURE_LOC]] = !DILocation(line: [[@LINE-9]],