diff options
author | Johannes Doerfert <johannes@jdoerfert.de> | 2022-02-16 11:05:09 -0600 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2022-03-01 14:13:33 -0800 |
commit | f58ab32850211621d5986da2d687be0d550e7140 (patch) | |
tree | 35f9d37c9fdefbdf43d98dc55c98f794e0d02df9 | |
parent | 4327d39b15b22b9ee23582e5455df5b2a093fe8d (diff) |
[Attributor][FIX] Pipe UsedAssumedInformation through more interfaces
`UsedAssumedInformation` is a return argument utilized to determine what
information is known. Most APIs used it already but
`genericValueTraversal` did not. This adds it to `genericValueTraversal`
and replaces `AllCallSitesKnown` of `checkForAllCallSites` with the
commonly used `UsedAssumedInformation`.
This was supposed to be a NFC commit, then the test change appeared.
Turns out, we had one user of `AllCallSitesKnown` (AANoReturn) and the
way we set `AllCallSitesKnown` was wrong as we ignored the fact some
call sites were optimistically assumed dead. Included a dedicated test
for this as well now.
Fixes https://github.com/llvm/llvm-project/issues/53884
-rw-r--r-- | llvm/include/llvm/Transforms/IPO/Attributor.h | 14 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/AttributorAttributes.cpp | 91 | ||||
-rw-r--r-- | llvm/test/Transforms/Attributor/norecurse.ll | 50 | ||||
-rw-r--r-- | llvm/test/Transforms/OpenMP/custom_state_machines.ll | 40 |
5 files changed, 143 insertions, 84 deletions
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 7eee16f71d64..8677a0ba62f2 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -192,6 +192,7 @@ bool getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, SmallVectorImpl<Value *> &Objects, const AbstractAttribute &QueryingAA, const Instruction *CtxI, + bool &UsedAssumedInformation, bool Intraprocedural = false); /// Collect all potential values of the one stored by \p SI into @@ -1824,23 +1825,24 @@ public: /// This method will evaluate \p Pred on call sites and return /// true if \p Pred holds in every call sites. However, this is only possible /// all call sites are known, hence the function has internal linkage. - /// If true is returned, \p AllCallSitesKnown is set if all possible call - /// sites of the function have been visited. + /// If true is returned, \p UsedAssumedInformation is set if assumed + /// information was used to skip or simplify potential call sites. bool checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, - bool RequireAllCallSites, bool &AllCallSitesKnown); + bool RequireAllCallSites, + bool &UsedAssumedInformation); /// Check \p Pred on all call sites of \p Fn. /// /// This method will evaluate \p Pred on call sites and return /// true if \p Pred holds in every call sites. However, this is only possible /// all call sites are known, hence the function has internal linkage. - /// If true is returned, \p AllCallSitesKnown is set if all possible call - /// sites of the function have been visited. + /// If true is returned, \p UsedAssumedInformation is set if assumed + /// information was used to skip or simplify potential call sites. bool checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const Function &Fn, bool RequireAllCallSites, const AbstractAttribute *QueryingAA, - bool &AllCallSitesKnown); + bool &UsedAssumedInformation); /// Check \p Pred on all values potentially returned by \p F. /// diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index d66140a726f6..7bca2084c448 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -320,7 +320,8 @@ bool AA::getPotentialCopiesOfStoredValue( Value &Ptr = *SI.getPointerOperand(); SmallVector<Value *, 8> Objects; - if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, QueryingAA, &SI)) { + if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, QueryingAA, &SI, + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "Underlying objects stored into could not be determined\n";); return false; @@ -514,10 +515,10 @@ isPotentiallyReachable(Attributor &A, const Instruction &FromI, return true; }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; Result = !A.checkForAllCallSites(CheckCallSite, *FromFn, /* RequireAllCallSites */ true, - &QueryingAA, AllCallSitesKnown); + &QueryingAA, UsedAssumedInformation); if (Result) { LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI << " in @" << FromFn->getName() @@ -1277,7 +1278,7 @@ bool Attributor::checkForAllUses( bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const AbstractAttribute &QueryingAA, bool RequireAllCallSites, - bool &AllCallSitesKnown) { + bool &UsedAssumedInformation) { // We can try to determine information from // the call sites. However, this is only possible all call sites are known, // hence the function has internal linkage. @@ -1286,31 +1287,26 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, if (!AssociatedFunction) { LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP << "\n"); - AllCallSitesKnown = false; return false; } return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites, - &QueryingAA, AllCallSitesKnown); + &QueryingAA, UsedAssumedInformation); } bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const Function &Fn, bool RequireAllCallSites, const AbstractAttribute *QueryingAA, - bool &AllCallSitesKnown) { + bool &UsedAssumedInformation) { if (RequireAllCallSites && !Fn.hasLocalLinkage()) { LLVM_DEBUG( dbgs() << "[Attributor] Function " << Fn.getName() << " has no internal linkage, hence not all call sites are known\n"); - AllCallSitesKnown = false; return false; } - // If we do not require all call sites we might not see all. - AllCallSitesKnown = RequireAllCallSites; - SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses())); for (unsigned u = 0; u < Uses.size(); ++u) { const Use &U = *Uses[u]; @@ -1322,7 +1318,6 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser() << "\n"; }); - bool UsedAssumedInformation = false; if (isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation, /* CheckBBLivenessOnly */ true)) { LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n"); @@ -1795,7 +1790,7 @@ void Attributor::identifyDeadInternalFunctions() { if (!F) continue; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (checkForAllCallSites( [&](AbstractCallSite ACS) { Function *Callee = ACS.getInstruction()->getFunction(); @@ -1803,7 +1798,7 @@ void Attributor::identifyDeadInternalFunctions() { (Functions.count(Callee) && Callee->hasLocalLinkage() && !LiveInternalFns.count(Callee)); }, - *F, true, nullptr, AllCallSitesKnown)) { + *F, true, nullptr, UsedAssumedInformation)) { continue; } @@ -2290,9 +2285,9 @@ bool Attributor::isValidFunctionSignatureRewrite( } // Avoid callbacks for now. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr, - AllCallSitesKnown)) { + UsedAssumedInformation)) { LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n"); return false; } @@ -2305,7 +2300,6 @@ bool Attributor::isValidFunctionSignatureRewrite( // Forbid must-tail calls for now. // TODO: - bool UsedAssumedInformation = false; auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn); if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr, nullptr, {Instruction::Call}, @@ -2514,9 +2508,9 @@ ChangeStatus Attributor::rewriteFunctionSignatures( }; // Use the CallSiteReplacementCreator to create replacement call sites. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn, - true, nullptr, AllCallSitesKnown); + true, nullptr, UsedAssumedInformation); (void)Success; assert(Success && "Assumed call site replacement to succeed!"); diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 6dadfebae038..5593a297d2d8 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -261,7 +261,8 @@ static bool genericValueTraversal( StateTy &State, function_ref<bool(Value &, const Instruction *, StateTy &, bool)> VisitValueCB, - const Instruction *CtxI, bool UseValueSimplify = true, int MaxValues = 16, + const Instruction *CtxI, bool &UsedAssumedInformation, + bool UseValueSimplify = true, int MaxValues = 16, function_ref<Value *(Value *)> StripCB = nullptr, bool Intraprocedural = false) { @@ -321,7 +322,6 @@ static bool genericValueTraversal( // Look through select instructions, visit assumed potential values. if (auto *SI = dyn_cast<SelectInst>(V)) { - bool UsedAssumedInformation = false; Optional<Constant *> C = A.getAssumedConstant( *SI->getCondition(), QueryingAA, UsedAssumedInformation); bool NoValueYet = !C.hasValue(); @@ -348,6 +348,7 @@ static bool genericValueTraversal( BasicBlock *IncomingBB = PHI->getIncomingBlock(u); if (LivenessAA->isEdgeDead(IncomingBB, PHI->getParent())) { AnyDead = true; + UsedAssumedInformation |= !LivenessAA->isAtFixpoint(); continue; } Worklist.push_back( @@ -359,7 +360,7 @@ static bool genericValueTraversal( if (auto *Arg = dyn_cast<Argument>(V)) { if (!Intraprocedural && !Arg->hasPassPointeeByValueCopyAttr()) { SmallVector<Item> CallSiteValues; - bool AllCallSitesKnown = true; + bool UsedAssumedInformation = false; if (A.checkForAllCallSites( [&](AbstractCallSite ACS) { // Callbacks might not have a corresponding call site operand, @@ -370,7 +371,7 @@ static bool genericValueTraversal( CallSiteValues.push_back({CSOp, ACS.getInstruction()}); return true; }, - *Arg->getParent(), true, &QueryingAA, AllCallSitesKnown)) { + *Arg->getParent(), true, &QueryingAA, UsedAssumedInformation)) { Worklist.append(CallSiteValues); continue; } @@ -378,7 +379,6 @@ static bool genericValueTraversal( } if (UseValueSimplify && !isa<Constant>(V)) { - bool UsedAssumedInformation = false; Optional<Value *> SimpleV = A.getAssumedSimplified(*V, QueryingAA, UsedAssumedInformation); if (!SimpleV.hasValue()) @@ -413,6 +413,7 @@ bool AA::getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, SmallVectorImpl<Value *> &Objects, const AbstractAttribute &QueryingAA, const Instruction *CtxI, + bool &UsedAssumedInformation, bool Intraprocedural) { auto StripCB = [&](Value *V) { return getUnderlyingObject(V); }; SmallPtrSet<Value *, 8> SeenObjects; @@ -425,7 +426,7 @@ bool AA::getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr, }; if (!genericValueTraversal<decltype(Objects)>( A, IRPosition::value(Ptr), QueryingAA, Objects, VisitValueCB, CtxI, - true, 32, StripCB, Intraprocedural)) + UsedAssumedInformation, true, 32, StripCB, Intraprocedural)) return false; return true; } @@ -571,9 +572,9 @@ static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA, return T->isValidState(); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true, - AllCallSitesKnown)) + UsedAssumedInformation)) S.indicatePessimisticFixpoint(); else if (T.hasValue()) S ^= *T; @@ -1895,17 +1896,18 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) { return true; }; + bool UsedAssumedInformation = false; auto ReturnInstCB = [&](Instruction &I) { ReturnInst &Ret = cast<ReturnInst>(I); return genericValueTraversal<ReturnInst>( A, IRPosition::value(*Ret.getReturnValue()), *this, Ret, ReturnValueCB, - &I, /* UseValueSimplify */ true, /* MaxValues */ 16, + &I, UsedAssumedInformation, /* UseValueSimplify */ true, + /* MaxValues */ 16, /* StripCB */ nullptr, /* Intraprocedural */ true); }; // Discover returned values from all live returned instructions in the // associated function. - bool UsedAssumedInformation = false; if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret}, UsedAssumedInformation)) return indicatePessimisticFixpoint(); @@ -2421,8 +2423,10 @@ struct AANonNullFloating : public AANonNullImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -2500,14 +2504,15 @@ struct AANoRecurseFunction final : AANoRecurseImpl { DepClassTy::NONE); return NoRecurseAA.isKnownNoRecurse(); }; - bool AllCallSitesKnown; - if (A.checkForAllCallSites(CallSitePred, *this, true, AllCallSitesKnown)) { + bool UsedAssumedInformation = false; + if (A.checkForAllCallSites(CallSitePred, *this, true, + UsedAssumedInformation)) { // If we know all call sites and all are known no-recurse, we are done. // If all known call sites, which might not be all that exist, are known // to be no-recurse, we are not done but we can continue to assume // no-recurse. If one of the call sites we have not visited will become // live, another update is triggered. - if (AllCallSitesKnown) + if (!UsedAssumedInformation) indicateOptimisticFixpoint(); return ChangeStatus::UNCHANGED; } @@ -3147,10 +3152,10 @@ struct AANoAliasArgument final // If the argument is never passed through callbacks, no-alias cannot break // synchronization. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (A.checkForAllCallSites( [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this, - true, AllCallSitesKnown)) + true, UsedAssumedInformation)) return Base::updateImpl(A); // TODO: add no-alias but make sure it doesn't break synchronization by @@ -3728,9 +3733,8 @@ struct AAIsDeadReturned : public AAIsDeadValueImpl { return areAllUsesAssumedDead(A, *ACS.getInstruction()); }; - bool AllCallSitesKnown; if (!A.checkForAllCallSites(PredForCallSite, *this, true, - AllCallSitesKnown)) + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return ChangeStatus::UNCHANGED; @@ -4313,8 +4317,10 @@ struct AADereferenceableFloating : AADereferenceableImpl { }; DerefState T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<DerefState>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -4579,8 +4585,10 @@ struct AAAlignFloating : AAAlignImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); // TODO: If we know we visited all incoming values, thus no are assumed @@ -5360,7 +5368,9 @@ struct AAValueSimplifyImpl : AAValueSimplify { Value &Ptr = *L.getPointerOperand(); SmallVector<Value *, 8> Objects; - if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, AA, &L)) + bool UsedAssumedInformation = false; + if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, AA, &L, + UsedAssumedInformation)) return false; const auto *TLI = @@ -5372,7 +5382,6 @@ struct AAValueSimplifyImpl : AAValueSimplify { if (isa<ConstantPointerNull>(Obj)) { // A null pointer access can be undefined but any offset from null may // be OK. We do not try to optimize the latter. - bool UsedAssumedInformation = false; if (!NullPointerIsDefined(L.getFunction(), Ptr.getType()->getPointerAddressSpace()) && A.getAssumedSimplified(Ptr, AA, UsedAssumedInformation) == Obj) @@ -5478,14 +5487,14 @@ struct AAValueSimplifyArgument final : AAValueSimplifyImpl { // Generate a answer specific to a call site context. bool Success; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (hasCallBaseContext() && getCallBaseContext()->getCalledFunction() == Arg->getParent()) Success = PredForCallSite( AbstractCallSite(&getCallBaseContext()->getCalledOperandUse())); else Success = A.checkForAllCallSites(PredForCallSite, *this, true, - AllCallSitesKnown); + UsedAssumedInformation); if (!Success) if (!askSimplifiedValueForOtherAAs(A)) @@ -5755,8 +5764,10 @@ struct AAValueSimplifyFloating : AAValueSimplifyImpl { }; bool Dummy = false; + bool UsedAssumedInformation = false; if (!genericValueTraversal<bool>(A, getIRPosition(), *this, Dummy, VisitValueCB, getCtxI(), + UsedAssumedInformation, /* UseValueSimplify */ false)) if (!askSimplifiedValueForOtherAAs(A)) return indicatePessimisticFixpoint(); @@ -6168,7 +6179,8 @@ ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) { // branches etc. SmallVector<Value *, 8> Objects; if (!AA::getAssumedUnderlyingObjects(A, *DI.CB->getArgOperand(0), Objects, - *this, DI.CB)) { + *this, DI.CB, + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "[H2S] Unexpected failure in getAssumedUnderlyingObjects!\n"); @@ -6446,10 +6458,10 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { Optional<Type *> identifyPrivatizableType(Attributor &A) override { // If this is a byval argument and we know all the call sites (so we can // rewrite them), there is no need to check them explicitly. - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (getIRPosition().hasAttr(Attribute::ByVal) && A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this, - true, AllCallSitesKnown)) + true, UsedAssumedInformation)) return getAssociatedValue().getType()->getPointerElementType(); Optional<Type *> Ty; @@ -6499,7 +6511,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { return !Ty.hasValue() || Ty.getValue(); }; - if (!A.checkForAllCallSites(CallSiteCheck, *this, true, AllCallSitesKnown)) + if (!A.checkForAllCallSites(CallSiteCheck, *this, true, + UsedAssumedInformation)) return nullptr; return Ty; } @@ -6546,9 +6559,9 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { return TTI->areTypesABICompatible( CB->getCaller(), CB->getCalledFunction(), ReplacementTypes); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; if (!A.checkForAllCallSites(CallSiteCheck, *this, true, - AllCallSitesKnown)) { + UsedAssumedInformation)) { LLVM_DEBUG( dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for " << Fn.getName() << "\n"); @@ -6675,7 +6688,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { }; if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true, - AllCallSitesKnown)) + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return ChangeStatus::UNCHANGED; @@ -7775,7 +7788,9 @@ void AAMemoryLocationImpl::categorizePtrValue( << getMemoryLocationsAsStr(State.getAssumed()) << "]\n"); SmallVector<Value *, 8> Objects; + bool UsedAssumedInformation = false; if (!AA::getAssumedUnderlyingObjects(A, Ptr, Objects, *this, &I, + UsedAssumedInformation, /* Intraprocedural */ true)) { LLVM_DEBUG( dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n"); @@ -8591,8 +8606,10 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { IntegerRangeState T(getBitWidth()); + bool UsedAssumedInformation = false; if (!genericValueTraversal<IntegerRangeState>(A, getIRPosition(), *this, T, VisitValueCB, getCtxI(), + UsedAssumedInformation, /* UseValueSimplify */ false)) return indicatePessimisticFixpoint(); @@ -9403,8 +9420,10 @@ struct AANoUndefFloating : public AANoUndefImpl { }; StateType T; + bool UsedAssumedInformation = false; if (!genericValueTraversal<StateType>(A, getIRPosition(), *this, T, - VisitValueCB, getCtxI())) + VisitValueCB, getCtxI(), + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return clampStateAndIndicateChange(getState(), T); @@ -9521,9 +9540,10 @@ struct AACallEdgesCallSite : public AACallEdgesImpl { // Process any value that we might call. auto ProcessCalledOperand = [&](Value *V) { bool DummyValue = false; + bool UsedAssumedInformation = false; if (!genericValueTraversal<bool>(A, IRPosition::value(*V), *this, DummyValue, VisitValue, nullptr, - false)) { + UsedAssumedInformation, false)) { // If we haven't gone through all values, assume that there are unknown // callees. setHasUnknownCallee(true, Change); @@ -9942,12 +9962,13 @@ struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl { return !getAssumed().empty() || !getKnown().empty(); }; - bool AllCallSitesKnown; + bool UsedAssumedInformation = false; // Get the intersection of all assumptions held by this node's predecessors. // If we don't know all the call sites then this is either an entry into the // call graph or an empty node. This node is known to only contain its own // assumptions and can be propagated to its successors. - if (!A.checkForAllCallSites(CallSitePred, *this, true, AllCallSitesKnown)) + if (!A.checkForAllCallSites(CallSitePred, *this, true, + UsedAssumedInformation)) return indicatePessimisticFixpoint(); return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; diff --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll index 61bba0a6044e..dd096a32c147 100644 --- a/llvm/test/Transforms/Attributor/norecurse.ll +++ b/llvm/test/Transforms/Attributor/norecurse.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals -; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM -; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM @@ -71,7 +71,7 @@ define void @intrinsic(i8* %dest, i8* %src, i32 %len) { ; CHECK: Function Attrs: argmemonly nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@intrinsic ; CHECK-SAME: (i8* nocapture nofree writeonly [[DEST:%.*]], i8* nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) #[[ATTR4:[0-9]+]] { -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) #[[ATTR8:[0-9]+]] +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) #[[ATTR9:[0-9]+]] ; CHECK-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) @@ -250,6 +250,47 @@ Dead: ret i32 1 } +define i1 @test_rec_neg(i1 %c) norecurse { +; CHECK: Function Attrs: norecurse +; CHECK-LABEL: define {{[^@]+}}@test_rec_neg +; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR8:[0-9]+]] { +; CHECK-NEXT: [[RC1:%.*]] = call noundef i1 @rec(i1 noundef true) +; CHECK-NEXT: br i1 [[RC1]], label [[T:%.*]], label [[F:%.*]] +; CHECK: t: +; CHECK-NEXT: [[RC2:%.*]] = call noundef i1 @rec(i1 [[C]]) +; CHECK-NEXT: ret i1 [[RC2]] +; CHECK: f: +; CHECK-NEXT: ret i1 [[RC1]] +; + %rc1 = call i1 @rec(i1 true) + br i1 %rc1, label %t, label %f +t: + %rc2 = call i1 @rec(i1 %c) + ret i1 %rc2 +f: + ret i1 %rc1 +} + +define internal i1 @rec(i1 %c1) { +; CHECK-LABEL: define {{[^@]+}}@rec +; CHECK-SAME: (i1 [[C1:%.*]]) { +; CHECK-NEXT: br i1 [[C1]], label [[T:%.*]], label [[F:%.*]] +; CHECK: t: +; CHECK-NEXT: ret i1 true +; CHECK: f: +; CHECK-NEXT: [[R:%.*]] = call i1 @rec(i1 noundef true) +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret i1 false +; + br i1 %c1, label %t, label %f +t: + ret i1 true +f: + %r = call i1 @rec(i1 true) + call void @unknown() + ret i1 false +} + ;. ; CHECK: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; CHECK: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } @@ -259,5 +300,6 @@ Dead: ; CHECK: attributes #[[ATTR5:[0-9]+]] = { argmemonly nofree nounwind willreturn } ; CHECK: attributes #[[ATTR6]] = { norecurse nosync readnone } ; CHECK: attributes #[[ATTR7]] = { null_pointer_is_valid } -; CHECK: attributes #[[ATTR8]] = { willreturn } +; CHECK: attributes #[[ATTR8]] = { norecurse } +; CHECK: attributes #[[ATTR9]] = { willreturn } ;. diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines.ll b/llvm/test/Transforms/OpenMP/custom_state_machines.ll index e17679b2a896..c0f51d3bbcf6 100644 --- a/llvm/test/Transforms/OpenMP/custom_state_machines.ll +++ b/llvm/test/Transforms/OpenMP/custom_state_machines.ll @@ -1620,9 +1620,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-NEXT: ret void ; ; -; AMDGPU: Function Attrs: convergent noinline norecurse nounwind +; AMDGPU: Function Attrs: convergent noinline nounwind ; AMDGPU-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; AMDGPU-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { +; AMDGPU-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { ; AMDGPU-NEXT: entry: ; AMDGPU-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; AMDGPU-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -1632,7 +1632,7 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-NEXT: br label [[RETURN:%.*]] ; AMDGPU: if.end: ; AMDGPU-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1 -; AMDGPU-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR11:[0-9]+]] +; AMDGPU-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR8]] ; AMDGPU-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after_after.internalized() #[[ATTR8]] ; AMDGPU-NEXT: br label [[RETURN]] ; AMDGPU: return: @@ -1772,9 +1772,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-NEXT: ret void ; ; -; AMDGPU: Function Attrs: convergent noinline norecurse nounwind +; AMDGPU: Function Attrs: convergent noinline nounwind ; AMDGPU-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after_after.internalized -; AMDGPU-SAME: () #[[ATTR0]] { +; AMDGPU-SAME: () #[[ATTR1]] { ; AMDGPU-NEXT: entry: ; AMDGPU-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [0 x i8*], align 8 ; AMDGPU-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef @[[GLOB2]]) #[[ATTR3]] @@ -2590,9 +2590,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-NEXT: ret void ; ; -; NVPTX: Function Attrs: convergent noinline norecurse nounwind +; NVPTX: Function Attrs: convergent noinline nounwind ; NVPTX-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; NVPTX-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { +; NVPTX-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { ; NVPTX-NEXT: entry: ; NVPTX-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; NVPTX-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -2602,7 +2602,7 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-NEXT: br label [[RETURN:%.*]] ; NVPTX: if.end: ; NVPTX-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1 -; NVPTX-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR11:[0-9]+]] +; NVPTX-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR8]] ; NVPTX-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after_after.internalized() #[[ATTR8]] ; NVPTX-NEXT: br label [[RETURN]] ; NVPTX: return: @@ -2741,9 +2741,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-NEXT: ret void ; ; -; NVPTX: Function Attrs: convergent noinline norecurse nounwind +; NVPTX: Function Attrs: convergent noinline nounwind ; NVPTX-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after_after.internalized -; NVPTX-SAME: () #[[ATTR0]] { +; NVPTX-SAME: () #[[ATTR1]] { ; NVPTX-NEXT: entry: ; NVPTX-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [0 x i8*], align 8 ; NVPTX-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef @[[GLOB2]]) #[[ATTR3]] @@ -3315,9 +3315,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-DISABLED-NEXT: ret void ; ; -; AMDGPU-DISABLED: Function Attrs: convergent noinline norecurse nounwind +; AMDGPU-DISABLED: Function Attrs: convergent noinline nounwind ; AMDGPU-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; AMDGPU-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { +; AMDGPU-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { ; AMDGPU-DISABLED-NEXT: entry: ; AMDGPU-DISABLED-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; AMDGPU-DISABLED-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -3327,7 +3327,7 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-DISABLED-NEXT: br label [[RETURN:%.*]] ; AMDGPU-DISABLED: if.end: ; AMDGPU-DISABLED-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1 -; AMDGPU-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR11:[0-9]+]] +; AMDGPU-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR8]] ; AMDGPU-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after_after.internalized() #[[ATTR8]] ; AMDGPU-DISABLED-NEXT: br label [[RETURN]] ; AMDGPU-DISABLED: return: @@ -3436,9 +3436,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; AMDGPU-DISABLED-NEXT: ret void ; ; -; AMDGPU-DISABLED: Function Attrs: convergent noinline norecurse nounwind +; AMDGPU-DISABLED: Function Attrs: convergent noinline nounwind ; AMDGPU-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after_after.internalized -; AMDGPU-DISABLED-SAME: () #[[ATTR0]] { +; AMDGPU-DISABLED-SAME: () #[[ATTR1]] { ; AMDGPU-DISABLED-NEXT: entry: ; AMDGPU-DISABLED-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [0 x i8*], align 8 ; AMDGPU-DISABLED-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef @[[GLOB2]]) #[[ATTR3]] @@ -4010,9 +4010,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-DISABLED-NEXT: ret void ; ; -; NVPTX-DISABLED: Function Attrs: convergent noinline norecurse nounwind +; NVPTX-DISABLED: Function Attrs: convergent noinline nounwind ; NVPTX-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after.internalized -; NVPTX-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR0]] { +; NVPTX-DISABLED-SAME: (i32 [[A:%.*]]) #[[ATTR1]] { ; NVPTX-DISABLED-NEXT: entry: ; NVPTX-DISABLED-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 ; NVPTX-DISABLED-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 @@ -4022,7 +4022,7 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-DISABLED-NEXT: br label [[RETURN:%.*]] ; NVPTX-DISABLED: if.end: ; NVPTX-DISABLED-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], 1 -; NVPTX-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR11:[0-9]+]] +; NVPTX-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after.internalized(i32 [[SUB]]) #[[ATTR8]] ; NVPTX-DISABLED-NEXT: call void @simple_state_machine_interprocedural_nested_recursive_after_after.internalized() #[[ATTR8]] ; NVPTX-DISABLED-NEXT: br label [[RETURN]] ; NVPTX-DISABLED: return: @@ -4131,9 +4131,9 @@ attributes #9 = { convergent nounwind readonly willreturn } ; NVPTX-DISABLED-NEXT: ret void ; ; -; NVPTX-DISABLED: Function Attrs: convergent noinline norecurse nounwind +; NVPTX-DISABLED: Function Attrs: convergent noinline nounwind ; NVPTX-DISABLED-LABEL: define {{[^@]+}}@simple_state_machine_interprocedural_nested_recursive_after_after.internalized -; NVPTX-DISABLED-SAME: () #[[ATTR0]] { +; NVPTX-DISABLED-SAME: () #[[ATTR1]] { ; NVPTX-DISABLED-NEXT: entry: ; NVPTX-DISABLED-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [0 x i8*], align 8 ; NVPTX-DISABLED-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef @[[GLOB2]]) #[[ATTR3]] |