1 //===--- 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" 19 using namespace clang; 20 using namespace CodeGen; 21 22 //===----------------------------------------------------------------------===// 23 // OpenMP Directive Emission 24 //===----------------------------------------------------------------------===// 25 26 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { 27 const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt()); 28 llvm::Value *CapturedStruct = GenerateCapturedStmtArgument(*CS); 29 30 llvm::Value *OutlinedFn; 31 { 32 CodeGenFunction CGF(CGM, true); 33 CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind()); 34 CGF.CapturedStmtInfo = &CGInfo; 35 OutlinedFn = CGF.GenerateCapturedStmtFunction(*CS); 36 } 37 38 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/) 39 llvm::Value *Args[] = { 40 CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()), 41 Builder.getInt32(1), // Number of arguments after 'microtask' argument 42 // (there is only one additional argument - 'context') 43 Builder.CreateBitCast(OutlinedFn, 44 CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()), 45 EmitCastToVoidPtr(CapturedStruct)}; 46 llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction( 47 CGOpenMPRuntime::OMPRTL__kmpc_fork_call); 48 EmitRuntimeCall(RTLFn, Args); 49 } 50 51 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { 52 const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt()); 53 const Stmt *Body = CS->getCapturedStmt(); 54 LoopStack.setParallel(); 55 LoopStack.setVectorizerEnable(true); 56 for (auto C : S.clauses()) { 57 switch (C->getClauseKind()) { 58 case OMPC_safelen: { 59 RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(), 60 AggValueSlot::ignored(), true); 61 llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); 62 LoopStack.setVectorizerWidth(Val->getZExtValue()); 63 // In presence of finite 'safelen', it may be unsafe to mark all 64 // the memory instructions parallel, because loop-carried 65 // dependences of 'safelen' iterations are possible. 66 LoopStack.setParallel(false); 67 break; 68 } 69 default: 70 // Not handled yet 71 ; 72 } 73 } 74 EmitStmt(Body); 75 } 76 77 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) { 78 llvm_unreachable("CodeGen for 'omp for' is not supported yet."); 79 } 80 81 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) { 82 llvm_unreachable("CodeGen for 'omp for simd' is not supported yet."); 83 } 84 85 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) { 86 llvm_unreachable("CodeGen for 'omp sections' is not supported yet."); 87 } 88 89 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) { 90 llvm_unreachable("CodeGen for 'omp section' is not supported yet."); 91 } 92 93 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) { 94 llvm_unreachable("CodeGen for 'omp single' is not supported yet."); 95 } 96 97 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) { 98 llvm_unreachable("CodeGen for 'omp master' is not supported yet."); 99 } 100 101 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { 102 // __kmpc_critical(); 103 // <captured_body> 104 // __kmpc_end_critical(); 105 // 106 107 auto Lock = CGM.getOpenMPRuntime().GetCriticalRegionLock( 108 S.getDirectiveName().getAsString()); 109 CGM.getOpenMPRuntime().EmitOMPCriticalRegionStart(*this, Lock, 110 S.getLocStart()); 111 { 112 RunCleanupsScope Scope(*this); 113 EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 114 EnsureInsertPoint(); 115 } 116 CGM.getOpenMPRuntime().EmitOMPCriticalRegionEnd(*this, Lock, S.getLocEnd()); 117 } 118 119 void 120 CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) { 121 llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet."); 122 } 123 124 void CodeGenFunction::EmitOMPParallelForSimdDirective( 125 const OMPParallelForSimdDirective &) { 126 llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet."); 127 } 128 129 void CodeGenFunction::EmitOMPParallelSectionsDirective( 130 const OMPParallelSectionsDirective &) { 131 llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet."); 132 } 133 134 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) { 135 llvm_unreachable("CodeGen for 'omp task' is not supported yet."); 136 } 137 138 void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) { 139 llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet."); 140 } 141 142 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) { 143 llvm_unreachable("CodeGen for 'omp barrier' is not supported yet."); 144 } 145 146 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) { 147 llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet."); 148 } 149 150 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) { 151 llvm_unreachable("CodeGen for 'omp flush' is not supported yet."); 152 } 153 154 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) { 155 llvm_unreachable("CodeGen for 'omp ordered' is not supported yet."); 156 } 157 158 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) { 159 llvm_unreachable("CodeGen for 'omp atomic' is not supported yet."); 160 } 161 162 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) { 163 llvm_unreachable("CodeGen for 'omp target' is not supported yet."); 164 } 165 166