Commit e3b69230 authored by Alexey Bataev's avatar Alexey Bataev
Browse files

Merging r258307 and r258495:

------------------------------------------------------------------------
r258307 | abataev | 2016-01-20 15:29:47 +0300 (Wed, 20 Jan 2016) | 3 lines

[OPENMP 4.0] Fix for codegen of 'cancel' directive within 'sections' directive.
Allow to emit code for 'cancel' directive within 'sections' directive with single sub-section.

------------------------------------------------------------------------
r258495 | abataev | 2016-01-22 11:56:50 +0300 (Fri, 22 Jan 2016) | 3 lines

[OPENMP] Generalize codegen for 'sections'-based directive.
If 'sections' directive has only one sub-section, the code for 'single'-based directive was emitted. Removed this codegen, because it causes crashes in different cases.

------------------------------------------------------------------------

llvm-svn: 259160
parent 994d374e
Loading
Loading
Loading
Loading
+4 −13
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
    if (ThreadID != nullptr)
      return ThreadID;
  }
  if (auto OMPRegionInfo =
  if (auto *OMPRegionInfo =
          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
    if (OMPRegionInfo->getThreadIDVariable()) {
      // Check if this an outlined function with thread id passed as argument.
@@ -1356,7 +1356,7 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
// return the address of that temp.
Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
                                             SourceLocation Loc) {
  if (auto OMPRegionInfo =
  if (auto *OMPRegionInfo =
          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
    if (OMPRegionInfo->getThreadIDVariable())
      return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
@@ -1717,15 +1717,10 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
  }
  // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
  // thread_id);
  auto *OMPRegionInfo =
      dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
  // Do not emit barrier call in the single directive emitted in some rare cases
  // for sections directives.
  if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
    return;
  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
                         getThreadID(CGF, Loc)};
  if (OMPRegionInfo) {
  if (auto *OMPRegionInfo =
          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
    if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
      auto *Result = CGF.EmitRuntimeCall(
          createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
@@ -3649,8 +3644,6 @@ void CGOpenMPRuntime::emitCancellationPointCall(
  // global_tid, kmp_int32 cncl_kind);
  if (auto *OMPRegionInfo =
          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
    if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
      return;
    if (OMPRegionInfo->hasCancel()) {
      llvm::Value *Args[] = {
          emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
@@ -3687,8 +3680,6 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
  // kmp_int32 cncl_kind);
  if (auto *OMPRegionInfo =
          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
    if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
      return;
    auto &&ThenGen = [this, Loc, CancelRegion,
                      OMPRegionInfo](CodeGenFunction &CGF) {
      llvm::Value *Args[] = {
+100 −126
Original line number Diff line number Diff line
@@ -1657,15 +1657,15 @@ OpenMPDirectiveKind
CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
  auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
  auto *CS = dyn_cast<CompoundStmt>(Stmt);
  if (CS && CS->size() > 1) {
  bool HasLastprivates = false;
    auto &&CodeGen = [&S, CS, &HasLastprivates](CodeGenFunction &CGF) {
  auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF) {
    auto &C = CGF.CGM.getContext();
    auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
    // Emit helper vars inits.
    LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
                                  CGF.Builder.getInt32(0));
      auto *GlobalUBVal = CGF.Builder.getInt32(CS->size() - 1);
    auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1)
                                      : CGF.Builder.getInt32(0);
    LValue UB =
        createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
    LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
@@ -1683,9 +1683,9 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
                        OK_Ordinary, S.getLocStart(),
                        /*fpContractable=*/false);
    // Increment for loop counter.
      UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue,
                        OK_Ordinary, S.getLocStart());
      auto BodyGen = [CS, &S, &IV](CodeGenFunction &CGF) {
    UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
                      S.getLocStart());
    auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) {
      // Iterate through all sections and emit a switch construct:
      // switch (IV) {
      //   case 0:
@@ -1700,7 +1700,8 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
      auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
      auto *SwitchStmt = CGF.Builder.CreateSwitch(
          CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB,
            CS->size());
          CS == nullptr ? 1 : CS->size());
      if (CS) {
        unsigned CaseNumber = 0;
        for (auto *SubStmt : CS->children()) {
          auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
@@ -1710,6 +1711,13 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
          CGF.EmitBranch(ExitBB);
          ++CaseNumber;
        }
      } else {
        auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
        CGF.EmitBlock(CaseBB);
        SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
        CGF.EmitStmt(Stmt);
        CGF.EmitBranch(ExitBB);
      }
      CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
    };

@@ -1729,8 +1737,8 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
    // Emit static non-chunked loop.
    CGF.CGM.getOpenMPRuntime().emitForStaticInit(
        CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
          /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
          LB.getAddress(), UB.getAddress(), ST.getAddress());
        /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(),
        UB.getAddress(), ST.getAddress());
    // UB = min(UB, GlobalUB);
    auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart());
    auto *MinUBGlobalUB = CGF.Builder.CreateSelect(
@@ -1770,40 +1778,6 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
  }
  return OMPD_sections;
}
  // If only one section is found - no need to generate loop, emit as a single
  // region.
  bool HasFirstprivates;
  // No need to generate reductions for sections with single section region, we
  // can use original shared variables for all operations.
  bool HasReductions = S.hasClausesOfKind<OMPReductionClause>();
  // No need to generate lastprivates for sections with single section region,
  // we can use original shared variable for all calculations with barrier at
  // the end of the sections.
  bool HasLastprivates = S.hasClausesOfKind<OMPLastprivateClause>();
  auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {
    CodeGenFunction::OMPPrivateScope SingleScope(CGF);
    HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
    CGF.EmitOMPPrivateClause(S, SingleScope);
    (void)SingleScope.Privatize();

    CGF.EmitStmt(Stmt);
  };
  CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
                                          llvm::None, llvm::None, llvm::None,
                                          llvm::None);
  // Emit barrier for firstprivates, lastprivates or reductions only if
  // 'sections' directive has 'nowait' clause. Otherwise the barrier will be
  // generated by the codegen for the directive.
  if ((HasFirstprivates || HasLastprivates || HasReductions) &&
      S.getSingleClause<OMPNowaitClause>()) {
    // Emit implicit barrier to synchronize threads and avoid data races on
    // initialization of firstprivate variables.
    CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown,
                                           /*EmitChecks=*/false,
                                           /*ForceSimpleCall=*/true);
  }
  return OMPD_single;
}

void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
  LexicalScope Scope(*this, S.getSourceRange());
+8 −6
Original line number Diff line number Diff line
@@ -19,9 +19,10 @@ int main (int argc, char **argv) {
{
#pragma omp cancel sections
}
// CHECK: call i32 @__kmpc_single(
// CHECK-NOT: @__kmpc_cancel
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call i32 @__kmpc_cancel(
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: call void @__kmpc_barrier(%ident_t*
#pragma omp sections
{
@@ -125,9 +126,10 @@ for (int i = 0; i < argc; ++i) {
// CHECK: ret i32 0

// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
// CHECK: call i32 @__kmpc_single(
// CHECK-NOT: @__kmpc_cancel
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call i32 @__kmpc_cancel(
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void

// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
+20 −6
Original line number Diff line number Diff line
@@ -22,9 +22,16 @@ int main (int argc, char **argv) {
#pragma omp cancel sections
  }
}
// CHECK: call i32 @__kmpc_single(
// CHECK-NOT: @__kmpc_cancellationpoint
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: call void @__kmpc_barrier(%ident_t*
#pragma omp sections
{
@@ -126,9 +133,16 @@ for (int i = 0; i < argc; ++i) {
// CHECK: ret i32 0

// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
// CHECK: call i32 @__kmpc_single(
// CHECK-NOT: @__kmpc_cancellationpoint
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: [[RES:%.+]] = call i32 @__kmpc_cancellationpoint(%ident_t* {{[^,]+}}, i32 [[GTID:%.+]], i32 3)
// CHECK: [[CMP:%.+]] = icmp ne i32 [[RES]], 0
// CHECK: br i1 [[CMP]], label %[[EXIT:[^,].+]], label %[[CONTINUE:.+]]
// CHECK: [[EXIT]]
// CHECK: call i32 @__kmpc_cancel_barrier(%ident_t*
// CHECK: br label
// CHECK: [[CONTINUE]]
// CHECK: br label
// CHECK: call void @__kmpc_for_static_fini(
// CHECK: ret void

// CHECK: define internal void @{{[^(]+}}(i32* {{[^,]+}}, i32* {{[^,]+}})
+3 −8
Original line number Diff line number Diff line
@@ -78,15 +78,10 @@ int main() {
// CHECK-LABEL: tmain
// CHECK:       call void {{.*}} @__kmpc_fork_call(
// CHECK-NOT:   __kmpc_global_thread_num
// CHECK:       [[RES:%.+]] = call i32 @__kmpc_single(
// CHECK-NEXT:  [[BOOLRES:%.+]] = icmp ne i32 [[RES]], 0
// CHECK-NEXT:  br i1 [[BOOLRES]], label %[[THEN:.+]], label %[[END:.+]]
// CHECK:       [[THEN]]
// CHECK-NEXT:  invoke void @{{.*}}foo{{.*}}()
// CHECK:       call void @__kmpc_for_static_init_4(
// CHECK:       invoke void @{{.*}}foo{{.*}}()
// CHECK-NEXT:  unwind label %[[TERM_LPAD:.+]]
// CHECK:       call void @__kmpc_end_single(
// CHECK-NEXT:  br label %[[END]]
// CHECK:       [[END]]
// CHECK:       call void @__kmpc_for_static_fini(
// CHECK-NEXT:  ret
// CHECK:       [[TERM_LPAD]]
// CHECK:       call void @__clang_call_terminate(i8*
Loading