1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This provides a class for OpenMP runtime code generation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CGOpenMPRuntime.h" 15 #include "CodeGenFunction.h" 16 #include "clang/AST/StmtOpenMP.h" 17 #include "clang/AST/Decl.h" 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/IR/CallSite.h" 20 #include "llvm/IR/DerivedTypes.h" 21 #include "llvm/IR/GlobalValue.h" 22 #include "llvm/IR/Value.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <cassert> 25 26 using namespace clang; 27 using namespace CodeGen; 28 29 namespace { 30 /// \brief API for captured statement code generation in OpenMP constructs. 31 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 32 public: 33 CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS, 34 const VarDecl *ThreadIDVar) 35 : CGCapturedStmtInfo(CS, CR_OpenMP), ThreadIDVar(ThreadIDVar), 36 Directive(D) { 37 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 38 } 39 40 /// \brief Gets a variable or parameter for storing global thread id 41 /// inside OpenMP construct. 42 const VarDecl *getThreadIDVariable() const { return ThreadIDVar; } 43 44 /// \brief Gets an LValue for the current ThreadID variable. 45 LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 46 47 static bool classof(const CGCapturedStmtInfo *Info) { 48 return Info->getKind() == CR_OpenMP; 49 } 50 51 /// \brief Emit the captured statement body. 52 void EmitBody(CodeGenFunction &CGF, Stmt *S) override; 53 54 /// \brief Get the name of the capture helper. 55 StringRef getHelperName() const override { return ".omp_outlined."; } 56 57 private: 58 /// \brief A variable or parameter storing global thread id for OpenMP 59 /// constructs. 60 const VarDecl *ThreadIDVar; 61 /// \brief OpenMP executable directive associated with the region. 62 const OMPExecutableDirective &Directive; 63 }; 64 } // namespace 65 66 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 67 return CGF.MakeNaturalAlignAddrLValue( 68 CGF.GetAddrOfLocalVar(ThreadIDVar), 69 CGF.getContext().getPointerType(ThreadIDVar->getType())); 70 } 71 72 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) { 73 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 74 CGF.EmitOMPPrivateClause(Directive, PrivateScope); 75 CGF.EmitOMPFirstprivateClause(Directive, PrivateScope); 76 if (PrivateScope.Privatize()) { 77 // Emit implicit barrier to synchronize threads and avoid data races. 78 auto Flags = static_cast<CGOpenMPRuntime::OpenMPLocationFlags>( 79 CGOpenMPRuntime::OMP_IDENT_KMPC | 80 CGOpenMPRuntime::OMP_IDENT_BARRIER_IMPL); 81 CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(), 82 Flags); 83 } 84 CGCapturedStmtInfo::EmitBody(CGF, S); 85 } 86 87 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 88 : CGM(CGM), DefaultOpenMPPSource(nullptr) { 89 IdentTy = llvm::StructType::create( 90 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 91 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 92 CGM.Int8PtrTy /* psource */, nullptr); 93 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 94 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 95 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 96 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 97 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 98 } 99 100 llvm::Value * 101 CGOpenMPRuntime::EmitOpenMPOutlinedFunction(const OMPExecutableDirective &D, 102 const VarDecl *ThreadIDVar) { 103 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 104 CodeGenFunction CGF(CGM, true); 105 CGOpenMPRegionInfo CGInfo(D, *CS, ThreadIDVar); 106 CGF.CapturedStmtInfo = &CGInfo; 107 return CGF.GenerateCapturedStmtFunction(*CS); 108 } 109 110 llvm::Value * 111 CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) { 112 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 113 if (!Entry) { 114 if (!DefaultOpenMPPSource) { 115 // Initialize default location for psource field of ident_t structure of 116 // all ident_t objects. Format is ";file;function;line;column;;". 117 // Taken from 118 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 119 DefaultOpenMPPSource = 120 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;"); 121 DefaultOpenMPPSource = 122 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 123 } 124 auto DefaultOpenMPLocation = new llvm::GlobalVariable( 125 CGM.getModule(), IdentTy, /*isConstant*/ true, 126 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr); 127 DefaultOpenMPLocation->setUnnamedAddr(true); 128 129 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 130 llvm::Constant *Values[] = {Zero, 131 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 132 Zero, Zero, DefaultOpenMPPSource}; 133 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 134 DefaultOpenMPLocation->setInitializer(Init); 135 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation; 136 return DefaultOpenMPLocation; 137 } 138 return Entry; 139 } 140 141 llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation( 142 CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) { 143 // If no debug info is generated - return global default location. 144 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo || 145 Loc.isInvalid()) 146 return GetOrCreateDefaultOpenMPLocation(Flags); 147 148 assert(CGF.CurFn && "No function in current CodeGenFunction."); 149 150 llvm::Value *LocValue = nullptr; 151 OpenMPLocThreadIDMapTy::iterator I = OpenMPLocThreadIDMap.find(CGF.CurFn); 152 if (I != OpenMPLocThreadIDMap.end()) { 153 LocValue = I->second.DebugLoc; 154 } else { 155 // Generate "ident_t .kmpc_loc.addr;" 156 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr"); 157 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy)); 158 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 159 Elem.second.DebugLoc = AI; 160 LocValue = AI; 161 162 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 163 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 164 CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags), 165 llvm::ConstantExpr::getSizeOf(IdentTy), 166 CGM.PointerAlignInBytes); 167 } 168 169 // char **psource = &.kmpc_loc_<flags>.addr.psource; 170 llvm::Value *PSource = 171 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource); 172 173 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 174 if (OMPDebugLoc == nullptr) { 175 SmallString<128> Buffer2; 176 llvm::raw_svector_ostream OS2(Buffer2); 177 // Build debug location 178 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 179 OS2 << ";" << PLoc.getFilename() << ";"; 180 if (const FunctionDecl *FD = 181 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 182 OS2 << FD->getQualifiedNameAsString(); 183 } 184 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 185 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 186 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 187 } 188 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 189 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 190 191 return LocValue; 192 } 193 194 llvm::Value *CGOpenMPRuntime::GetOpenMPThreadID(CodeGenFunction &CGF, 195 SourceLocation Loc) { 196 assert(CGF.CurFn && "No function in current CodeGenFunction."); 197 198 llvm::Value *ThreadID = nullptr; 199 // Check whether we've already cached a load of the thread id in this 200 // function. 201 OpenMPLocThreadIDMapTy::iterator I = OpenMPLocThreadIDMap.find(CGF.CurFn); 202 if (I != OpenMPLocThreadIDMap.end()) { 203 ThreadID = I->second.ThreadID; 204 if (ThreadID != nullptr) 205 return ThreadID; 206 } 207 if (auto OMPRegionInfo = 208 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 209 // Check if this an outlined function with thread id passed as argument. 210 auto ThreadIDVar = OMPRegionInfo->getThreadIDVariable(); 211 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 212 auto RVal = CGF.EmitLoadOfLValue(LVal, Loc); 213 LVal = CGF.MakeNaturalAlignAddrLValue(RVal.getScalarVal(), 214 ThreadIDVar->getType()); 215 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 216 // If value loaded in entry block, cache it and use it everywhere in 217 // function. 218 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 219 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 220 Elem.second.ThreadID = ThreadID; 221 } 222 } else { 223 // This is not an outlined function region - need to call __kmpc_int32 224 // kmpc_global_thread_num(ident_t *loc). 225 // Generate thread id value and cache this value for use across the 226 // function. 227 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 228 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 229 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)}; 230 ThreadID = CGF.EmitRuntimeCall( 231 CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args); 232 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 233 Elem.second.ThreadID = ThreadID; 234 } 235 return ThreadID; 236 } 237 238 void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) { 239 assert(CGF.CurFn && "No function in current CodeGenFunction."); 240 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 241 OpenMPLocThreadIDMap.erase(CGF.CurFn); 242 } 243 244 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 245 return llvm::PointerType::getUnqual(IdentTy); 246 } 247 248 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 249 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 250 } 251 252 llvm::Constant * 253 CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { 254 llvm::Constant *RTLFn = nullptr; 255 switch (Function) { 256 case OMPRTL__kmpc_fork_call: { 257 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 258 // microtask, ...); 259 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 260 getKmpc_MicroPointerTy()}; 261 llvm::FunctionType *FnTy = 262 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 263 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 264 break; 265 } 266 case OMPRTL__kmpc_global_thread_num: { 267 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 268 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 269 llvm::FunctionType *FnTy = 270 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 271 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 272 break; 273 } 274 case OMPRTL__kmpc_critical: { 275 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 276 // kmp_critical_name *crit); 277 llvm::Type *TypeParams[] = { 278 getIdentTyPointerTy(), CGM.Int32Ty, 279 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 280 llvm::FunctionType *FnTy = 281 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 282 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 283 break; 284 } 285 case OMPRTL__kmpc_end_critical: { 286 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 287 // kmp_critical_name *crit); 288 llvm::Type *TypeParams[] = { 289 getIdentTyPointerTy(), CGM.Int32Ty, 290 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 291 llvm::FunctionType *FnTy = 292 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 293 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 294 break; 295 } 296 case OMPRTL__kmpc_barrier: { 297 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 298 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 299 llvm::FunctionType *FnTy = 300 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 301 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 302 break; 303 } 304 case OMPRTL__kmpc_push_num_threads: { 305 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 306 // kmp_int32 num_threads) 307 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 308 CGM.Int32Ty}; 309 llvm::FunctionType *FnTy = 310 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 311 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 312 break; 313 } 314 case OMPRTL__kmpc_serialized_parallel: { 315 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 316 // global_tid); 317 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 318 llvm::FunctionType *FnTy = 319 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 320 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 321 break; 322 } 323 case OMPRTL__kmpc_end_serialized_parallel: { 324 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 325 // global_tid); 326 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 327 llvm::FunctionType *FnTy = 328 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 329 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 330 break; 331 } 332 } 333 return RTLFn; 334 } 335 336 void CGOpenMPRuntime::EmitOMPParallelCall(CodeGenFunction &CGF, 337 SourceLocation Loc, 338 llvm::Value *OutlinedFn, 339 llvm::Value *CapturedStruct) { 340 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/) 341 llvm::Value *Args[] = { 342 EmitOpenMPUpdateLocation(CGF, Loc), 343 CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument 344 // (there is only one additional argument - 'context') 345 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()), 346 CGF.EmitCastToVoidPtr(CapturedStruct)}; 347 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_fork_call); 348 CGF.EmitRuntimeCall(RTLFn, Args); 349 } 350 351 void CGOpenMPRuntime::EmitOMPSerialCall(CodeGenFunction &CGF, 352 SourceLocation Loc, 353 llvm::Value *OutlinedFn, 354 llvm::Value *CapturedStruct) { 355 auto ThreadID = GetOpenMPThreadID(CGF, Loc); 356 // Build calls: 357 // __kmpc_serialized_parallel(&Loc, GTid); 358 llvm::Value *SerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID}; 359 auto RTLFn = 360 CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_serialized_parallel); 361 CGF.EmitRuntimeCall(RTLFn, SerArgs); 362 363 // OutlinedFn(>id, &zero, CapturedStruct); 364 auto ThreadIDAddr = EmitThreadIDAddress(CGF, Loc); 365 auto Int32Ty = 366 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 367 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr"); 368 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 369 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct}; 370 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 371 372 // __kmpc_end_serialized_parallel(&Loc, GTid); 373 llvm::Value *EndSerArgs[] = {EmitOpenMPUpdateLocation(CGF, Loc), ThreadID}; 374 RTLFn = CreateRuntimeFunction( 375 CGOpenMPRuntime::OMPRTL__kmpc_end_serialized_parallel); 376 CGF.EmitRuntimeCall(RTLFn, EndSerArgs); 377 } 378 379 // If we're inside an (outlined) parallel region, use the region info's 380 // thread-ID variable (it is passed in a first argument of the outlined function 381 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 382 // regular serial code region, get thread ID by calling kmp_int32 383 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 384 // return the address of that temp. 385 llvm::Value *CGOpenMPRuntime::EmitThreadIDAddress(CodeGenFunction &CGF, 386 SourceLocation Loc) { 387 if (auto OMPRegionInfo = 388 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 389 return CGF.EmitLoadOfLValue(OMPRegionInfo->getThreadIDVariableLValue(CGF), 390 SourceLocation()).getScalarVal(); 391 auto ThreadID = GetOpenMPThreadID(CGF, Loc); 392 auto Int32Ty = 393 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 394 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 395 CGF.EmitStoreOfScalar(ThreadID, 396 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty)); 397 398 return ThreadIDTemp; 399 } 400 401 llvm::Value *CGOpenMPRuntime::GetCriticalRegionLock(StringRef CriticalName) { 402 SmallString<256> Buffer; 403 llvm::raw_svector_ostream Out(Buffer); 404 Out << ".gomp_critical_user_" << CriticalName << ".var"; 405 auto RuntimeCriticalName = Out.str(); 406 auto &Elem = CriticalRegionVarNames.GetOrCreateValue(RuntimeCriticalName); 407 if (Elem.getValue() != nullptr) 408 return Elem.getValue(); 409 410 auto Lock = new llvm::GlobalVariable( 411 CGM.getModule(), KmpCriticalNameTy, /*IsConstant*/ false, 412 llvm::GlobalValue::CommonLinkage, 413 llvm::Constant::getNullValue(KmpCriticalNameTy), Elem.getKey()); 414 Elem.setValue(Lock); 415 return Lock; 416 } 417 418 void CGOpenMPRuntime::EmitOMPCriticalRegionStart(CodeGenFunction &CGF, 419 llvm::Value *RegionLock, 420 SourceLocation Loc) { 421 // Prepare other arguments and build a call to __kmpc_critical 422 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), 423 GetOpenMPThreadID(CGF, Loc), RegionLock}; 424 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_critical); 425 CGF.EmitRuntimeCall(RTLFn, Args); 426 } 427 428 void CGOpenMPRuntime::EmitOMPCriticalRegionEnd(CodeGenFunction &CGF, 429 llvm::Value *RegionLock, 430 SourceLocation Loc) { 431 // Prepare other arguments and build a call to __kmpc_end_critical 432 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), 433 GetOpenMPThreadID(CGF, Loc), RegionLock}; 434 auto RTLFn = 435 CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_end_critical); 436 CGF.EmitRuntimeCall(RTLFn, Args); 437 } 438 439 void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF, 440 SourceLocation Loc, 441 OpenMPLocationFlags Flags) { 442 // Build call __kmpc_barrier(loc, thread_id) 443 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, Flags), 444 GetOpenMPThreadID(CGF, Loc)}; 445 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_barrier); 446 CGF.EmitRuntimeCall(RTLFn, Args); 447 } 448 449 void CGOpenMPRuntime::EmitOMPNumThreadsClause(CodeGenFunction &CGF, 450 llvm::Value *NumThreads, 451 SourceLocation Loc) { 452 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 453 llvm::Value *Args[] = { 454 EmitOpenMPUpdateLocation(CGF, Loc), GetOpenMPThreadID(CGF, Loc), 455 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 456 llvm::Constant *RTLFn = CGF.CGM.getOpenMPRuntime().CreateRuntimeFunction( 457 CGOpenMPRuntime::OMPRTL__kmpc_push_num_threads); 458 CGF.EmitRuntimeCall(RTLFn, Args); 459 } 460 461