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(ptr @[[GLOB1:[0-9]+]]) 16 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 17 // ALL: omp_parallel: 18 // ALL-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 0, ptr @_Z17nested_parallel_0v..omp_par.1) 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 { ptr, ptr, ptr }, align 8 37 // ALL-NEXT: [[R_ADDR:%.*]] = alloca ptr, align 8 38 // ALL-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 39 // ALL-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 40 // ALL-NEXT: store ptr [[R:%.*]], ptr [[R_ADDR]], align 8 41 // ALL-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 42 // ALL-NEXT: store double [[B:%.*]], ptr [[B_ADDR]], align 8 43 // ALL-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) 44 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 45 // ALL: omp_parallel: 46 // ALL-NEXT: [[GEP_A_ADDR15:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG14]], i32 0, i32 0 47 // ALL-NEXT: store ptr [[A_ADDR]], ptr [[GEP_A_ADDR15]], align 8 48 // ALL-NEXT: [[GEP_B_ADDR16:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG14]], i32 0, i32 1 49 // ALL-NEXT: store ptr [[B_ADDR]], ptr [[GEP_B_ADDR16]], align 8 50 // ALL-NEXT: [[GEP_R_ADDR17:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG14]], i32 0, i32 2 51 // ALL-NEXT: store ptr [[R_ADDR]], ptr [[GEP_R_ADDR17]], align 8 52 // ALL-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @_Z17nested_parallel_1Pfid..omp_par.2, ptr [[STRUCTARG14]]) 53 // ALL-NEXT: br label [[OMP_PAR_OUTLINED_EXIT13:%.*]] 54 // ALL: omp.par.outlined.exit13: 55 // ALL-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] 56 // ALL: omp.par.exit.split: 57 // ALL-NEXT: ret void 58 // 59 void nested_parallel_1(float *r, int a, double b) { 60 #pragma omp parallel 61 { 62 #pragma omp parallel 63 { 64 *r = a + b; 65 } 66 } 67 } 68 69 // ALL-LABEL: @_Z17nested_parallel_2Pfid( 70 // ALL-NEXT: entry: 71 // ALL-NEXT: [[STRUCTARG:%.*]] = alloca { ptr, ptr, ptr }, align 8 72 // ALL-NEXT: [[R_ADDR:%.*]] = alloca ptr, align 8 73 // ALL-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 74 // ALL-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 75 // ALL-NEXT: store ptr [[R:%.*]], ptr [[R_ADDR]], align 8 76 // ALL-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 77 // ALL-NEXT: store double [[B:%.*]], ptr [[B_ADDR]], align 8 78 // ALL-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) 79 // ALL-NEXT: br label [[OMP_PARALLEL:%.*]] 80 // ALL: omp_parallel: 81 // ALL-NEXT: [[GEP_A_ADDR:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG]], i32 0, i32 0 82 // ALL-NEXT: store ptr [[A_ADDR]], ptr [[GEP_A_ADDR]], align 8 83 // ALL-NEXT: [[GEP_B_ADDR:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG]], i32 0, i32 1 84 // ALL-NEXT: store ptr [[B_ADDR]], ptr [[GEP_B_ADDR]], align 8 85 // ALL-NEXT: [[GEP_R_ADDR:%.*]] = getelementptr { ptr, ptr, ptr }, ptr [[STRUCTARG]], i32 0, i32 2 86 // ALL-NEXT: store ptr [[R_ADDR]], ptr [[GEP_R_ADDR]], align 8 87 // ALL-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @_Z17nested_parallel_2Pfid..omp_par.5, ptr [[STRUCTARG]]) 88 // ALL-NEXT: br label [[OMP_PAR_OUTLINED_EXIT55:%.*]] 89 // ALL: omp.par.outlined.exit55: 90 // ALL-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] 91 // ALL: omp.par.exit.split: 92 // ALL-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 93 // ALL-NEXT: [[CONV56:%.*]] = sitofp i32 [[TMP0]] to double 94 // ALL-NEXT: [[TMP1:%.*]] = load double, ptr [[B_ADDR]], align 8 95 // ALL-NEXT: [[ADD57:%.*]] = fadd double [[CONV56]], [[TMP1]] 96 // ALL-NEXT: [[CONV58:%.*]] = fptrunc double [[ADD57]] to float 97 // ALL-NEXT: [[TMP2:%.*]] = load ptr, ptr [[R_ADDR]], align 8 98 // ALL-NEXT: store float [[CONV58]], ptr [[TMP2]], align 4 99 // ALL-NEXT: ret void 100 // 101 void nested_parallel_2(float *r, int a, double b) { 102 #pragma omp parallel 103 { 104 *r = a + b; 105 #pragma omp parallel 106 { 107 *r = a + b; 108 #pragma omp parallel 109 { 110 *r = a + b; 111 } 112 *r = a + b; 113 #pragma omp parallel 114 { 115 *r = a + b; 116 } 117 *r = a + b; 118 } 119 *r = a + b; 120 } 121 *r = a + b; 122 } 123 124 #endif 125