diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1481,6 +1481,12 @@ bool &UsedAssumedInformation) { return getAssumedSimplified(IRP, &AA, UsedAssumedInformation); } + Optional getAssumedSimplified(const Value &V, + const AbstractAttribute &AA, + bool &UsedAssumedInformation) { + return getAssumedSimplified(IRPosition::value(V), AA, + UsedAssumedInformation); + } /// Register \p CB as a simplification callback. /// `Attributor::getAssumedSimplified` will use these callbacks before @@ -1507,6 +1513,12 @@ bool &UsedAssumedInformation); public: + /// Translate \p V from the callee context into the call site context. + Optional + translateArgumentToCallSiteContent(Optional V, CallBase &CB, + const AbstractAttribute &AA, + bool &UsedAssumedInformation); + /// Return true if \p AA (or its context instruction) is assumed dead. /// /// If \p LivenessAA is not provided it is queried. @@ -2654,7 +2666,6 @@ virtual llvm::iterator_range returned_values() const = 0; virtual size_t getNumReturnValues() const = 0; - virtual const SmallSetVector &getUnresolvedCalls() const = 0; /// Create an abstract attribute view for the position \p IRP. static AAReturnedValues &createForPosition(const IRPosition &IRP, diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/MustExecute.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/IRBuilder.h" @@ -670,6 +671,21 @@ return const_cast(&IRP.getAssociatedValue()); } +Optional Attributor::translateArgumentToCallSiteContent( + Optional V, CallBase &CB, const AbstractAttribute &AA, + bool &UsedAssumedInformation) { + if (!V.hasValue()) + return V; + if (*V == nullptr || isa(*V)) + return V; + if (auto *Arg = dyn_cast(*V)) + if (!Arg->hasPointeeInMemoryValueAttr()) + return getAssumedSimplified( + IRPosition::callsite_argument(CB, Arg->getArgNo()), AA, + UsedAssumedInformation); + return nullptr; +} + Attributor::~Attributor() { // The abstract attributes are allocated via the BumpPtrAllocator Allocator, // thus we cannot delete them. We can, and want to, destruct them though. @@ -1365,11 +1381,17 @@ // Do not replace uses in returns if the value is a must-tail call we will // not delete. - if (isa(U->getUser())) + if (auto *RI = dyn_cast(U->getUser())) { if (auto *CI = dyn_cast(OldV->stripPointerCasts())) if (CI->isMustTailCall() && (!ToBeDeletedInsts.count(CI) || !isRunOn(*CI->getCaller()))) return; + // If we rewrite a return and the new value is not an argument, strip the + // `returned` attribute as it is wrong now. + if (!isa(NewV)) + for (auto &Arg : RI->getFunction()->args()) + Arg.removeAttr(Attribute::Returned); + } // Do not perform call graph altering changes outside the SCC. if (auto *CB = dyn_cast(U->getUser())) @@ -2292,10 +2314,7 @@ if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) { IRPosition CBRetPos = IRPosition::callsite_returned(CB); - - // Call site return integer values might be limited by a constant range. - if (Callee->getReturnType()->isIntegerTy()) - getOrCreateAAFor(CBRetPos); + getOrCreateAAFor(CBRetPos); } for (int I = 0, E = CB.getNumArgOperands(); I < E; ++I) { diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -831,13 +831,6 @@ /// return instructions that might return them. MapVector> ReturnedValues; - /// Mapping to remember the number of returned values for a call site such - /// that we can avoid updates if nothing changed. - DenseMap NumReturnedValuesPerKnownAA; - - /// Set of unresolved calls returned by the associated function. - SmallSetVector UnresolvedCalls; - /// State flags /// ///{ @@ -904,10 +897,6 @@ return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end()); } - const SmallSetVector &getUnresolvedCalls() const override { - return UnresolvedCalls; - } - /// Return the number of potential return values, -1 if unknown. size_t getNumReturnValues() const override { return isValidState() ? ReturnedValues.size() : -1; @@ -962,16 +951,6 @@ // Bookkeeping. STATS_DECLTRACK(UniqueReturnValue, FunctionReturn, "Number of function with unique return"); - - // Callback to replace the uses of CB with the constant C. - auto ReplaceCallSiteUsersWith = [&A](CallBase &CB, Constant &C) { - if (CB.use_empty()) - return ChangeStatus::UNCHANGED; - if (A.changeValueAfterManifest(CB, C)) - return ChangeStatus::CHANGED; - return ChangeStatus::UNCHANGED; - }; - // If the assumed unique return value is an argument, annotate it. if (auto *UniqueRVArg = dyn_cast(UniqueRV.getValue())) { if (UniqueRVArg->getType()->canLosslesslyBitCastTo( @@ -979,40 +958,13 @@ getIRPosition() = IRPosition::argument(*UniqueRVArg); Changed = IRAttribute::manifest(A); } - } else if (auto *RVC = dyn_cast(UniqueRV.getValue())) { - // We can replace the returned value with the unique returned constant. - Value &AnchorValue = getAnchorValue(); - if (Function *F = dyn_cast(&AnchorValue)) { - for (const Use &U : F->uses()) - if (CallBase *CB = dyn_cast(U.getUser())) - if (CB->isCallee(&U)) { - Constant *RVCCast = - CB->getType() == RVC->getType() - ? RVC - : ConstantExpr::getPointerCast(RVC, CB->getType()); - Changed = ReplaceCallSiteUsersWith(*CB, *RVCCast) | Changed; - } - } else { - assert(isa(AnchorValue) && - "Expcected a function or call base anchor!"); - Constant *RVCCast = - AnchorValue.getType() == RVC->getType() - ? RVC - : ConstantExpr::getPointerCast(RVC, AnchorValue.getType()); - Changed = ReplaceCallSiteUsersWith(cast(AnchorValue), *RVCCast); - } - if (Changed == ChangeStatus::CHANGED) - STATS_DECLTRACK(UniqueConstantReturnValue, FunctionReturn, - "Number of function returns replaced by constant return"); } - return Changed; } const std::string AAReturnedValuesImpl::getAsStr() const { return (isAtFixpoint() ? "returns(#" : "may-return(#") + - (isValidState() ? std::to_string(getNumReturnValues()) : "?") + - ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]"; + (isValidState() ? std::to_string(getNumReturnValues()) : "?") + ")"; } Optional @@ -1046,11 +998,6 @@ // encountered an overdefined one during an update. for (auto &It : ReturnedValues) { Value *RV = It.first; - - CallBase *CB = dyn_cast(RV); - if (CB && !UnresolvedCalls.count(CB)) - continue; - if (!Pred(*RV, It.second)) return false; } @@ -1059,180 +1006,35 @@ } ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) { - size_t NumUnresolvedCalls = UnresolvedCalls.size(); - bool Changed = false; - - // State used in the value traversals starting in returned values. - struct RVState { - // The map in which we collect return values -> return instrs. - decltype(ReturnedValues) &RetValsMap; - // The flag to indicate a change. - bool &Changed; - // The return instrs we come from. - SmallSetVector RetInsts; - }; + ChangeStatus Changed = ChangeStatus::UNCHANGED; - // Callback for a leaf value returned by the associated function. - auto VisitValueCB = [](Value &Val, const Instruction *, RVState &RVS, - bool) -> bool { - auto Size = RVS.RetValsMap[&Val].size(); - RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end()); - bool Inserted = RVS.RetValsMap[&Val].size() != Size; - RVS.Changed |= Inserted; - LLVM_DEBUG({ - if (Inserted) - dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val - << " => " << RVS.RetInsts.size() << "\n"; - }); + auto ReturnValueCB = [&](Value &V, const Instruction *CtxI, ReturnInst &Ret, + bool) -> bool { + bool UsedAssumedInformation = false; + Optional SimpleRetVal = + A.getAssumedSimplified(V, *this, UsedAssumedInformation); + if (!SimpleRetVal.hasValue()) + return true; + Value *RetVal = *SimpleRetVal ? *SimpleRetVal : &V; + assert(AA::isValidInScope(*RetVal, Ret.getFunction()) && + "Assumed returned value should be valid in function scope!"); + if (ReturnedValues[RetVal].insert(&Ret)) + Changed = ChangeStatus::CHANGED; return true; }; - // Helper method to invoke the generic value traversal. - auto VisitReturnedValue = [&](Value &RV, RVState &RVS, - const Instruction *CtxI) { - IRPosition RetValPos = IRPosition::value(RV, getCallBaseContext()); - return genericValueTraversal(A, RetValPos, *this, RVS, - VisitValueCB, CtxI, - /* UseValueSimplify */ false); - }; - - // Callback for all "return intructions" live in the associated function. - auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) { + auto ReturnInstCB = [&](Instruction &I) { ReturnInst &Ret = cast(I); - RVState RVS({ReturnedValues, Changed, {}}); - RVS.RetInsts.insert(&Ret); - return VisitReturnedValue(*Ret.getReturnValue(), RVS, &I); + return genericValueTraversal( + A, IRPosition::value(*Ret.getReturnValue()), *this, Ret, ReturnValueCB, + &I); }; - // Start by discovering returned values from all live returned instructions in - // the associated function. - if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret})) + // Discover returned values from all live returned instructions in the + // associated function. + if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret})) return indicatePessimisticFixpoint(); - - // Once returned values "directly" present in the code are handled we try to - // resolve returned calls. To avoid modifications to the ReturnedValues map - // while we iterate over it we kept record of potential new entries in a copy - // map, NewRVsMap. - decltype(ReturnedValues) NewRVsMap; - - auto HandleReturnValue = [&](Value *RV, - SmallSetVector &RIs) { - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *RV << " by #" - << RIs.size() << " RIs\n"); - CallBase *CB = dyn_cast(RV); - if (!CB || UnresolvedCalls.count(CB)) - return; - - if (!CB->getCalledFunction()) { - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB - << "\n"); - UnresolvedCalls.insert(CB); - return; - } - - // TODO: use the function scope once we have call site AAReturnedValues. - const auto &RetValAA = A.getAAFor( - *this, IRPosition::function(*CB->getCalledFunction()), - DepClassTy::REQUIRED); - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: " - << RetValAA << "\n"); - - // Skip dead ends, thus if we do not know anything about the returned - // call we mark it as unresolved and it will stay that way. - if (!RetValAA.getState().isValidState()) { - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB - << "\n"); - UnresolvedCalls.insert(CB); - return; - } - - // Do not try to learn partial information. If the callee has unresolved - // return values we will treat the call as unresolved/opaque. - auto &RetValAAUnresolvedCalls = RetValAA.getUnresolvedCalls(); - if (!RetValAAUnresolvedCalls.empty()) { - UnresolvedCalls.insert(CB); - return; - } - - // Now check if we can track transitively returned values. If possible, thus - // if all return value can be represented in the current scope, do so. - bool Unresolved = false; - for (auto &RetValAAIt : RetValAA.returned_values()) { - Value *RetVal = RetValAAIt.first; - if (isa(RetVal) || isa(RetVal) || - isa(RetVal)) - continue; - // Anything that did not fit in the above categories cannot be resolved, - // mark the call as unresolved. - LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value " - "cannot be translated: " - << *RetVal << "\n"); - UnresolvedCalls.insert(CB); - Unresolved = true; - break; - } - - if (Unresolved) - return; - - // Now track transitively returned values. - unsigned &NumRetAA = NumReturnedValuesPerKnownAA[CB]; - if (NumRetAA == RetValAA.getNumReturnValues()) { - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Skip call as it has not " - "changed since it was seen last\n"); - return; - } - NumRetAA = RetValAA.getNumReturnValues(); - - for (auto &RetValAAIt : RetValAA.returned_values()) { - Value *RetVal = RetValAAIt.first; - if (Argument *Arg = dyn_cast(RetVal)) { - // Arguments are mapped to call site operands and we begin the traversal - // again. - bool Unused = false; - RVState RVS({NewRVsMap, Unused, RetValAAIt.second}); - VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS, CB); - continue; - } - if (isa(RetVal)) { - // Call sites are resolved by the callee attribute over time, no need to - // do anything for us. - continue; - } - if (isa(RetVal)) { - // Constants are valid everywhere, we can simply take them. - NewRVsMap[RetVal].insert(RIs.begin(), RIs.end()); - continue; - } - } - }; - - for (auto &It : ReturnedValues) - HandleReturnValue(It.first, It.second); - - // Because processing the new information can again lead to new return values - // we have to be careful and iterate until this iteration is complete. The - // idea is that we are in a stable state at the end of an update. All return - // values have been handled and properly categorized. We might not update - // again if we have not requested a non-fix attribute so we cannot "wait" for - // the next update to analyze a new return value. - while (!NewRVsMap.empty()) { - auto It = std::move(NewRVsMap.back()); - NewRVsMap.pop_back(); - - assert(!It.second.empty() && "Entry does not add anything."); - auto &ReturnInsts = ReturnedValues[It.first]; - for (ReturnInst *RI : It.second) - if (ReturnInsts.insert(RI)) { - LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value " - << *It.first << " => " << *RI << "\n"); - HandleReturnValue(It.first, ReturnInsts); - Changed = true; - } - } - - Changed |= (NumUnresolvedCalls != UnresolvedCalls.size()); - return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; + return Changed; } struct AAReturnedValuesFunction final : public AAReturnedValuesImpl { @@ -1943,7 +1745,8 @@ // If we reach here, we know we have an instruction // that accesses memory through a pointer operand, // for which getPointerOperand() should give it to us. - const Value *PtrOp = getPointerOperand(&I, /* AllowVolatile */ true); + Value *PtrOp = + const_cast(getPointerOperand(&I, /* AllowVolatile */ true)); assert(PtrOp && "Expected pointer operand of memory accessing instruction"); @@ -1985,7 +1788,7 @@ return true; // We know we have a branch instruction. - auto BrInst = cast(&I); + auto *BrInst = cast(&I); // Unconditional branches are never considered UB. if (BrInst->isUnconditional()) @@ -2202,27 +2005,27 @@ // action was taken and the caller should stop. // Otherwise, we return the simplified value that the caller should // use for specific processing. - Optional stopOnUndefOrAssumed(Attributor &A, const Value *V, + Optional stopOnUndefOrAssumed(Attributor &A, Value *V, Instruction *I) { bool UsedAssumedInformation = false; Optional SimplifiedV = A.getAssumedSimplified( IRPosition::value(*V), *this, UsedAssumedInformation); - if (UsedAssumedInformation) { + if (!UsedAssumedInformation) { // Don't depend on assumed values. - return llvm::None; - } - if (!SimplifiedV.hasValue()) { - // If it is known (which we tested above) but it doesn't have a value, - // then we can assume `undef` and hence the instruction is UB. - KnownUBInsts.insert(I); - return llvm::None; + if (!SimplifiedV.hasValue()) { + // If it is known (which we tested above) but it doesn't have a value, + // then we can assume `undef` and hence the instruction is UB. + KnownUBInsts.insert(I); + return llvm::None; + } + if (*SimplifiedV != nullptr) + V = *SimplifiedV; } - Value *Val = SimplifiedV.getValue(); - if (isa(Val)) { + if (isa(V)) { KnownUBInsts.insert(I); return llvm::None; } - return Val; + return V; } }; @@ -2821,6 +2624,10 @@ /// Check if all uses are assumed dead. bool areAllUsesAssumedDead(Attributor &A, Value &V) { + // Callers might not check the type, void has no uses. + if (V.getType()->isVoidTy()) + return true; + // If we replace a value with a constant there are no uses left afterwards. if (!isa(V)) { bool UsedAssumedInformation = false; @@ -4561,7 +4368,7 @@ const std::string getAsStr() const override { LLVM_DEBUG({ errs() << "SAV: " << SimplifiedAssociatedValue << " "; - if (SimplifiedAssociatedValue) + if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue) errs() << "SAV: " << **SimplifiedAssociatedValue << " "; }); return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple") @@ -4573,18 +4380,34 @@ /// See AAValueSimplify::getAssumedSimplifiedValue() Optional getAssumedSimplifiedValue(Attributor &A) const override { - if (!isValidState()) - return const_cast(&getAssociatedValue()); return SimplifiedAssociatedValue; } + /// Return a value we can use as replacement for the associated one, or + /// nullptr if we don't have one that makes sense. + virtual Value *getReplacementValue() const { + Value *NewV; + NewV = SimplifiedAssociatedValue.hasValue() + ? SimplifiedAssociatedValue.getValue() + : UndefValue::get(getAssociatedType()); + if (!NewV) + return nullptr; + NewV = AA::getWithType(*NewV, *getAssociatedType()); + if (!NewV || NewV == &getAssociatedValue() || + !AA::isValidInScope(*NewV, getAnchorScope())) + return nullptr; + return NewV; + } + /// Helper function for querying AAValueSimplify and updating candicate. /// \param IRP The value position we are trying to unify with SimplifiedValue bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA, - const IRPosition &IRP) { + const IRPosition &IRP, bool Simplify = true) { bool UsedAssumedInformation = false; - Optional QueryingValueSimplified = - A.getAssumedSimplified(IRP, QueryingAA, UsedAssumedInformation); + Optional QueryingValueSimplified = &IRP.getAssociatedValue(); + if (Simplify) + QueryingValueSimplified = + A.getAssumedSimplified(IRP, QueryingAA, UsedAssumedInformation); return unionAssumed(QueryingValueSimplified); } @@ -4623,24 +4446,14 @@ /// See AbstractAttribute::manifest(...). ChangeStatus manifest(Attributor &A) override { ChangeStatus Changed = ChangeStatus::UNCHANGED; - - if (SimplifiedAssociatedValue.hasValue() && - !SimplifiedAssociatedValue.getValue()) + if (getAssociatedValue().user_empty()) return Changed; - Value &V = getAssociatedValue(); - auto *C = SimplifiedAssociatedValue.hasValue() - ? dyn_cast(SimplifiedAssociatedValue.getValue()) - : UndefValue::get(V.getType()); - if (C && C != &V && !V.user_empty()) { - Value *NewV = AA::getWithType(*C, *V.getType()); - // We can replace the AssociatedValue with the constant. - if (NewV && NewV != &V) { - LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *NewV - << " :: " << *this << "\n"); - if (A.changeValueAfterManifest(V, *NewV)) - Changed = ChangeStatus::CHANGED; - } + if (auto *NewV = getReplacementValue()) { + LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue() << " -> " + << *NewV << " :: " << *this << "\n"); + if (A.changeValueAfterManifest(getAssociatedValue(), *NewV)) + Changed = ChangeStatus::CHANGED; } return Changed | AAValueSimplify::manifest(A); @@ -4648,11 +4461,8 @@ /// See AbstractState::indicatePessimisticFixpoint(...). ChangeStatus indicatePessimisticFixpoint() override { - // NOTE: Associated value will be returned in a pessimistic fixpoint and is - // regarded as known. That's why`indicateOptimisticFixpoint` is called. SimplifiedAssociatedValue = &getAssociatedValue(); - indicateOptimisticFixpoint(); - return ChangeStatus::CHANGED; + return AAValueSimplify::indicatePessimisticFixpoint(); } }; @@ -4703,14 +4513,27 @@ if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID) return false; + // Simplify the argument operand explicitly and check if the result is + // valid in the current scope. This avoids refering to simplified values + // in other functions, e.g., we don't want to say a an argument in a + // static function is actually an argument in a different function. + Value &ArgOp = ACSArgPos.getAssociatedValue(); + bool UsedAssumedInformation; + Optional SimpleArgOp = + A.getAssumedSimplified(ACSArgPos, *this, UsedAssumedInformation); + if (!SimpleArgOp.hasValue()) + return true; + Value *SimpleArgOpVal = *SimpleArgOp ? *SimpleArgOp : &ArgOp; + if (!AA::isValidInScope(*SimpleArgOpVal, getAnchorScope())) + return false; + // We can only propagate thread independent values through callbacks. // This is different to direct/indirect call sites because for them we // know the thread executing the caller and callee is the same. For // callbacks this is not guaranteed, thus a thread dependent value could // be different for the caller and callee, making it invalid to propagate. - Value &ArgOp = ACSArgPos.getAssociatedValue(); if (ACS.isCallbackCall()) - if (auto *C = dyn_cast(&ArgOp)) + if (auto *C = dyn_cast(SimpleArgOpVal)) if (C->isThreadDependent()) return false; return checkAndUpdate(A, *this, ACSArgPos); @@ -4745,6 +4568,13 @@ AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A) : AAValueSimplifyImpl(IRP, A) {} + /// See AAValueSimplify::getAssumedSimplifiedValue() + Optional getAssumedSimplifiedValue(Attributor &A) const override { + if (!isValidState()) + return nullptr; + return SimplifiedAssociatedValue; + } + /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { auto Before = SimplifiedAssociatedValue; @@ -4766,36 +4596,25 @@ ChangeStatus manifest(Attributor &A) override { ChangeStatus Changed = ChangeStatus::UNCHANGED; - if (SimplifiedAssociatedValue.hasValue() && - !SimplifiedAssociatedValue.getValue()) - return Changed | AAValueSimplify::manifest(A); - - auto *C = SimplifiedAssociatedValue.hasValue() - ? dyn_cast(SimplifiedAssociatedValue.getValue()) - : UndefValue::get(getAssociatedType()); - if (!C || C == &getAssociatedValue()) - return Changed | AAValueSimplify::manifest(A); - - auto PredForReturned = - [&](Value &V, const SmallSetVector &RetInsts) { - // We can replace the AssociatedValue with the constant. - if (&V == C || isa(V)) + if (auto *NewV = getReplacementValue()) { + auto PredForReturned = + [&](Value &, const SmallSetVector &RetInsts) { + for (ReturnInst *RI : RetInsts) { + Value *ReturnedVal = RI->getReturnValue(); + if (ReturnedVal == NewV || isa(ReturnedVal)) + return true; + assert(RI->getFunction() == getAnchorScope() && + "ReturnInst in wrong function!"); + LLVM_DEBUG(dbgs() + << "[ValueSimplify] " << *ReturnedVal << " -> " + << *NewV << " in " << *RI << " :: " << *this << "\n"); + if (A.changeUseAfterManifest(RI->getOperandUse(0), *NewV)) + Changed = ChangeStatus::CHANGED; + } return true; - - for (ReturnInst *RI : RetInsts) { - if (RI->getFunction() != getAnchorScope()) - continue; - Value *NewV = AA::getWithType(*C, *RI->getReturnValue()->getType()); - if (!NewV) - continue; - LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *NewV - << " in " << *RI << " :: " << *this << "\n"); - if (A.changeUseAfterManifest(RI->getOperandUse(0), *NewV)) - Changed = ChangeStatus::CHANGED; - } - return true; - }; - A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this); + }; + A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this); + } return Changed | AAValueSimplify::manifest(A); } @@ -4934,7 +4753,7 @@ /// See AbstractAttribute::initialize(...). void initialize(Attributor &A) override { - SimplifiedAssociatedValue = &getAnchorValue(); + SimplifiedAssociatedValue = nullptr; indicateOptimisticFixpoint(); } /// See AbstractAttribute::initialize(...). @@ -4957,19 +4776,43 @@ } }; -struct AAValueSimplifyCallSiteReturned : AAValueSimplifyReturned { +struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl { AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A) - : AAValueSimplifyReturned(IRP, A) {} + : AAValueSimplifyImpl(IRP, A) {} - /// See AbstractAttribute::manifest(...). - ChangeStatus manifest(Attributor &A) override { - return AAValueSimplifyImpl::manifest(A); + void initialize(Attributor &A) override { + if (!getAssociatedFunction()) + indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + auto Before = SimplifiedAssociatedValue; + auto &RetAA = A.getAAFor( + *this, IRPosition::function(*getAssociatedFunction()), + DepClassTy::REQUIRED); + auto PredForReturned = + [&](Value &RetVal, const SmallSetVector &RetInsts) { + bool UsedAssumedInformation; + Optional CSRetVal = A.translateArgumentToCallSiteContent( + &RetVal, *cast(getCtxI()), *this, + UsedAssumedInformation); + SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice( + SimplifiedAssociatedValue, CSRetVal, getAssociatedType()); + return SimplifiedAssociatedValue != Optional(nullptr); + }; + if (!RetAA.checkForAllReturnedValuesAndReturnInsts(PredForReturned)) + if (!askSimplifiedValueForOtherAAs(A)) + return indicatePessimisticFixpoint(); + return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED + : ChangeStatus ::CHANGED; } void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(value_simplify) } }; + struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating { AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A) : AAValueSimplifyFloating(IRP, A) {} @@ -4978,23 +4821,11 @@ ChangeStatus manifest(Attributor &A) override { ChangeStatus Changed = ChangeStatus::UNCHANGED; - if (SimplifiedAssociatedValue.hasValue() && - !SimplifiedAssociatedValue.getValue()) - return Changed; - - Value &V = getAssociatedValue(); - auto *C = SimplifiedAssociatedValue.hasValue() - ? dyn_cast(SimplifiedAssociatedValue.getValue()) - : UndefValue::get(V.getType()); - if (C) { + if (auto *NewV = getReplacementValue()) { Use &U = cast(&getAnchorValue()) ->getArgOperandUse(getCallSiteArgNo()); - // We can replace the AssociatedValue with the constant. - if (&V != C) { - if (Value *NewV = AA::getWithType(*C, *V.getType())) - if (A.changeUseAfterManifest(U, *NewV)) - Changed = ChangeStatus::CHANGED; - } + if (A.changeUseAfterManifest(U, *NewV)) + Changed = ChangeStatus::CHANGED; } return Changed | AAValueSimplify::manifest(A); diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.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=5 -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=5 -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=6 -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=6 -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 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.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=3 -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=3 -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=2 -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=2 -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 target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.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=3 -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=3 -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 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll @@ -8,37 +8,20 @@ target triple = "x86_64-unknown-linux-gnu" define i64 @fn2() { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fn2 -; IS__TUNIT_OPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR0]] -; IS__TUNIT_OPM-NEXT: ret i64 [[CALL2]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2 -; IS__TUNIT_NPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR0]], !range [[RNG0:![0-9]+]] -; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] -; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fn2 -; IS__CGSCC_OPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 -; IS__CGSCC_OPM-NEXT: [[DIV:%.*]] = sdiv i64 8, 0 -; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR1:[0-9]+]] -; IS__CGSCC_OPM-NEXT: ret i64 [[CALL2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2 +; IS__TUNIT____-SAME: () #[[ATTR0:[0-9]+]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i64 undef ; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fn2 -; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 -; IS__CGSCC_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, 0 -; IS__CGSCC_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] -; IS__CGSCC_NPM-NEXT: ret i64 [[CALL2]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2 +; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CONV:%.*]] = sext i32 undef to i64 +; IS__CGSCC____-NEXT: [[DIV:%.*]] = sdiv i64 8, 0 +; IS__CGSCC____-NEXT: ret i64 undef ; entry: %conv = sext i32 undef to i64 @@ -48,32 +31,22 @@ } define i64 @fn2b(i32 %arg) { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fn2b -; IS__TUNIT_OPM-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] { -; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 -; IS__TUNIT_OPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] -; IS__TUNIT_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #[[ATTR0]] -; IS__TUNIT_OPM-NEXT: ret i64 [[CALL2]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2b -; IS__TUNIT_NPM-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] { -; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 -; IS__TUNIT_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] -; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #[[ATTR0]], !range [[RNG0]] -; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2b +; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 +; IS__TUNIT____-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] +; IS__TUNIT____-NEXT: ret i64 [[DIV]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2b -; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 ; IS__CGSCC____-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] -; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] -; IS__CGSCC____-NEXT: ret i64 [[CALL2]] +; IS__CGSCC____-NEXT: ret i64 [[DIV]] ; entry: %conv = sext i32 %arg to i64 @@ -83,35 +56,23 @@ } define i64 @fn2c() { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fn2c -; IS__TUNIT_OPM-SAME: () #[[ATTR0]] { -; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 noundef 42) #[[ATTR0]] -; IS__TUNIT_OPM-NEXT: ret i64 [[CALL2]] -; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2c -; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { -; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 noundef 42) #[[ATTR0]], !range [[RNG0]] -; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2c +; IS__TUNIT____-SAME: () #[[ATTR0]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i64 42 ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fn2c ; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 -; IS__CGSCC_OPM-NEXT: [[ADD:%.*]] = add i64 42, 0 -; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 noundef 42) #[[ATTR1]] -; IS__CGSCC_OPM-NEXT: ret i64 [[CALL2]] +; IS__CGSCC_OPM-NEXT: ret i64 42 ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fn2c ; IS__CGSCC_NPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 -; IS__CGSCC_NPM-NEXT: [[ADD:%.*]] = add i64 42, 0 ; IS__CGSCC_NPM-NEXT: ret i64 42 ; entry: @@ -122,21 +83,11 @@ } define internal i64 @fn1(i64 %p1) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@fn1 -; IS__TUNIT____-SAME: (i64 returned [[P1:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0 -; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]] -; IS__TUNIT____-NEXT: ret i64 [[COND]] -; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn1 -; IS__CGSCC____-SAME: (i64 returned [[P1:%.*]]) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i64 [[P1:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0 -; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]] -; IS__CGSCC____-NEXT: ret i64 [[COND]] +; IS__CGSCC____-NEXT: ret i64 undef ; entry: %tobool = icmp ne i64 %p1, 0 @@ -147,9 +98,4 @@ ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn } -;. -; IS__TUNIT_NPM: [[RNG0]] = !{i64 -2147483606, i64 2147483690} -;. -; IS__CGSCC____: [[RNG0]] = !{i64 -8, i64 43} ;. diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll @@ -18,8 +18,7 @@ ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4 -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) #[[ATTR3:[0-9]+]] -; IS__TUNIT____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__TUNIT____-NEXT: store i32 [[TMP0]], i32* [[P]], align 4 ; IS__TUNIT____-NEXT: br label [[FOR_COND1]] ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret void @@ -34,8 +33,7 @@ ; IS__CGSCC____: if.end: ; IS__CGSCC____-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4 -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) -; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC____-NEXT: store i32 [[TMP0]], i32* [[P]], align 4 ; IS__CGSCC____-NEXT: br label [[FOR_COND1]] ; IS__CGSCC____: exit: ; IS__CGSCC____-NEXT: ret void @@ -57,21 +55,11 @@ } define internal i32 @fn1(i32 %p1) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@fn1 -; IS__TUNIT____-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1:[0-9]+]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; IS__TUNIT____-NEXT: ret i32 [[COND]] -; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn1 -; IS__CGSCC____-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1:[0-9]+]] { +; IS__CGSCC____-SAME: (i32 [[P1:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; IS__CGSCC____-NEXT: ret i32 [[COND]] +; IS__CGSCC____-NEXT: ret i32 undef ; entry: %tobool = icmp ne i32 %p1, 0 @@ -83,7 +71,7 @@ ; ; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn_no_null_opt -; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] { +; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] ; IS__TUNIT____: for.cond1: @@ -91,8 +79,7 @@ ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) #[[ATTR3]] -; IS__TUNIT____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__TUNIT____-NEXT: store i32 [[TMP0]], i32* [[P]], align 4 ; IS__TUNIT____-NEXT: br label [[FOR_COND1]] ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret void @@ -107,8 +94,7 @@ ; IS__CGSCC____: if.end: ; IS__CGSCC____-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) -; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC____-NEXT: store i32 [[TMP0]], i32* [[P]], align 4 ; IS__CGSCC____-NEXT: br label [[FOR_COND1]] ; IS__CGSCC____: exit: ; IS__CGSCC____-NEXT: ret void @@ -130,21 +116,11 @@ } define internal i32 @fn0(i32 %p1) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@fn0 -; IS__TUNIT____-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; IS__TUNIT____-NEXT: ret i32 [[COND]] -; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn0 -; IS__CGSCC____-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32 [[P1:%.*]]) #[[ATTR1]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; IS__CGSCC____-NEXT: ret i32 [[COND]] +; IS__CGSCC____-NEXT: ret i32 undef ; entry: %tobool = icmp ne i32 %p1, 0 @@ -153,9 +129,7 @@ } ;. ; IS__TUNIT____: attributes #[[ATTR0]] = { argmemonly nofree nosync nounwind } -; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } -; IS__TUNIT____: attributes #[[ATTR2]] = { nofree nosync nounwind null_pointer_is_valid } -; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind readnone } +; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind null_pointer_is_valid } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll @@ -118,8 +118,8 @@ define internal i16 @vararg_prop(i16 %p1, ...) { ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_prop -; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], ...) #[[ATTR0]] { -; IS__CGSCC____-NEXT: ret i16 7 +; IS__CGSCC____-SAME: (i16 [[P1:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC____-NEXT: ret i16 undef ; ret i16 %p1 } @@ -127,12 +127,12 @@ define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@vararg_no_prop -; IS__TUNIT____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { +; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { ; IS__TUNIT____-NEXT: ret i16 7 ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_no_prop -; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { ; IS__CGSCC____-NEXT: ret i16 7 ; ret i16 %p1 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll b/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.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=3 -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=3 -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=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-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 ; @@ -42,13 +42,13 @@ define internal i32 @cb0(i32 %zero) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@cb0 -; IS__TUNIT____-SAME: (i32 returned [[ZERO:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__TUNIT____-SAME: (i32 [[ZERO:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i32 0 ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@cb0 -; IS__CGSCC____-SAME: (i32 returned [[ZERO:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-SAME: (i32 [[ZERO:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: ret i32 0 ; diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.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=6 -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=6 -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 ; PR36485 @@ -10,37 +10,69 @@ define i8* @start(i8 %v) { ; -; IS__TUNIT____-LABEL: define {{[^@]+}}@start -; IS__TUNIT____-SAME: (i8 [[V:%.*]]) { -; IS__TUNIT____-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 -; IS__TUNIT____-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; IS__TUNIT____: true: -; IS__TUNIT____-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) -; IS__TUNIT____-NEXT: ret i8* [[CA]] -; IS__TUNIT____: false: -; IS__TUNIT____-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 -; IS__TUNIT____-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] -; IS__TUNIT____: c2_true: -; IS__TUNIT____-NEXT: ret i8* null -; IS__TUNIT____: c2_false: -; IS__TUNIT____-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) -; IS__TUNIT____-NEXT: ret i8* [[CA2]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@start +; IS__TUNIT_OPM-SAME: (i8 [[V:%.*]]) { +; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__TUNIT_OPM: true: +; IS__TUNIT_OPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) +; IS__TUNIT_OPM-NEXT: ret i8* [[CA]] +; IS__TUNIT_OPM: false: +; IS__TUNIT_OPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__TUNIT_OPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__TUNIT_OPM: c2_true: +; IS__TUNIT_OPM-NEXT: ret i8* null +; IS__TUNIT_OPM: c2_false: +; IS__TUNIT_OPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) +; IS__TUNIT_OPM-NEXT: ret i8* [[CA2]] ; -; IS__CGSCC____-LABEL: define {{[^@]+}}@start -; IS__CGSCC____-SAME: (i8 [[V:%.*]]) { -; IS__CGSCC____-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 -; IS__CGSCC____-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; IS__CGSCC____: true: -; IS__CGSCC____-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) -; IS__CGSCC____-NEXT: ret i8* [[CA]] -; IS__CGSCC____: false: -; IS__CGSCC____-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 -; IS__CGSCC____-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] -; IS__CGSCC____: c2_true: -; IS__CGSCC____-NEXT: ret i8* undef -; IS__CGSCC____: c2_false: -; IS__CGSCC____-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) -; IS__CGSCC____-NEXT: ret i8* [[CA2]] +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@start +; IS__TUNIT_NPM-SAME: (i8 [[V:%.*]]) { +; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__TUNIT_NPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__TUNIT_NPM: true: +; IS__TUNIT_NPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 undef) +; IS__TUNIT_NPM-NEXT: ret i8* [[CA]] +; IS__TUNIT_NPM: false: +; IS__TUNIT_NPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__TUNIT_NPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__TUNIT_NPM: c2_true: +; IS__TUNIT_NPM-NEXT: ret i8* null +; IS__TUNIT_NPM: c2_false: +; IS__TUNIT_NPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) +; IS__TUNIT_NPM-NEXT: ret i8* [[CA2]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@start +; IS__CGSCC_OPM-SAME: (i8 [[V:%.*]]) { +; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__CGSCC_OPM: true: +; IS__CGSCC_OPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) +; IS__CGSCC_OPM-NEXT: ret i8* [[CA]] +; IS__CGSCC_OPM: false: +; IS__CGSCC_OPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__CGSCC_OPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__CGSCC_OPM: c2_true: +; IS__CGSCC_OPM-NEXT: ret i8* undef +; IS__CGSCC_OPM: c2_false: +; IS__CGSCC_OPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) +; IS__CGSCC_OPM-NEXT: ret i8* [[CA2]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@start +; IS__CGSCC_NPM-SAME: (i8 [[V:%.*]]) { +; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__CGSCC_NPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__CGSCC_NPM: true: +; IS__CGSCC_NPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 undef) +; IS__CGSCC_NPM-NEXT: ret i8* [[CA]] +; IS__CGSCC_NPM: false: +; IS__CGSCC_NPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__CGSCC_NPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__CGSCC_NPM: c2_true: +; IS__CGSCC_NPM-NEXT: ret i8* undef +; IS__CGSCC_NPM: c2_false: +; IS__CGSCC_NPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) +; IS__CGSCC_NPM-NEXT: ret i8* [[CA2]] ; %c1 = icmp eq i8 %v, 0 br i1 %c1, label %true, label %false @@ -60,11 +92,17 @@ } define internal i8* @side_effects(i8 %v) { -; CHECK-LABEL: define {{[^@]+}}@side_effects -; CHECK-SAME: (i8 [[V:%.*]]) { -; CHECK-NEXT: [[I1:%.*]] = call i32 @external() -; CHECK-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 [[V]]) -; CHECK-NEXT: ret i8* [[CA]] +; IS________OPM-LABEL: define {{[^@]+}}@side_effects +; IS________OPM-SAME: (i8 [[V:%.*]]) { +; IS________OPM-NEXT: [[I1:%.*]] = call i32 @external() +; IS________OPM-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 [[V]]) +; IS________OPM-NEXT: ret i8* [[CA]] +; +; IS________NPM-LABEL: define {{[^@]+}}@side_effects +; IS________NPM-SAME: (i8 [[V:%.*]]) { +; IS________NPM-NEXT: [[I1:%.*]] = call i32 @external() +; IS________NPM-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 noundef 0) +; IS________NPM-NEXT: ret i8* [[CA]] ; %i1 = call i32 @external() diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll b/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.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=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 -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -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=6 -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 ; diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll @@ -40,7 +40,7 @@ ; IS__TUNIT____-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 ; IS__TUNIT____-NEXT: [[THREAD:%.*]] = alloca i64, align 8 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @foo, i8* noalias nocapture nofree readnone align 536870912 undef) -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) "no-capture-maybe-returned" undef) +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(8) undef) ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @baz, i8* noalias nocapture nofree noundef nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) ; IS__TUNIT____-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @buz, i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[ALLOC2]]) ; IS__TUNIT____-NEXT: ret i32 0 @@ -51,7 +51,7 @@ ; IS__CGSCC____-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 ; IS__CGSCC____-NEXT: [[THREAD:%.*]] = alloca i64, align 8 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @foo, i8* noalias nocapture nofree noundef readnone align 536870912 null) -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*)) +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nocapture nofree noundef nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*)) ; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @baz, i8* noalias nocapture nofree noundef nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) ; IS__CGSCC____-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 536870912 null, i8* (i8*)* noundef nonnull @buz, i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[ALLOC2]]) ; IS__CGSCC____-NEXT: ret i32 0 @@ -72,13 +72,13 @@ define internal i8* @foo(i8* %arg) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@foo -; IS__TUNIT____-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree readnone align 536870912 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i8* null ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo -; IS__CGSCC____-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree readnone align 536870912 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: ret i8* null ; @@ -89,13 +89,13 @@ define internal i8* @bar(i8* %arg) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@bar -; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(8) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] { +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR0]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@bar -; IS__CGSCC____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(8) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) ; diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll @@ -22,17 +22,17 @@ ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@incdec -; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* noalias nofree noundef nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: T: ; IS__CGSCC____-NEXT: [[X1:%.*]] = add i32 [[X]], 1 ; IS__CGSCC____-NEXT: store i32 [[X1]], i32* [[V]], align 4 -; IS__CGSCC____-NEXT: ret i32* [[V]] +; IS__CGSCC____-NEXT: ret i32* undef ; IS__CGSCC____: F: ; IS__CGSCC____-NEXT: [[X2:%.*]] = sub i32 [[X]], 1 ; IS__CGSCC____-NEXT: store i32 [[X2]], i32* [[V]], align 4 -; IS__CGSCC____-NEXT: ret i32* [[V]] +; IS__CGSCC____-NEXT: ret i32* undef ; %X = load i32, i32* %V br i1 %C, label %T, label %F @@ -86,7 +86,7 @@ ; IS__TUNIT____: OK: ; IS__TUNIT____-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 ; IS__TUNIT____-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]] -; IS__TUNIT____-NEXT: store i32 [[Z]], i32* [[W]], align 4 +; IS__TUNIT____-NEXT: store i32 [[Z]], i32* [[Q]], align 4 ; IS__TUNIT____-NEXT: br label [[RET:%.*]] ; IS__TUNIT____: LPAD: ; IS__TUNIT____-NEXT: unreachable @@ -97,7 +97,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] personality i32 (...)* @__gxx_personality_v0 { ; IS__CGSCC____-NEXT: [[Q:%.*]] = alloca i32, align 4 -; IS__CGSCC____-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC____-NEXT: [[W:%.*]] = call i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC____-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR3:[0-9]+]] ; IS__CGSCC____-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 ; IS__CGSCC____-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR4:[0-9]+]] @@ -105,7 +105,7 @@ ; IS__CGSCC____: OK: ; IS__CGSCC____-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 ; IS__CGSCC____-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]] -; IS__CGSCC____-NEXT: store i32 [[Z]], i32* [[W]], align 4 +; IS__CGSCC____-NEXT: store i32 [[Z]], i32* [[Q]], align 4 ; IS__CGSCC____-NEXT: br label [[RET:%.*]] ; IS__CGSCC____: LPAD: ; IS__CGSCC____-NEXT: unreachable diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -157,23 +157,14 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@f1 -; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { -; IS__TUNIT____-NEXT: br label [[TMP3:%.*]] -; IS__TUNIT____: 2: -; IS__TUNIT____-NEXT: unreachable -; IS__TUNIT____: 3: -; IS__TUNIT____-NEXT: ret i8* [[TMP0]] -; ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1 -; IS__CGSCC_OPM-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +; IS__CGSCC_OPM-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]] ; IS__CGSCC_OPM: 2: ; IS__CGSCC_OPM-NEXT: unreachable ; IS__CGSCC_OPM: 3: -; IS__CGSCC_OPM-NEXT: ret i8* @a1 +; IS__CGSCC_OPM-NEXT: ret i8* undef ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1 @@ -204,24 +195,22 @@ ; IS__CGSCC_OPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_OPM: 2: -; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = tail call i8* @f1(i8* noalias nonnull readnone align 536870912 dereferenceable(4294967295) undef) -; IS__CGSCC_OPM-NEXT: br label [[TMP5:%.*]] -; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: unreachable -; IS__CGSCC_OPM: 5: -; IS__CGSCC_OPM-NEXT: ret i8* [[TMP3]] +; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: ret i8* undef ; ; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2 ; IS__CGSCC_NPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_NPM: 2: -; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = tail call i8* @f1() -; IS__CGSCC_NPM-NEXT: br label [[TMP5:%.*]] -; IS__CGSCC_NPM: 4: +; IS__CGSCC_NPM-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC_NPM: 3: ; IS__CGSCC_NPM-NEXT: unreachable -; IS__CGSCC_NPM: 5: -; IS__CGSCC_NPM-NEXT: ret i8* @a1 +; IS__CGSCC_NPM: 4: +; IS__CGSCC_NPM-NEXT: ret i8* undef ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -278,8 +267,7 @@ ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7 ; IS__TUNIT____-SAME: () #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) #[[ATTR9:[0-9]+]] -; IS__TUNIT____-NEXT: ret i8* [[C]] +; IS__TUNIT____-NEXT: ret i8* @a1 ; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7 @@ -295,12 +283,12 @@ define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { ; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1b -; IS__CGSCC_OPM-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { +; IS__CGSCC_OPM-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]] ; IS__CGSCC_OPM: 2: ; IS__CGSCC_OPM-NEXT: unreachable ; IS__CGSCC_OPM: 3: -; IS__CGSCC_OPM-NEXT: ret i8* @a1 +; IS__CGSCC_OPM-NEXT: ret i8* undef ; ; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1b @@ -333,24 +321,22 @@ ; IS__CGSCC_OPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3]] { ; IS__CGSCC_OPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_OPM: 2: -; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nonnull readnone align 536870912 dereferenceable(4294967295) undef) -; IS__CGSCC_OPM-NEXT: br label [[TMP5:%.*]] -; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC_OPM: 3: ; IS__CGSCC_OPM-NEXT: unreachable -; IS__CGSCC_OPM: 5: -; IS__CGSCC_OPM-NEXT: ret i8* [[TMP3]] +; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: ret i8* undef ; ; IS__CGSCC_NPM: Function Attrs: noinline nounwind uwtable ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2b ; IS__CGSCC_NPM-SAME: (i8* nonnull readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] { ; IS__CGSCC_NPM-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC_NPM: 2: -; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = tail call i8* @f1b() -; IS__CGSCC_NPM-NEXT: br label [[TMP5:%.*]] -; IS__CGSCC_NPM: 4: +; IS__CGSCC_NPM-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC_NPM: 3: ; IS__CGSCC_NPM-NEXT: unreachable -; IS__CGSCC_NPM: 5: -; IS__CGSCC_NPM-NEXT: ret i8* @a1 +; IS__CGSCC_NPM: 4: +; IS__CGSCC_NPM-NEXT: ret i8* undef ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -1104,7 +1090,7 @@ define i64 @ptr2int(i32* %p) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr2int -; IS__TUNIT____-SAME: (i32* nofree readnone [[P:%.*]]) #[[ATTR9]] { +; IS__TUNIT____-SAME: (i32* nofree readnone [[P:%.*]]) #[[ATTR9:[0-9]+]] { ; IS__TUNIT____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 ; IS__TUNIT____-NEXT: ret i64 [[P2I]] ; diff --git a/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll b/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll --- a/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll +++ b/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll @@ -68,10 +68,10 @@ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]] ; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = call i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] ; CHECK-NEXT: br label [[TMP8:%.*]] ; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = call i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] +; CHECK-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] ; CHECK-NEXT: br label [[TMP8]] ; CHECK: 8: ; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ] diff --git a/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll b/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll --- a/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll +++ b/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll @@ -68,10 +68,10 @@ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]] ; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = call i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]] ; CHECK-NEXT: br label [[TMP8:%.*]] ; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = call i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] +; CHECK-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]] ; CHECK-NEXT: br label [[TMP8]] ; CHECK: 8: ; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ] @@ -94,16 +94,12 @@ } define i32 @test_pcheck1(i32 %0) #0 { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck1 -; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: ret i32 1 -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck1 -; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]] -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101 -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP4]] +; CHECK-LABEL: define {{[^@]+}}@test_pcheck1 +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] ; ; IS__TUNIT_____ENABLED-LABEL: define {{[^@]+}}@test_pcheck1 ; IS__TUNIT_____ENABLED-SAME: (i32 [[TMP0:%.*]]) @@ -115,16 +111,12 @@ } define i32 @test_pcheck2(i32 %0) #0 { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck2 -; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: ret i32 1 -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck2 -; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]] -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99 -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP4]] +; CHECK-LABEL: define {{[^@]+}}@test_pcheck2 +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] ; %2 = call i32 @test(i32 %0, i32 0) %3 = icmp sgt i32 %2, 99 @@ -133,19 +125,12 @@ } define i32 @test_ncheck1(i32 %0) #0 { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck1 -; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG0]] -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50 -; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__TUNIT____-NEXT: ret i32 [[TMP4]] -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck1 -; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]] -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50 -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP4]] +; CHECK-LABEL: define {{[^@]+}}@test_ncheck1 +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] ; %2 = call i32 @test(i32 %0, i32 1) %3 = icmp sgt i32 %2, 50 @@ -154,19 +139,12 @@ } define i32 @test_ncheck2(i32 %0) #0 { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck2 -; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG1]] -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150 -; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__TUNIT____-NEXT: ret i32 [[TMP4]] -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck2 -; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]] -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150 -; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP4]] +; CHECK-LABEL: define {{[^@]+}}@test_ncheck2 +; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] ; %2 = call i32 @test(i32 %0, i32 0) %3 = icmp sgt i32 %2, 150 @@ -185,10 +163,7 @@ ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone sspstrong uwtable willreturn } ; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn } ;. -; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101} -; IS__TUNIT____: [[RNG1]] = !{i32 100, i32 201} -;. -; IS__CGSCC____: [[RNG0]] = !{i32 0, i32 101} -; IS__CGSCC____: [[RNG1]] = !{i32 100, i32 201} -; IS__CGSCC____: [[RNG2]] = !{i32 0, i32 201} +; CHECK: [[RNG0]] = !{i32 0, i32 101} +; CHECK: [[RNG1]] = !{i32 100, i32 201} +; CHECK: [[RNG2]] = !{i32 0, i32 201} ;. diff --git a/llvm/test/Transforms/Attributor/cb_range_enabled.ll b/llvm/test/Transforms/Attributor/cb_range_enabled.ll --- a/llvm/test/Transforms/Attributor/cb_range_enabled.ll +++ b/llvm/test/Transforms/Attributor/cb_range_enabled.ll @@ -64,19 +64,9 @@ ; we need to look into this again. For the purpose of making some progress we take this regression ; for now, call site contexts are not on by default anyway (yet). define i32 @test1_pcheck(i32 %unknown) { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_pcheck -; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG1:![0-9]+]] -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90 -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 -; IS__TUNIT____-NEXT: ret i32 [[TMP3]] -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_pcheck -; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1:![0-9]+]] -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90 -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP3]] +; CHECK-LABEL: define {{[^@]+}}@test1_pcheck +; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 1 ; %1 = call i32 @test1(i32 %unknown, i32 20) %2 = icmp sle i32 %1, 90 @@ -85,19 +75,9 @@ } define i32 @test2_pcheck(i32 %unknown) { -; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_pcheck -; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG2:![0-9]+]] -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20 -; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 -; IS__TUNIT____-NEXT: ret i32 [[TMP3]] -; -; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_pcheck -; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG2:![0-9]+]] -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20 -; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 -; IS__CGSCC____-NEXT: ret i32 [[TMP3]] +; CHECK-LABEL: define {{[^@]+}}@test2_pcheck +; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: ret i32 1 ; %1 = call i32 @test2(i32 %unknown, i32 20) %2 = icmp sge i32 %1, 20 @@ -110,14 +90,14 @@ define i32 @test1_ncheck(i32 %unknown) { ; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_ncheck ; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG1]] +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG1:![0-9]+]] ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10 ; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 ; IS__TUNIT____-NEXT: ret i32 [[TMP3]] ; ; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_ncheck ; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1:![0-9]+]] ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10 ; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 ; IS__CGSCC____-NEXT: ret i32 [[TMP3]] @@ -131,14 +111,14 @@ define i32 @test2_ncheck(i32 %unknown) { ; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_ncheck ; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG2]] +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR0]], !range [[RNG2:![0-9]+]] ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30 ; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 ; IS__TUNIT____-NEXT: ret i32 [[TMP3]] ; ; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_ncheck ; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG2]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG2:![0-9]+]] ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30 ; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 ; IS__CGSCC____-NEXT: ret i32 [[TMP3]] diff --git a/llvm/test/Transforms/Attributor/cgscc_bugs.ll b/llvm/test/Transforms/Attributor/cgscc_bugs.ll --- a/llvm/test/Transforms/Attributor/cgscc_bugs.ll +++ b/llvm/test/Transforms/Attributor/cgscc_bugs.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=13 -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=13 -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=12 -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=12 -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 diff --git a/llvm/test/Transforms/Attributor/depgraph.ll b/llvm/test/Transforms/Attributor/depgraph.ll --- a/llvm/test/Transforms/Attributor/depgraph.ll +++ b/llvm/test/Transforms/Attributor/depgraph.ll @@ -53,29 +53,30 @@ ; GRAPH: [AAIsDead] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state Live[#BB 4/4][#TBEP 0][#KDE 1] ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %3 = icmp eq i32 %2, 0' at position {flt: [@-1]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %3 = icmp eq i32 %2, 0' at position {flt: [@-1]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAWillReturn] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state may-noreturn ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAUndefinedBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state undefined-behavior ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state assumed-live ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoUndef] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state may-undef-or-poison ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAReturnedValues] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state returns(#3)[#UC: 1] +; GRAPH-NEXT: [AAReturnedValues] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state returns(#3) ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoUnwind] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state nounwind ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned -; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned -; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind ; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind ; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned +; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind +; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind +; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-EMPTY: @@ -85,7 +86,7 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' %2 = load i32, i32* %0, align 4' at position {flt: [@-1]} with state assumed-live ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {flt: [@-1]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {flt: [@-1]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAValueConstantRange] for CtxI ' %2 = load i32, i32* %0, align 4' at position {flt: [@-1]} with state range(32) ; GRAPH-EMPTY: @@ -104,18 +105,19 @@ ; GRAPH-NEXT: [AANoRecurse] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state may-recurse ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state readonly +; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly +; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state readonly ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly -; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state readonly +; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly -; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned -; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state readonly ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned +; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAMemoryLocation] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state memory:argument ; GRAPH-NEXT: updates [AAMemoryLocation] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state memory:argument @@ -123,7 +125,7 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAHeapToStack] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state [H2S] Mallocs Good/Bad: 0/1 ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAAlign] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state align<1-16> ; GRAPH-NEXT: updates [AAAlign] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state align<1-16> @@ -161,6 +163,7 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state readonly ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state readonly +; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state readonly ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoFree] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state nofree ; GRAPH-NEXT: updates [AANoFree] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state nofree @@ -171,11 +174,15 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoUnwind] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nounwind ; GRAPH-NEXT: updates [AAIsDead] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state assumed-live +; GRAPH-NEXT: updates [AAIsDead] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state assumed-live ; GRAPH-NEXT: updates [AANoUnwind] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state nounwind ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAMemoryBehavior] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state readonly +; GRAPH-NEXT: updates [AAIsDead] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state assumed-live ; GRAPH-NEXT: updates [AAMemoryBehavior] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state readonly ; GRAPH-EMPTY: +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state not-simple +; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state assumed-live ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state simplified @@ -185,6 +192,7 @@ ; GRAPH-NEXT: [AANoCapture] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned +; GRAPH-NEXT: updates [AANoCapture] for CtxI ' %2 = load i32, i32* %0, align 4' at position {arg: [@0]} with state assumed not-captured-maybe-returned ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoAlias] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state may-alias ; GRAPH-EMPTY: @@ -197,7 +205,7 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAValueConstantRange] for CtxI ' %3 = icmp eq i32 %2, 0' at position {flt: [@-1]} with state range(1) ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI <> at position {flt: [@-1]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI <> at position {flt: [@-1]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAValueConstantRange] for CtxI <> at position {flt: [@-1]} with state range(32)<[0,1) / [0,1)> ; GRAPH-EMPTY: @@ -207,14 +215,10 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoReturn] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state may-return ; GRAPH-EMPTY: -; GRAPH-NEXT: [AANoAlias] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state may-alias -; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state simplified +; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state not-simple ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoUndef] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state may-undef-or-poison ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAValueSimplify] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state simplified -; GRAPH-EMPTY: ; GRAPH-NEXT: [AAAlign] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state align<16-16> ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANonNull] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state nonnull @@ -222,14 +226,17 @@ ; GRAPH-NEXT: updates [AANonNull] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_arg: [@0]} with state nonnull ; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state nonnull ; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state nonnull +; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state nonnull ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' ret i32* %.0' at position {flt: [@-1]} with state assumed-live ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' br label %8' at position {flt: [@-1]} with state assumed-live ; GRAPH-EMPTY: +; GRAPH-NEXT: [AAIsDead] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state assumed-live +; GRAPH-EMPTY: ; GRAPH-NEXT: [AAIsDead] for CtxI ' br label %8' at position {flt: [@-1]} with state assumed-live ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAIsDead] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state assumed-live +; GRAPH-NEXT: [AANoAlias] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state may-alias ; GRAPH-EMPTY: ; GRAPH-NEXT: [AAMemoryLocation] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state memory:argument ; GRAPH-NEXT: updates [AAMemoryLocation] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state memory:argument @@ -238,21 +245,19 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoRecurse] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state may-recurse ; GRAPH-EMPTY: -; GRAPH-NEXT: [AANoFree] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nofree -; GRAPH-NEXT: updates [AANoFree] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state nofree -; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoSync] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nosync ; GRAPH-NEXT: updates [AANoSync] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state nosync ; GRAPH-EMPTY: -; GRAPH-NEXT: [AAAlign] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state align<1-16> -; GRAPH-NEXT: updates [AAAlign] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state align<1-16> +; GRAPH-NEXT: [AANoFree] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs: [@-1]} with state nofree +; GRAPH-NEXT: updates [AANoFree] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn:checkAndAdvance [checkAndAdvance@-1]} with state nofree ; GRAPH-EMPTY: -; GRAPH-NEXT: [AADereferenceable] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state unknown-dereferenceable +; GRAPH-NEXT: [AADereferenceable] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state unknown-dereferenceable ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANonNull] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state nonnull ; GRAPH-NEXT: updates [AANonNull] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state nonnull ; GRAPH-EMPTY: -; GRAPH-NEXT: [AADereferenceable] for CtxI ' %5 = getelementptr inbounds i32, i32* %0, i64 4' at position {flt: [@-1]} with state unknown-dereferenceable +; GRAPH-NEXT: [AAAlign] for CtxI ' %6 = call i32* @checkAndAdvance(i32* %5)' at position {cs_ret: [@-1]} with state align<1-16> +; GRAPH-NEXT: updates [AAAlign] for CtxI ' %2 = load i32, i32* %0, align 4' at position {fn_ret:checkAndAdvance [checkAndAdvance@-1]} with state align<1-16> ; GRAPH-NOT: update diff --git a/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll b/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll --- a/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll +++ b/llvm/test/Transforms/Attributor/dereferenceable-2-inseltpoison.ll @@ -299,15 +299,13 @@ ; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable ; IS__TUNIT____-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] { -; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 -; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable ; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] { -; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 -; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2 ; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 diff --git a/llvm/test/Transforms/Attributor/dereferenceable-2.ll b/llvm/test/Transforms/Attributor/dereferenceable-2.ll --- a/llvm/test/Transforms/Attributor/dereferenceable-2.ll +++ b/llvm/test/Transforms/Attributor/dereferenceable-2.ll @@ -299,15 +299,13 @@ ; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable ; IS__TUNIT____-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] { -; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 -; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable ; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] { -; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 -; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2 ; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 diff --git a/llvm/test/Transforms/Attributor/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll @@ -41,11 +41,9 @@ ; IS________OPM: f: ; IS________OPM-NEXT: br label [[J:%.*]] ; IS________OPM: f2: -; IS________OPM-NEXT: [[C1:%.*]] = bitcast i8* [[M]] to i32* -; IS________OPM-NEXT: [[C2:%.*]] = bitcast i32* [[C1]] to i8* -; IS________OPM-NEXT: [[L:%.*]] = load i8, i8* [[C2]], align 1 +; IS________OPM-NEXT: [[L:%.*]] = load i8, i8* [[M]], align 1 ; IS________OPM-NEXT: call void @usei8(i8 [[L]]) -; IS________OPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef [[C2]]) #[[ATTR5:[0-9]+]] +; IS________OPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef [[M]]) #[[ATTR5:[0-9]+]] ; IS________OPM-NEXT: br label [[J]] ; IS________OPM: dead: ; IS________OPM-NEXT: unreachable @@ -64,11 +62,9 @@ ; IS________NPM: f: ; IS________NPM-NEXT: br label [[J:%.*]] ; IS________NPM: f2: -; IS________NPM-NEXT: [[C1:%.*]] = bitcast i8* [[M]] to i32* -; IS________NPM-NEXT: [[C2:%.*]] = bitcast i32* [[C1]] to i8* -; IS________NPM-NEXT: [[L:%.*]] = load i8, i8* [[C2]], align 1 +; IS________NPM-NEXT: [[L:%.*]] = load i8, i8* [[M]], align 1 ; IS________NPM-NEXT: call void @usei8(i8 [[L]]) -; IS________NPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef [[C2]]) #[[ATTR6:[0-9]+]] +; IS________NPM-NEXT: call void @no_sync_func(i8* nocapture nofree noundef [[M]]) #[[ATTR6:[0-9]+]] ; IS________NPM-NEXT: br label [[J]] ; IS________NPM: dead: ; IS________NPM-NEXT: unreachable @@ -540,10 +536,9 @@ ; IS________OPM-NEXT: br label [[TMP8]] ; IS________OPM: 15: ; IS________OPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8* -; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP17]]) -; IS________OPM-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________OPM-NEXT: ret i32 [[TMP18]] +; IS________OPM-NEXT: call void @free(i8* nocapture noundef [[TMP2]]) +; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________OPM-NEXT: ret i32 [[TMP17]] ; ; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg ; IS________NPM-SAME: (i32 [[TMP0:%.*]]) { @@ -571,9 +566,8 @@ ; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 ; IS________NPM-NEXT: br label [[TMP8]] ; IS________NPM: 15: -; IS________NPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* -; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP17]] +; IS________NPM-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________NPM-NEXT: ret i32 [[TMP16]] ; %2 = call noalias i8* @malloc(i64 4) %3 = bitcast i8* %2 to i32* diff --git a/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll b/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack_gpu.ll @@ -404,10 +404,9 @@ ; CHECK-NEXT: br label [[TMP8]] ; CHECK: 15: ; CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4 -; CHECK-NEXT: [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8* -; CHECK-NEXT: call void @free(i8* nocapture noundef [[TMP17]]) -; CHECK-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4 -; CHECK-NEXT: ret i32 [[TMP18]] +; CHECK-NEXT: call void @free(i8* nocapture noundef [[TMP2]]) +; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 +; CHECK-NEXT: ret i32 [[TMP17]] ; %2 = call noalias i8* @malloc(i64 4) %3 = bitcast i8* %2 to i32* diff --git a/llvm/test/Transforms/Attributor/internalize.ll b/llvm/test/Transforms/Attributor/internalize.ll --- a/llvm/test/Transforms/Attributor/internalize.ll +++ b/llvm/test/Transforms/Attributor/internalize.ll @@ -8,8 +8,8 @@ ; Deep Wrapper enabled -; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=12 -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM,CHECK_ENABLED,NOT_CGSCC_NPM_ENABLED,NOT_CGSCC_OPM_ENABLED,NOT_TUNIT_NPM_ENABLED,IS__TUNIT_____ENABLED,IS________OPM_ENABLED,IS__TUNIT_OPM_ENABLED -; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=12 -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM,CHECK_ENABLED,NOT_CGSCC_OPM_ENABLED,NOT_CGSCC_NPM_ENABLED,NOT_TUNIT_OPM_ENABLED,IS__TUNIT_____ENABLED,IS________NPM_ENABLED,IS__TUNIT_NPM_ENABLED +; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=13 -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM,CHECK_ENABLED,NOT_CGSCC_NPM_ENABLED,NOT_CGSCC_OPM_ENABLED,NOT_TUNIT_NPM_ENABLED,IS__TUNIT_____ENABLED,IS________OPM_ENABLED,IS__TUNIT_OPM_ENABLED +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=13 -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM,CHECK_ENABLED,NOT_CGSCC_OPM_ENABLED,NOT_CGSCC_NPM_ENABLED,NOT_TUNIT_OPM_ENABLED,IS__TUNIT_____ENABLED,IS________NPM_ENABLED,IS__TUNIT_NPM_ENABLED ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM,CHECK_ENABLED,NOT_TUNIT_NPM_ENABLED,NOT_TUNIT_OPM_ENABLED,NOT_CGSCC_NPM_ENABLED,IS__CGSCC_____ENABLED,IS________OPM_ENABLED,IS__CGSCC_OPM_ENABLED ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -attributor-allow-deep-wrappers -disable-inlining -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM,CHECK_ENABLED,NOT_TUNIT_NPM_ENABLED,NOT_TUNIT_OPM_ENABLED,NOT_CGSCC_OPM_ENABLED,IS__CGSCC_____ENABLED,IS________NPM_ENABLED,IS__CGSCC_NPM_ENABLED diff --git a/llvm/test/Transforms/Attributor/memory_locations.ll b/llvm/test/Transforms/Attributor/memory_locations.ll --- a/llvm/test/Transforms/Attributor/memory_locations.ll +++ b/llvm/test/Transforms/Attributor/memory_locations.ll @@ -639,20 +639,20 @@ ; IS__TUNIT____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 ; IS__TUNIT____-NEXT: ret i8 [[R]] ; IS__TUNIT____: f: -; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 +; IS__TUNIT____-NEXT: store i8 1, i8* [[ALLOC]], align 1 ; IS__TUNIT____-NEXT: ret i8 0 ; -; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind +; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal2 -; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]], i1 [[C:%.*]]) #[[ATTR8]] { +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull readnone [[PTR:%.*]], i1 [[C:%.*]]) #[[ATTR9]] { ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC____: t: -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal2(i8* noalias nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal2(i8* noalias nocapture nofree nonnull readnone dereferenceable(1) undef, i1 noundef false) #[[ATTR9]] ; IS__CGSCC____-NEXT: [[R:%.*]] = load i8, i8* [[ALLOC]], align 1 ; IS__CGSCC____-NEXT: ret i8 [[R]] ; IS__CGSCC____: f: -; IS__CGSCC____-NEXT: store i8 1, i8* [[PTR]], align 1 +; IS__CGSCC____-NEXT: store i8 1, i8* [[ALLOC]], align 1 ; IS__CGSCC____-NEXT: ret i8 0 ; %alloc = alloca i8 @@ -676,7 +676,7 @@ ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@readnone_caller2 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR9]] { -; IS__CGSCC____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal2(i8* undef, i1 [[C]]) #[[ATTR12]] +; IS__CGSCC____-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal2(i8* undef, i1 [[C]]) #[[ATTR13:[0-9]+]] ; IS__CGSCC____-NEXT: ret i8 [[R]] ; %r = call i8 @recursive_not_readnone_internal2(i8* undef, i1 %c) @@ -742,4 +742,5 @@ ; IS__CGSCC____: attributes #[[ATTR10]] = { nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR11]] = { nofree nosync nounwind } ; IS__CGSCC____: attributes #[[ATTR12]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind readnone } ;. diff --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll --- a/llvm/test/Transforms/Attributor/noalias.ll +++ b/llvm/test/Transforms/Attributor/noalias.ll @@ -417,25 +417,21 @@ ; IS________OPM-LABEL: define {{[^@]+}}@test12_4() { ; IS________OPM-NEXT: [[A:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) ; IS________OPM-NEXT: [[B:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; IS________OPM-NEXT: [[A_0:%.*]] = getelementptr i8, i8* [[A]], i64 0 ; IS________OPM-NEXT: [[A_1:%.*]] = getelementptr i8, i8* [[A]], i64 1 -; IS________OPM-NEXT: [[B_0:%.*]] = getelementptr i8, i8* [[B]], i64 0 ; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[B]]) -; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A_0]]) +; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A]]) ; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A_1]]) -; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A_0]], i8* nocapture [[B_0]]) +; IS________OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[B]]) ; IS________OPM-NEXT: ret void ; ; NOT_TUNIT_OPM-LABEL: define {{[^@]+}}@test12_4() { ; NOT_TUNIT_OPM-NEXT: [[A:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) ; NOT_TUNIT_OPM-NEXT: [[B:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; NOT_TUNIT_OPM-NEXT: [[A_0:%.*]] = getelementptr i8, i8* [[A]], i64 0 ; NOT_TUNIT_OPM-NEXT: [[A_1:%.*]] = getelementptr i8, i8* [[A]], i64 1 -; NOT_TUNIT_OPM-NEXT: [[B_0:%.*]] = getelementptr i8, i8* [[B]], i64 0 ; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* noalias nocapture [[A]], i8* noalias nocapture [[B]]) -; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A_0]]) +; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A]]) ; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[A_1]]) -; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* nocapture [[A_0]], i8* nocapture [[B_0]]) +; NOT_TUNIT_OPM-NEXT: tail call void @two_args(i8* nocapture [[A]], i8* nocapture [[B]]) ; NOT_TUNIT_OPM-NEXT: ret void ; %A = tail call noalias i8* @malloc(i64 4) @@ -469,9 +465,7 @@ define void @test13_use_noalias(){ ; CHECK-LABEL: define {{[^@]+}}@test13_use_noalias() { ; CHECK-NEXT: [[M1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; CHECK-NEXT: [[C1:%.*]] = bitcast i8* [[M1]] to i16* -; CHECK-NEXT: [[C2:%.*]] = bitcast i16* [[C1]] to i8* -; CHECK-NEXT: call void @use_i8_internal(i8* noalias nocapture [[C2]]) +; CHECK-NEXT: call void @use_i8_internal(i8* noalias nocapture [[M1]]) ; CHECK-NEXT: ret void ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test13_use_noalias() @@ -490,11 +484,8 @@ define void @test13_use_alias(){ ; CHECK-LABEL: define {{[^@]+}}@test13_use_alias() { ; CHECK-NEXT: [[M1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4) -; CHECK-NEXT: [[C1:%.*]] = bitcast i8* [[M1]] to i16* -; CHECK-NEXT: [[C2A:%.*]] = bitcast i16* [[C1]] to i8* -; CHECK-NEXT: [[C2B:%.*]] = bitcast i16* [[C1]] to i8* -; CHECK-NEXT: call void @use_i8_internal(i8* nocapture [[C2A]]) -; CHECK-NEXT: call void @use_i8_internal(i8* nocapture [[C2B]]) +; CHECK-NEXT: call void @use_i8_internal(i8* nocapture [[M1]]) +; CHECK-NEXT: call void @use_i8_internal(i8* nocapture [[M1]]) ; CHECK-NEXT: ret void ; %m1 = tail call noalias i8* @malloc(i64 4) diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -245,27 +245,23 @@ ; IS__TUNIT____-NEXT: e: ; IS__TUNIT____-NEXT: br label [[L:%.*]] ; IS__TUNIT____: l: -; IS__TUNIT____-NEXT: [[X:%.*]] = phi i32* [ [[P]], [[E:%.*]] ] -; IS__TUNIT____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] -; IS__TUNIT____-NEXT: [[TMP:%.*]] = bitcast i32* [[X]] to i32* -; IS__TUNIT____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__TUNIT____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E:%.*]] ] +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[P]], i32* [[Y]] ; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS__TUNIT____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__TUNIT____-NEXT: store i32 0, i32* [[P]], align 4 ; IS__TUNIT____-NEXT: store i32* [[Y]], i32** @g, align 8 ; IS__TUNIT____-NEXT: ret i32 [[VAL]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc1 -; IS__CGSCC____-SAME: (i32* nofree [[Q:%.*]], i32* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) #[[ATTR5:[0-9]+]] { +; IS__CGSCC____-SAME: (i32* nofree [[Q:%.*]], i32* nocapture nofree align 4 [[P:%.*]], i1 [[B:%.*]]) #[[ATTR5:[0-9]+]] { ; IS__CGSCC____-NEXT: e: ; IS__CGSCC____-NEXT: br label [[L:%.*]] ; IS__CGSCC____: l: -; IS__CGSCC____-NEXT: [[X:%.*]] = phi i32* [ [[P]], [[E:%.*]] ] -; IS__CGSCC____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] -; IS__CGSCC____-NEXT: [[TMP:%.*]] = bitcast i32* [[X]] to i32* -; IS__CGSCC____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__CGSCC____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E:%.*]] ] +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[P]], i32* [[Y]] ; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS__CGSCC____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__CGSCC____-NEXT: store i32 0, i32* [[P]], align 4 ; IS__CGSCC____-NEXT: store i32* [[Y]], i32** @g, align 8 ; IS__CGSCC____-NEXT: ret i32 [[VAL]] ; @@ -335,8 +331,8 @@ ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@nc2 -; IS__CGSCC____-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) #[[ATTR5]] { -; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 noundef false) #[[ATTR16:[0-9]+]] +; IS__CGSCC____-SAME: (i32* nocapture nofree align 4 [[P:%.*]], i32* nofree [[Q:%.*]]) #[[ATTR5]] { +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree align 4 [[P]], i1 noundef false) #[[ATTR16:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; [#uses=0] @@ -826,7 +822,7 @@ ; CHECK-SAME: (i8* nocapture readonly [[A:%.*]], i8* readonly returned [[B:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[P:%.*]] = call i8* @unknownpi8pi8(i8* [[A]], i8* [[B]]) -; CHECK-NEXT: ret i8* [[P]] +; CHECK-NEXT: ret i8* [[B]] ; entry: %p = call i8* @unknownpi8pi8(i8* %A, i8* %B) @@ -839,7 +835,7 @@ ; CHECK-SAME: (i8* nocapture readonly [[A:%.*]], i8* readonly returned [[B:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[P:%.*]] = call i8* @unknownpi8pi8(i8* readonly [[A]], i8* readonly [[B]]) #[[ATTR4]] -; CHECK-NEXT: ret i8* [[P]] +; CHECK-NEXT: ret i8* [[B]] ; entry: %p = call i8* @unknownpi8pi8(i8* %A, i8* %B) nounwind readonly diff --git a/llvm/test/Transforms/Attributor/nocapture-2.ll b/llvm/test/Transforms/Attributor/nocapture-2.ll --- a/llvm/test/Transforms/Attributor/nocapture-2.ll +++ b/llvm/test/Transforms/Attributor/nocapture-2.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=8 -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=8 -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=11 -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=11 -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 ; @@ -219,9 +219,9 @@ ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i16* ; CHECK-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[CALL]] to double* -; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(8) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[CALL1]] to i32* -; CHECK-NEXT: [[CALL2:%.*]] = call float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL2]] to i32* ; CHECK-NEXT: br label [[COND_END:%.*]] ; CHECK: cond.false: @@ -254,6 +254,7 @@ ret float* %4 } +; FIXME: the call1 below to scc_B should return dereferenceable_or_null(8) (as the callee does). Something prevented that deduction and needs to be investigated. define i64* @scc_B(double* dereferenceable_or_null(8) %a) { ; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@scc_B @@ -265,9 +266,9 @@ ; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[A]] to i32* ; CHECK-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[CALL]] to double* -; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(8) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[CALL1]] to i16* -; CHECK-NEXT: [[CALL2:%.*]] = call i8* @scc_C(i16* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] ; CHECK-NEXT: br label [[COND_END:%.*]] ; CHECK: cond.false: ; CHECK-NEXT: [[TMP3:%.*]] = bitcast double* [[A]] to i8* @@ -312,7 +313,7 @@ ; CHECK-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.true: ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i16* [[A]] to double* -; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(8) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i64* [[CALL1]] to i8* ; CHECK-NEXT: br label [[COND_END:%.*]] ; CHECK: cond.false: @@ -321,7 +322,7 @@ ; CHECK: cond.end: ; CHECK-NEXT: [[COND:%.*]] = phi i8* [ [[TMP1]], [[COND_TRUE]] ], [ [[CALL2]], [[COND_FALSE]] ] ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[COND]] to i32* -; CHECK-NEXT: [[CALL3:%.*]] = call float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL3:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL3]] to i8* ; CHECK-NEXT: ret i8* [[TMP3]] ; @@ -497,14 +498,14 @@ ; IS__TUNIT____-SAME: (i64* nofree returned writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR9]] -; IS__TUNIT____-NEXT: ret i64* [[CALL]] +; IS__TUNIT____-NEXT: ret i64* [[A]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_0a ; IS__CGSCC____-SAME: (i64* nofree noundef nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] -; IS__CGSCC____-NEXT: ret i64* [[CALL]] +; IS__CGSCC____-NEXT: ret i64* [[A]] ; entry: %call = call i64* @not_captured_but_returned_0(i64* %a) @@ -524,7 +525,7 @@ ; IS__TUNIT____-SAME: (i64* nofree writeonly align 8 [[A:%.*]]) #[[ATTR4]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR9]] -; IS__TUNIT____-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[CALL]] to i64 +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[A]] to i64 ; IS__TUNIT____-NEXT: store i64 [[TMP0]], i64* [[A]], align 8 ; IS__TUNIT____-NEXT: ret void ; @@ -533,7 +534,7 @@ ; IS__CGSCC____-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR4]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] -; IS__CGSCC____-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[CALL]] to i64 +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[A]] to i64 ; IS__CGSCC____-NEXT: store i64 [[TMP0]], i64* [[A]], align 8 ; IS__CGSCC____-NEXT: ret void ; @@ -701,7 +702,7 @@ ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR8:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR8]] -; CHECK-NEXT: ret i32* [[CALL]] +; CHECK-NEXT: ret i32* [[R]] ; entry: %call = call i32* @readonly_unknown(i32* %b, i32* %r) nounwind @@ -715,7 +716,7 @@ ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR8]] -; CHECK-NEXT: ret i32* [[CALL]] +; CHECK-NEXT: ret i32* [[R]] ; entry: %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) nounwind @@ -729,7 +730,7 @@ ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1b(i32* nocapture readonly [[B]], i32* readonly [[R]]) #[[ATTR8]] -; CHECK-NEXT: ret i32* [[CALL]] +; CHECK-NEXT: ret i32* [[R]] ; entry: %call = call i32* @readonly_unknown_r1b(i32* %b, i32* %r) @@ -742,7 +743,7 @@ ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR6]] -; CHECK-NEXT: ret i32* [[CALL]] +; CHECK-NEXT: ret i32* [[R]] ; entry: %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll --- a/llvm/test/Transforms/Attributor/nonnull.ll +++ b/llvm/test/Transforms/Attributor/nonnull.ll @@ -276,7 +276,7 @@ ; CHECK-NEXT: [[PHI:%.*]] = phi i8* [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: ret i8* [[PHI]] +; CHECK-NEXT: ret i8* [[RET]] ; entry: %ret = call i8* @ret_nonnull() @@ -292,14 +292,12 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7 ; IS__TUNIT____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { -; IS__TUNIT____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 0 -; IS__TUNIT____-NEXT: ret i8* [[B]] +; IS__TUNIT____-NEXT: ret i8* [[A]] ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7 ; IS__CGSCC____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 0 -; IS__CGSCC____-NEXT: ret i8* [[B]] +; IS__CGSCC____-NEXT: ret i8* [[A]] ; %b = getelementptr inbounds i8, i8* %a, i64 0 ret i8* %b diff --git a/llvm/test/Transforms/Attributor/potential.ll b/llvm/test/Transforms/Attributor/potential.ll --- a/llvm/test/Transforms/Attributor/potential.ll +++ b/llvm/test/Transforms/Attributor/potential.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 -enable-new-pm=0 -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=24 -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=24 -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 -enable-new-pm=0 -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=23 -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=23 -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 -enable-new-pm=0 -attributor-cgscc -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 ; @@ -568,25 +568,15 @@ ; FIXME: returned value can be simplified to 0 define i32 @potential_test11(i1 %c) { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@potential_test11 -; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { -; IS__TUNIT_OPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR0]], !range [[RNG2:![0-9]+]] -; IS__TUNIT_OPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR0]], !range [[RNG3:![0-9]+]] -; IS__TUNIT_OPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR0]] -; IS__TUNIT_OPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] -; IS__TUNIT_OPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] -; IS__TUNIT_OPM-NEXT: ret i32 [[ACC2]] -; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@potential_test11 -; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { -; IS__TUNIT_NPM-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR0]], !range [[RNG2:![0-9]+]] -; IS__TUNIT_NPM-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR0]], !range [[RNG3:![0-9]+]] -; IS__TUNIT_NPM-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR0]], !range [[RNG2]] -; IS__TUNIT_NPM-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] -; IS__TUNIT_NPM-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] -; IS__TUNIT_NPM-NEXT: ret i32 [[ACC2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test11 +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { +; IS__TUNIT____-NEXT: [[ZERO1:%.*]] = call i32 @optimize_undef_1(i1 [[C]]) #[[ATTR0]], !range [[RNG2:![0-9]+]] +; IS__TUNIT____-NEXT: [[ZERO2:%.*]] = call i32 @optimize_undef_2(i1 [[C]]) #[[ATTR0]], !range [[RNG3:![0-9]+]] +; IS__TUNIT____-NEXT: [[ZERO3:%.*]] = call i32 @optimize_undef_3(i1 [[C]]) #[[ATTR0]], !range [[RNG2]] +; IS__TUNIT____-NEXT: [[ACC1:%.*]] = add i32 [[ZERO1]], [[ZERO2]] +; IS__TUNIT____-NEXT: [[ACC2:%.*]] = add i32 [[ACC1]], [[ZERO3]] +; IS__TUNIT____-NEXT: ret i32 [[ACC2]] ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test11 @@ -633,7 +623,7 @@ ; IS__TUNIT_NPM: t: ; IS__TUNIT_NPM-NEXT: ret i32 0 ; IS__TUNIT_NPM: f: -; IS__TUNIT_NPM-NEXT: ret i32 0 +; IS__TUNIT_NPM-NEXT: ret i32 undef ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@optimize_poison_1 @@ -651,7 +641,7 @@ ; IS__CGSCC_NPM: t: ; IS__CGSCC_NPM-NEXT: ret i32 0 ; IS__CGSCC_NPM: f: -; IS__CGSCC_NPM-NEXT: ret i32 0 +; IS__CGSCC_NPM-NEXT: ret i32 undef ; br i1 %c, label %t, label %f t: @@ -677,7 +667,7 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@potential_test12 ; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR0]] { -; IS__CGSCC_OPM-NEXT: [[ZERO:%.*]] = call i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG3]] +; IS__CGSCC_OPM-NEXT: [[ZERO:%.*]] = call noundef i32 @optimize_poison_1(i1 [[C]]) #[[ATTR2]], !range [[RNG3]] ; IS__CGSCC_OPM-NEXT: ret i32 [[ZERO]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -715,7 +705,7 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@potential_test13_caller1 ; IS__TUNIT____-SAME: () #[[ATTR0]] { -; IS__TUNIT____-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR0]], !range [[RNG2:![0-9]+]] +; IS__TUNIT____-NEXT: [[RET:%.*]] = call i32 @potential_test13_callee(i32 noundef 0) #[[ATTR0]], !range [[RNG2]] ; IS__TUNIT____-NEXT: ret i32 [[RET]] ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -801,12 +801,12 @@ define dso_local i32 @test-5() { ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test-5() { ; IS__TUNIT_OPM-NEXT: entry: -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 noundef 0), !range [[RNG3:![0-9]+]] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noundef i32 @rec(i32 noundef 0), !range [[RNG3:![0-9]+]] ; IS__TUNIT_OPM-NEXT: ret i32 [[CALL]] ; ; NOT_TUNIT_OPM-LABEL: define {{[^@]+}}@test-5() { ; NOT_TUNIT_OPM-NEXT: entry: -; NOT_TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 noundef 0), !range [[RNG4:![0-9]+]] +; NOT_TUNIT_OPM-NEXT: [[CALL:%.*]] = call noundef i32 @rec(i32 noundef 0), !range [[RNG4:![0-9]+]] ; NOT_TUNIT_OPM-NEXT: ret i32 [[CALL]] ; entry: @@ -1462,10 +1462,10 @@ ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false ; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT_OPM: t: -; IS__TUNIT_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) #[[ATTR1]], !range [[RNG3]] +; IS__TUNIT_OPM-NEXT: [[RET1:%.*]] = call noundef i32 @func(i1 noundef [[C]]) #[[ATTR1]], !range [[RNG3]] ; IS__TUNIT_OPM-NEXT: ret i32 [[RET1]] ; IS__TUNIT_OPM: f: -; IS__TUNIT_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR1]], !range [[RNG3]] +; IS__TUNIT_OPM-NEXT: [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR1]], !range [[RNG3]] ; IS__TUNIT_OPM-NEXT: ret i32 [[RET2]] ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn @@ -1474,10 +1474,10 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false ; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT_NPM: t: -; IS__TUNIT_NPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef true) #[[ATTR1]], !range [[RNG4]] +; IS__TUNIT_NPM-NEXT: [[RET1:%.*]] = call noundef i32 @func(i1 noundef true) #[[ATTR1]], !range [[RNG4]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RET1]] ; IS__TUNIT_NPM: f: -; IS__TUNIT_NPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR1]], !range [[RNG4]] +; IS__TUNIT_NPM-NEXT: [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR1]], !range [[RNG4]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RET2]] ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -1486,10 +1486,10 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_OPM: t: -; IS__CGSCC_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) #[[ATTR5]], !range [[RNG4]] +; IS__CGSCC_OPM-NEXT: [[RET1:%.*]] = call noundef i32 @func(i1 noundef [[C]]) #[[ATTR5]], !range [[RNG4]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RET1]] ; IS__CGSCC_OPM: f: -; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR5]], !range [[RNG4]] +; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR5]], !range [[RNG4]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RET2]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -1498,10 +1498,10 @@ ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false ; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_NPM: t: -; IS__CGSCC_NPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef true) #[[ATTR3]], !range [[RNG4]] +; IS__CGSCC_NPM-NEXT: [[RET1:%.*]] = call noundef i32 @func(i1 noundef true) #[[ATTR3]], !range [[RNG4]] ; IS__CGSCC_NPM-NEXT: ret i32 [[RET1]] ; IS__CGSCC_NPM: f: -; IS__CGSCC_NPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR3]], !range [[RNG4]] +; IS__CGSCC_NPM-NEXT: [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR3]], !range [[RNG4]] ; IS__CGSCC_NPM-NEXT: ret i32 [[RET2]] ; %c = select i1 %d, i1 true, i1 false @@ -1515,23 +1515,38 @@ } define internal i32 @less_than_65536(i32 %arg) { +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_65536 +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: [[SHRINKED:%.*]] = udiv i32 undef, 65536 +; IS__CGSCC____-NEXT: ret i32 undef ; %shrinked = udiv i32 %arg, 65536 ret i32 %shrinked } define internal i1 @is_less_than_65536(i32 %arg) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@is_less_than_65536 +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp ult i32 undef, 65536 +; IS__CGSCC____-NEXT: ret i1 undef +; %cmp = icmp ult i32 %arg, 65536 ret i1 %cmp } define i1 @check_divided_range(i32 %arg) { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@check_divided_range -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@check_divided_range -; IS__CGSCC_NPM-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { -; IS__CGSCC_NPM-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@check_divided_range +; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: ret i1 true +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@check_divided_range +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i1 true ; %csret1 = call i32 @less_than_65536(i32 0) %csret2 = call i32 @less_than_65536(i32 %arg) @@ -1542,23 +1557,32 @@ } define internal i32 @cast_and_return(i1 %c) { +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cast_and_return +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: [[RET:%.*]] = zext i1 undef to i32 +; IS__CGSCC____-NEXT: ret i32 undef ; %ret = zext i1 %c to i32 ret i32 %ret } define internal i1 @is_less_than_3(i32 %c) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@is_less_than_3 +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i1 undef +; %cmp = icmp slt i32 %c, 3 ret i1 %cmp } define i1 @check_casted_range(i1 %c) { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@check_casted_range -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@check_casted_range -; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { -; IS__TUNIT_NPM-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@check_casted_range +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: ret i1 true ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@check_casted_range @@ -1654,6 +1678,35 @@ } define internal i32 @less_than_100_2(i32 %c) { +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@less_than_100_2 +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: switch i32 [[C]], label [[OTHERWISE:%.*]] [ +; IS__CGSCC____-NEXT: i32 0, label [[ONZERO:%.*]] +; IS__CGSCC____-NEXT: i32 1, label [[ONONE:%.*]] +; IS__CGSCC____-NEXT: i32 2, label [[ONTWO:%.*]] +; IS__CGSCC____-NEXT: i32 3, label [[ONTHREE:%.*]] +; IS__CGSCC____-NEXT: i32 4, label [[ONFOUR:%.*]] +; IS__CGSCC____-NEXT: i32 5, label [[ONFIVE:%.*]] +; IS__CGSCC____-NEXT: i32 6, label [[ONSIX:%.*]] +; IS__CGSCC____-NEXT: ] +; IS__CGSCC____: onzero: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: onone: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: ontwo: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: onthree: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: onfour: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: onfive: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: onsix: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: otherwise: +; IS__CGSCC____-NEXT: ret i32 undef ; switch i32 %c, label %otherwise [ i32 0, label %onzero i32 1, label %onone @@ -1681,18 +1734,22 @@ } define internal i1 @is_less_than_100_2(i32 %c) { +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@is_less_than_100_2 +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 undef, 100 +; IS__CGSCC____-NEXT: ret i1 undef ; %cmp = icmp slt i32 %c, 100 ret i1 %cmp } define i1 @propagate_range2(i32 %c) { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@propagate_range2 -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@propagate_range2 -; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { -; IS__TUNIT_NPM-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@propagate_range2 +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: ret i1 true ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@propagate_range2 @@ -1714,12 +1771,6 @@ ; IS__TUNIT_OPM-NEXT: [[R:%.*]] = icmp ne i8 [[V]], 0 ; IS__TUNIT_OPM-NEXT: ret i1 [[R]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@non_zero -; IS__TUNIT_NPM-SAME: (i8 [[V:%.*]]) #[[ATTR1]] { -; IS__TUNIT_NPM-NEXT: [[R:%.*]] = icmp ne i8 [[V]], 0 -; IS__TUNIT_NPM-NEXT: ret i1 [[R]] -; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@non_zero ; IS__CGSCC_OPM-SAME: (i8 [[V:%.*]]) #[[ATTR1]] { @@ -1728,9 +1779,8 @@ ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@non_zero -; IS__CGSCC_NPM-SAME: (i8 [[V:%.*]]) #[[ATTR1]] { -; IS__CGSCC_NPM-NEXT: [[R:%.*]] = icmp ne i8 [[V]], 0 -; IS__CGSCC_NPM-NEXT: ret i1 [[R]] +; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: ret i1 undef ; %r = icmp ne i8 %v, 0 ret i1 %r @@ -1757,8 +1807,7 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] ; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__TUNIT_NPM: t: -; IS__TUNIT_NPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR1]] -; IS__TUNIT_NPM-NEXT: ret i1 [[R]] +; IS__TUNIT_NPM-NEXT: ret i1 true ; IS__TUNIT_NPM: f: ; IS__TUNIT_NPM-NEXT: ret i1 false ; @@ -1781,8 +1830,7 @@ ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] ; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_NPM: t: -; IS__CGSCC_NPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR3]] -; IS__CGSCC_NPM-NEXT: ret i1 [[R]] +; IS__CGSCC_NPM-NEXT: ret i1 true ; IS__CGSCC_NPM: f: ; IS__CGSCC_NPM-NEXT: ret i1 false ; diff --git a/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll b/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll --- a/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll +++ b/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll @@ -43,7 +43,7 @@ ; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32* @internal_ret1_rrw(i32* nofree align 4 [[R0]], i32* nofree [[R0]], i32* nofree [[W0]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree readonly [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) #[[ATTR3:[0-9]+]] ; IS__TUNIT____-NEXT: [[CALL3:%.*]] = call i32* @internal_ret1_rw(i32* nofree align 4 [[R0]], i32* nofree [[W0]]) #[[ATTR2]] -; IS__TUNIT____-NEXT: ret i32* [[CALL3]] +; IS__TUNIT____-NEXT: ret i32* [[W0]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@external_ret2_nrw @@ -53,7 +53,7 @@ ; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @internal_ret1_rrw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree [[W0]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC____-NEXT: [[CALL3:%.*]] = call i32* @internal_ret1_rw(i32* nofree nonnull align 4 dereferenceable(4) [[R0]], i32* nofree [[W0]]) #[[ATTR2]] -; IS__CGSCC____-NEXT: ret i32* [[CALL3]] +; IS__CGSCC____-NEXT: ret i32* [[W0]] ; entry: %call = call i32* @internal_ret0_nw(i32* %n0, i32* %w0) @@ -86,12 +86,12 @@ ; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32* @internal_ret0_nw(i32* nofree [[N0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL5]], [[IF_END]] ], [ [[N0]], [[IF_THEN]] ] -; IS__TUNIT____-NEXT: ret i32* [[RETVAL_0]] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[N0]], [[IF_END]] ], [ [[N0]], [[IF_THEN]] ] +; IS__TUNIT____-NEXT: ret i32* [[N0]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret0_nw -; IS__CGSCC____-SAME: (i32* nofree returned [[N0:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[R0:%.*]] = alloca i32, align 4 ; IS__CGSCC____-NEXT: [[R1:%.*]] = alloca i32, align 4 @@ -111,8 +111,8 @@ ; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32* @internal_ret0_nw(i32* nofree [[N0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL5]], [[IF_END]] ], [ [[N0]], [[IF_THEN]] ] -; IS__CGSCC____-NEXT: ret i32* [[RETVAL_0]] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[N0]], [[IF_END]] ], [ [[N0]], [[IF_THEN]] ] +; IS__CGSCC____-NEXT: ret i32* undef ; entry: %r0 = alloca i32, align 4 @@ -143,7 +143,7 @@ define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) { ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_ret1_rrw -; IS__TUNIT____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[R1:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { +; IS__TUNIT____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree [[R1:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 ; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 @@ -166,12 +166,12 @@ ; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call i32* @internal_ret0_nw(i32* nofree nonnull align 4 dereferenceable(4) [[R1]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL8]], [[IF_END]] ], [ [[R1]], [[IF_THEN]] ] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[R1]], [[IF_END]] ], [ [[R1]], [[IF_THEN]] ] ; IS__TUNIT____-NEXT: ret i32* undef ; ; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret1_rrw -; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree nonnull returned align 4 dereferenceable(4) [[R1:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree nonnull align 4 dereferenceable(4) [[R1:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 ; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 @@ -194,7 +194,7 @@ ; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call i32* @internal_ret0_nw(i32* nofree nonnull align 4 dereferenceable(4) [[R1]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL8]], [[IF_END]] ], [ [[R1]], [[IF_THEN]] ] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[R1]], [[IF_END]] ], [ [[R1]], [[IF_THEN]] ] ; IS__CGSCC____-NEXT: ret i32* undef ; entry: @@ -293,12 +293,12 @@ ; IS__TUNIT____-NEXT: [[CALL4:%.*]] = call i32* @external_ret2_nrw(i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0]], i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL4]], [[IF_END]] ], [ [[W0]], [[IF_THEN]] ] -; IS__TUNIT____-NEXT: ret i32* [[RETVAL_0]] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[W0]], [[IF_END]] ], [ [[W0]], [[IF_THEN]] ] +; IS__TUNIT____-NEXT: ret i32* [[W0]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret1_rw -; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[W0:%.*]]) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree [[W0:%.*]]) #[[ATTR0]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 ; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 @@ -315,8 +315,8 @@ ; IS__CGSCC____-NEXT: [[CALL4:%.*]] = call i32* @external_ret2_nrw(i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0]], i32* nofree noundef nonnull align 4 dereferenceable(4) [[R0]], i32* nofree nonnull align 4 dereferenceable(4) [[W0]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL4]], [[IF_END]] ], [ [[W0]], [[IF_THEN]] ] -; IS__CGSCC____-NEXT: ret i32* [[RETVAL_0]] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[W0]], [[IF_END]] ], [ [[W0]], [[IF_THEN]] ] +; IS__CGSCC____-NEXT: ret i32* undef ; entry: %0 = load i32, i32* %r0, align 4 @@ -348,7 +348,7 @@ ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree readonly [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) #[[ATTR3]] ; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32* @external_ret2_nrw(i32* nofree [[N0]], i32* nofree [[R0]], i32* nofree [[W0]]) #[[ATTR2]] -; IS__TUNIT____-NEXT: ret i32* [[CALL1]] +; IS__TUNIT____-NEXT: ret i32* [[W0]] ; ; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@external_source_ret2_nrw @@ -356,7 +356,7 @@ ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @external_sink_ret2_nrw(i32* nofree [[N0]], i32* nocapture nofree readonly [[R0]], i32* nofree writeonly "no-capture-maybe-returned" [[W0]]) #[[ATTR3]] ; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32* @external_ret2_nrw(i32* nofree [[N0]], i32* nofree [[R0]], i32* nofree [[W0]]) #[[ATTR4]] -; IS__CGSCC____-NEXT: ret i32* [[CALL1]] +; IS__CGSCC____-NEXT: ret i32* [[W0]] ; entry: %call = call i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) diff --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll --- a/llvm/test/Transforms/Attributor/readattrs.ll +++ b/llvm/test/Transforms/Attributor/readattrs.ll @@ -143,16 +143,14 @@ ; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_2 ; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR0]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) #[[ATTR1]] -; IS__TUNIT____-NEXT: store i32 10, i32* [[CALL]], align 4 +; IS__TUNIT____-NEXT: store i32 10, i32* [[P]], align 4 ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_2 ; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR3]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call align 4 i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) #[[ATTR11:[0-9]+]] -; IS__CGSCC____-NEXT: store i32 10, i32* [[CALL]], align 4 +; IS__CGSCC____-NEXT: store i32 10, i32* [[P]], align 4 ; IS__CGSCC____-NEXT: ret void ; entry: @@ -176,7 +174,7 @@ ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test9 ; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR4:[0-9]+]] { -; IS__CGSCC____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) #[[ATTR12:[0-9]+]] +; IS__CGSCC____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) #[[ATTR11:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1>) @@ -195,7 +193,7 @@ ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test10 ; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR5:[0-9]+]] { -; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef , <4 x i32> undef) #[[ATTR13:[0-9]+]] +; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef , <4 x i32> undef) #[[ATTR12:[0-9]+]] ; IS__CGSCC____-NEXT: ret <4 x i32> [[RES]] ; %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1>, <4 x i32>undef) @@ -233,7 +231,7 @@ ; IS__CGSCC____: Function Attrs: argmemonly nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test12_2 ; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR7:[0-9]+]] { -; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) #[[ATTR14:[0-9]+]] +; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) #[[ATTR13:[0-9]+]] ; IS__CGSCC____-NEXT: ret <4 x i32> [[RES]] ; %res = call <4 x i32> @test12_1(<4 x i32*> %ptrs) @@ -432,25 +430,7 @@ define void @ptr_use_chain(i8* %ptr) { ; CHECK-LABEL: define {{[^@]+}}@ptr_use_chain ; CHECK-SAME: (i8* [[PTR:%.*]]) { -; CHECK-NEXT: [[BC0:%.*]] = bitcast i8* [[PTR]] to i32* -; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[BC0]] to i8* -; CHECK-NEXT: [[BC2:%.*]] = bitcast i8* [[BC1]] to i32* -; CHECK-NEXT: [[BC3:%.*]] = bitcast i32* [[BC2]] to i8* -; CHECK-NEXT: [[BC4:%.*]] = bitcast i8* [[BC3]] to i32* -; CHECK-NEXT: [[BC5:%.*]] = bitcast i32* [[BC4]] to i8* -; CHECK-NEXT: [[BC6:%.*]] = bitcast i8* [[BC5]] to i32* -; CHECK-NEXT: [[BC7:%.*]] = bitcast i32* [[BC6]] to i8* -; CHECK-NEXT: [[BC8:%.*]] = bitcast i8* [[BC7]] to i32* -; CHECK-NEXT: [[BC9:%.*]] = bitcast i32* [[BC8]] to i8* -; CHECK-NEXT: [[ABC2:%.*]] = bitcast i8* [[BC9]] to i32* -; CHECK-NEXT: [[ABC3:%.*]] = bitcast i32* [[ABC2]] to i8* -; CHECK-NEXT: [[ABC4:%.*]] = bitcast i8* [[ABC3]] to i32* -; CHECK-NEXT: [[ABC5:%.*]] = bitcast i32* [[ABC4]] to i8* -; CHECK-NEXT: [[ABC6:%.*]] = bitcast i8* [[ABC5]] to i32* -; CHECK-NEXT: [[ABC7:%.*]] = bitcast i32* [[ABC6]] to i8* -; CHECK-NEXT: [[ABC8:%.*]] = bitcast i8* [[ABC7]] to i32* -; CHECK-NEXT: [[ABC9:%.*]] = bitcast i32* [[ABC8]] to i8* -; CHECK-NEXT: call void @escape_i8(i8* [[ABC9]]) +; CHECK-NEXT: call void @escape_i8(i8* [[PTR]]) ; CHECK-NEXT: ret void ; %bc0 = bitcast i8* %ptr to i32* @@ -518,8 +498,7 @@ ; IS__CGSCC____: attributes #[[ATTR8]] = { argmemonly nofree norecurse nounwind willreturn } ; IS__CGSCC____: attributes #[[ATTR9]] = { readnone } ; IS__CGSCC____: attributes #[[ATTR10]] = { nounwind readonly } -; IS__CGSCC____: attributes #[[ATTR11]] = { readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR12]] = { willreturn writeonly } -; IS__CGSCC____: attributes #[[ATTR13]] = { readonly willreturn } -; IS__CGSCC____: attributes #[[ATTR14]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR11]] = { willreturn writeonly } +; IS__CGSCC____: attributes #[[ATTR12]] = { readonly willreturn } +; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind } ;. diff --git a/llvm/test/Transforms/Attributor/returned.ll b/llvm/test/Transforms/Attributor/returned.ll --- a/llvm/test/Transforms/Attributor/returned.ll +++ b/llvm/test/Transforms/Attributor/returned.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=6 -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=6 -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=9 -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=9 -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 ; @@ -64,17 +64,15 @@ ; IS__TUNIT____-LABEL: define {{[^@]+}}@scc_r1 ; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR5:[0-9]+]] -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[CALL]]) #[[ATTR6:[0-9]+]] -; IS__TUNIT____-NEXT: ret i32 [[CALL1]] +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR6:[0-9]+]] +; IS__TUNIT____-NEXT: ret i32 [[R]] ; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_r1 ; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR6:[0-9]+]] -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[CALL]]) #[[ATTR7:[0-9]+]] -; IS__CGSCC____-NEXT: ret i32 [[CALL1]] +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR7:[0-9]+]] +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: %call = call i32 @sink_r0(i32 %r) @@ -90,20 +88,18 @@ ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__TUNIT____: if.then: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR5]] -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[CALL]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__TUNIT____: if.then3: -; IS__TUNIT____-NEXT: [[CALL4:%.*]] = call i32 @sink_r0(i32 [[B]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[CALL6]], i32 undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[CALL5]], i32 [[CALL7]], i32 [[CALL8]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[CALL4]], i32 [[CALL9]], i32 undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: if.end12: ; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] @@ -114,33 +110,31 @@ ; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[COND_END]] ; IS__TUNIT____: cond.end: -; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] -; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__TUNIT____-NEXT: ret i32 [[R]] ; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_r2 ; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) #[[ATTR1]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__CGSCC____: if.then: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR6]] -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[CALL]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] ; IS__CGSCC____: if.end: ; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__CGSCC____: if.then3: -; IS__CGSCC____-NEXT: [[CALL4:%.*]] = call i32 @sink_r0(i32 [[B]]) ; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR7]] ; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[CALL6]], i32 undef) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR7]] ; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[CALL5]], i32 [[CALL7]], i32 [[CALL8]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[CALL4]], i32 [[CALL9]], i32 undef) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: if.end12: ; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] @@ -151,11 +145,11 @@ ; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[COND_END]] ; IS__CGSCC____: cond.end: -; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] -; IS__CGSCC____-NEXT: ret i32 [[RETVAL_0]] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: %cmp = icmp sgt i32 %a, %b @@ -209,20 +203,18 @@ ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__TUNIT____: if.then: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR5]] -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[CALL]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__TUNIT____: if.then3: -; IS__TUNIT____-NEXT: [[CALL4:%.*]] = call i32 @sink_r0(i32 [[B]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[CALL6]], i32 undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[CALL5]], i32 [[CALL7]], i32 [[CALL8]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[CALL4]], i32 [[CALL9]], i32 undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[B]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[B]], i32 undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: if.end12: ; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] @@ -233,33 +225,24 @@ ; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[COND_END]] ; IS__TUNIT____: cond.end: -; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[B]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] ; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] ; -; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_rX ; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) #[[ATTR1]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__CGSCC____: if.then: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @sink_r0(i32 [[R]]) #[[ATTR6]] -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[CALL]]) #[[ATTR8:[0-9]+]] ; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] ; IS__CGSCC____: if.end: ; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__CGSCC____: if.then3: -; IS__CGSCC____-NEXT: [[CALL4:%.*]] = call i32 @sink_r0(i32 [[B]]) -; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR8]] -; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR8]] -; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[CALL6]], i32 undef) #[[ATTR8]] -; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR8]] -; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[CALL5]], i32 [[CALL7]], i32 [[CALL8]]) #[[ATTR8]] -; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[CALL4]], i32 [[CALL9]], i32 undef) #[[ATTR8]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: if.end12: ; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] @@ -267,13 +250,12 @@ ; IS__CGSCC____: cond.true: ; IS__CGSCC____-NEXT: br label [[COND_END:%.*]] ; IS__CGSCC____: cond.false: -; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]] ; IS__CGSCC____-NEXT: br label [[COND_END]] ; IS__CGSCC____: cond.end: -; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[B]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] ; IS__CGSCC____-NEXT: ret i32 [[RETVAL_0]] ; entry: @@ -361,19 +343,17 @@ define double* @ptr_scc_r1(double* %a, double* %r, double* %b) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r1 -; IS__TUNIT____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone returned [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR1]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR5]] -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[R]], double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: ret double* [[CALL1]] +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: ret double* [[R]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r1 -; IS__CGSCC____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone returned [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR2:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[R]], double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: ret double* [[CALL1]] +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: ret double* [[R]] ; entry: %call = call double* @ptr_sink_r0(double* %r) @@ -384,25 +364,23 @@ define double* @ptr_scc_r2(double* %a, double* %b, double* %r) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r2 -; IS__TUNIT____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]], double* nofree readnone returned [[R:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nocapture nofree readnone [[B:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR1]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp ugt double* [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__TUNIT____: if.then: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR5]] -; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[B]], double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp ult double* [[A]], [[B]] ; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__TUNIT____: if.then3: -; IS__TUNIT____-NEXT: [[CALL4:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[R]], double* noalias nofree readnone [[R]], double* noalias nofree readnone [[R]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL6]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[CALL5]], double* noalias nofree readnone [[CALL7]], double* noalias nofree readnone [[CALL8]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[CALL4]], double* noalias nofree readnone [[CALL9]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: if.end12: ; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq double* [[A]], [[B]] @@ -410,36 +388,34 @@ ; IS__TUNIT____: cond.true: ; IS__TUNIT____-NEXT: br label [[COND_END:%.*]] ; IS__TUNIT____: cond.false: -; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[COND_END]] ; IS__TUNIT____: cond.end: -; IS__TUNIT____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__TUNIT____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__TUNIT____-NEXT: br label [[RETURN]] ; IS__TUNIT____: return: -; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] -; IS__TUNIT____-NEXT: ret double* [[RETVAL_0]] +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__TUNIT____-NEXT: ret double* [[R]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r2 -; IS__CGSCC____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]], double* nofree readnone returned [[R:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nocapture nofree readnone [[B:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp ugt double* [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__CGSCC____: if.then: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR6]] -; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[B]], double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] ; IS__CGSCC____: if.end: ; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp ult double* [[A]], [[B]] ; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] ; IS__CGSCC____: if.then3: -; IS__CGSCC____-NEXT: [[CALL4:%.*]] = call double* @ptr_sink_r0(double* noalias nofree readnone "no-capture-maybe-returned" [[B]]) -; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[R]], double* noalias nofree readnone [[R]], double* noalias nofree readnone [[R]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL6]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[CALL5]], double* noalias nofree readnone [[CALL7]], double* noalias nofree readnone [[CALL8]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nofree readnone [[CALL4]], double* noalias nofree readnone [[CALL9]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: if.end12: ; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq double* [[A]], [[B]] @@ -447,14 +423,14 @@ ; IS__CGSCC____: cond.true: ; IS__CGSCC____-NEXT: br label [[COND_END:%.*]] ; IS__CGSCC____: cond.false: -; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[COND_END]] ; IS__CGSCC____: cond.end: -; IS__CGSCC____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] +; IS__CGSCC____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] ; IS__CGSCC____-NEXT: br label [[RETURN]] ; IS__CGSCC____: return: -; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] -; IS__CGSCC____-NEXT: ret double* [[RETVAL_0]] +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] +; IS__CGSCC____-NEXT: ret double* [[R]] ; entry: %cmp = icmp ugt double* %a, %b @@ -516,7 +492,7 @@ ; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt0 -; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR2:[0-9]+]] { +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR3:[0-9]+]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: unreachable ; @@ -543,7 +519,7 @@ ; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt1 -; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR2]] { +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR3]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: unreachable ; @@ -563,14 +539,14 @@ ; IS__TUNIT____-SAME: (i32* nofree readnone returned [[A:%.*]]) #[[ATTR1]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt2(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: ret i32* [[CALL]] +; IS__TUNIT____-NEXT: ret i32* [[A]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt2_helper -; IS__CGSCC____-SAME: (i32* nofree readnone returned [[A:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32* nofree readnone returned [[A:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt2(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: ret i32* [[CALL]] +; IS__CGSCC____-NEXT: ret i32* [[A]] ; entry: %call = call i32* @rt2(i32* %a, i32* %a) @@ -588,12 +564,12 @@ ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt2_helper(i32* noalias nofree readnone [[A]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[IF_END]] ; IS__TUNIT____: if.end: -; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[CALL]], [[IF_THEN]] ] +; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ] ; IS__TUNIT____-NEXT: ret i32* [[SEL]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt2 -; IS__CGSCC____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] @@ -601,7 +577,7 @@ ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt2_helper(i32* noalias nofree readnone [[A]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[IF_END]] ; IS__CGSCC____: if.end: -; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[CALL]], [[IF_THEN]] ] +; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ] ; IS__CGSCC____-NEXT: ret i32* [[SEL]] ; entry: @@ -622,17 +598,17 @@ define i32* @rt3_helper(i32* %a, i32* %b) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@rt3_helper -; IS__TUNIT____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { ; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR6]] -; IS__TUNIT____-NEXT: ret i32* [[CALL]] +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: ret i32* [[B]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt3_helper -; IS__CGSCC____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] -; IS__CGSCC____-NEXT: ret i32* [[CALL]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: ret i32* [[B]] ; entry: %call = call i32* @rt3(i32* %a, i32* %b) @@ -642,29 +618,29 @@ define i32* @rt3(i32* %a, i32 *%b) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@rt3 -; IS__TUNIT____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null ; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__TUNIT____: if.then: -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR6]] +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[IF_END]] ; IS__TUNIT____: if.end: -; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[CALL]], [[IF_THEN]] ] -; IS__TUNIT____-NEXT: ret i32* [[SEL]] +; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ] +; IS__TUNIT____-NEXT: ret i32* [[B]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@rt3 -; IS__CGSCC____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null ; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; IS__CGSCC____: if.then: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[IF_END]] ; IS__CGSCC____: if.end: -; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[CALL]], [[IF_THEN]] ] -; IS__CGSCC____-NEXT: ret i32* [[SEL]] +; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ] +; IS__CGSCC____-NEXT: ret i32* [[B]] ; entry: %cmp = icmp eq i32* %a, null @@ -699,8 +675,8 @@ ; ; IS__CGSCC____: Function Attrs: noinline nounwind uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_unknown_fn -; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR3:[0-9]+]] { -; IS__CGSCC____-NEXT: tail call void @unknown_fn(i32* (i32*)* noundef nonnull @calls_unknown_fn) #[[ATTR9:[0-9]+]] +; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR4:[0-9]+]] { +; IS__CGSCC____-NEXT: tail call void @unknown_fn(i32* (i32*)* noundef nonnull @calls_unknown_fn) #[[ATTR8:[0-9]+]] ; IS__CGSCC____-NEXT: ret i32* [[R]] ; tail call void @unknown_fn(i32* (i32*)* nonnull @calls_unknown_fn) @@ -722,11 +698,17 @@ ; Verify the maybe-redefined function is not annotated: ; define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 { -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@maybe_redefined_fn -; CHECK-SAME: (i32* [[R:%.*]]) #[[ATTR3:[0-9]+]] { -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32* [[R]] +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@maybe_redefined_fn +; IS__TUNIT____-SAME: (i32* [[R:%.*]]) #[[ATTR3]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32* [[R]] +; +; IS__CGSCC____: Function Attrs: noinline nounwind uwtable +; IS__CGSCC____-LABEL: define {{[^@]+}}@maybe_redefined_fn +; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32* [[R]] ; entry: ret i32* %r @@ -742,9 +724,9 @@ ; ; IS__CGSCC____: Function Attrs: noinline nounwind uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn -; IS__CGSCC____-SAME: (i32* returned [[R:%.*]]) #[[ATTR3]] { +; IS__CGSCC____-SAME: (i32* returned [[R:%.*]]) #[[ATTR4]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn(i32* [[R]]) #[[ATTR9]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn(i32* [[R]]) #[[ATTR8]] ; IS__CGSCC____-NEXT: ret i32* [[R]] ; entry: @@ -765,11 +747,17 @@ ; Verify the maybe-redefined function is not annotated: ; define linkonce_odr i32* @maybe_redefined_fn2(i32* %r) #0 { -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@maybe_redefined_fn2 -; CHECK-SAME: (i32* [[R:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32* [[R]] +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@maybe_redefined_fn2 +; IS__TUNIT____-SAME: (i32* [[R:%.*]]) #[[ATTR3]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32* [[R]] +; +; IS__CGSCC____: Function Attrs: noinline nounwind uwtable +; IS__CGSCC____-LABEL: define {{[^@]+}}@maybe_redefined_fn2 +; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32* [[R]] ; entry: ret i32* %r @@ -785,9 +773,9 @@ ; ; IS__CGSCC____: Function Attrs: noinline nounwind uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2 -; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR3]] { +; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn2(i32* [[R]]) #[[ATTR9]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn2(i32* [[R]]) #[[ATTR8]] ; IS__CGSCC____-NEXT: ret i32* [[CALL]] ; entry: @@ -815,10 +803,7 @@ ; IS__TUNIT____: if.then: ; IS__TUNIT____-NEXT: br label [[IF_END]] ; IS__TUNIT____: if.end: -; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] -; IS__TUNIT____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 -; IS__TUNIT____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] -; IS__TUNIT____-NEXT: ret double [[SEL]] +; IS__TUNIT____-NEXT: ret double [[B]] ; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@select_and_phi @@ -829,10 +814,7 @@ ; IS__CGSCC____: if.then: ; IS__CGSCC____-NEXT: br label [[IF_END]] ; IS__CGSCC____: if.end: -; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] -; IS__CGSCC____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 -; IS__CGSCC____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] -; IS__CGSCC____-NEXT: ret double [[SEL]] +; IS__CGSCC____-NEXT: ret double [[B]] ; entry: %cmp = fcmp ogt double %b, 0.000000e+00 @@ -870,14 +852,11 @@ ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR6]] ; IS__TUNIT____-NEXT: br label [[IF_END]] ; IS__TUNIT____: if.end: -; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi double [ [[CALL]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] -; IS__TUNIT____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 -; IS__TUNIT____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] -; IS__TUNIT____-NEXT: ret double [[SEL]] +; IS__TUNIT____-NEXT: ret double [[B]] ; ; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursion_select_and_phi -; IS__CGSCC____-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR2]] { ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[DEC:%.*]] = add nsw i32 [[A]], -1 ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 0 @@ -886,10 +865,7 @@ ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR7]] ; IS__CGSCC____-NEXT: br label [[IF_END]] ; IS__CGSCC____: if.end: -; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi double [ [[CALL]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] -; IS__CGSCC____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 -; IS__CGSCC____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] -; IS__CGSCC____-NEXT: ret double [[SEL]] +; IS__CGSCC____-NEXT: ret double [[B]] ; entry: %dec = add nsw i32 %a, -1 @@ -1207,17 +1183,29 @@ declare i32* @unknown(i32*) define i32* @ret_arg_or_unknown(i32* %b) #0 { -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown -; CHECK-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] -; CHECK: ret_arg: -; CHECK-NEXT: ret i32* [[B]] -; CHECK: ret_unknown: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) -; CHECK-NEXT: ret i32* [[CALL]] +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_arg_or_unknown +; IS__TUNIT____-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] +; IS__TUNIT____: ret_arg: +; IS__TUNIT____-NEXT: ret i32* [[B]] +; IS__TUNIT____: ret_unknown: +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) +; IS__TUNIT____-NEXT: ret i32* [[CALL]] +; +; IS__CGSCC____: Function Attrs: noinline nounwind uwtable +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_arg_or_unknown +; IS__CGSCC____-SAME: (i32* [[B:%.*]]) #[[ATTR4]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] +; IS__CGSCC____: ret_arg: +; IS__CGSCC____-NEXT: ret i32* [[B]] +; IS__CGSCC____: ret_unknown: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) +; IS__CGSCC____-NEXT: ret i32* [[CALL]] ; entry: %cmp = icmp eq i32* %b, null @@ -1232,20 +1220,35 @@ } define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 { -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi -; CHECK-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] -; CHECK: ret_arg: -; CHECK-NEXT: br label [[R:%.*]] -; CHECK: ret_unknown: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) -; CHECK-NEXT: br label [[R]] -; CHECK: r: -; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] -; CHECK-NEXT: ret i32* [[PHI]] +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi +; IS__TUNIT____-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] +; IS__TUNIT____: ret_arg: +; IS__TUNIT____-NEXT: br label [[R:%.*]] +; IS__TUNIT____: ret_unknown: +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) +; IS__TUNIT____-NEXT: br label [[R]] +; IS__TUNIT____: r: +; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] +; IS__TUNIT____-NEXT: ret i32* [[PHI]] +; +; IS__CGSCC____: Function Attrs: noinline nounwind uwtable +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi +; IS__CGSCC____-SAME: (i32* [[B:%.*]]) #[[ATTR4]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] +; IS__CGSCC____: ret_arg: +; IS__CGSCC____-NEXT: br label [[R:%.*]] +; IS__CGSCC____: ret_unknown: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) +; IS__CGSCC____-NEXT: br label [[R]] +; IS__CGSCC____: r: +; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] +; IS__CGSCC____-NEXT: ret i32* [[PHI]] ; entry: %cmp = icmp eq i32* %b, null @@ -1408,20 +1411,35 @@ declare void @noreturn() noreturn; define i32 @deadblockphi3(i32 %A, i1 %c) #0 { -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define {{[^@]+}}@deadblockphi3 -; CHECK-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]] -; CHECK: unreachablecall: -; CHECK-NEXT: call void @noreturn() #[[ATTR4:[0-9]+]] -; CHECK-NEXT: unreachable -; CHECK: unreachableblock2: -; CHECK-NEXT: unreachable -; CHECK: unreachableblock3: -; CHECK-NEXT: unreachable -; CHECK: r: -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockphi3 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) #[[ATTR3]] { +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]] +; IS__TUNIT____: unreachablecall: +; IS__TUNIT____-NEXT: call void @noreturn() #[[ATTR4:[0-9]+]] +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock3: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: r: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; +; IS__CGSCC____: Function Attrs: noinline nounwind uwtable +; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockphi3 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) #[[ATTR4]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]] +; IS__CGSCC____: unreachablecall: +; IS__CGSCC____-NEXT: call void @noreturn() #[[ATTR5:[0-9]+]] +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock3: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: r: +; IS__CGSCC____-NEXT: ret i32 [[A]] ; entry: br i1 %c, label %r, label %unreachablecall @@ -1486,10 +1504,10 @@ ; CHECK-NEXT: [[C2:%.*]] = call i32 @non_exact_2(i32 noundef 2) ; CHECK-NEXT: [[C3:%.*]] = call align 32 i32* @non_exact_3(i32* align 32 [[A]]) ; CHECK-NEXT: [[C4:%.*]] = call align 16 i32* @non_exact_4(i32* align 32 [[B]]) -; CHECK-NEXT: [[C3L:%.*]] = load i32, i32* [[C3]], align 32 +; CHECK-NEXT: [[C3L:%.*]] = load i32, i32* [[A]], align 32 ; CHECK-NEXT: [[C4L:%.*]] = load i32, i32* [[C4]], align 16 ; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[C0]], [[C1]] -; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[C2]] +; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], 2 ; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[C3L]] ; CHECK-NEXT: [[ADD4:%.*]] = add i32 [[ADD3]], [[C4L]] ; CHECK-NEXT: ret i32 [[ADD4]] @@ -1602,19 +1620,18 @@ ; IS__TUNIT____: attributes #[[ATTR2]] = { nofree noinline noreturn nosync nounwind readnone uwtable willreturn } ; IS__TUNIT____: attributes #[[ATTR3]] = { noinline nounwind uwtable } ; IS__TUNIT____: attributes #[[ATTR4]] = { noreturn } -; IS__TUNIT____: attributes #[[ATTR5]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR5:[0-9]+]] = { nofree nosync nounwind readnone willreturn } ; IS__TUNIT____: attributes #[[ATTR6]] = { nofree nosync nounwind readnone } ; IS__TUNIT____: attributes #[[ATTR7]] = { nounwind } ; IS__TUNIT____: attributes #[[ATTR8:[0-9]+]] = { nounwind readnone } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn } -; IS__CGSCC____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable } -; IS__CGSCC____: attributes #[[ATTR2]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn } -; IS__CGSCC____: attributes #[[ATTR3]] = { noinline nounwind uwtable } -; IS__CGSCC____: attributes #[[ATTR4]] = { noreturn } -; IS__CGSCC____: attributes #[[ATTR5:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR6]] = { readnone willreturn } +; IS__CGSCC____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable willreturn } +; IS__CGSCC____: attributes #[[ATTR2]] = { nofree noinline nosync nounwind readnone uwtable } +; IS__CGSCC____: attributes #[[ATTR3]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn } +; IS__CGSCC____: attributes #[[ATTR4]] = { noinline nounwind uwtable } +; IS__CGSCC____: attributes #[[ATTR5]] = { noreturn } +; IS__CGSCC____: attributes #[[ATTR6:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone } -; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind readnone } -; IS__CGSCC____: attributes #[[ATTR9]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind } ;. diff --git a/llvm/test/Transforms/Attributor/undefined_behavior.ll b/llvm/test/Transforms/Attributor/undefined_behavior.ll --- a/llvm/test/Transforms/Attributor/undefined_behavior.ll +++ b/llvm/test/Transforms/Attributor/undefined_behavior.ll @@ -1086,12 +1086,12 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer ; IS__TUNIT____-SAME: () #[[ATTR0]] { -; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____-NEXT: ret i32 undef ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer ; IS__CGSCC____-SAME: () #[[ATTR0]] { -; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____-NEXT: ret i32 undef ; %ret = call i32 @argument_noundef1(i32 undef) ret i32 %ret @@ -1115,12 +1115,12 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_pointer ; IS__TUNIT____-SAME: () #[[ATTR0]] { -; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____-NEXT: ret i32* undef ; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_pointer ; IS__CGSCC____-SAME: () #[[ATTR0]] { -; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____-NEXT: ret i32* undef ; %ret = call i32* @argument_noundef2(i32* undef) ret i32* %ret diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -433,21 +433,14 @@ define i32* @complicated_args_inalloca(i32* %arg) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_inalloca -; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR1]] { -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nofree writeonly inalloca(i32) "no-capture-maybe-returned" [[ARG]]) #[[ATTR1]] +; IS__TUNIT____-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call nonnull dereferenceable(4) i32* @test_inalloca(i32* noalias nofree writeonly inalloca(i32) "no-capture-maybe-returned" [[ARG]]) #[[ATTR1]] ; IS__TUNIT____-NEXT: ret i32* [[CALL]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_inalloca -; IS__CGSCC_OPM-SAME: (i32* nofree noundef nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR1]] { -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nofree noundef nonnull writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[ARG]]) #[[ATTR7:[0-9]+]] -; IS__CGSCC_OPM-NEXT: ret i32* [[CALL]] -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_inalloca -; IS__CGSCC_NPM-SAME: (i32* nofree noundef nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR1]] { -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nofree noundef nonnull writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[ARG]]) #[[ATTR6:[0-9]+]] -; IS__CGSCC_NPM-NEXT: ret i32* [[CALL]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_inalloca +; IS__CGSCC____-SAME: (i32* nofree noundef nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i32* [[ARG]] ; %call = call i32* @test_inalloca(i32* inalloca(i32) %arg) ret i32* %call @@ -471,29 +464,27 @@ ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@complicated_args_preallocated ; IS__TUNIT_OPM-SAME: () #[[ATTR0:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR7:[0-9]+]] -; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR1]] [ "preallocated"(token [[C]]) ] +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call noundef nonnull align 536870912 dereferenceable(4) i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR1]] [ "preallocated"(token [[C]]) ] ; IS__TUNIT_OPM-NEXT: ret i32* [[CALL]] ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@complicated_args_preallocated ; IS__TUNIT_NPM-SAME: () #[[ATTR0:[0-9]+]] { ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR6:[0-9]+]] -; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR1]] [ "preallocated"(token [[C]]) ] +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call noundef nonnull align 536870912 dereferenceable(4) i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR1]] [ "preallocated"(token [[C]]) ] ; IS__TUNIT_NPM-NEXT: ret i32* [[CALL]] ; ; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_preallocated ; IS__CGSCC_OPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR8:[0-9]+]] -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR9:[0-9]+]] [ "preallocated"(token [[C]]) ] -; IS__CGSCC_OPM-NEXT: ret i32* [[CALL]] +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR7:[0-9]+]] +; IS__CGSCC_OPM-NEXT: ret i32* null ; ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_preallocated ; IS__CGSCC_NPM-SAME: () #[[ATTR0:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR7:[0-9]+]] -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree noundef writeonly preallocated(i32) align 536870912 null) #[[ATTR8:[0-9]+]] [ "preallocated"(token [[C]]) ] -; IS__CGSCC_NPM-NEXT: ret i32* [[CALL]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR6:[0-9]+]] +; IS__CGSCC_NPM-NEXT: ret i32* null ; %c = call token @llvm.call.preallocated.setup(i32 1) %call = call i32* @test_preallocated(i32* preallocated(i32) null) ["preallocated"(token %c)] @@ -542,15 +533,10 @@ } define internal %struct.X* @test_nest(%struct.X* nest %a) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@test_nest -; IS__TUNIT____-SAME: (%struct.X* nest noalias nofree noundef readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { -; IS__TUNIT____-NEXT: ret %struct.X* [[A]] -; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_nest -; IS__CGSCC____-SAME: (%struct.X* nest noalias nofree noundef readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { -; IS__CGSCC____-NEXT: ret %struct.X* [[A]] +; IS__CGSCC____-SAME: (%struct.X* nest noalias nocapture nofree readnone align 536870912 [[A:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret %struct.X* undef ; ret %struct.X* %a } @@ -558,20 +544,12 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_nest ; IS__TUNIT____-SAME: () #[[ATTR1]] { -; IS__TUNIT____-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree noundef readnone align 536870912 null) #[[ATTR1]] -; IS__TUNIT____-NEXT: ret %struct.X* [[CALL]] +; IS__TUNIT____-NEXT: ret %struct.X* null ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_nest -; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree noundef readnone align 536870912 null) #[[ATTR7]] -; IS__CGSCC_OPM-NEXT: ret %struct.X* [[CALL]] -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_nest -; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree noundef readnone align 536870912 null) #[[ATTR6]] -; IS__CGSCC_NPM-NEXT: ret %struct.X* [[CALL]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_nest +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret %struct.X* null ; %call = call %struct.X* @test_nest(%struct.X* null) ret %struct.X* %call @@ -648,13 +626,13 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_byval2 ; IS__CGSCC_OPM-SAME: () #[[ATTR3]] { -; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i8* @test_byval2() #[[ATTR10:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i8* @test_byval2() #[[ATTR8:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i8* [[C]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_byval2 ; IS__CGSCC_NPM-SAME: () #[[ATTR3]] { -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i8* @test_byval2() #[[ATTR9:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i8* @test_byval2() #[[ATTR7:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i8* [[C]] ; %c = call i8* @test_byval2(%struct.X* byval(%struct.X) @S) @@ -991,7 +969,7 @@ ; IS__CGSCC_OPM-NEXT: [[OR:%.*]] = or i1 false, [[C]] ; IS__CGSCC_OPM-NEXT: br i1 [[OR]], label [[A:%.*]], label [[B:%.*]] ; IS__CGSCC_OPM: a: -; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i1 @undef_then_null(i1 noundef false) #[[ATTR11:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i1 @undef_then_null(i1 noundef false) #[[ATTR9:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i1 undef ; IS__CGSCC_OPM: b: ; IS__CGSCC_OPM-NEXT: ret i1 undef @@ -1004,7 +982,7 @@ ; IS__CGSCC_NPM-NEXT: [[OR:%.*]] = or i1 false, [[C]] ; IS__CGSCC_NPM-NEXT: br i1 [[OR]], label [[A:%.*]], label [[B:%.*]] ; IS__CGSCC_NPM: a: -; IS__CGSCC_NPM-NEXT: [[R2:%.*]] = call i1 @undef_then_null(i1 noundef false) #[[ATTR10:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[R2:%.*]] = call i1 @undef_then_null(i1 noundef false) #[[ATTR8:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i1 undef ; IS__CGSCC_NPM: b: ; IS__CGSCC_NPM-NEXT: ret i1 undef @@ -1035,6 +1013,7 @@ ret i1 %r1 } define internal i1 @undef_then_1(i1 %c, i32 %i32A, i32 %i32B) { +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@undef_then_1 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { @@ -1270,11 +1249,9 @@ ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nofree nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR7]] = { readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR8]] = { willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR10]] = { readonly willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR11]] = { nofree nosync nounwind readnone } +; IS__CGSCC_OPM: attributes #[[ATTR7]] = { willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR8]] = { readonly willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree nosync nounwind readnone } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } @@ -1282,9 +1259,7 @@ ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nofree nosync nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR6]] = { readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR7]] = { willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nounwind readnone willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR9]] = { readonly willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR10]] = { nofree nosync nounwind readnone } +; IS__CGSCC_NPM: attributes #[[ATTR6]] = { willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR7]] = { readonly willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree nosync nounwind readnone } ;. diff --git a/llvm/test/Transforms/OpenMP/replace_globalization.ll b/llvm/test/Transforms/OpenMP/replace_globalization.ll --- a/llvm/test/Transforms/OpenMP/replace_globalization.ll +++ b/llvm/test/Transforms/OpenMP/replace_globalization.ll @@ -28,7 +28,7 @@ ret void } -; CHECK: %{{.*}} = bitcast i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([16 x i8], [16 x i8] addrspace(3)* [[SHARED_X]], i32 0, i32 0) to i8*) to [4 x i32]* +; CHECK: call void @use.internalized(i8* nofree writeonly addrspacecast (i8 addrspace(3)* getelementptr inbounds ([16 x i8], [16 x i8] addrspace(3)* [[SHARED_X]], i32 0, i32 0) to i8*)) define internal void @baz() { entry: %tid = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() @@ -45,7 +45,7 @@ ret void } -; CHECK: %{{.*}} = bitcast i8* addrspacecast (i8 addrspace(3)* getelementptr inbounds ([4 x i8], [4 x i8] addrspace(3)* [[SHARED_Y]], i32 0, i32 0) to i8*) to [4 x i32]* +; CHECK: call void @use.internalized(i8* nofree writeonly addrspacecast (i8 addrspace(3)* getelementptr inbounds ([4 x i8], [4 x i8] addrspace(3)* [[SHARED_Y]], i32 0, i32 0) to i8*)) define internal void @qux() { entry: %tid = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()