Skip to content

Commit

Permalink
Fix IIA Edge Functions (#700)
Browse files Browse the repository at this point in the history
* Fix joinImpl + IIAAKillOrReplaceEF in IIA

* minor

---------

Co-authored-by: Martin Mory <[email protected]>
  • Loading branch information
fabianbs96 and MMory authored Feb 29, 2024
1 parent fec44a5 commit a56fc58
Showing 1 changed file with 53 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "phasar/Utils/Logger.h"

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constant.h"
Expand Down Expand Up @@ -629,26 +630,19 @@ class IDEInstInteractionAnalysisT
// variables using generalized initial seeds

// Generate zero value at the entry points
Seeds.addSeed(SP, this->getZeroValue(), bottomElement());
Seeds.addSeed(SP, this->getZeroValue(), Bottom{});
// Generate formal parameters of entry points, e.g. main(). Formal
// parameters will otherwise cause trouble by overriding alloca
// instructions without being valid data-flow facts themselves.
for (const auto &Arg : SP->getFunction()->args()) {
Seeds.addSeed(SP, &Arg, Bottom{});
Seeds.addSeed(SP, &Arg, BitVectorSet<e_t>());
}
// Generate all global variables using generalized initial seeds

for (const auto &G : this->IRDB->getModule()->globals()) {
if (const auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(&G)) {
l_t InitialValues = BitVectorSet<e_t>();
std::set<e_t> EdgeFacts;
if (EdgeFactGen) {
EdgeFacts = EdgeFactGen(GV);
// fill BitVectorSet
InitialValues =
BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
}
Seeds.addSeed(SP, GV, InitialValues);
l_t InitialValues = bvSetFrom(invoke_or_default(EdgeFactGen, GV));
Seeds.addSeed(SP, GV, std::move(InitialValues));
}
}
});
Expand Down Expand Up @@ -691,7 +685,12 @@ class IDEInstInteractionAnalysisT
if (SuccNode == Store->getPointerOperand() ||
PT.isInReachableAllocationSites(Store->getPointerOperand(), SuccNode,
true, Store)) {
return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts);
if (isZeroValue(CurrNode)) {
return IIAAKillOrReplaceEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
return IIAAAddLabelsEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
}

Expand All @@ -709,7 +708,7 @@ class IDEInstInteractionAnalysisT
// v
// y
//
if ((CurrNode == SuccNode) && CurrNode == Store->getPointerOperand()) {
if (CurrNode == SuccNode && CurrNode == Store->getPointerOperand()) {
// y obtains its value(s) from its original allocation and the store
// instruction under analysis.
IF_LOG_ENABLED({
Expand All @@ -722,7 +721,8 @@ class IDEInstInteractionAnalysisT
PHASAR_LOG_LEVEL(DFADEBUG, '\n');
});
// obtain label from the original allocation
return IIAAKillOrReplaceEFCache.createEdgeFunction(UserEdgeFacts);
return IIAAKillOrReplaceEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}

} else {
Expand Down Expand Up @@ -800,7 +800,11 @@ class IDEInstInteractionAnalysisT

// We generate Curr in this instruction, so we have to annotate it with
// edge labels
return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts);
if (isZeroValue(CurrNode)) {
return IIAAKillOrReplaceEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
return IIAAAddLabelsEFCache.createEdgeFunction(std::move(UserEdgeFacts));
}

// Otherwise stick to identity.
Expand Down Expand Up @@ -835,7 +839,7 @@ class IDEInstInteractionAnalysisT
}
}
if (isZeroValue(SrcNode) && SRetParams.count(DestNode)) {
return IIAAAddLabelsEFCache.createEdgeFunction();
return IIAAKillOrReplaceEFCache.createEdgeFunction();
}
// Everything else can be passed as identity.
return EdgeIdentity<l_t>{};
Expand Down Expand Up @@ -863,14 +867,8 @@ class IDEInstInteractionAnalysisT
if (const auto *CD =
llvm::dyn_cast<llvm::ConstantData>(Ret->getReturnValue())) {
// Check if the user has registered a fact generator function
l_t UserEdgeFacts = BitVectorSet<e_t>();
std::set<e_t> EdgeFacts;
if (EdgeFactGen) {
EdgeFacts = EdgeFactGen(ExitInst);
// fill BitVectorSet
UserEdgeFacts = BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
}
return IIAAAddLabelsEFCache.createEdgeFunction(
l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, ExitInst));
return IIAAKillOrReplaceEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
}
Expand All @@ -883,34 +881,29 @@ class IDEInstInteractionAnalysisT
d_t RetSiteNode,
llvm::ArrayRef<f_t> Callees) override {
// Check if the user has registered a fact generator function
l_t UserEdgeFacts = BitVectorSet<e_t>();
std::set<e_t> EdgeFacts;
if (EdgeFactGen) {
EdgeFacts = EdgeFactGen(CallSite);
// fill BitVectorSet
UserEdgeFacts = BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
}
l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, CallSite));

