Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h =================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h @@ -32,8 +32,7 @@ } // namespace llvm namespace clang { -class VarDecl; - +class Expr; class OMPExecutableDirective; class VarDecl; @@ -93,7 +92,9 @@ OMPRTL__kmpc_end_serialized_parallel, // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, // kmp_int32 num_threads); - OMPRTL__kmpc_push_num_threads + OMPRTL__kmpc_push_num_threads, + // Call to void __kmpc_flush(ident_t *loc, ...); + OMPRTL__kmpc_flush }; private: @@ -329,6 +330,11 @@ EmitOMPThreadPrivateVarDefinition(const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF = nullptr); + + /// \brief Emit flush of the variables specified in 'omp flush' directive. + /// \param Vars List of variables to flush. + virtual void EmitOMPFlush(CodeGenFunction &CGF, ArrayRef Vars, + SourceLocation Loc); }; } // namespace CodeGen } // namespace clang Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp @@ -363,6 +363,14 @@ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); break; } + case OMPRTL__kmpc_flush: { + // Build void __kmpc_flush(ident_t *loc, ...); + llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); + break; + } } return RTLFn; } @@ -651,3 +659,14 @@ CGF.EmitRuntimeCall(RTLFn, Args); } +void CGOpenMPRuntime::EmitOMPFlush(CodeGenFunction &CGF, ArrayRef, + SourceLocation Loc) { + // Build call void __kmpc_flush(ident_t *loc, ...) + // FIXME: List of variables is ignored by libiomp5 runtime, no need to + // generate it, just request full memory fence. + llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc), + llvm::ConstantInt::get(CGM.Int32Ty, 0)}; + auto *RTLFn = CGF.CGM.getOpenMPRuntime().CreateRuntimeFunction( + CGOpenMPRuntime::OMPRTL__kmpc_flush); + CGF.EmitRuntimeCall(RTLFn, Args); +} Index: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp @@ -543,8 +543,17 @@ llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet."); } -void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) { - llvm_unreachable("CodeGen for 'omp flush' is not supported yet."); +void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { + CGM.getOpenMPRuntime().EmitOMPFlush( + *this, [&]() -> ArrayRef { + if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) { + auto FlushClause = cast(C); + return llvm::makeArrayRef(FlushClause->varlist_begin(), + FlushClause->varlist_end()); + } + return llvm::None; + }(), + S.getLocStart()); } void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) { Index: cfe/trunk/test/OpenMP/flush_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/flush_codegen.cpp +++ cfe/trunk/test/OpenMP/flush_codegen.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -g -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +template +T tmain(T argc) { + static T a; +#pragma omp flush +#pragma omp flush(a) + return a + argc; +} + +// CHECK-LABEL: @main +int main() { + static int a; +#pragma omp flush +#pragma omp flush(a) + // CHECK: call void (%{{.+}}*, ...)* @__kmpc_flush(%{{.+}}* {{(@|%).+}}, i32 0) + // CHECK: call void (%{{.+}}*, ...)* @__kmpc_flush(%{{.+}}* {{(@|%).+}}, i32 0) + return tmain(a); + // CHECK: call {{.*}} [[TMAIN:@.+]]( + // CHECK: ret +} + +// CHECK: [[TMAIN]] +// CHECK: call void (%{{.+}}*, ...)* @__kmpc_flush(%{{.+}}* {{(@|%).+}}, i32 0) +// CHECK: call void (%{{.+}}*, ...)* @__kmpc_flush(%{{.+}}* {{(@|%).+}}, i32 0) +// CHECK: ret + +#endif