Author: abataev Date: Fri Mar 4 03:22:22 2016 New Revision: 262699 URL: http://llvm.org/viewvc/llvm-project?rev=262699&view=rev Log: [OPENMP 4.0] Codegen for 'declare reduction' construct.
Emit function for 'combiner' part of 'declare reduction' construct and 'initialilzer' part, if any. Added: cfe/trunk/test/OpenMP/declare_reduction_codegen.c cfe/trunk/test/OpenMP/declare_reduction_codegen.cpp Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h cfe/trunk/include/clang/AST/GlobalDecl.h cfe/trunk/include/clang/Basic/DeclNodes.td cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h cfe/trunk/lib/CodeGen/ModuleBuilder.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/OpenMP/threadprivate_codegen.cpp Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclOpenMP.h?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclOpenMP.h (original) +++ cfe/trunk/include/clang/AST/DeclOpenMP.h Fri Mar 4 03:22:22 2016 @@ -99,7 +99,7 @@ public: /// \endcode /// /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. -class OMPDeclareReductionDecl final : public NamedDecl, public DeclContext { +class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { private: friend class ASTDeclReader; /// \brief Combiner for declare reduction construct. @@ -110,21 +110,18 @@ private: /// scope with the same name. Required for proper templates instantiation if /// the declare reduction construct is declared inside compound statement. LazyDeclPtr PrevDeclInScope; - /// \brief Type of declare reduction construct. - QualType Ty; virtual void anchor(); OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope) - : NamedDecl(DK, DC, L, Name), DeclContext(DK), Combiner(nullptr), - Initializer(nullptr), PrevDeclInScope(PrevDeclInScope), Ty(Ty) {} + : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr), + Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {} void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { PrevDeclInScope = Prev; } - void setType(QualType T) { Ty = T; } public: /// \brief Create declare reduction node. @@ -153,8 +150,6 @@ public: OMPDeclareReductionDecl *getPrevDeclInScope(); const OMPDeclareReductionDecl *getPrevDeclInScope() const; - QualType getType() const { return Ty; } - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OMPDeclareReduction; } static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) { Modified: cfe/trunk/include/clang/AST/GlobalDecl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/GlobalDecl.h?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/GlobalDecl.h (original) +++ cfe/trunk/include/clang/AST/GlobalDecl.h Fri Mar 4 03:22:22 2016 @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/Basic/ABI.h" namespace clang { @@ -43,6 +44,7 @@ public: GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } + GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} Modified: cfe/trunk/include/clang/Basic/DeclNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DeclNodes.td (original) +++ cfe/trunk/include/clang/Basic/DeclNodes.td Fri Mar 4 03:22:22 2016 @@ -37,6 +37,7 @@ def Named : Decl<1>; def EnumConstant : DDecl<Value>; def UnresolvedUsingValue : DDecl<Value>; def IndirectField : DDecl<Value>; + def OMPDeclareReduction : DDecl<Value>, DeclContext; def Declarator : DDecl<Value, 1>; def Field : DDecl<Declarator>; def ObjCIvar : DDecl<Field>; @@ -75,7 +76,6 @@ def Named : Decl<1>; def ObjCImplementation : DDecl<ObjCImpl>; def ObjCProperty : DDecl<Named>; def ObjCCompatibleAlias : DDecl<Named>; - def OMPDeclareReduction : DDecl<Named>, DeclContext; def LinkageSpec : Decl, DeclContext; def ObjCPropertyImpl : Decl; def FileScopeAsm : Decl; Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Mar 4 03:22:22 2016 @@ -8508,7 +8508,9 @@ bool ASTContext::DeclMustBeEmitted(const else if (isa<PragmaDetectMismatchDecl>(D)) return true; else if (isa<OMPThreadPrivateDecl>(D)) - return true; + return !D->getDeclContext()->isDependentContext(); + else if (isa<OMPDeclareReductionDecl>(D)) + return !D->getDeclContext()->isDependentContext(); else return false; Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Mar 4 03:22:22 2016 @@ -16,6 +16,7 @@ #include "CGCleanup.h" #include "CGDebugInfo.h" #include "CGOpenCLRuntime.h" +#include "CGOpenMPRuntime.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" @@ -120,7 +121,7 @@ void CodeGenFunction::EmitDecl(const Dec } case Decl::OMPDeclareReduction: - return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D)); + return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D), this); case Decl::Typedef: // typedef int X; case Decl::TypeAlias: { // using X = int; [C++0x] @@ -1867,6 +1868,10 @@ void CodeGenFunction::EmitParmDecl(const EmitVarAnnotations(&D, DeclPtr.getPointer()); } -void CodeGenModule::EmitOMPDeclareReduction( - const OMPDeclareReductionDecl * /*D*/) {} +void CodeGenModule::EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, + CodeGenFunction *CGF) { + if (!LangOpts.OpenMP || (!LangOpts.EmitAllDecls && !D->isUsed())) + return; + getOpenMPRuntime().emitUserDefinedReduction(CGF, D); +} Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Fri Mar 4 03:22:22 2016 @@ -593,8 +593,7 @@ LValue CGOpenMPTaskOutlinedRegionInfo::g } CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) - : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr), - OffloadEntriesInfoManager(CGM) { + : CGM(CGM), OffloadEntriesInfoManager(CGM) { IdentTy = llvm::StructType::create( "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, @@ -612,6 +611,82 @@ void CGOpenMPRuntime::clear() { InternalVars.clear(); } +static llvm::Function * +emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, + const Expr *CombinerInitializer, const VarDecl *In, + const VarDecl *Out, bool IsCombiner) { + // void .omp_combiner.(Ty *in, Ty *out); + auto &C = CGM.getContext(); + QualType PtrTy = C.getPointerType(Ty).withRestrict(); + FunctionArgList Args; + ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), + /*Id=*/nullptr, PtrTy); + ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), + /*Id=*/nullptr, PtrTy); + Args.push_back(&OmpInParm); + Args.push_back(&OmpOutParm); + FunctionType::ExtInfo Info; + auto &FnInfo = + CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info, + /*isVariadic=*/false); + auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo); + auto *Fn = llvm::Function::Create( + FnTy, llvm::GlobalValue::InternalLinkage, + IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule()); + CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo); + CodeGenFunction CGF(CGM); + // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. + // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. + CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args); + CodeGenFunction::OMPPrivateScope Scope(CGF); + Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); + Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address { + return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) + .getAddress(); + }); + Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); + Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address { + return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) + .getAddress(); + }); + (void)Scope.Privatize(); + CGF.EmitIgnoredExpr(CombinerInitializer); + Scope.ForceCleanup(); + CGF.FinishFunction(); + return Fn; +} + +void CGOpenMPRuntime::emitUserDefinedReduction( + CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { + if (UDRMap.count(D) > 0) + return; + auto &C = CGM.getContext(); + if (!In || !Out) { + In = &C.Idents.get("omp_in"); + Out = &C.Idents.get("omp_out"); + } + llvm::Function *Combiner = emitCombinerOrInitializer( + CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()), + cast<VarDecl>(D->lookup(Out).front()), + /*IsCombiner=*/true); + llvm::Function *Initializer = nullptr; + if (auto *Init = D->getInitializer()) { + if (!Priv || !Orig) { + Priv = &C.Idents.get("omp_priv"); + Orig = &C.Idents.get("omp_orig"); + } + Initializer = emitCombinerOrInitializer( + CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()), + cast<VarDecl>(D->lookup(Priv).front()), + /*IsCombiner=*/false); + } + UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer))); + if (CGF) { + auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); + Decls.second.push_back(D); + } +} + // Layout information for ident_t. static CharUnits getIdentAlign(CodeGenModule &CGM) { return CGM.getPointerAlign(); @@ -801,6 +876,12 @@ void CGOpenMPRuntime::functionFinished(C assert(CGF.CurFn && "No function in current CodeGenFunction."); if (OpenMPLocThreadIDMap.count(CGF.CurFn)) OpenMPLocThreadIDMap.erase(CGF.CurFn); + if (FunctionUDRMap.count(CGF.CurFn) > 0) { + for(auto *D : FunctionUDRMap[CGF.CurFn]) { + UDRMap.erase(D); + } + FunctionUDRMap.erase(CGF.CurFn); + } } llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Fri Mar 4 03:22:22 2016 @@ -38,6 +38,8 @@ class Expr; class GlobalDecl; class OMPExecutableDirective; class VarDecl; +class OMPDeclareReductionDecl; +class IdentifierInfo; namespace CodeGen { class Address; @@ -50,7 +52,7 @@ class CGOpenMPRuntime { CodeGenModule &CGM; /// \brief Default const ident_t object used for initialization of all other /// ident_t objects. - llvm::Constant *DefaultOpenMPPSource; + llvm::Constant *DefaultOpenMPPSource = nullptr; /// \brief Map of flags and corresponding default locations. typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy; OpenMPDefaultLocMapTy OpenMPDefaultLocMap; @@ -73,6 +75,20 @@ class CGOpenMPRuntime { typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy> OpenMPLocThreadIDMapTy; OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap; + /// Map of UDRs and corresponding combiner/initializer. + typedef llvm::DenseMap<const OMPDeclareReductionDecl *, + std::pair<llvm::Function *, llvm::Function *>> + UDRMapTy; + UDRMapTy UDRMap; + /// Map of functions and locally defined UDRs. + typedef llvm::DenseMap<llvm::Function *, + SmallVector<const OMPDeclareReductionDecl *, 4>> + FunctionUDRMapTy; + FunctionUDRMapTy FunctionUDRMap; + IdentifierInfo *In = nullptr; + IdentifierInfo *Out = nullptr; + IdentifierInfo *Priv = nullptr; + IdentifierInfo *Orig = nullptr; /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32 /// kmp_critical_name[8]; llvm::ArrayType *KmpCriticalNameTy; @@ -84,7 +100,7 @@ class CGOpenMPRuntime { llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator> InternalVars; /// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); - llvm::Type *KmpRoutineEntryPtrTy; + llvm::Type *KmpRoutineEntryPtrTy = nullptr; QualType KmpRoutineEntryPtrQTy; /// \brief Type typedef struct kmp_task { /// void * shareds; /**< pointer to block of pointers to @@ -364,6 +380,9 @@ public: virtual ~CGOpenMPRuntime() {} virtual void clear(); + /// Emit code for the specified user defined reduction construct. + virtual void emitUserDefinedReduction(CodeGenFunction *CGF, + const OMPDeclareReductionDecl *D); /// \brief Emits outlined function for the specified OpenMP parallel directive /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, /// kmp_int32 BoundID, struct context_vars*). Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp Fri Mar 4 03:22:22 2016 @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CGOpenMPRuntimeNVPTX.h" +#include "clang/AST/DeclOpenMP.h" using namespace clang; using namespace CodeGen; Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Mar 4 03:22:22 2016 @@ -1543,10 +1543,17 @@ void CodeGenModule::EmitGlobal(GlobalDec } } - // If this is OpenMP device, check if it is legal to emit this global - // normally. - if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD)) - return; + if (LangOpts.OpenMP) { + // If this is OpenMP device, check if it is legal to emit this global + // normally. + if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD)) + return; + if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Global)) { + if (MustBeEmitted(Global)) + EmitOMPDeclareReduction(DRD); + return; + } + } // Ignore declarations, they will be emitted on their first use. if (const auto *FD = dyn_cast<FunctionDecl>(Global)) { Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Mar 4 03:22:22 2016 @@ -1112,7 +1112,8 @@ public: void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); /// \brief Emit a code for declare reduction construct. - void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D); + void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, + CodeGenFunction *CGF = nullptr); /// Returns whether we need bit sets attached to vtables. bool NeedVTableBitSets(); Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original) +++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Fri Mar 4 03:22:22 2016 @@ -187,6 +187,15 @@ namespace { } } } + // For OpenMP emit declare reduction functions, if required. + if (Ctx->getLangOpts().OpenMP) { + for (Decl *Member : D->decls()) { + if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) { + if (Ctx->DeclMustBeEmitted(DRD)) + Builder->EmitGlobal(DRD); + } + } + } } void HandleTagDeclRequiredDefinition(const TagDecl *D) override { Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 4 03:22:22 2016 @@ -2861,6 +2861,7 @@ ExprResult Sema::BuildDeclarationNameExp // Unresolved using declarations are dependent. case Decl::EnumConstant: case Decl::UnresolvedUsingValue: + case Decl::OMPDeclareReduction: valueKind = VK_RValue; break; Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Mar 4 03:22:22 2016 @@ -2396,12 +2396,11 @@ void ASTDeclReader::VisitOMPThreadPrivat } void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { - VisitNamedDecl(D); + VisitValueDecl(D); D->setLocation(Reader.ReadSourceLocation(F, Record, Idx)); D->setCombiner(Reader.ReadExpr(F)); D->setInitializer(Reader.ReadExpr(F)); D->PrevDeclInScope = Reader.ReadDeclID(F, Record, Idx); - D->setType(Reader.readType(F, Record, Idx)); } void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { @@ -2458,10 +2457,10 @@ static bool isConsumerInterestedIn(Decl isa<ObjCImplDecl>(D) || isa<ImportDecl>(D) || isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D) || - isa<OMPThreadPrivateDecl>(D) || - isa<OMPDeclareReductionDecl>(D)) + isa<PragmaDetectMismatchDecl>(D)) return true; + if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D)) + return !D->getDeclContext()->isFunctionOrMethod(); if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && Var->isThisDeclarationADefinition() == VarDecl::Definition; Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Mar 4 03:22:22 2016 @@ -1655,12 +1655,11 @@ void ASTDeclWriter::VisitOMPThreadPrivat } void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { - VisitNamedDecl(D); + VisitValueDecl(D); Writer.AddSourceLocation(D->getLocStart(), Record); Writer.AddStmt(D->getCombiner()); Writer.AddStmt(D->getInitializer()); Writer.AddDeclRef(D->getPrevDeclInScope(), Record); - Writer.AddTypeRef(D->getType(), Record); Code = serialization::DECL_OMP_DECLARE_REDUCTION; } Added: cfe/trunk/test/OpenMP/declare_reduction_codegen.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_reduction_codegen.c?rev=262699&view=auto ============================================================================== --- cfe/trunk/test/OpenMP/declare_reduction_codegen.c (added) +++ cfe/trunk/test/OpenMP/declare_reduction_codegen.c Fri Mar 4 03:22:22 2016 @@ -0,0 +1,158 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls +// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix=CHECK-LOAD %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +// CHECK: [[SSS_INT:.+]] = type { i32 } +// CHECK-LOAD: [[SSS_INT:.+]] = type { i32 } + +#pragma omp declare reduction(+ : int, char : omp_out *= omp_in) +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[MUL:%.+]] = mul nsw i32 +// CHECK-NEXT: store i32 [[MUL]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: store i32 [[MUL]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) +// CHECK: sext i8 +// CHECK: sext i8 +// CHECK: [[MUL:%.+]] = mul nsw i32 +// CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 +// CHECK-NEXT: store i8 [[TRUNC]], i8* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) +// CHECK-LOAD: sext i8 +// CHECK-LOAD: sext i8 +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 +// CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = 15 + omp_orig) +// CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias) +// CHECK: [[ADD:%.+]] = fadd float +// CHECK-NEXT: store float [[ADD]], float* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias) +// CHECK: [[ADD:%.+]] = fadd float 1.5 +// CHECK-NEXT: store float [[ADD]], float* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias) +// CHECK-LOAD: [[ADD:%.+]] = fadd float +// CHECK-LOAD-NEXT: store float [[ADD]], float* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(float* noalias, float* noalias) +// CHECK-LOAD: [[ADD:%.+]] = fadd float 1.5 +// CHECK-LOAD-NEXT: store float [[ADD]], float* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +struct SSS { + int field; +#pragma omp declare reduction(+ : int, char : omp_out *= omp_in) + // CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) + // CHECK: [[MUL:%.+]] = mul nsw i32 + // CHECK-NEXT: store i32 [[MUL]], i32* + // CHECK-NEXT: ret void + // CHECK-NEXT: } + + // CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) + // CHECK: sext i8 + // CHECK: sext i8 + // CHECK: [[MUL:%.+]] = mul nsw i32 + // CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 + // CHECK-NEXT: store i8 [[TRUNC]], i8* + // CHECK-NEXT: ret void + // CHECK-NEXT: } +}; + +void init(struct SSS *priv, struct SSS orig); + +#pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) +// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK: call void @llvm.memcpy +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK: call void @init( +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK-LOAD: call void @llvm.memcpy +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK-LOAD: call void @init( +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK-LABEL: @main +// CHECK-LOAD-LABEL: @main +int main() { +#pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) + // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK: call void @llvm.memcpy + // CHECK-NEXT: ret void + // CHECK-NEXT: } + // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK: call void @init( + // CHECK-NEXT: ret void + // CHECK-NEXT: } + // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK-LOAD: call void @llvm.memcpy + // CHECK-LOAD-NEXT: ret void + // CHECK-LOAD-NEXT: } + // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK-LOAD: call void @init( + // CHECK-LOAD-NEXT: ret void + // CHECK-LOAD-NEXT: } + { +#pragma omp declare reduction(fun : struct SSS : omp_out = omp_in) initializer(init(&omp_priv, omp_orig)) + // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK: call void @llvm.memcpy + // CHECK-NEXT: ret void + // CHECK-NEXT: } + // CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK: call void @init( + // CHECK-NEXT: ret void + // CHECK-NEXT: } + // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK-LOAD: call void @llvm.memcpy + // CHECK-LOAD-NEXT: ret void + // CHECK-LOAD-NEXT: } + // CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) + // CHECK-LOAD: call void @init( + // CHECK-LOAD-NEXT: ret void + // CHECK-LOAD-NEXT: } + } + return 0; +} + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: store i32 [[MUL]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) +// CHECK-LOAD: sext i8 +// CHECK-LOAD: sext i8 +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 +// CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } +#endif Added: cfe/trunk/test/OpenMP/declare_reduction_codegen.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_reduction_codegen.cpp?rev=262699&view=auto ============================================================================== --- cfe/trunk/test/OpenMP/declare_reduction_codegen.cpp (added) +++ cfe/trunk/test/OpenMP/declare_reduction_codegen.cpp Fri Mar 4 03:22:22 2016 @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls +// RUN: %clang_cc1 -fopenmp -x c++ -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls | FileCheck --check-prefix=CHECK-LOAD %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +// CHECK: [[SSS_INT:.+]] = type { i32 } +// CHECK-LOAD: [[SSS_INT:.+]] = type { i32 } + +#pragma omp declare reduction(+ : int, char : omp_out *= omp_in) +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[MUL:%.+]] = mul nsw i32 +// CHECK-NEXT: store i32 [[MUL]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: store i32 [[MUL]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) +// CHECK: sext i8 +// CHECK: sext i8 +// CHECK: [[MUL:%.+]] = mul nsw i32 +// CHECK-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 +// CHECK-NEXT: store i8 [[TRUNC]], i8* +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i8* noalias, i8* noalias) +// CHECK-LOAD: sext i8 +// CHECK-LOAD: sext i8 +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 +// CHECK-LOAD-NEXT: [[TRUNC:%.+]] = trunc i32 [[MUL]] to i8 +// CHECK-LOAD-NEXT: store i8 [[TRUNC]], i8* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +template <class T> +struct SSS { + T a; +#pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig) +}; + +SSS<int> d; + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[XOR:%.+]] = xor i32 +// CHECK-NEXT: store i32 [[XOR]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[ADD:%.+]] = add nsw i32 24, +// CHECK-NEXT: store i32 [[ADD]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define void [[INIT:@[^(]+]]([[SSS_INT]]* +// CHECK-LOAD: define void [[INIT:@[^(]+]]([[SSS_INT]]* +void init(SSS<int> &lhs, SSS<int> &rhs) {} + +#pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig)) +// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK: call void @llvm.memcpy +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK: call void [[INIT]]( +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK-LOAD: call void @llvm.memcpy +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}([[SSS_INT]]* noalias, [[SSS_INT]]* noalias) +// CHECK-LOAD: call void [[INIT]]( +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +template <typename T> +T foo(T a) { +#pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = 15 * omp_orig) + { +#pragma omp declare reduction(fun : T : omp_out /= omp_in) initializer(omp_priv = 11 - omp_orig) + } + return a; +} + +// CHECK-LABEL: @main +int main() { + int i = 0; + SSS<int> sss; + // TODO: Add support for scoped reduction identifiers + // #pragma omp parallel reduction(SSS<int>::fun : i) + // TODO-CHECK: #pragma omp parallel reduction(SSS<int>::fun: i) + { + i += 1; + } + // #pragma omp parallel reduction(::fun:sss) + // TODO-CHECK: #pragma omp parallel reduction(::fun: sss) + { + } + return foo(15); +} + +// CHECK-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32 +// CHECK-LOAD-LABEL: i32 @{{.+}}foo{{[^(].+}}(i32 + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[XOR:%.+]] = xor i32 +// CHECK-LOAD-NEXT: store i32 [[XOR]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[ADD:%.+]] = add nsw i32 24, +// CHECK-LOAD-NEXT: store i32 [[ADD]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[ADD:%.+]] = add nsw i32 +// CHECK-NEXT: store i32 [[ADD]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[ADD:%.+]] = add nsw i32 +// CHECK-LOAD-NEXT: store i32 [[ADD]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[MUL:%.+]] = mul nsw i32 15, +// CHECK-NEXT: store i32 [[MUL]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[MUL:%.+]] = mul nsw i32 15, +// CHECK-LOAD-NEXT: store i32 [[MUL]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[DIV:%.+]] = sdiv i32 +// CHECK-NEXT: store i32 [[DIV]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[DIV:%.+]] = sdiv i32 +// CHECK-LOAD-NEXT: store i32 [[DIV]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK: [[SUB:%.+]] = sub nsw i32 11, +// CHECK-NEXT: store i32 [[SUB]], i32* +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// CHECK-LOAD: define internal {{.*}}void @{{[^(]+}}(i32* noalias, i32* noalias) +// CHECK-LOAD: [[SUB:%.+]] = sub nsw i32 11, +// CHECK-LOAD-NEXT: store i32 [[SUB]], i32* +// CHECK-LOAD-NEXT: ret void +// CHECK-LOAD-NEXT: } + +#endif Modified: cfe/trunk/test/OpenMP/threadprivate_codegen.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_codegen.cpp?rev=262699&r1=262698&r2=262699&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/threadprivate_codegen.cpp (original) +++ cfe/trunk/test/OpenMP/threadprivate_codegen.cpp Fri Mar 4 03:22:22 2016 @@ -948,5 +948,5 @@ int foobar() { // CHECK-TLS: call void [[ST_S4_ST_CXX_INIT]] // CHECK-TLS: [[DONE_LABEL]] -// CHECK-TLS: declare {{.*}} void [[GS3_TLS_INIT]] -// CHECK-TLS: declare {{.*}} void [[STATIC_S_TLS_INIT]] +// CHECK-TLS-DAG: declare {{.*}} void [[GS3_TLS_INIT]] +// CHECK-TLS-DAG: declare {{.*}} void [[STATIC_S_TLS_INIT]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits