1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 2 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-enable-irbuilder -x c++ -emit-llvm %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefixes=ALL,IRBUILDER 3 // %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o /tmp/t1 %s 4 // %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch /tmp/t1 -verify %s -emit-llvm -o - | FileCheck --check-prefixes=ALL-DEBUG,IRBUILDER-DEBUG %s 5 6 // expected-no-diagnostics 7 8 // TODO: Teach the update script to check new functions too. 9 10 #ifndef HEADER 11 #define HEADER 12 13 // ALL-LABEL: @_Z17nested_parallel_0v( 14 // ALL-NEXT: entry: 15 // ALL-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1:[0-9]+]]) 16 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 17 // ALL: omp_parallel: 18 // ALL-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @_Z17nested_parallel_0v..omp_par.1 to void (i32*, i32*, ...)*)) 19 // ALL-NEXT: br label [[OMP_PAR_OUTLINED_EXIT12:%.*]] 20 // ALL: omp.par.outlined.exit12: 21 // ALL-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] 22 // ALL: omp.par.exit.split: 23 // ALL-NEXT: ret void 24 // 25 void nested_parallel_0(void) { 26 #pragma omp parallel 27 { 28 #pragma omp parallel 29 { 30 } 31 } 32 } 33 34 // ALL-LABEL: @_Z17nested_parallel_1Pfid( 35 // ALL-NEXT: entry: 36 // ALL-NEXT: [[STRUCTARG14:%.*]] = alloca { { i32*, double*, float** }*, i32*, double*, float** }, align 8 37 // ALL-NEXT: [[STRUCTARG:%.*]] = alloca { i32*, double*, float** }, align 8 38 // ALL-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 39 // ALL-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 40 // ALL-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 41 // ALL-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 42 // ALL-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 43 // ALL-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 44 // ALL-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]]) 45 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 46 // ALL: omp_parallel: 47 // ALL-NEXT: [[GEP_STRUCTARG:%.*]] = getelementptr { { i32*, double*, float** }*, i32*, double*, float** }, { { i32*, double*, float** }*, i32*, double*, float** }* [[STRUCTARG14]], i32 0, i32 0 48 // ALL-NEXT: store { i32*, double*, float** }* [[STRUCTARG]], { i32*, double*, float** }** [[GEP_STRUCTARG]], align 8 49 // ALL-NEXT: [[GEP_A_ADDR15:%.*]] = getelementptr { { i32*, double*, float** }*, i32*, double*, float** }, { { i32*, double*, float** }*, i32*, double*, float** }* [[STRUCTARG14]], i32 0, i32 1 50 // ALL-NEXT: store i32* [[A_ADDR]], i32** [[GEP_A_ADDR15]], align 8 51 // ALL-NEXT: [[GEP_B_ADDR16:%.*]] = getelementptr { { i32*, double*, float** }*, i32*, double*, float** }, { { i32*, double*, float** }*, i32*, double*, float** }* [[STRUCTARG14]], i32 0, i32 2 52 // ALL-NEXT: store double* [[B_ADDR]], double** [[GEP_B_ADDR16]], align 8 53 // ALL-NEXT: [[GEP_R_ADDR17:%.*]] = getelementptr { { i32*, double*, float** }*, i32*, double*, float** }, { { i32*, double*, float** }*, i32*, double*, float** }* [[STRUCTARG14]], i32 0, i32 3 54 // ALL-NEXT: store float** [[R_ADDR]], float*** [[GEP_R_ADDR17]], align 8 55 // ALL-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, { { i32*, double*, float** }*, i32*, double*, float** }*)* @_Z17nested_parallel_1Pfid..omp_par.2 to void (i32*, i32*, ...)*), { { i32*, double*, float** }*, i32*, double*, float** }* [[STRUCTARG14]]) 56 // ALL-NEXT: br label [[OMP_PAR_OUTLINED_EXIT13:%.*]] 57 // ALL: omp.par.outlined.exit13: 58 // ALL-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] 59 // ALL: omp.par.exit.split: 60 // ALL-NEXT: ret void 61 // 62 void nested_parallel_1(float *r, int a, double b) { 63 #pragma omp parallel 64 { 65 #pragma omp parallel 66 { 67 *r = a + b; 68 } 69 } 70 } 71 72 // ALL-LABEL: @_Z17nested_parallel_2Pfid( 73 // ALL-NEXT: entry: 74 // ALL-NEXT: [[STRUCTARG68:%.*]] = alloca { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, align 8 75 // ALL-NEXT: [[STRUCTARG64:%.*]] = alloca { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }, align 8 76 // ALL-NEXT: [[STRUCTARG59:%.*]] = alloca { i32*, double*, float** }, align 8 77 // ALL-NEXT: [[STRUCTARG:%.*]] = alloca { i32*, double*, float** }, align 8 78 // ALL-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 79 // ALL-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 80 // ALL-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 81 // ALL-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 82 // ALL-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 83 // ALL-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 84 // ALL-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]]) 85 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 86 // ALL: omp_parallel: 87 // ALL-NEXT: [[GEP_A_ADDR:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 0 88 // ALL-NEXT: store i32* [[A_ADDR]], i32** [[GEP_A_ADDR]], align 8 89 // ALL-NEXT: [[GEP_B_ADDR:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 1 90 // ALL-NEXT: store double* [[B_ADDR]], double** [[GEP_B_ADDR]], align 8 91 // ALL-NEXT: [[GEP_R_ADDR:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 2 92 // ALL-NEXT: store float** [[R_ADDR]], float*** [[GEP_R_ADDR]], align 8 93 // ALL-NEXT: [[GEP_STRUCTARG64:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 3 94 // ALL-NEXT: store { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG64]], { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }** [[GEP_STRUCTARG64]], align 8 95 // ALL-NEXT: [[GEP_STRUCTARG69:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 4 96 // ALL-NEXT: store { i32*, double*, float** }* [[STRUCTARG]], { i32*, double*, float** }** [[GEP_STRUCTARG69]], align 8 97 // ALL-NEXT: [[GEP_STRUCTARG5970:%.*]] = getelementptr { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]], i32 0, i32 5 98 // ALL-NEXT: store { i32*, double*, float** }* [[STRUCTARG59]], { i32*, double*, float** }** [[GEP_STRUCTARG5970]], align 8 99 // ALL-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @[[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }*)* @_Z17nested_parallel_2Pfid..omp_par.5 to void (i32*, i32*, ...)*), { i32*, double*, float**, { i32*, double*, float**, { i32*, double*, float** }*, { i32*, double*, float** }* }*, { i32*, double*, float** }*, { i32*, double*, float** }* }* [[STRUCTARG68]]) 100 // ALL-NEXT: br label [[OMP_PAR_OUTLINED_EXIT55:%.*]] 101 // ALL: omp.par.outlined.exit55: 102 // ALL-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] 103 // ALL: omp.par.exit.split: 104 // ALL-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 105 // ALL-NEXT: [[CONV56:%.*]] = sitofp i32 [[TMP0]] to double 106 // ALL-NEXT: [[TMP1:%.*]] = load double, double* [[B_ADDR]], align 8 107 // ALL-NEXT: [[ADD57:%.*]] = fadd double [[CONV56]], [[TMP1]] 108 // ALL-NEXT: [[CONV58:%.*]] = fptrunc double [[ADD57]] to float 109 // ALL-NEXT: [[TMP2:%.*]] = load float*, float** [[R_ADDR]], align 8 110 // ALL-NEXT: store float [[CONV58]], float* [[TMP2]], align 4 111 // ALL-NEXT: ret void 112 // 113 void nested_parallel_2(float *r, int a, double b) { 114 #pragma omp parallel 115 { 116 *r = a + b; 117 #pragma omp parallel 118 { 119 *r = a + b; 120 #pragma omp parallel 121 { 122 *r = a + b; 123 } 124 *r = a + b; 125 #pragma omp parallel 126 { 127 *r = a + b; 128 } 129 *r = a + b; 130 } 131 *r = a + b; 132 } 133 *r = a + b; 134 } 135 136 #endif 137