diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1452,6 +1452,19 @@ } } +static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, + SourceLocation Loc, + SmallString<128> &Buffer) { + llvm::raw_svector_ostream OS(Buffer); + // Build debug location + PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); + OS << ";" << PLoc.getFilename() << ";"; + if (const auto *FD = dyn_cast_or_null(CGF.CurFuncDecl)) + OS << FD->getQualifiedNameAsString(); + OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; + return OS.str(); +} + llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags) { @@ -1461,6 +1474,15 @@ Loc.isInvalid()) return getOrCreateDefaultLocation(Flags).getPointer(); + llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); + if (OMPBuilder) { + SmallString<128> Buffer; + OMPBuilder->updateToLocation(CGF.Builder.saveIP()); + auto *SrcLocStr = OMPBuilder->getOrCreateSrcLocStr( + getIdentStringFromSourceLocation(CGF, Loc, Buffer)); + return OMPBuilder->getOrCreateIdent(SrcLocStr, IdentFlag(Flags)); + } + assert(CGF.CurFn && "No function in current CodeGenFunction."); CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); @@ -1494,15 +1516,9 @@ llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); if (OMPDebugLoc == nullptr) { - SmallString<128> Buffer2; - llvm::raw_svector_ostream OS2(Buffer2); - // Build debug location - PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); - OS2 << ";" << PLoc.getFilename() << ";"; - if (const auto *FD = dyn_cast_or_null(CGF.CurFuncDecl)) - OS2 << FD->getQualifiedNameAsString(); - OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; - OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); + SmallString<128> Buffer; + OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr( + getIdentStringFromSourceLocation(CGF, Loc, Buffer)); OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; } // *psource = ";;;;;;"; @@ -1516,6 +1532,15 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, SourceLocation Loc) { assert(CGF.CurFn && "No function in current CodeGenFunction."); + llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); + if (OMPBuilder) { + SmallString<128> Buffer; + OMPBuilder->updateToLocation(CGF.Builder.saveIP()); + auto *SrcLocStr = OMPBuilder->getOrCreateSrcLocStr( + getIdentStringFromSourceLocation(CGF, Loc, Buffer)); + return OMPBuilder->getOrCreateThreadID( + OMPBuilder->getOrCreateIdent(SrcLocStr)); + } llvm::Value *ThreadID = nullptr; // Check whether we've already cached a load of the thread id in this diff --git a/clang/test/OpenMP/irbuilder_nested_parallel_for.c b/clang/test/OpenMP/irbuilder_nested_parallel_for.c new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/irbuilder_nested_parallel_for.c @@ -0,0 +1,299 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-enable-irbuilder -x c++ -emit-llvm %s -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefixes=CHECK %s +// RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -verify %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK-DEBUG %s + +// expected-no-diagnostics + +// TODO: Teach the update script to check new functions too. + +#ifndef HEADER +#define HEADER + +// CHECK-LABEL: @_Z14parallel_for_0v( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @1) +// CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK: omp_parallel: +// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @_Z14parallel_for_0v..omp_par to void (i32*, i32*, ...)*)) +// CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT:%.*]] +// CHECK: omp.par.outlined.exit: +// CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK: omp.par.exit.split: +// CHECK-NEXT: ret void +// +// CHECK-DEBUG-LABEL: @_Z14parallel_for_0v( +// CHECK-DEBUG-NEXT: entry: +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @1), !dbg !10 +// CHECK-DEBUG-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK-DEBUG: omp_parallel: +// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @_Z14parallel_for_0v..omp_par to void (i32*, i32*, ...)*)), !dbg !11 +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_OUTLINED_EXIT:%.*]] +// CHECK-DEBUG: omp.par.outlined.exit: +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK-DEBUG: omp.par.exit.split: +// CHECK-DEBUG-NEXT: ret void, !dbg !14 +// +void parallel_for_0(void) { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) { + } + } +} + +// CHECK-LABEL: @_Z14parallel_for_1Pfid( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @1) +// CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK: omp_parallel: +// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.1 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]) +// CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT19:%.*]] +// CHECK: omp.par.outlined.exit19: +// CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK: omp.par.exit.split: +// CHECK-NEXT: ret void +// +// CHECK-DEBUG-LABEL: @_Z14parallel_for_1Pfid( +// CHECK-DEBUG-NEXT: entry: +// CHECK-DEBUG-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 +// CHECK-DEBUG-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 +// CHECK-DEBUG-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata float** [[R_ADDR]], metadata !38, metadata !DIExpression()), !dbg !39 +// CHECK-DEBUG-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], metadata !40, metadata !DIExpression()), !dbg !39 +// CHECK-DEBUG-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata double* [[B_ADDR]], metadata !41, metadata !DIExpression()), !dbg !39 +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @12), !dbg !42 +// CHECK-DEBUG-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK-DEBUG: omp_parallel: +// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @12, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_1Pfid..omp_par.1 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), !dbg !43 +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_OUTLINED_EXIT19:%.*]] +// CHECK-DEBUG: omp.par.outlined.exit19: +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK-DEBUG: omp.par.exit.split: +// CHECK-DEBUG-NEXT: ret void, !dbg !45 +// +void parallel_for_1(float *r, int a, double b) { +#pragma omp parallel + { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) { + *r = a + b; + } + } + } +} + +// CHECK-LABEL: @_Z14parallel_for_2Pfid( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[DOTOMP_IV212:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[TMP213:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTOMP_LB214:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTOMP_UB215:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTOMP_STRIDE216:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[DOTOMP_IS_LAST217:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[I218:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @1) +// CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK: omp_parallel: +// CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]) +// CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT211:%.*]] +// CHECK: omp.par.outlined.exit211: +// CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK: omp.par.exit.split: +// CHECK-NEXT: store i32 0, i32* [[DOTOMP_LB214]], align 4 +// CHECK-NEXT: store i32 99, i32* [[DOTOMP_UB215]], align 4 +// CHECK-NEXT: store i32 1, i32* [[DOTOMP_STRIDE216]], align 4 +// CHECK-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST217]], align 4 +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM219:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @41) +// CHECK-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* @2, i32 [[OMP_GLOBAL_THREAD_NUM219]], i32 34, i32* [[DOTOMP_IS_LAST217]], i32* [[DOTOMP_LB214]], i32* [[DOTOMP_UB215]], i32* [[DOTOMP_STRIDE216]], i32 1, i32 1) +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4 +// CHECK-NEXT: [[CMP220:%.*]] = icmp sgt i32 [[TMP0]], 99 +// CHECK-NEXT: br i1 [[CMP220]], label [[COND_TRUE221:%.*]], label [[COND_FALSE222:%.*]] +// CHECK: cond.true221: +// CHECK-NEXT: br label [[COND_END223:%.*]] +// CHECK: cond.false222: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4 +// CHECK-NEXT: br label [[COND_END223]] +// CHECK: cond.end223: +// CHECK-NEXT: [[COND224:%.*]] = phi i32 [ 99, [[COND_TRUE221]] ], [ [[TMP1]], [[COND_FALSE222]] ] +// CHECK-NEXT: store i32 [[COND224]], i32* [[DOTOMP_UB215]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[DOTOMP_LB214]], align 4 +// CHECK-NEXT: store i32 [[TMP2]], i32* [[DOTOMP_IV212]], align 4 +// CHECK-NEXT: br label [[OMP_INNER_FOR_COND225:%.*]] +// CHECK: omp.inner.for.cond225: +// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4 +// CHECK-NEXT: [[CMP226:%.*]] = icmp sle i32 [[TMP3]], [[TMP4]] +// CHECK-NEXT: br i1 [[CMP226]], label [[OMP_INNER_FOR_BODY227:%.*]], label [[OMP_INNER_FOR_END236:%.*]] +// CHECK: omp.inner.for.body227: +// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4 +// CHECK-NEXT: [[MUL228:%.*]] = mul nsw i32 [[TMP5]], 1 +// CHECK-NEXT: [[ADD229:%.*]] = add nsw i32 0, [[MUL228]] +// CHECK-NEXT: store i32 [[ADD229]], i32* [[I218]], align 4 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[A_ADDR]], align 4 +// CHECK-NEXT: [[CONV230:%.*]] = sitofp i32 [[TMP6]] to double +// CHECK-NEXT: [[TMP7:%.*]] = load double, double* [[B_ADDR]], align 8 +// CHECK-NEXT: [[ADD231:%.*]] = fadd double [[CONV230]], [[TMP7]] +// CHECK-NEXT: [[CONV232:%.*]] = fptrunc double [[ADD231]] to float +// CHECK-NEXT: [[TMP8:%.*]] = load float*, float** [[R_ADDR]], align 8 +// CHECK-NEXT: store float [[CONV232]], float* [[TMP8]], align 4 +// CHECK-NEXT: br label [[OMP_BODY_CONTINUE233:%.*]] +// CHECK: omp.body.continue233: +// CHECK-NEXT: br label [[OMP_INNER_FOR_INC234:%.*]] +// CHECK: omp.inner.for.inc234: +// CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4 +// CHECK-NEXT: [[ADD235:%.*]] = add nsw i32 [[TMP9]], 1 +// CHECK-NEXT: store i32 [[ADD235]], i32* [[DOTOMP_IV212]], align 4 +// CHECK-NEXT: br label [[OMP_INNER_FOR_COND225]] +// CHECK: omp.inner.for.end236: +// CHECK-NEXT: br label [[OMP_LOOP_EXIT237:%.*]] +// CHECK: omp.loop.exit237: +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM238:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @43) +// CHECK-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @2, i32 [[OMP_GLOBAL_THREAD_NUM238]]) +// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM239:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @1) +// CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* @7, i32 [[OMP_GLOBAL_THREAD_NUM239]]) +// CHECK-NEXT: ret void +// +// CHECK-DEBUG-LABEL: @_Z14parallel_for_2Pfid( +// CHECK-DEBUG-NEXT: entry: +// CHECK-DEBUG-NEXT: [[R_ADDR:%.*]] = alloca float*, align 8 +// CHECK-DEBUG-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[B_ADDR:%.*]] = alloca double, align 8 +// CHECK-DEBUG-NEXT: [[DOTOMP_IV212:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[TMP213:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[DOTOMP_LB214:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[DOTOMP_UB215:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[DOTOMP_STRIDE216:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[DOTOMP_IS_LAST217:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: [[I218:%.*]] = alloca i32, align 4 +// CHECK-DEBUG-NEXT: store float* [[R:%.*]], float** [[R_ADDR]], align 8 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata float** [[R_ADDR]], metadata !65, metadata !DIExpression()), !dbg !66 +// CHECK-DEBUG-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[A_ADDR]], metadata !67, metadata !DIExpression()), !dbg !66 +// CHECK-DEBUG-NEXT: store double [[B:%.*]], double* [[B_ADDR]], align 8 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata double* [[B_ADDR]], metadata !68, metadata !DIExpression()), !dbg !66 +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @25), !dbg !69 +// CHECK-DEBUG-NEXT: br label [[OMP_PARALLEL:%.*]] +// CHECK-DEBUG: omp_parallel: +// CHECK-DEBUG-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @25, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, double*, float**)* @_Z14parallel_for_2Pfid..omp_par.4 to void (i32*, i32*, ...)*), i32* [[A_ADDR]], double* [[B_ADDR]], float** [[R_ADDR]]), !dbg !70 +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_OUTLINED_EXIT211:%.*]] +// CHECK-DEBUG: omp.par.outlined.exit211: +// CHECK-DEBUG-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] +// CHECK-DEBUG: omp.par.exit.split: +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[DOTOMP_IV212]], metadata !73, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[DOTOMP_LB214]], metadata !76, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: store i32 0, i32* [[DOTOMP_LB214]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[DOTOMP_UB215]], metadata !78, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: store i32 99, i32* [[DOTOMP_UB215]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[DOTOMP_STRIDE216]], metadata !79, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: store i32 1, i32* [[DOTOMP_STRIDE216]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[DOTOMP_IS_LAST217]], metadata !80, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST217]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: call void @llvm.dbg.declare(metadata i32* [[I218]], metadata !81, metadata !DIExpression()), !dbg !75 +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM219:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @97) +// CHECK-DEBUG-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* @96, i32 [[OMP_GLOBAL_THREAD_NUM219]], i32 34, i32* [[DOTOMP_IS_LAST217]], i32* [[DOTOMP_LB214]], i32* [[DOTOMP_UB215]], i32* [[DOTOMP_STRIDE216]], i32 1, i32 1), !dbg !82 +// CHECK-DEBUG-NEXT: [[TMP0:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[CMP220:%.*]] = icmp sgt i32 [[TMP0]], 99, !dbg !77 +// CHECK-DEBUG-NEXT: br i1 [[CMP220]], label [[COND_TRUE221:%.*]], label [[COND_FALSE222:%.*]], !dbg !77 +// CHECK-DEBUG: cond.true221: +// CHECK-DEBUG-NEXT: br label [[COND_END223:%.*]], !dbg !77 +// CHECK-DEBUG: cond.false222: +// CHECK-DEBUG-NEXT: [[TMP1:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: br label [[COND_END223]], !dbg !77 +// CHECK-DEBUG: cond.end223: +// CHECK-DEBUG-NEXT: [[COND224:%.*]] = phi i32 [ 99, [[COND_TRUE221]] ], [ [[TMP1]], [[COND_FALSE222]] ], !dbg !77 +// CHECK-DEBUG-NEXT: store i32 [[COND224]], i32* [[DOTOMP_UB215]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[TMP2:%.*]] = load i32, i32* [[DOTOMP_LB214]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: store i32 [[TMP2]], i32* [[DOTOMP_IV212]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: br label [[OMP_INNER_FOR_COND225:%.*]], !dbg !83 +// CHECK-DEBUG: omp.inner.for.cond225: +// CHECK-DEBUG-NEXT: [[TMP3:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[TMP4:%.*]] = load i32, i32* [[DOTOMP_UB215]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[CMP226:%.*]] = icmp sle i32 [[TMP3]], [[TMP4]], !dbg !77 +// CHECK-DEBUG-NEXT: br i1 [[CMP226]], label [[OMP_INNER_FOR_BODY227:%.*]], label [[OMP_INNER_FOR_END236:%.*]], !dbg !83 +// CHECK-DEBUG: omp.inner.for.body227: +// CHECK-DEBUG-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[MUL228:%.*]] = mul nsw i32 [[TMP5]], 1, !dbg !77 +// CHECK-DEBUG-NEXT: [[ADD229:%.*]] = add nsw i32 0, [[MUL228]], !dbg !77 +// CHECK-DEBUG-NEXT: store i32 [[ADD229]], i32* [[I218]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[TMP6:%.*]] = load i32, i32* [[A_ADDR]], align 4, !dbg !84 +// CHECK-DEBUG-NEXT: [[CONV230:%.*]] = sitofp i32 [[TMP6]] to double, !dbg !84 +// CHECK-DEBUG-NEXT: [[TMP7:%.*]] = load double, double* [[B_ADDR]], align 8, !dbg !84 +// CHECK-DEBUG-NEXT: [[ADD231:%.*]] = fadd double [[CONV230]], [[TMP7]], !dbg !84 +// CHECK-DEBUG-NEXT: [[CONV232:%.*]] = fptrunc double [[ADD231]] to float, !dbg !84 +// CHECK-DEBUG-NEXT: [[TMP8:%.*]] = load float*, float** [[R_ADDR]], align 8, !dbg !84 +// CHECK-DEBUG-NEXT: store float [[CONV232]], float* [[TMP8]], align 4, !dbg !84 +// CHECK-DEBUG-NEXT: br label [[OMP_BODY_CONTINUE233:%.*]], !dbg !84 +// CHECK-DEBUG: omp.body.continue233: +// CHECK-DEBUG-NEXT: br label [[OMP_INNER_FOR_INC234:%.*]], !dbg !82 +// CHECK-DEBUG: omp.inner.for.inc234: +// CHECK-DEBUG-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_IV212]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: [[ADD235:%.*]] = add nsw i32 [[TMP9]], 1, !dbg !77 +// CHECK-DEBUG-NEXT: store i32 [[ADD235]], i32* [[DOTOMP_IV212]], align 4, !dbg !77 +// CHECK-DEBUG-NEXT: br label [[OMP_INNER_FOR_COND225]], !dbg !82, !llvm.loop !85 +// CHECK-DEBUG: omp.inner.for.end236: +// CHECK-DEBUG-NEXT: br label [[OMP_LOOP_EXIT237:%.*]], !dbg !82 +// CHECK-DEBUG: omp.loop.exit237: +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM238:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @100) +// CHECK-DEBUG-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @99, i32 [[OMP_GLOBAL_THREAD_NUM238]]), !dbg !82 +// CHECK-DEBUG-NEXT: [[OMP_GLOBAL_THREAD_NUM239:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @103), !dbg !82 +// CHECK-DEBUG-NEXT: call void @__kmpc_barrier(%struct.ident_t* @102, i32 [[OMP_GLOBAL_THREAD_NUM239]]), !dbg !82 +// CHECK-DEBUG-NEXT: ret void, !dbg !86 +// +void parallel_for_2(float *r, int a, double b) { +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; + } +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; +#pragma omp parallel + { +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; + } +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; + } +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; + } +#pragma omp for + for (int i = 0; i < 100; ++i) + *r = a + b; +} + +#endif