blob: bef723f5aedd15f45ceeab2213edf7d47edce5a7 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- 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/Decl.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/IR/DerivedTypes.h"
19#include "llvm/IR/GlobalValue.h"
20#include "llvm/IR/Value.h"
21#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000022#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000023
24using namespace clang;
25using namespace CodeGen;
26
Alexey Bataev4a5bb772014-10-08 14:01:46 +000027void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) {
Alexey Bataev435ad7b2014-10-10 09:48:26 +000028 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
29 CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
30 if (PrivateScope.Privatize()) {
Alexey Bataev4a5bb772014-10-08 14:01:46 +000031 // Emit implicit barrier to synchronize threads and avoid data races.
32 auto Flags = static_cast<CGOpenMPRuntime::OpenMPLocationFlags>(
33 CGOpenMPRuntime::OMP_IDENT_KMPC |
34 CGOpenMPRuntime::OMP_IDENT_BARRIER_IMPL);
35 CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(),
36 Flags);
Alexey Bataev4a5bb772014-10-08 14:01:46 +000037 }
38 CGCapturedStmtInfo::EmitBody(CGF, S);
Alexey Bataev4a5bb772014-10-08 14:01:46 +000039}
40
Alexey Bataev9959db52014-05-06 10:08:46 +000041CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
42 : CGM(CGM), DefaultOpenMPPSource(nullptr) {
43 IdentTy = llvm::StructType::create(
44 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
45 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +000046 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +000047 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +000048 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
49 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +000050 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +000051 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +000052}
53
54llvm::Value *
55CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
Alexey Bataev15007ba2014-05-07 06:18:01 +000056 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +000057 if (!Entry) {
58 if (!DefaultOpenMPPSource) {
59 // Initialize default location for psource field of ident_t structure of
60 // all ident_t objects. Format is ";file;function;line;column;;".
61 // Taken from
62 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
63 DefaultOpenMPPSource =
64 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
65 DefaultOpenMPPSource =
66 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
67 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +000068 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
69 CGM.getModule(), IdentTy, /*isConstant*/ true,
70 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +000071 DefaultOpenMPLocation->setUnnamedAddr(true);
Alexey Bataev9959db52014-05-06 10:08:46 +000072
73 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +000074 llvm::Constant *Values[] = {Zero,
75 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
76 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +000077 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
78 DefaultOpenMPLocation->setInitializer(Init);
Alexey Bataev4a5bb772014-10-08 14:01:46 +000079 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +000080 return DefaultOpenMPLocation;
81 }
82 return Entry;
83}
84
85llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
86 CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) {
87 // If no debug info is generated - return global default location.
88 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
89 Loc.isInvalid())
90 return GetOrCreateDefaultOpenMPLocation(Flags);
91
92 assert(CGF.CurFn && "No function in current CodeGenFunction.");
93
Alexey Bataev9959db52014-05-06 10:08:46 +000094 llvm::Value *LocValue = nullptr;
95 OpenMPLocMapTy::iterator I = OpenMPLocMap.find(CGF.CurFn);
96 if (I != OpenMPLocMap.end()) {
97 LocValue = I->second;
98 } else {
Alexey Bataev15007ba2014-05-07 06:18:01 +000099 // Generate "ident_t .kmpc_loc.addr;"
100 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
Alexey Bataev9959db52014-05-06 10:08:46 +0000101 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
102 OpenMPLocMap[CGF.CurFn] = AI;
103 LocValue = AI;
104
105 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
106 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
107 CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags),
108 llvm::ConstantExpr::getSizeOf(IdentTy),
109 CGM.PointerAlignInBytes);
110 }
111
112 // char **psource = &.kmpc_loc_<flags>.addr.psource;
113 llvm::Value *PSource =
114 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
115
Alexey Bataevf002aca2014-05-30 05:48:40 +0000116 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
117 if (OMPDebugLoc == nullptr) {
118 SmallString<128> Buffer2;
119 llvm::raw_svector_ostream OS2(Buffer2);
120 // Build debug location
121 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
122 OS2 << ";" << PLoc.getFilename() << ";";
123 if (const FunctionDecl *FD =
124 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
125 OS2 << FD->getQualifiedNameAsString();
126 }
127 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
128 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
129 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000130 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000131 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000132 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
133
Alexey Bataev9959db52014-05-06 10:08:46 +0000134 return LocValue;
135}
136
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000137llvm::Value *CGOpenMPRuntime::GetOpenMPThreadID(CodeGenFunction &CGF,
138 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000139 assert(CGF.CurFn && "No function in current CodeGenFunction.");
140
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000141 llvm::Value *ThreadID = nullptr;
142 OpenMPThreadIDMapTy::iterator I = OpenMPThreadIDMap.find(CGF.CurFn);
143 if (I != OpenMPThreadIDMap.end()) {
144 ThreadID = I->second;
Alexey Bataev9959db52014-05-06 10:08:46 +0000145 } else {
Alexey Bataevd6c57552014-07-25 07:55:17 +0000146 // Check if current function is a function which has first parameter
147 // with type int32 and name ".global_tid.".
148 if (!CGF.CurFn->arg_empty() &&
149 CGF.CurFn->arg_begin()->getType()->isPointerTy() &&
150 CGF.CurFn->arg_begin()
151 ->getType()
152 ->getPointerElementType()
153 ->isIntegerTy() &&
154 CGF.CurFn->arg_begin()
155 ->getType()
156 ->getPointerElementType()
157 ->getIntegerBitWidth() == 32 &&
158 CGF.CurFn->arg_begin()->hasName() &&
159 CGF.CurFn->arg_begin()->getName() == ".global_tid.") {
160 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
161 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000162 ThreadID = CGF.Builder.CreateLoad(CGF.CurFn->arg_begin());
Alexey Bataevd6c57552014-07-25 07:55:17 +0000163 } else {
164 // Generate "int32 .kmpc_global_thread_num.addr;"
165 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
166 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
167 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)};
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000168 ThreadID = CGF.EmitRuntimeCall(
Alexey Bataevd6c57552014-07-25 07:55:17 +0000169 CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
170 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000171 OpenMPThreadIDMap[CGF.CurFn] = ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000172 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000173 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000174}
175
176void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) {
177 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000178 if (OpenMPThreadIDMap.count(CGF.CurFn))
179 OpenMPThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000180 if (OpenMPLocMap.count(CGF.CurFn))
181 OpenMPLocMap.erase(CGF.CurFn);
182}
183
184llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
185 return llvm::PointerType::getUnqual(IdentTy);
186}
187
188llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
189 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
190}
191
192llvm::Constant *
193CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
194 llvm::Constant *RTLFn = nullptr;
195 switch (Function) {
196 case OMPRTL__kmpc_fork_call: {
197 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
198 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000199 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
200 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000201 llvm::FunctionType *FnTy =
202 llvm::FunctionType::get(CGM.VoidTy, TypeParams, true);
203 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
204 break;
205 }
206 case OMPRTL__kmpc_global_thread_num: {
207 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000208 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000209 llvm::FunctionType *FnTy =
210 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false);
211 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
212 break;
213 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000214 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000215 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
216 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000217 llvm::Type *TypeParams[] = {
218 getIdentTyPointerTy(), CGM.Int32Ty,
219 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
220 llvm::FunctionType *FnTy =
221 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
222 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
223 break;
224 }
225 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000226 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
227 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000228 llvm::Type *TypeParams[] = {
229 getIdentTyPointerTy(), CGM.Int32Ty,
230 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
231 llvm::FunctionType *FnTy =
232 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
233 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
234 break;
235 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000236 case OMPRTL__kmpc_barrier: {
237 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
238 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
239 llvm::FunctionType *FnTy =
240 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
241 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
242 break;
243 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000244 }
245 return RTLFn;
246}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000247
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000248void CGOpenMPRuntime::EmitOMPParallelCall(CodeGenFunction &CGF,
249 SourceLocation Loc,
250 llvm::Value *OutlinedFn,
251 llvm::Value *CapturedStruct) {
252 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
253 llvm::Value *Args[] = {
254 EmitOpenMPUpdateLocation(CGF, Loc),
255 CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
256 // (there is only one additional argument - 'context')
257 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
258 CGF.EmitCastToVoidPtr(CapturedStruct)};
259 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
260 CGF.EmitRuntimeCall(RTLFn, Args);
261}
262
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000263llvm::Value *CGOpenMPRuntime::GetCriticalRegionLock(StringRef CriticalName) {
264 SmallString<256> Buffer;
265 llvm::raw_svector_ostream Out(Buffer);
266 Out << ".gomp_critical_user_" << CriticalName << ".var";
267 auto RuntimeCriticalName = Out.str();
268 auto &Elem = CriticalRegionVarNames.GetOrCreateValue(RuntimeCriticalName);
269 if (Elem.getValue() != nullptr)
270 return Elem.getValue();
271
272 auto Lock = new llvm::GlobalVariable(
273 CGM.getModule(), KmpCriticalNameTy, /*IsConstant*/ false,
274 llvm::GlobalValue::CommonLinkage,
275 llvm::Constant::getNullValue(KmpCriticalNameTy), Elem.getKey());
276 Elem.setValue(Lock);
277 return Lock;
278}
279
280void CGOpenMPRuntime::EmitOMPCriticalRegionStart(CodeGenFunction &CGF,
281 llvm::Value *RegionLock,
282 SourceLocation Loc) {
283 // Prepare other arguments and build a call to __kmpc_critical
284 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000285 GetOpenMPThreadID(CGF, Loc), RegionLock};
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000286 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_critical);
287 CGF.EmitRuntimeCall(RTLFn, Args);
288}
289
290void CGOpenMPRuntime::EmitOMPCriticalRegionEnd(CodeGenFunction &CGF,
291 llvm::Value *RegionLock,
292 SourceLocation Loc) {
Alexey Bataevf9472182014-09-22 12:32:31 +0000293 // Prepare other arguments and build a call to __kmpc_end_critical
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000294 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc),
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000295 GetOpenMPThreadID(CGF, Loc), RegionLock};
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000296 auto RTLFn =
297 CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_end_critical);
298 CGF.EmitRuntimeCall(RTLFn, Args);
299}
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000300
301void CGOpenMPRuntime::EmitOMPBarrierCall(CodeGenFunction &CGF,
302 SourceLocation Loc,
303 OpenMPLocationFlags Flags) {
304 // Build call __kmpc_barrier(loc, thread_id)
305 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc, Flags),
306 GetOpenMPThreadID(CGF, Loc)};
307 auto RTLFn = CreateRuntimeFunction(CGOpenMPRuntime::OMPRTL__kmpc_barrier);
308 CGF.EmitRuntimeCall(RTLFn, Args);
309}
310