Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -29,7 +29,7 @@ // automatically capture a potential dependence from Q to P. This dependence // will cause P to be reevaluated whenever Q changes in the future. // -// The Attributor will only reevaluated abstract attributes that might have +// The Attributor will only reevaluate abstract attributes that might have // changed since the last iteration. That means that the Attribute will not // revisit all instructions/blocks/functions in the module but only query // an update from a subset of the abstract attributes. @@ -152,8 +152,8 @@ /// The positions we distinguish in the IR. /// - /// The values are chosen such that the KindOrArgNo member has a value >= 1 - /// if it is an argument or call site argument while a value < 1 indicates the + /// The values are chosen such that the KindOrArgNo member has a value >= 0 + /// if it is an argument or call site argument while a value < 0 indicates the /// respective kind of that value. enum Kind : int { IRP_INVALID = -6, ///< An invalid position. @@ -273,18 +273,11 @@ /// Return the associated function, if any. Function *getAssociatedFunction() const { - if (auto *CB = dyn_cast(AnchorVal)) - return CB->getCalledFunction(); assert(KindOrArgNo != IRP_INVALID && "Invalid position does not have an anchor scope!"); - Value &V = getAnchorValue(); - if (isa(V)) - return &cast(V); - if (isa(V)) - return cast(V).getParent(); - if (isa(V)) - return cast(V).getFunction(); - return nullptr; + if (auto *CB = dyn_cast(AnchorVal)) + return CB->getCalledFunction(); + return getAnchorScope(); } /// Return the associated argument, if any. @@ -474,7 +467,10 @@ /// The value this position is anchored at. Value *AnchorVal; - /// The argument number, if non-negative, or the position "kind". + /// If AnchorVal is Argument or CallBase then this number should be + /// non-negative and it denotes the argument or call site argument index + /// respectively. Otherwise, it denotes the kind of this IRPosition according + /// to Kind above. int KindOrArgNo; }; @@ -2291,7 +2287,8 @@ /// Add accessed bytes to the map. void addAccessedBytes(int64_t Offset, uint64_t Size) { - AccessedBytesMap[Offset] = std::max(AccessedBytesMap[Offset], Size); + uint64_t &AccessedBytes = AccessedBytesMap[Offset]; + AccessedBytes = std::max(AccessedBytes, Size); // Known bytes might increase. computeKnownDerefBytesFromAccessedMap(); Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -558,7 +558,7 @@ ChangeStatus IRAttributeManifest::manifestAttrs(Attributor &A, const IRPosition &IRP, const ArrayRef &DeducedAttrs) { - Function *ScopeFn = IRP.getAssociatedFunction(); + Function *ScopeFn = IRP.getAnchorScope(); IRPosition::Kind PK = IRP.getPositionKind(); // In the following some generic code that will manifest attributes in @@ -627,8 +627,7 @@ return; case IRPosition::IRP_ARGUMENT: case IRPosition::IRP_RETURNED: - IRPositions.emplace_back( - IRPosition::function(*IRP.getAssociatedFunction())); + IRPositions.emplace_back(IRPosition::function(*IRP.getAnchorScope())); return; case IRPosition::IRP_CALL_SITE: assert(ICS && "Expected call site!"); @@ -2529,7 +2528,7 @@ void initialize(Attributor &A) override { AAWillReturn::initialize(A); - Function *F = getAssociatedFunction(); + Function *F = getAnchorScope(); if (!F || !A.isFunctionIPOAmendable(*F) || mayContainUnboundedCycle(*F, A)) indicatePessimisticFixpoint(); } @@ -3114,7 +3113,7 @@ /// See AbstractAttribute::initialize(...). void initialize(Attributor &A) override { - if (!A.isFunctionIPOAmendable(*getAssociatedFunction())) + if (!A.isFunctionIPOAmendable(*getAnchorScope())) indicatePessimisticFixpoint(); } @@ -3285,7 +3284,7 @@ /// See AbstractAttribute::initialize(...). void initialize(Attributor &A) override { - const Function *F = getAssociatedFunction(); + const Function *F = getAnchorScope(); if (F && !F->isDeclaration()) { ToBeExploredFrom.insert(&F->getEntryBlock().front()); assumeLive(A, F->getEntryBlock()); @@ -3295,7 +3294,7 @@ /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" + - std::to_string(getAssociatedFunction()->size()) + "][#TBEP " + + std::to_string(getAnchorScope()->size()) + "][#TBEP " + std::to_string(ToBeExploredFrom.size()) + "][#KDE " + std::to_string(KnownDeadEnds.size()) + "]"; } @@ -3306,7 +3305,7 @@ "Attempted to manifest an invalid state!"); ChangeStatus HasChanged = ChangeStatus::UNCHANGED; - Function &F = *getAssociatedFunction(); + Function &F = *getAnchorScope(); if (AssumedLiveBlocks.empty()) { A.deleteAfterManifest(F); @@ -3358,7 +3357,7 @@ /// See AAIsDead::isAssumedDead(BasicBlock *). bool isAssumedDead(const BasicBlock *BB) const override { - assert(BB->getParent() == getAssociatedFunction() && + assert(BB->getParent() == getAnchorScope() && "BB must be in the same anchor scope function."); if (!getAssumed()) @@ -3373,7 +3372,7 @@ /// See AAIsDead::isAssumed(Instruction *I). bool isAssumedDead(const Instruction *I) const override { - assert(I->getParent()->getParent() == getAssociatedFunction() && + assert(I->getParent()->getParent() == getAnchorScope() && "Instruction must be in the same anchor scope function."); if (!getAssumed()) @@ -3527,7 +3526,7 @@ ChangeStatus Change = ChangeStatus::UNCHANGED; LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/" - << getAssociatedFunction()->size() << "] BBs and " + << getAnchorScope()->size() << "] BBs and " << ToBeExploredFrom.size() << " exploration points and " << KnownDeadEnds.size() << " known dead ends\n"); @@ -3607,7 +3606,7 @@ // discovered any non-trivial dead end and (2) not ruled unreachable code // dead. if (ToBeExploredFrom.empty() && - getAssociatedFunction()->size() == AssumedLiveBlocks.size() && + getAnchorScope()->size() == AssumedLiveBlocks.size() && llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) { return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0; })) @@ -3947,7 +3946,7 @@ takeKnownMaximum(Attr.getValueAsInt()); if (getIRPosition().isFnInterfaceKind() && - (!getAssociatedFunction() || + (!getAnchorScope() || !A.isFunctionIPOAmendable(*getAssociatedFunction()))) indicatePessimisticFixpoint(); } @@ -4748,7 +4747,7 @@ void initialize(Attributor &A) override { AAValueSimplifyImpl::initialize(A); - if (!getAssociatedFunction() || getAssociatedFunction()->isDeclaration()) + if (!getAnchorScope() || getAnchorScope()->isDeclaration()) indicatePessimisticFixpoint(); if (hasAttr({Attribute::InAlloca, Attribute::StructRet, Attribute::Nest}, /* IgnoreSubsumingPositions */ true)) @@ -4998,7 +4997,7 @@ "Attempted to manifest an invalid state!"); ChangeStatus HasChanged = ChangeStatus::UNCHANGED; - Function *F = getAssociatedFunction(); + Function *F = getAnchorScope(); const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F); for (Instruction *MallocCall : MallocCalls) { @@ -5075,7 +5074,7 @@ }; ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) { - const Function *F = getAssociatedFunction(); + const Function *F = getAnchorScope(); const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F); MustBeExecutedContextExplorer &Explorer = @@ -7675,7 +7674,7 @@ unsigned IterationCounter = 1; - SmallVector ChangedAAs; + SmallVector ChangedAAs; SetVector Worklist, InvalidAAs; Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end()); @@ -8318,7 +8317,7 @@ switch (I.getOpcode()) { default: assert((!ImmutableCallSite(&I)) && (!isa(&I)) && - "New call site/base instruction type needs to be known int the " + "New call site/base instruction type needs to be known in the " "Attributor."); break; case Instruction::Load: @@ -8647,6 +8646,10 @@ // while we identify default attribute opportunities. Attributor A(Functions, InfoCache, CGUpdater, DepRecInterval); + // Note: _Don't_ combine/fuse this loop with the one below because + // when A.identifyDefaultAbstractAttributes() is called for one + // function, it assumes that the information cach has been + // initialized for _all_ functions. for (Function *F : Functions) A.initializeInformationCache(*F);