Skip to content

Commit

Permalink
[Attributor] Create a call site position for AACalledges
Browse files Browse the repository at this point in the history
This patch adds a call site position for AACallEdges, this
allows us to ask questions about which functions a specific
`CallBase` might call.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D106208
  • Loading branch information
kuterd committed Sep 12, 2021
1 parent fb7fbe4 commit 2cc6f7c
Showing 1 changed file with 105 additions and 77 deletions.
182 changes: 105 additions & 77 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9347,77 +9347,137 @@ struct AANoUndefCallSiteReturned final
void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
};

struct AACallEdgesFunction : public AACallEdges {
AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
: AACallEdges(IRP, A) {}
struct AACallEdgesImpl : public AACallEdges {
AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}

virtual const SetVector<Function *> &getOptimisticEdges() const override {
return CalledFunctions;
}

virtual bool hasUnknownCallee() const override { return HasUnknownCallee; }

virtual bool hasNonAsmUnknownCallee() const override {
return HasUnknownCalleeNonAsm;
}

const std::string getAsStr() const override {
return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
std::to_string(CalledFunctions.size()) + "]";
}

void trackStatistics() const override {}

protected:
void addCalledFunction(Function *Fn, ChangeStatus &Change) {
if (CalledFunctions.insert(Fn)) {
Change = ChangeStatus::CHANGED;
LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
<< "\n");
}
}

void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
if (!HasUnknownCallee)
Change = ChangeStatus::CHANGED;
if (NonAsm && !HasUnknownCalleeNonAsm)
Change = ChangeStatus::CHANGED;
HasUnknownCalleeNonAsm |= NonAsm;
HasUnknownCallee = true;
}

private:
/// Optimistic set of functions that might be called by this position.
SetVector<Function *> CalledFunctions;

/// Is there any call with a unknown callee.
bool HasUnknownCallee = false;

/// Is there any call with a unknown callee, excluding any inline asm.
bool HasUnknownCalleeNonAsm = false;
};

