Index: llvm/lib/Transforms/IPO/OpenMPOpt.cpp =================================================================== --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO/OpenMPOpt.h" +#include "OpenMPOptPriv.h" #include "llvm/ADT/EnumeratedArray.h" #include "llvm/ADT/Statistic.h" @@ -95,152 +96,7 @@ struct AAICVTracker; -/// OpenMP specific information. For now, stores RFIs and ICVs also needed for -/// Attributor runs. -struct OMPInformationCache : public InformationCache { - OMPInformationCache(Module &M, AnalysisGetter &AG, - BumpPtrAllocator &Allocator, SetVector *CGSCC, - SmallPtrSetImpl &ModuleSlice) - : InformationCache(M, AG, Allocator, CGSCC), ModuleSlice(ModuleSlice), - OMPBuilder(M) { - OMPBuilder.initialize(); - initializeRuntimeFunctions(); - initializeInternalControlVars(); - } - - /// Generic information that describes an internal control variable. - struct InternalControlVarInfo { - /// The kind, as described by InternalControlVar enum. - InternalControlVar Kind; - - /// The name of the ICV. - StringRef Name; - - /// Environment variable associated with this ICV. - StringRef EnvVarName; - - /// Initial value kind. - ICVInitValue InitKind; - - /// Initial value. - ConstantInt *InitValue; - - /// Setter RTL function associated with this ICV. - RuntimeFunction Setter; - - /// Getter RTL function associated with this ICV. - RuntimeFunction Getter; - - /// RTL Function corresponding to the override clause of this ICV - RuntimeFunction Clause; - }; - - /// Generic information that describes a runtime function - struct RuntimeFunctionInfo { - - /// The kind, as described by the RuntimeFunction enum. - RuntimeFunction Kind; - - /// The name of the function. - StringRef Name; - - /// Flag to indicate a variadic function. - bool IsVarArg; - - /// The return type of the function. - Type *ReturnType; - - /// The argument types of the function. - SmallVector ArgumentTypes; - - /// The declaration if available. - Function *Declaration = nullptr; - - /// Uses of this runtime function per function containing the use. - using UseVector = SmallVector; - - /// Return the vector of uses in function \p F. - UseVector &getOrCreateUseVector(Function *F) { - std::shared_ptr &UV = UsesMap[F]; - if (!UV) - UV = std::make_shared(); - return *UV; - } - - /// Return the vector of uses in function \p F or `nullptr` if there are - /// none. - const UseVector *getUseVector(Function &F) const { - auto I = UsesMap.find(&F); - if (I != UsesMap.end()) - return I->second.get(); - return nullptr; - } - - /// Return how many functions contain uses of this runtime function. - size_t getNumFunctionsWithUses() const { return UsesMap.size(); } - - /// Return the number of arguments (or the minimal number for variadic - /// functions). - size_t getNumArgs() const { return ArgumentTypes.size(); } - - /// Run the callback \p CB on each use and forget the use if the result is - /// true. The callback will be fed the function in which the use was - /// encountered as second argument. - void foreachUse(function_ref CB) { - for (auto &It : UsesMap) - foreachUse(CB, It.first, It.second.get()); - } - - /// Run the callback \p CB on each use within the function \p F and forget - /// the use if the result is true. - void foreachUse(function_ref CB, Function *F, - UseVector *Uses = nullptr) { - SmallVector ToBeDeleted; - ToBeDeleted.clear(); - - unsigned Idx = 0; - UseVector &UV = Uses ? *Uses : getOrCreateUseVector(F); - - for (Use *U : UV) { - if (CB(*U, *F)) - ToBeDeleted.push_back(Idx); - ++Idx; - } - - // Remove the to-be-deleted indices in reverse order as prior - // modifcations will not modify the smaller indices. - while (!ToBeDeleted.empty()) { - unsigned Idx = ToBeDeleted.pop_back_val(); - UV[Idx] = UV.back(); - UV.pop_back(); - } - } - - private: - /// Map from functions to all uses of this runtime function contained in - /// them. - DenseMap> UsesMap; - }; - - /// The slice of the module we are allowed to look at. - SmallPtrSetImpl &ModuleSlice; - - /// An OpenMP-IR-Builder instance - OpenMPIRBuilder OMPBuilder; - - /// Map from runtime function kind to the runtime function description. - EnumeratedArray - RFIs; - - /// Map from ICV kind to the ICV description. - EnumeratedArray - ICVs; - - /// Helper to initialize all internal control variable information for those - /// defined in OMPKinds.def. - void initializeInternalControlVars() { +void OMPInformationCache::initializeInternalControlVars() { #define ICV_RT_SET(_Name, RTL) \ { \ auto &ICV = ICVs[_Name]; \ @@ -274,63 +130,58 @@ } \ } #include "llvm/Frontend/OpenMP/OMPKinds.def" - } +} - /// Returns true if the function declaration \p F matches the runtime - /// function types, that is, return type \p RTFRetType, and argument types - /// \p RTFArgTypes. - static bool declMatchesRTFTypes(Function *F, Type *RTFRetType, - SmallVector &RTFArgTypes) { - // TODO: We should output information to the user (under debug output - // and via remarks). +bool OMPInformationCache::declMatchesRTFTypes( + Function *F, Type *RTFRetType, SmallVector &RTFArgTypes) { + // TODO: We should output information to the user (under debug output + // and via remarks). - if (!F) - return false; - if (F->getReturnType() != RTFRetType) - return false; - if (F->arg_size() != RTFArgTypes.size()) + if (!F) + return false; + if (F->getReturnType() != RTFRetType) + return false; + if (F->arg_size() != RTFArgTypes.size()) + return false; + + auto RTFTyIt = RTFArgTypes.begin(); + for (Argument &Arg : F->args()) { + if (Arg.getType() != *RTFTyIt) return false; - auto RTFTyIt = RTFArgTypes.begin(); - for (Argument &Arg : F->args()) { - if (Arg.getType() != *RTFTyIt) - return false; + ++RTFTyIt; + } - ++RTFTyIt; - } + return true; +} - return true; - } +void OMPInformationCache::initializeRuntimeFunctions() { + // Helper to collect all uses of the decleration in the UsesMap. + auto CollectUses = [&](RuntimeFunctionInfo &RFI) { + unsigned NumUses = 0; + if (!RFI.Declaration) + return NumUses; + OMPBuilder.addAttributes(RFI.Kind, *RFI.Declaration); - /// Helper to initialize all runtime function information for those defined - /// in OpenMPKinds.def. - void initializeRuntimeFunctions() { - // Helper to collect all uses of the decleration in the UsesMap. - auto CollectUses = [&](RuntimeFunctionInfo &RFI) { - unsigned NumUses = 0; - if (!RFI.Declaration) - return NumUses; - OMPBuilder.addAttributes(RFI.Kind, *RFI.Declaration); - - NumOpenMPRuntimeFunctionsIdentified += 1; - NumOpenMPRuntimeFunctionUsesIdentified += RFI.Declaration->getNumUses(); - - // TODO: We directly convert uses into proper calls and unknown uses. - for (Use &U : RFI.Declaration->uses()) { - if (Instruction *UserI = dyn_cast(U.getUser())) { - if (ModuleSlice.count(UserI->getFunction())) { - RFI.getOrCreateUseVector(UserI->getFunction()).push_back(&U); - ++NumUses; - } - } else { - RFI.getOrCreateUseVector(nullptr).push_back(&U); + NumOpenMPRuntimeFunctionsIdentified += 1; + NumOpenMPRuntimeFunctionUsesIdentified += RFI.Declaration->getNumUses(); + + // TODO: We directly convert uses into proper calls and unknown uses. + for (Use &U : RFI.Declaration->uses()) { + if (Instruction *UserI = dyn_cast(U.getUser())) { + if (ModuleSlice.count(UserI->getFunction())) { + RFI.getOrCreateUseVector(UserI->getFunction()).push_back(&U); ++NumUses; } + } else { + RFI.getOrCreateUseVector(nullptr).push_back(&U); + ++NumUses; } - return NumUses; - }; + } + return NumUses; + }; - Module &M = *((*ModuleSlice.begin())->getParent()); + Module &M = *((*ModuleSlice.begin())->getParent()); #define OMP_RTL(_Enum, _Name, _IsVarArg, _ReturnType, ...) \ { \ @@ -358,9 +209,26 @@ } #include "llvm/Frontend/OpenMP/OMPKinds.def" - // TODO: We should attach the attributes defined in OMPKinds.def. - } -}; + // TODO: We should attach the attributes defined in OMPKinds.def. +} + +CallInst *OMPInformationCache::getCallIfRegularCall( + Use &U, OMPInformationCache::RuntimeFunctionInfo *RFI) { + CallInst *CI = dyn_cast(U.getUser()); + if (CI && CI->isCallee(&U) && !CI->hasOperandBundles() && + (!RFI || CI->getCalledFunction() == RFI->Declaration)) + return CI; + return nullptr; +} + +CallInst *OMPInformationCache::getCallIfRegularCall( + Value &V, OMPInformationCache::RuntimeFunctionInfo *RFI) { + CallInst *CI = dyn_cast(&V); + if (CI && !CI->hasOperandBundles() && + (!RFI || CI->getCalledFunction() == RFI->Declaration)) + return CI; + return nullptr; +} struct OpenMPOpt { @@ -409,28 +277,6 @@ return Changed; } - /// Return the call if \p U is a callee use in a regular call. If \p RFI is - /// given it has to be the callee or a nullptr is returned. - static CallInst *getCallIfRegularCall( - Use &U, OMPInformationCache::RuntimeFunctionInfo *RFI = nullptr) { - CallInst *CI = dyn_cast(U.getUser()); - if (CI && CI->isCallee(&U) && !CI->hasOperandBundles() && - (!RFI || CI->getCalledFunction() == RFI->Declaration)) - return CI; - return nullptr; - } - - /// Return the call if \p V is a regular call. If \p RFI is given it has to be - /// the callee or a nullptr is returned. - static CallInst *getCallIfRegularCall( - Value &V, OMPInformationCache::RuntimeFunctionInfo *RFI = nullptr) { - CallInst *CI = dyn_cast(&V); - if (CI && !CI->hasOperandBundles() && - (!RFI || CI->getCalledFunction() == RFI->Declaration)) - return CI; - return nullptr; - } - private: /// Try to delete parallel regions if possible. bool deleteParallelRegions() { @@ -444,7 +290,7 @@ bool Changed = false; auto DeleteCallCB = [&](Use &U, Function &) { - CallInst *CI = getCallIfRegularCall(U); + CallInst *CI = OMPInformationCache::getCallIfRegularCall(U); if (!CI) return false; auto *Fn = dyn_cast( @@ -552,7 +398,7 @@ bool SingleChoice = true; Value *Ident = nullptr; auto CombineIdentStruct = [&](Use &U, Function &Caller) { - CallInst *CI = getCallIfRegularCall(U, &RFI); + CallInst *CI = OMPInformationCache::getCallIfRegularCall(U, &RFI); if (!CI || &F != &Caller) return false; Ident = combinedIdentStruct(Ident, CI->getArgOperand(0), @@ -607,7 +453,7 @@ if (!ReplVal) { for (Use *U : *UV) - if (CallInst *CI = getCallIfRegularCall(*U, &RFI)) { + if (CallInst *CI = OMPInformationCache::getCallIfRegularCall(*U, &RFI)) { if (!CanBeMoved(*CI)) continue; @@ -641,7 +487,7 @@ bool Changed = false; auto ReplaceAndDeleteCB = [&](Use &U, Function &Caller) { - CallInst *CI = getCallIfRegularCall(U, &RFI); + CallInst *CI = OMPInformationCache::getCallIfRegularCall(U, &RFI); if (!CI || CI == ReplVal || &F != &Caller) return false; assert(CI->getCaller() == &F && "Unexpected call!"); @@ -676,10 +522,10 @@ if (!F.hasLocalLinkage()) return false; for (Use &U : F.uses()) { - if (CallInst *CI = getCallIfRegularCall(U)) { + if (CallInst *CI = OMPInformationCache::getCallIfRegularCall(U)) { Value *ArgOp = CI->getArgOperand(ArgNo); if (CI == &RefCI || GTIdArgs.count(ArgOp) || - getCallIfRegularCall( + OMPInformationCache::getCallIfRegularCall( *ArgOp, &OMPInfoCache.RFIs[OMPRTL___kmpc_global_thread_num])) continue; } @@ -703,7 +549,8 @@ OMPInfoCache.RFIs[OMPRTL___kmpc_global_thread_num]; GlobThreadNumRFI.foreachUse([&](Use &U, Function &F) { - if (CallInst *CI = getCallIfRegularCall(U, &GlobThreadNumRFI)) + if (CallInst *CI = + OMPInformationCache::getCallIfRegularCall(U, &GlobThreadNumRFI)) AddUserArgs(*CI); return false; }); @@ -849,7 +696,7 @@ bool Changed = false; auto ReplaceAndDeleteCB = [&](Use &U, Function &Caller) { - CallInst *CI = OpenMPOpt::getCallIfRegularCall(U, &GetterRFI); + CallInst *CI = OMPInformationCache::getCallIfRegularCall(U, &GetterRFI); Instruction *UserI = cast(U.getUser()); Value *ReplVal = getReplacementValue(ICV, UserI, A); @@ -887,7 +734,7 @@ auto &SetterRFI = OMPInfoCache.RFIs[OMPInfoCache.ICVs[ICV].Setter]; auto TrackValues = [&](Use &U, Function &) { - CallInst *CI = OpenMPOpt::getCallIfRegularCall(U); + CallInst *CI = OMPInformationCache::getCallIfRegularCall(U); if (!CI) return false; Index: llvm/lib/Transforms/IPO/OpenMPOptPriv.h =================================================================== --- /dev/null +++ llvm/lib/Transforms/IPO/OpenMPOptPriv.h @@ -0,0 +1,192 @@ +//===- OpenMPOptPriv.h - Private structs for OpenMPOpt ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_OPENMP_OPT_PRIV_H +#define LLVM_TRANSFORMS_IPO_OPENMP_OPT_PRIV_H + +#include "llvm/ADT/EnumeratedArray.h" +#include "llvm/Transforms/IPO/Attributor.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" + +using namespace llvm; +using namespace omp; + + +namespace { +/// OpenMP specific information. For now, stores RFIs and ICVs also needed for +/// Attributor runs. +struct OMPInformationCache : public InformationCache { + OMPInformationCache(Module &M, AnalysisGetter &AG, + BumpPtrAllocator &Allocator, SetVector *CGSCC, + SmallPtrSetImpl &ModuleSlice) + : InformationCache(M, AG, Allocator, CGSCC), ModuleSlice(ModuleSlice), + OMPBuilder(M) { + OMPBuilder.initialize(); + initializeRuntimeFunctions(); + initializeInternalControlVars(); + } + + /// Generic information that describes an internal control variable. + struct InternalControlVarInfo { + /// The kind, as described by InternalControlVar enum. + InternalControlVar Kind; + + /// The name of the ICV. + StringRef Name; + + /// Environment variable associated with this ICV. + StringRef EnvVarName; + + /// Initial value kind. + ICVInitValue InitKind; + + /// Initial value. + ConstantInt *InitValue; + + /// Setter RTL function associated with this ICV. + RuntimeFunction Setter; + + /// Getter RTL function associated with this ICV. + RuntimeFunction Getter; + + /// RTL Function corresponding to the override clause of this ICV + RuntimeFunction Clause; + }; + + /// Generic information that describes a runtime function + struct RuntimeFunctionInfo { + + /// The kind, as described by the RuntimeFunction enum. + RuntimeFunction Kind; + + /// The name of the function. + StringRef Name; + + /// Flag to indicate a variadic function. + bool IsVarArg; + + /// The return type of the function. + Type *ReturnType; + + /// The argument types of the function. + SmallVector ArgumentTypes; + + /// The declaration if available. + Function *Declaration = nullptr; + + /// Uses of this runtime function per function containing the use. + using UseVector = SmallVector; + + /// Return the vector of uses in function \p F. + UseVector &getOrCreateUseVector(Function *F) { + std::shared_ptr &UV = UsesMap[F]; + if (!UV) + UV = std::make_shared(); + return *UV; + } + + /// Return the vector of uses in function \p F or `nullptr` if there are + /// none. + const UseVector *getUseVector(Function &F) const { + auto I = UsesMap.find(&F); + if (I != UsesMap.end()) + return I->second.get(); + return nullptr; + } + + /// Return how many functions contain uses of this runtime function. + size_t getNumFunctionsWithUses() const { return UsesMap.size(); } + + /// Return the number of arguments (or the minimal number for variadic + /// functions). + size_t getNumArgs() const { return ArgumentTypes.size(); } + + /// Run the callback \p CB on each use and forget the use if the result is + /// true. The callback will be fed the function in which the use was + /// encountered as second argument. + void foreachUse(function_ref CB) { + for (auto &It : UsesMap) + foreachUse(CB, It.first, It.second.get()); + } + + /// Run the callback \p CB on each use within the function \p F and forget + /// the use if the result is true. + void foreachUse(function_ref CB, Function *F, + UseVector *Uses = nullptr) { + SmallVector ToBeDeleted; + ToBeDeleted.clear(); + + unsigned Idx = 0; + UseVector &UV = Uses ? *Uses : getOrCreateUseVector(F); + + for (Use *U : UV) { + if (CB(*U, *F)) + ToBeDeleted.push_back(Idx); + ++Idx; + } + + // Remove the to-be-deleted indices in reverse order as prior + // modifcations will not modify the smaller indices. + while (!ToBeDeleted.empty()) { + unsigned Idx = ToBeDeleted.pop_back_val(); + UV[Idx] = UV.back(); + UV.pop_back(); + } + } + + private: + /// Map from functions to all uses of this runtime function contained in + /// them. + DenseMap> UsesMap; + }; + + /// The slice of the module we are allowed to look at. + SmallPtrSetImpl &ModuleSlice; + + /// An OpenMP-IR-Builder instance + OpenMPIRBuilder OMPBuilder; + + /// Map from runtime function kind to the runtime function description. + EnumeratedArray + RFIs; + + /// Map from ICV kind to the ICV description. + EnumeratedArray + ICVs; + + /// Helper to initialize all internal control variable information for those + /// defined in OMPKinds.def. + void initializeInternalControlVars(); + + /// Helper to initialize all runtime function information for those defined + /// in OpenMPKinds.def. + void initializeRuntimeFunctions(); + + /// Returns true if the function declaration \p F matches the runtime + /// function types, that is, return type \p RTFRetType, and argument types + /// \p RTFArgTypes. + static bool declMatchesRTFTypes(Function *F, Type *RTFRetType, + SmallVector &RTFArgTypes); + + /// Return the call if \p U is a callee use in a regular call. If \p RFI is +/// given it has to be the callee or a nullptr is returned. + static CallInst *getCallIfRegularCall( + Use &U, OMPInformationCache::RuntimeFunctionInfo *RFI = nullptr); + +/// Return the call if \p V is a regular call. If \p RFI is given it has to be +/// the callee or a nullptr is returned. + static CallInst *getCallIfRegularCall( + Value &V, OMPInformationCache::RuntimeFunctionInfo *RFI = nullptr); +}; + +} // end anonymous namespace + +#endif // LLVM_TRANSFORMS_IPO_OPENMP_OPT_PRIV_H \ No newline at end of file