]> granicus.if.org Git - clang/commitdiff
[OPENMP, NVPTX] Add check for SPMD mode in orphaned parallel directives.
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 16 May 2018 13:36:30 +0000 (13:36 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 16 May 2018 13:36:30 +0000 (13:36 +0000)
If the orphaned directive is executed in SPMD mode, we need to emit the
check for the SPMD mode and run the orphaned parallel directive in
sequential mode.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332467 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
test/OpenMP/nvptx_target_codegen.cpp

index 1f5bfee41bd90e3aff6999ebe5616c19a55662d5..559a26f6f357101dbb9602d660d7f2468fc3ae74 100644 (file)
@@ -96,6 +96,8 @@ enum OpenMPRTLFunctionNVPTX {
   /// Call to uint16_t __kmpc_parallel_level(ident_t *loc, kmp_int32
   /// global_tid);
   OMPRTL_NVPTX__kmpc_parallel_level,
+  /// Call to int8_t __kmpc_is_spmd_exec_mode();
+  OMPRTL_NVPTX__kmpc_is_spmd_exec_mode,
 };
 
 /// Pre(post)-action for different OpenMP constructs specialized for NVPTX.
@@ -220,8 +222,7 @@ class CheckVarsEscapingDeclContext final
                "Parameter captured by value with variably modified type");
         EscapedParameters.insert(VD);
       }
-    } else if (VD->getType()->isAnyPointerType() ||
-               VD->getType()->isReferenceType())
+    } else if (VD->getType()->isReferenceType())
       // Do not globalize variables with reference or pointer type.
       return;
     if (VD->getType()->isVariablyModifiedType())
@@ -317,8 +318,18 @@ public:
       return;
     if (D->hasAssociatedStmt()) {
       if (const auto *S =
-              dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt()))
+              dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) {
+        // Do not analyze directives that do not actually require capturing,
+        // like `omp for` or `omp simd` directives.
+        llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+        getOpenMPCaptureRegions(CaptureRegions, D->getDirectiveKind());
+        if (CaptureRegions.size() == 1 &&
+            CaptureRegions.back() == OMPD_unknown) {
+          VisitStmt(S->getCapturedStmt());
+          return;
+        }
         VisitOpenMPCapturedStmt(S);
+      }
     }
   }
   void VisitCapturedStmt(const CapturedStmt *S) {
@@ -1411,6 +1422,12 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) {
     RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_parallel_level");
     break;
   }
+  case OMPRTL_NVPTX__kmpc_is_spmd_exec_mode: {
+    // Build int8_t __kmpc_is_spmd_exec_mode();
+    auto *FnTy = llvm::FunctionType::get(CGM.Int8Ty, /*isVarArg=*/false);
+    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_is_spmd_exec_mode");
+    break;
+  }
   }
   return RTLFn;
 }
@@ -1828,7 +1845,9 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
       RCG(CGF);
     } else {
       // Check for master and then parallelism:
-      // if (is_master) {
+      // if (__kmpc_is_spmd_exec_mode()) {
+      //  Serialized execution.
+      // } else if (is_master) {
       //   Worker call.
       // } else if (__kmpc_parallel_level(loc, gtid)) {
       //   Serialized execution.
@@ -1837,13 +1856,22 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall(
       // }
       CGBuilderTy &Bld = CGF.Builder;
       llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
+      llvm::BasicBlock *SPMDCheckBB = CGF.createBasicBlock(".spmdcheck");
       llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
       llvm::BasicBlock *ParallelCheckBB =
           CGF.createBasicBlock(".parallelcheck");
+      llvm::Value *IsSPMD = Bld.CreateIsNotNull(CGF.EmitNounwindRuntimeCall(
+          createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_is_spmd_exec_mode)));
+      Bld.CreateCondBr(IsSPMD, SPMDCheckBB, MasterCheckBB);
+      CGF.EmitBlock(SPMDCheckBB);
+      SeqGen(CGF, Action);
+      CGF.EmitBranch(ExitBB);
+      CGF.EmitBlock(MasterCheckBB);
+      llvm::BasicBlock *MasterThenBB = CGF.createBasicBlock("master.then");
       llvm::Value *IsMaster =
           Bld.CreateICmpEQ(getNVPTXThreadID(CGF), getMasterThreadID(CGF));
-      Bld.CreateCondBr(IsMaster, MasterCheckBB, ParallelCheckBB);
-      CGF.EmitBlock(MasterCheckBB);
+      Bld.CreateCondBr(IsMaster, MasterThenBB, ParallelCheckBB);
+      CGF.EmitBlock(MasterThenBB);
       L0ParallelGen(CGF, Action);
       CGF.EmitBranch(ExitBB);
       // There is no need to emit line number for unconditional branch.
index 0a8e56106ed7a68616f089c5c70e08cef3cc8ba0..23dd23e86cd181951610f7dc56757b3cc972b372 100644 (file)
@@ -561,6 +561,16 @@ int baz(int f, double &a) {
   // CHECK: [[F_PTR:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[REC_ADDR]], i32 0, i32 0
   // CHECK: store i32 %{{.+}}, i32* [[F_PTR]],
   // CHECK: store i32 [[GTID]], i32* [[GTID_ADDR]],
+
+  // CHECK: [[RES:%.+]] = call i8 @__kmpc_is_spmd_exec_mode()
+  // CHECK: icmp ne i8 [[RES]], 0
+  // CHECK: br i1
+
+  // CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+  // CHECK: call void [[OUTLINED:@.+]](i32* [[GTID_ADDR]], i32* [[ZERO_ADDR]], i32* [[F_PTR]], double* %{{.+}})
+  // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @{{.+}}, i32 [[GTID]])
+  // CHECK: br label
+
   // CHECK: icmp eq i32
   // CHECK: br i1