struct AACallEdgesCallSite : public AACallEdgesImpl {
AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
: AACallEdgesImpl(IRP, A) {}
/// See AbstractAttribute::updateImpl(...).
ChangeStatus updateImpl(Attributor &A) override {
ChangeStatus Change = ChangeStatus::UNCHANGED;
bool OldHasUnknownCallee = HasUnknownCallee;
bool OldHasUnknownCalleeNonAsm = HasUnknownCalleeNonAsm;

auto AddCalledFunction = [&](Function *Fn) {
if (CalledFunctions.insert(Fn)) {
Change = ChangeStatus::CHANGED;
LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
<< "\n");
}
};

auto VisitValue = [&](Value &V, const Instruction *CtxI, bool &HasUnknown,
bool Stripped) -> bool {
if (Function *Fn = dyn_cast<Function>(&V)) {
AddCalledFunction(Fn);
addCalledFunction(Fn, Change);
} else {
LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
HasUnknown = true;
HasUnknownCalleeNonAsm = true;
setHasUnknownCallee(true, Change);
}

// Explore all values.
return true;
};

// Process any value that we might call.
auto ProcessCalledOperand = [&](Value *V, Instruction *Ctx) {
auto ProcessCalledOperand = [&](Value *V) {
bool DummyValue = false;
if (!genericValueTraversal<bool>(A, IRPosition::value(*V), *this,
HasUnknownCallee, VisitValue, nullptr,
DummyValue, VisitValue, nullptr,
false)) {
// If we haven't gone through all values, assume that there are unknown
// callees.
HasUnknownCallee = true;
HasUnknownCalleeNonAsm = true;
setHasUnknownCallee(true, Change);
}
};

auto ProcessCallInst = [&](Instruction &Inst) {
CallBase &CB = static_cast<CallBase &>(Inst);
if (CB.isInlineAsm()) {
HasUnknownCallee = true;
return true;
}
CallBase *CB = static_cast<CallBase *>(getCtxI());

// Process callee metadata if available.
if (auto *MD = Inst.getMetadata(LLVMContext::MD_callees)) {
for (auto &Op : MD->operands()) {
Function *Callee = mdconst::extract_or_null<Function>(Op);
if (Callee)
AddCalledFunction(Callee);
}
// Callees metadata grantees that the called function is one of its
// operands, So we are done.
return true;
if (CB->isInlineAsm()) {
setHasUnknownCallee(false, Change);
return Change;
}

// Process callee metadata if available.
if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) {
for (auto &Op : MD->operands()) {
Function *Callee = mdconst::extract_or_null<Function>(Op);
if (Callee)
addCalledFunction(Callee, Change);
}
return Change;
}

// The most simple case.
ProcessCalledOperand(CB.getCalledOperand(), &Inst);
// The most simple case.
ProcessCalledOperand(CB->getCalledOperand());

// Process callback functions.
SmallVector<const Use *, 4u> CallbackUses;
AbstractCallSite::getCallbackUses(CB, CallbackUses);
for (const Use *U : CallbackUses)
ProcessCalledOperand(U->get(), &Inst);
// Process callback functions.
SmallVector<const Use *, 4u> CallbackUses;
AbstractCallSite::getCallbackUses(*CB, CallbackUses);
for (const Use *U : CallbackUses)
ProcessCalledOperand(U->get());

return Change;
}
};

struct AACallEdgesFunction : public AACallEdgesImpl {
AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
: AACallEdgesImpl(IRP, A) {}

/// See AbstractAttribute::updateImpl(...).
ChangeStatus updateImpl(Attributor &A) override {
ChangeStatus Change = ChangeStatus::UNCHANGED;

auto ProcessCallInst = [&](Instruction &Inst) {
CallBase &CB = static_cast<CallBase &>(Inst);

auto &CBEdges = A.getAAFor<AACallEdges>(
*this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
if (CBEdges.hasNonAsmUnknownCallee())
setHasUnknownCallee(false, Change);
if (CBEdges.hasUnknownCallee())
setHasUnknownCallee(true, Change);

for (Function *F : CBEdges.getOptimisticEdges())
addCalledFunction(F, Change);

return true;
};
Expand All @@ -9428,43 +9488,11 @@ struct AACallEdgesFunction : public AACallEdges {
UsedAssumedInformation)) {
// If we haven't looked at all call like instructions, assume that there
// are unknown callees.
HasUnknownCallee = true;
HasUnknownCalleeNonAsm = true;
setHasUnknownCallee(true, Change);
}

// Track changes.
if (OldHasUnknownCallee != HasUnknownCallee ||
OldHasUnknownCalleeNonAsm != HasUnknownCalleeNonAsm)
Change = ChangeStatus::CHANGED;

return Change;
}

virtual const SetVector<Function *> &getOptimisticEdges() const override {
return CalledFunctions;
};

virtual bool hasUnknownCallee() const override { return HasUnknownCallee; }

virtual bool hasNonAsmUnknownCallee() const override {
return HasUnknownCalleeNonAsm;
}

const std::string getAsStr() const override {
return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
std::to_string(CalledFunctions.size()) + "]";
}

void trackStatistics() const override {}

/// Optimistic set of functions that might be called by this function.
SetVector<Function *> CalledFunctions;

/// Is there any call with a unknown callee.
bool HasUnknownCallee = false;

/// Is there any call with a unknown callee, excluding any inline asm.
bool HasUnknownCalleeNonAsm = false;
};

struct AAFunctionReachabilityFunction : public AAFunctionReachability {
Expand Down Expand Up @@ -9715,6 +9743,7 @@ CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)

CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
Expand All @@ -9734,7 +9763,6 @@ CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
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_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAFunctionReachability)

CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)
Expand Down

0 comments on commit 2cc6f7c

Please sign in to comment.