mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-26 14:58:59 -04:00

Currently all variables used in OpenMP regions are captured into a record and passed to outlined functions in this record. It may result in some poor performance because of too complex analysis later in optimization passes. Patch makes to emit outlined functions for parallel-based regions with a list of captured variables. It reduces code for 2*n GEPs, stores and loads at least. Codegen for task-based regions remains unchanged because runtime requires that all captured variables are passed in captured record. llvm-svn: 247251
125 lines
4.8 KiB
C++
125 lines
4.8 KiB
C++
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
|
|
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -emit-pch -o %t %s
|
|
// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix=CHECK %s
|
|
// expected-no-diagnostics
|
|
#ifndef HEADER
|
|
#define HEADER
|
|
|
|
void fn1();
|
|
void fn2();
|
|
void fn3();
|
|
void fn4();
|
|
void fn5();
|
|
void fn6();
|
|
|
|
int Arg;
|
|
|
|
// CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test
|
|
void gtid_test() {
|
|
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, {{.+}}* [[GTID_TEST_REGION1:@.+]] to void
|
|
#pragma omp parallel
|
|
#pragma omp parallel if (parallel: false)
|
|
gtid_test();
|
|
// CHECK: ret void
|
|
}
|
|
|
|
// CHECK: define internal {{.*}}void [[GTID_TEST_REGION1]](i{{.+}}* noalias [[GTID_PARAM:%.+]], i32* noalias
|
|
// CHECK: store i{{[0-9]+}}* [[GTID_PARAM]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]],
|
|
// CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
|
|
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_ADDR]]
|
|
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]])
|
|
// CHECK: [[GTID_ADDR:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
|
|
// CHECK: call void [[GTID_TEST_REGION2:@.+]](i{{[0-9]+}}* [[GTID_ADDR]]
|
|
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]])
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal {{.*}}void [[GTID_TEST_REGION2]](
|
|
// CHECK: call {{.*}}void @{{.+}}gtid_test
|
|
// CHECK: ret void
|
|
|
|
template <typename T>
|
|
int tmain(T Arg) {
|
|
#pragma omp parallel if (true)
|
|
fn1();
|
|
#pragma omp parallel if (false)
|
|
fn2();
|
|
#pragma omp parallel if (parallel: Arg)
|
|
fn3();
|
|
return 0;
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main()
|
|
int main() {
|
|
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
|
|
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN4:@.+]] to void
|
|
#pragma omp parallel if (true)
|
|
fn4();
|
|
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
|
|
// CHECK: call void [[CAP_FN5:@.+]](i32* [[GTID_ADDR]],
|
|
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
#pragma omp parallel if (false)
|
|
fn5();
|
|
|
|
// CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]]
|
|
// CHECK: [[OMP_THEN]]
|
|
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN6:@.+]] to void
|
|
// CHECK: br label %[[OMP_END:.+]]
|
|
// CHECK: [[OMP_ELSE]]
|
|
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
|
|
// CHECK: call void [[CAP_FN6]](i32* [[GTID_ADDR]],
|
|
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: br label %[[OMP_END]]
|
|
// CHECK: [[OMP_END]]
|
|
#pragma omp parallel if (Arg)
|
|
fn6();
|
|
// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
|
|
return tmain(Arg);
|
|
}
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN4]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn4
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN5]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn5
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN6]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn6
|
|
// CHECK: ret void
|
|
|
|
// CHECK-LABEL: define {{.+}} @{{.+}}tmain
|
|
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num(
|
|
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN1:@.+]] to void
|
|
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
|
|
// CHECK: call void [[CAP_FN2:@.+]](i32* [[GTID_ADDR]],
|
|
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]]
|
|
// CHECK: [[OMP_THEN]]
|
|
// CHECK: call {{.*}}void {{.+}} @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{.+}} 0, void {{.+}}* [[CAP_FN3:@.+]] to void
|
|
// CHECK: br label %[[OMP_END:.+]]
|
|
// CHECK: [[OMP_ELSE]]
|
|
// CHECK: call {{.*}}void @__kmpc_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: store i32 [[GTID]], i32* [[GTID_ADDR:%.+]],
|
|
// CHECK: call void [[CAP_FN3]](i32* [[GTID_ADDR]],
|
|
// CHECK: call {{.*}}void @__kmpc_end_serialized_parallel(%{{.+}}* @{{.+}}, i32 [[GTID]])
|
|
// CHECK: br label %[[OMP_END]]
|
|
// CHECK: [[OMP_END]]
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN1]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn1
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN2]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn2
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal {{.*}}void [[CAP_FN3]]
|
|
// CHECK: call {{.*}}void @{{.+}}fn3
|
|
// CHECK: ret void
|
|
|
|
#endif
|