// Model call to heap allocating functions (new, new[], malloc, etc.) --
// only model direct calls, though.
if (Callees.size() == 1) {
for (const auto *Callee : Callees) {
if (this->ICF->isHeapAllocatingFunction(Callee)) {
// Let H be a heap allocating function.
//
// 0 --> x
//
// Edge function:
//
// 0
// \
const auto *Callee = Callees.front();

if (this->ICF->isHeapAllocatingFunction(Callee)) {
// Let H be a heap allocating function.
//
// 0 --> x
//
// Edge function:
//
// 0
// \
// %i = call H \ \x.x \cup { commit of('%i = call H') }
// v
// i
//
if (isZeroValue(CallNode) && RetSiteNode == CallSite) {
return IIAAAddLabelsEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
// v
// i
//
if (isZeroValue(CallNode) && RetSiteNode == CallSite) {
return IIAAKillOrReplaceEFCache.createEdgeFunction(
std::move(UserEdgeFacts));
}
}
}
Expand Down Expand Up @@ -944,10 +937,6 @@ class IDEInstInteractionAnalysisT
return nullptr;
}

inline l_t topElement() override { return Top{}; }

inline l_t bottomElement() override { return Bottom{}; }

inline l_t join(l_t Lhs, l_t Rhs) override { return joinImpl(Lhs, Rhs); }

// Provide some handy helper edge functions to improve reuse.
Expand All @@ -956,7 +945,7 @@ class IDEInstInteractionAnalysisT
// others).
struct IIAAKillOrReplaceEF {
using l_t = typename AnalysisDomainTy::l_t;
l_t Replacement{};
l_t Replacement = BitVectorSet<e_t>();

l_t computeTarget(ByConstRef<l_t> /* Src */) const { return Replacement; }

Expand All @@ -972,27 +961,13 @@ class IDEInstInteractionAnalysisT
"IIAAKillOrReplaceEF is too large for SOO");

if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(SecondFunction)) {
auto ADCache =
SecondFunction.template getCacheOrNull<IIAAAddLabelsEF>();
assert(ADCache != nullptr);
if (This->isKillAll()) {
return ADCache->createEdgeFunction(*AD);
}
auto Union =
IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data);
return ADCache->createEdgeFunction(std::move(Union));
return Cache->createEdgeFunction(std::move(Union));
}

if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
if (This->isKillAll()) {
return Cache->createEdgeFunction(*KR);
}
if (KR->isKillAll()) {
return SecondFunction;
}
auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement,
KR->Replacement);
return Cache->createEdgeFunction(std::move(Union));
return SecondFunction;
}
llvm::report_fatal_error(
"found unexpected edge function in 'IIAAKillOrReplaceEF'");
Expand Down Expand Up @@ -1033,6 +1008,8 @@ class IDEInstInteractionAnalysisT
return Replacement == Other.Replacement;
}

[[nodiscard]] bool isConstant() const noexcept { return true; }

friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const IIAAKillOrReplaceEF &EF) {
OS << "EF: (IIAAKillOrReplaceEF)<->";
Expand Down Expand Up @@ -1061,7 +1038,7 @@ class IDEInstInteractionAnalysisT
// add all labels provided by Data.
struct IIAAAddLabelsEF {
using l_t = typename AnalysisDomainTy::l_t;
l_t Data{};
l_t Data = BitVectorSet<e_t>();

l_t computeTarget(ByConstRef<l_t> Src) const {
return IDEInstInteractionAnalysisT::joinImpl(Src, Data);
Expand All @@ -1083,7 +1060,7 @@ class IDEInstInteractionAnalysisT
return Cache->createEdgeFunction(std::move(Union));
}
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
return Cache->createEdgeFunction(KR->Replacement);
return SecondFunction;
}
llvm::report_fatal_error(
"found unexpected edge function in 'IIAAAddLabelsEF'");
Expand Down Expand Up @@ -1214,9 +1191,8 @@ class IDEInstInteractionAnalysisT
}

protected:
static inline bool isZeroValueImpl(d_t d) {
return LLVMZeroValue::isLLVMZeroValue(d);
}
// NOLINTNEXTLINE(readability-identifier-naming)
static constexpr auto isZeroValueImpl = LLVMZeroValue::isLLVMZeroValue;

static void printEdgeFactImpl(llvm::raw_ostream &OS,
ByConstRef<l_t> EdgeFact) {
Expand Down Expand Up @@ -1244,10 +1220,10 @@ class IDEInstInteractionAnalysisT
}

static inline l_t joinImpl(ByConstRef<l_t> Lhs, ByConstRef<l_t> Rhs) {
if (Lhs.isTop() || Lhs.isBottom()) {
if (Lhs.isTop() || Rhs.isBottom()) {
return Rhs;
}
if (Rhs.isTop() || Rhs.isBottom()) {
if (Rhs.isTop() || Lhs.isBottom()) {
return Lhs;
}
const auto &LhsSet = std::get<BitVectorSet<e_t>>(Lhs);
Expand All @@ -1270,7 +1246,7 @@ class IDEInstInteractionAnalysisT
// at some point. Therefore, we only care for the variables and their
// associated values and ignore at which point a variable may holds as a
// data-flow fact.
const auto Variable = Result.getColumnKey();
const auto &Variable = Result.getColumnKey();
const auto &Value = Result.getValue();
// skip result entry if variable is not in the set of all variables
if (Variables.find(Variable) == Variables.end()) {
Expand Down

0 comments on commit a56fc58

Please sign in to comment.