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 @@ -3855,6 +3855,36 @@ static const char ID; }; +/// An abstract state for querying live call edges. +/// This interface uses the Attributor's optimistic liveness +/// information to compute the edges that are alive. +struct AACallEdges: public StateWrapper { + using Base = StateWrapper; + + AACallEdges(const IRPosition &IRP, Attributor &A) : Base(IRP) {} + + /// Create an abstract attribute view for the position \p IRP. + static AACallEdges &createForPosition(const IRPosition &IRP, Attributor &A); + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AACallEdges"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + virtual const DenseSet& getOptimisticEdges() const = 0; + + /// This function should return true if the type of the \p AA is AACallEdges. + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + /// Unique ID (due to the unique address) + static const char ID; +}; + + + /// Run options, used by the pass manager. enum AttributorRunOption { NONE = 0, 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 @@ -134,6 +134,7 @@ PIPE_OPERATOR(AAUndefinedBehavior) PIPE_OPERATOR(AAPotentialValues) PIPE_OPERATOR(AANoUndef) +PIPE_OPERATOR(AACallEdges) #undef PIPE_OPERATOR } // namespace llvm @@ -8133,6 +8134,73 @@ /// See AbstractAttribute::trackStatistics() void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) } }; + +//TODO: Implement GraphTraits ? +struct AACallEdgesFunction : public AACallEdges { + AACallEdgesFunction(const IRPosition &IRP, Attributor &A) + : AACallEdges(IRP, A) {} + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + ChangeStatus Change = ChangeStatus::UNCHANGED; + + // A dependency will be added if the information is used. + const AAIsDead &LivenessAA = A.getAAFor(*this, + getIRPosition(), + DepClassTy::NONE); + + // Opcodes of callable instructions. These all ineherit from CallBase. + auto Opcodes = { + (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr, + (unsigned)Instruction::Call + }; + + auto AddCalledFunction = [&](Function *Fn) { + // Track the changes. + if (CalledFunctions.insert(Fn).second) + Change = Change | ChangeStatus::CHANGED; + }; + + auto ProcessCallInst = [&](Instruction &Inst) { + CallBase &CB = static_cast(Inst); + Function *Callee = CB.getCalledFunction(); + // The most simple case. + if (Callee) + AddCalledFunction(Callee); + + //Process callback functions. + SmallVector CallbackUses; + AbstractCallSite::getCallbackUses(CB, CallbackUses); + for (const Use *U : CallbackUses) { + AbstractCallSite ACS(U); + Function *Fn = ACS.getCalledFunction(); + Value *Val = U->get(); + // Ask the attributor if the value is alive. + if (Fn && !A.isAssumedDead(IRPosition::value(*Val), this, &LivenessAA)) + AddCalledFunction(Fn); + } + return true; + }; + // Visit all callable instructions. + A.checkForAllInstructions(ProcessCallInst, *this, Opcodes); + + return Change; + } + + virtual const DenseSet& getOptimisticEdges() const override { + return CalledFunctions; + }; + + const std::string getAsStr() const override { + //TODO: Be more informative. + return "CallEdges"; + } + + void trackStatistics() const override {} + + DenseSet CalledFunctions; +}; + } // namespace const char AAReturnedValues::ID = 0; @@ -8158,6 +8226,7 @@ const char AAValueConstantRange::ID = 0; const char AAPotentialValues::ID = 0; const char AANoUndef::ID = 0; +const char AACallEdges::ID = 0; // Macro magic to create the static generator function for attributes that // follow the naming scheme. @@ -8277,6 +8346,8 @@ CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack) CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReachability) CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior) +CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges) + CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)