If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function. If condition evaluates to false, the code executes serial version of the code by executing the following code: call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>); proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>); call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>); Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false). Differential Revision: http://reviews.llvm.org/D9143 llvm-svn: 235507
134 lines
5.7 KiB
C++
134 lines
5.7 KiB
C++
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
|
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
|
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -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{{.+}} 1, {{.+}}* [[GTID_TEST_REGION1:@.+]] to void
|
|
#pragma omp parallel
|
|
#pragma omp task if (false)
|
|
gtid_test();
|
|
// CHECK: ret void
|
|
}
|
|
|
|
// CHECK: define internal void [[GTID_TEST_REGION1]](i32* [[GTID_PARAM:%.+]], i
|
|
// CHECK: store i32* [[GTID_PARAM]], i32** [[GTID_ADDR_REF:%.+]],
|
|
// CHECK: [[GTID_ADDR:%.+]] = load i32*, i32** [[GTID_ADDR_REF]]
|
|
// CHECK: [[GTID:%.+]] = load i32, i32* [[GTID_ADDR]]
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc(
|
|
// CHECK: [[TASK_PTR:%.+]] = bitcast i8* [[ORIG_TASK_PTR]] to
|
|
// CHECK: call void @__kmpc_omp_task_begin_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: call i32 [[GTID_TEST_REGION2:@.+]](i32 [[GTID]], %{{.+}}* [[TASK_PTR]])
|
|
// CHECK: call void @__kmpc_omp_task_complete_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: ret void
|
|
|
|
// CHECK: define internal i32 [[GTID_TEST_REGION2]](
|
|
// CHECK: call void @{{.+}}gtid_test
|
|
// CHECK: ret i32
|
|
|
|
template <typename T>
|
|
int tmain(T Arg) {
|
|
#pragma omp task if (true)
|
|
fn1();
|
|
#pragma omp task if (false)
|
|
fn2();
|
|
#pragma omp task if (Arg)
|
|
fn3();
|
|
return 0;
|
|
}
|
|
|
|
// CHECK-LABEL: @main
|
|
int main() {
|
|
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc({{[^,]+}}, i32 [[GTID]], i32 1, i64 32, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[CAP_FN4:[^ ]+]] to i32 (i32, i8*)*))
|
|
// CHECK: call i32 @__kmpc_omp_task(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
#pragma omp task if (true)
|
|
fn4();
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc(
|
|
// CHECK: [[TASK_PTR:%.+]] = bitcast i8* [[ORIG_TASK_PTR]] to
|
|
// CHECK: call void @__kmpc_omp_task_begin_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: call i32 [[CAP_FN5:@.+]](i32 [[GTID]], %{{.+}}* [[TASK_PTR]])
|
|
// CHECK: call void @__kmpc_omp_task_complete_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
#pragma omp task if (false)
|
|
fn5();
|
|
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc({{[^,]+}}, i32 [[GTID]], i32 1, i64 32, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[CAP_FN6:[^ ]+]] to i32 (i32, i8*)*))
|
|
// CHECK: [[TASK_PTR:%.+]] = bitcast i8* [[ORIG_TASK_PTR]] to
|
|
// CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]]
|
|
// CHECK: [[OMP_THEN]]
|
|
// CHECK: call i32 @__kmpc_omp_task(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: br label %[[OMP_END:.+]]
|
|
// CHECK: [[OMP_ELSE]]
|
|
// CHECK: call void @__kmpc_omp_task_begin_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: call i32 [[CAP_FN6:@.+]](i32 [[GTID]], %{{.+}}* [[TASK_PTR]])
|
|
// CHECK: call void @__kmpc_omp_task_complete_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: br label %[[OMP_END]]
|
|
// CHECK: [[OMP_END]]
|
|
#pragma omp task if (Arg)
|
|
fn6();
|
|
// CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain
|
|
return tmain(Arg);
|
|
}
|
|
|
|
// CHECK: define internal i32 [[CAP_FN4]]
|
|
// CHECK: call void @{{.+}}fn4
|
|
// CHECK: ret i32
|
|
|
|
// CHECK: define internal i32 [[CAP_FN5]]
|
|
// CHECK: call void @{{.+}}fn5
|
|
// CHECK: ret i32
|
|
|
|
// CHECK: define internal i32 [[CAP_FN6]]
|
|
// CHECK: call void @{{.+}}fn6
|
|
// CHECK: ret i32
|
|
|
|
// CHECK-LABEL: define {{.+}} @{{.+}}tmain
|
|
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^,]+}}, i32 [[GTID]], i32 1, i64 32, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[CAP_FN1:[^ ]+]] to i32 (i32, i8*)*))
|
|
// CHECK: call i32 @__kmpc_omp_task(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc(
|
|
// CHECK: [[TASK_PTR:%.+]] = bitcast i8* [[ORIG_TASK_PTR]] to
|
|
// CHECK: call void @__kmpc_omp_task_begin_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: call i32 [[CAP_FN2:@.+]](i32 [[GTID]], %{{.+}}* [[TASK_PTR]])
|
|
// CHECK: call void @__kmpc_omp_task_complete_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
|
|
// CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^,]+}}, i32 [[GTID]], i32 1, i64 32, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[CAP_FN3:[^ ]+]] to i32 (i32, i8*)*))
|
|
// CHECK: [[TASK_PTR:%.+]] = bitcast i8* [[ORIG_TASK_PTR]] to
|
|
// CHECK: br i1 %{{.+}}, label %[[OMP_THEN:.+]], label %[[OMP_ELSE:.+]]
|
|
// CHECK: [[OMP_THEN]]
|
|
// CHECK: call i32 @__kmpc_omp_task(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: br label %[[OMP_END:.+]]
|
|
// CHECK: [[OMP_ELSE]]
|
|
// CHECK: call void @__kmpc_omp_task_begin_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: call i32 [[CAP_FN3:@.+]](i32 [[GTID]], %{{.+}}* [[TASK_PTR]])
|
|
// CHECK: call void @__kmpc_omp_task_complete_if0(%{{.+}}* @{{.+}}, i{{.+}} [[GTID]], i8* [[ORIG_TASK_PTR]])
|
|
// CHECK: br label %[[OMP_END]]
|
|
// CHECK: [[OMP_END]]
|
|
|
|
// CHECK: define internal i32 [[CAP_FN1]]
|
|
// CHECK: call void @{{.+}}fn1
|
|
// CHECK: ret i32
|
|
|
|
// CHECK: define internal i32 [[CAP_FN2]]
|
|
// CHECK: call void @{{.+}}fn2
|
|
// CHECK: ret i32
|
|
|
|
// CHECK: define internal i32 [[CAP_FN3]]
|
|
// CHECK: call void @{{.+}}fn3
|
|
// CHECK: ret i32
|
|
|
|
#endif
|