blob: 199322318b9280878f4bcb8227f9e659b94a2d83 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
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 contains code to emit OpenMP nodes as LLVM code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
17#include "clang/AST/Stmt.h"
18#include "clang/AST/StmtOpenMP.h"
Alexander Musman09184fe2014-09-30 05:29:28 +000019#include "TargetInfo.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000020using namespace clang;
21using namespace CodeGen;
22
23//===----------------------------------------------------------------------===//
24// OpenMP Directive Emission
25//===----------------------------------------------------------------------===//
26
27void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
28 const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
29 llvm::Value *CapturedStruct = GenerateCapturedStmtArgument(*CS);
30
31 llvm::Value *OutlinedFn;
32 {
33 CodeGenFunction CGF(CGM, true);
34 CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind());
35 CGF.CapturedStmtInfo = &CGInfo;
Alexey Bataevaca7fcf2014-06-30 02:55:54 +000036 OutlinedFn = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev9959db52014-05-06 10:08:46 +000037 }
38
39 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
40 llvm::Value *Args[] = {
Alexey Bataev23b69422014-06-18 07:08:49 +000041 CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
42 Builder.getInt32(1), // Number of arguments after 'microtask' argument
43 // (there is only one additional argument - 'context')
44 Builder.CreateBitCast(OutlinedFn,
45 CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
46 EmitCastToVoidPtr(CapturedStruct)};
Alexey Bataev9959db52014-05-06 10:08:46 +000047 llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction(
48 CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
49 EmitRuntimeCall(RTLFn, Args);
50}
Alexander Musman515ad8c2014-05-22 08:54:05 +000051
Alexander Musman09184fe2014-09-30 05:29:28 +000052static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
53 const OMPAlignedClause &Clause) {
54 unsigned ClauseAlignment = 0;
55 if (auto AlignmentExpr = Clause.getAlignment()) {
56 auto AlignmentCI =
57 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
58 ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
59 }
60 for (auto E : Clause.varlists()) {
61 unsigned Alignment = ClauseAlignment;
62 if (Alignment == 0) {
63 // OpenMP [2.8.1, Description]
64 // If no optional parameter isspecified, implementation-defined default
65 // alignments for SIMD instructions on the target platforms are assumed.
66 Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
67 E->getType());
68 }
69 assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
70 "alignment is not power of 2");
71 if (Alignment != 0) {
72 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
73 CGF.EmitAlignmentAssumption(PtrValue, Alignment);
74 }
75 }
76}
77
Alexander Musman515ad8c2014-05-22 08:54:05 +000078void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
79 const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
80 const Stmt *Body = CS->getCapturedStmt();
81 LoopStack.setParallel();
82 LoopStack.setVectorizerEnable(true);
83 for (auto C : S.clauses()) {
84 switch (C->getClauseKind()) {
85 case OMPC_safelen: {
86 RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
87 AggValueSlot::ignored(), true);
88 llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
89 LoopStack.setVectorizerWidth(Val->getZExtValue());
90 // In presence of finite 'safelen', it may be unsafe to mark all
91 // the memory instructions parallel, because loop-carried
92 // dependences of 'safelen' iterations are possible.
93 LoopStack.setParallel(false);
94 break;
95 }
Alexander Musman09184fe2014-09-30 05:29:28 +000096 case OMPC_aligned:
97 EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
98 break;
Alexander Musman515ad8c2014-05-22 08:54:05 +000099 default:
100 // Not handled yet
101 ;
102 }
103 }
104 EmitStmt(Body);
105}
106
Alexey Bataevf29276e2014-06-18 04:14:57 +0000107void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) {
Alexey Bataevd3f8dd22014-06-25 11:44:49 +0000108 llvm_unreachable("CodeGen for 'omp for' is not supported yet.");
Alexey Bataevf29276e2014-06-18 04:14:57 +0000109}
Alexey Bataevd3f8dd22014-06-25 11:44:49 +0000110
Alexander Musmanf82886e2014-09-18 05:12:34 +0000111void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
112 llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
113}
114
Alexey Bataevd3f8dd22014-06-25 11:44:49 +0000115void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
116 llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
117}
118
Alexey Bataev1e0498a2014-06-26 08:21:58 +0000119void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
120 llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
121}
122
Alexey Bataevd1e40fb2014-06-26 12:05:45 +0000123void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
124 llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
125}
126
Alexander Musman80c22892014-07-17 08:54:58 +0000127void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) {
128 llvm_unreachable("CodeGen for 'omp master' is not supported yet.");
129}
130
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000131void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
132 // __kmpc_critical();
133 // <captured_body>
134 // __kmpc_end_critical();
135 //
136
137 auto Lock = CGM.getOpenMPRuntime().GetCriticalRegionLock(
138 S.getDirectiveName().getAsString());
139 CGM.getOpenMPRuntime().EmitOMPCriticalRegionStart(*this, Lock,
140 S.getLocStart());
141 {
142 RunCleanupsScope Scope(*this);
143 EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
144 EnsureInsertPoint();
145 }
146 CGM.getOpenMPRuntime().EmitOMPCriticalRegionEnd(*this, Lock, S.getLocEnd());
Alexander Musmand9ed09f2014-07-21 09:42:05 +0000147}
148
Alexey Bataev4acb8592014-07-07 13:01:15 +0000149void
150CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
151 llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
152}
153
Alexander Musmane4e893b2014-09-23 09:33:00 +0000154void CodeGenFunction::EmitOMPParallelForSimdDirective(
155 const OMPParallelForSimdDirective &) {
156 llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
157}
158
Alexey Bataev84d0b3e2014-07-08 08:12:03 +0000159void CodeGenFunction::EmitOMPParallelSectionsDirective(
160 const OMPParallelSectionsDirective &) {
161 llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
162}
163
Alexey Bataev9c2e8ee2014-07-11 11:25:16 +0000164void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
165 llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
166}
167
Alexey Bataev68446b72014-07-18 07:47:19 +0000168void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
169 llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
170}
171
Alexey Bataev4d1dfea2014-07-18 09:11:51 +0000172void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) {
173 llvm_unreachable("CodeGen for 'omp barrier' is not supported yet.");
174}
175
Alexey Bataev2df347a2014-07-18 10:17:07 +0000176void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
177 llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
178}
179
Alexey Bataev6125da92014-07-21 11:26:11 +0000180void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) {
181 llvm_unreachable("CodeGen for 'omp flush' is not supported yet.");
182}
183
Alexey Bataev9fb6e642014-07-22 06:45:04 +0000184void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
185 llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
186}
187
Alexey Bataev0162e452014-07-22 10:10:35 +0000188void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
189 llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
190}
191
Alexey Bataev0bd520b2014-09-19 08:19:49 +0000192void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
193 llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
194}
195