diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 28bce7b90665..858931469974 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1287,6 +1287,12 @@ struct InformationCache { return AG.getAnalysis(F); } + /// Return true if \p F has the "kernel" function attribute + bool isKernel(const Function &F) { + FunctionInfo &FI = getFunctionInfo(F); + return FI.IsKernel; + } + /// Return true if \p Arg is involved in a must-tail call, thus the argument /// of the caller or callee. bool isInvolvedInMustTailCall(const Argument &Arg) { @@ -1361,6 +1367,9 @@ private: /// Function contains a `musttail` call. bool ContainsMustTailCall; + + /// Function has the `"kernel"` attribute + bool IsKernel; }; /// A map type from functions to informatio about it. diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 116f419129a2..a93284926d68 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -678,8 +678,8 @@ isPotentiallyReachable(Attributor &A, const Instruction &FromI, // kernel, values like allocas and shared memory are not accessible. We // implicitly check for this situation to avoid costly lookups. if (GoBackwardsCB && &ToFn != FromI.getFunction() && - !GoBackwardsCB(*FromI.getFunction()) && ToFn.hasFnAttribute("kernel") && - FromI.getFunction()->hasFnAttribute("kernel")) { + !GoBackwardsCB(*FromI.getFunction()) && A.getInfoCache().isKernel(ToFn) && + A.getInfoCache().isKernel(*FromI.getFunction())) { LLVM_DEBUG(dbgs() << "[AA] assume kernel cannot be reached from within the " "module; success\n";); return false; @@ -3191,6 +3191,8 @@ void InformationCache::initializeInformationCache(const Function &CF, // initialize the cache eagerly which would look the same to the users. Function &F = const_cast(CF); + FI.IsKernel = F.hasFnAttribute("kernel"); + // Walk all instructions to find interesting instructions that might be // queried by abstract attributes during their initialization or update. // This has to happen before we create attributes. diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index eb45df34771d..46d6d66593b4 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -885,9 +885,8 @@ protected: AAPointerInfo::OffsetInfo ReturnedOffsets; /// See AAPointerInfo::forallInterferingAccesses. - bool forallInterferingAccesses( - AA::RangeTy Range, - function_ref CB) const { + template + bool forallInterferingAccesses(AA::RangeTy Range, F CB) const { if (!isValidState() || !ReturnedOffsets.isUnassigned()) return false; @@ -906,10 +905,9 @@ protected: } /// See AAPointerInfo::forallInterferingAccesses. - bool forallInterferingAccesses( - Instruction &I, - function_ref CB, - AA::RangeTy &Range) const { + template + bool forallInterferingAccesses(Instruction &I, F CB, + AA::RangeTy &Range) const { if (!isValidState() || !ReturnedOffsets.isUnassigned()) return false; @@ -1176,7 +1174,7 @@ struct AAPointerInfoImpl // TODO: Use reaching kernels from AAKernelInfo (or move it to // AAExecutionDomain) such that we allow scopes other than kernels as long // as the reaching kernels are disjoint. - bool InstInKernel = Scope.hasFnAttribute("kernel"); + bool InstInKernel = A.getInfoCache().isKernel(Scope); bool ObjHasKernelLifetime = false; const bool UseDominanceReasoning = FindInterferingWrites && IsKnownNoRecurse; @@ -1210,7 +1208,7 @@ struct AAPointerInfoImpl // If the alloca containing function is not recursive the alloca // must be dead in the callee. const Function *AIFn = AI->getFunction(); - ObjHasKernelLifetime = AIFn->hasFnAttribute("kernel"); + ObjHasKernelLifetime = A.getInfoCache().isKernel(*AIFn); bool IsKnownNoRecurse; if (AA::hasAssumedIRAttr( A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL, @@ -1222,8 +1220,8 @@ struct AAPointerInfoImpl // as it is "dead" in the (unknown) callees. ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent()); if (ObjHasKernelLifetime) - IsLiveInCalleeCB = [](const Function &Fn) { - return !Fn.hasFnAttribute("kernel"); + IsLiveInCalleeCB = [&A](const Function &Fn) { + return !A.getInfoCache().isKernel(Fn); }; } @@ -1238,7 +1236,7 @@ struct AAPointerInfoImpl // If the object has kernel lifetime we can ignore accesses only reachable // by other kernels. For now we only skip accesses *in* other kernels. if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope && - AccScope->hasFnAttribute("kernel")) + A.getInfoCache().isKernel(*AccScope)) return true; if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {