Skip to content

Commit a56fc58

Browse files
fabianbs96MMory
andauthored
Fix IIA Edge Functions (#700)
* Fix joinImpl + IIAAKillOrReplaceEF in IIA * minor --------- Co-authored-by: Martin Mory <mmo@mail.upb.de>
1 parent fec44a5 commit a56fc58

1 file changed

Lines changed: 53 additions & 77 deletions

File tree

include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h

Lines changed: 53 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "phasar/Utils/Logger.h"
3131

3232
#include "llvm/ADT/SmallVector.h"
33+
#include "llvm/ADT/Twine.h"
3334
#include "llvm/IR/Argument.h"
3435
#include "llvm/IR/Attributes.h"
3536
#include "llvm/IR/Constant.h"
@@ -629,26 +630,19 @@ class IDEInstInteractionAnalysisT
629630
// variables using generalized initial seeds
630631

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

641642
for (const auto &G : this->IRDB->getModule()->globals()) {
642643
if (const auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(&G)) {
643-
l_t InitialValues = BitVectorSet<e_t>();
644-
std::set<e_t> EdgeFacts;
645-
if (EdgeFactGen) {
646-
EdgeFacts = EdgeFactGen(GV);
647-
// fill BitVectorSet
648-
InitialValues =
649-
BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
650-
}
651-
Seeds.addSeed(SP, GV, InitialValues);
644+
l_t InitialValues = bvSetFrom(invoke_or_default(EdgeFactGen, GV));
645+
Seeds.addSeed(SP, GV, std::move(InitialValues));
652646
}
653647
}
654648
});
@@ -691,7 +685,12 @@ class IDEInstInteractionAnalysisT
691685
if (SuccNode == Store->getPointerOperand() ||
692686
PT.isInReachableAllocationSites(Store->getPointerOperand(), SuccNode,
693687
true, Store)) {
694-
return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts);
688+
if (isZeroValue(CurrNode)) {
689+
return IIAAKillOrReplaceEFCache.createEdgeFunction(
690+
std::move(UserEdgeFacts));
691+
}
692+
return IIAAAddLabelsEFCache.createEdgeFunction(
693+
std::move(UserEdgeFacts));
695694
}
696695
}
697696

@@ -709,7 +708,7 @@ class IDEInstInteractionAnalysisT
709708
// v
710709
// y
711710
//
712-
if ((CurrNode == SuccNode) && CurrNode == Store->getPointerOperand()) {
711+
if (CurrNode == SuccNode && CurrNode == Store->getPointerOperand()) {
713712
// y obtains its value(s) from its original allocation and the store
714713
// instruction under analysis.
715714
IF_LOG_ENABLED({
@@ -722,7 +721,8 @@ class IDEInstInteractionAnalysisT
722721
PHASAR_LOG_LEVEL(DFADEBUG, '\n');
723722
});
724723
// obtain label from the original allocation
725-
return IIAAKillOrReplaceEFCache.createEdgeFunction(UserEdgeFacts);
724+
return IIAAKillOrReplaceEFCache.createEdgeFunction(
725+
std::move(UserEdgeFacts));
726726
}
727727

728728
} else {
@@ -800,7 +800,11 @@ class IDEInstInteractionAnalysisT
800800

801801
// We generate Curr in this instruction, so we have to annotate it with
802802
// edge labels
803-
return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts);
803+
if (isZeroValue(CurrNode)) {
804+
return IIAAKillOrReplaceEFCache.createEdgeFunction(
805+
std::move(UserEdgeFacts));
806+
}
807+
return IIAAAddLabelsEFCache.createEdgeFunction(std::move(UserEdgeFacts));
804808
}
805809

806810
// Otherwise stick to identity.
@@ -835,7 +839,7 @@ class IDEInstInteractionAnalysisT
835839
}
836840
}
837841
if (isZeroValue(SrcNode) && SRetParams.count(DestNode)) {
838-
return IIAAAddLabelsEFCache.createEdgeFunction();
842+
return IIAAKillOrReplaceEFCache.createEdgeFunction();
839843
}
840844
// Everything else can be passed as identity.
841845
return EdgeIdentity<l_t>{};
@@ -863,14 +867,8 @@ class IDEInstInteractionAnalysisT
863867
if (const auto *CD =
864868
llvm::dyn_cast<llvm::ConstantData>(Ret->getReturnValue())) {
865869
// Check if the user has registered a fact generator function
866-
l_t UserEdgeFacts = BitVectorSet<e_t>();
867-
std::set<e_t> EdgeFacts;
868-
if (EdgeFactGen) {
869-
EdgeFacts = EdgeFactGen(ExitInst);
870-
// fill BitVectorSet
871-
UserEdgeFacts = BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
872-
}
873-
return IIAAAddLabelsEFCache.createEdgeFunction(
870+
l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, ExitInst));
871+
return IIAAKillOrReplaceEFCache.createEdgeFunction(
874872
std::move(UserEdgeFacts));
875873
}
876874
}
@@ -883,34 +881,29 @@ class IDEInstInteractionAnalysisT
883881
d_t RetSiteNode,
884882
llvm::ArrayRef<f_t> Callees) override {
885883
// Check if the user has registered a fact generator function
886-
l_t UserEdgeFacts = BitVectorSet<e_t>();
887-
std::set<e_t> EdgeFacts;
888-
if (EdgeFactGen) {
889-
EdgeFacts = EdgeFactGen(CallSite);
890-
// fill BitVectorSet
891-
UserEdgeFacts = BitVectorSet<e_t>(EdgeFacts.begin(), EdgeFacts.end());
892-
}
884+
l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, CallSite));
885+
893886
// Model call to heap allocating functions (new, new[], malloc, etc.) --
894887
// only model direct calls, though.
895888
if (Callees.size() == 1) {
896-
for (const auto *Callee : Callees) {
897-
if (this->ICF->isHeapAllocatingFunction(Callee)) {
898-
// Let H be a heap allocating function.
899-
//
900-
// 0 --> x
901-
//
902-
// Edge function:
903-
//
904-
// 0
905-
// \
889+
const auto *Callee = Callees.front();
890+
891+
if (this->ICF->isHeapAllocatingFunction(Callee)) {
892+
// Let H be a heap allocating function.
893+
//
894+
// 0 --> x
895+
//
896+
// Edge function:
897+
//
898+
// 0
899+
// \
906900
// %i = call H \ \x.x \cup { commit of('%i = call H') }
907-
// v
908-
// i
909-
//
910-
if (isZeroValue(CallNode) && RetSiteNode == CallSite) {
911-
return IIAAAddLabelsEFCache.createEdgeFunction(
912-
std::move(UserEdgeFacts));
913-
}
901+
// v
902+
// i
903+
//
904+
if (isZeroValue(CallNode) && RetSiteNode == CallSite) {
905+
return IIAAKillOrReplaceEFCache.createEdgeFunction(
906+
std::move(UserEdgeFacts));
914907
}
915908
}
916909
}
@@ -944,10 +937,6 @@ class IDEInstInteractionAnalysisT
944937
return nullptr;
945938
}
946939

947-
inline l_t topElement() override { return Top{}; }
948-
949-
inline l_t bottomElement() override { return Bottom{}; }
950-
951940
inline l_t join(l_t Lhs, l_t Rhs) override { return joinImpl(Lhs, Rhs); }
952941

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

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

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

974963
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(SecondFunction)) {
975-
auto ADCache =
976-
SecondFunction.template getCacheOrNull<IIAAAddLabelsEF>();
977-
assert(ADCache != nullptr);
978-
if (This->isKillAll()) {
979-
return ADCache->createEdgeFunction(*AD);
980-
}
981964
auto Union =
982965
IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data);
983-
return ADCache->createEdgeFunction(std::move(Union));
966+
return Cache->createEdgeFunction(std::move(Union));
984967
}
985968

986969
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
987-
if (This->isKillAll()) {
988-
return Cache->createEdgeFunction(*KR);
989-
}
990-
if (KR->isKillAll()) {
991-
return SecondFunction;
992-
}
993-
auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement,
994-
KR->Replacement);
995-
return Cache->createEdgeFunction(std::move(Union));
970+
return SecondFunction;
996971
}
997972
llvm::report_fatal_error(
998973
"found unexpected edge function in 'IIAAKillOrReplaceEF'");
@@ -1033,6 +1008,8 @@ class IDEInstInteractionAnalysisT
10331008
return Replacement == Other.Replacement;
10341009
}
10351010

1011+
[[nodiscard]] bool isConstant() const noexcept { return true; }
1012+
10361013
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
10371014
const IIAAKillOrReplaceEF &EF) {
10381015
OS << "EF: (IIAAKillOrReplaceEF)<->";
@@ -1061,7 +1038,7 @@ class IDEInstInteractionAnalysisT
10611038
// add all labels provided by Data.
10621039
struct IIAAAddLabelsEF {
10631040
using l_t = typename AnalysisDomainTy::l_t;
1064-
l_t Data{};
1041+
l_t Data = BitVectorSet<e_t>();
10651042

10661043
l_t computeTarget(ByConstRef<l_t> Src) const {
10671044
return IDEInstInteractionAnalysisT::joinImpl(Src, Data);
@@ -1083,7 +1060,7 @@ class IDEInstInteractionAnalysisT
10831060
return Cache->createEdgeFunction(std::move(Union));
10841061
}
10851062
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
1086-
return Cache->createEdgeFunction(KR->Replacement);
1063+
return SecondFunction;
10871064
}
10881065
llvm::report_fatal_error(
10891066
"found unexpected edge function in 'IIAAAddLabelsEF'");
@@ -1214,9 +1191,8 @@ class IDEInstInteractionAnalysisT
12141191
}
12151192

12161193
protected:
1217-
static inline bool isZeroValueImpl(d_t d) {
1218-
return LLVMZeroValue::isLLVMZeroValue(d);
1219-
}
1194+
// NOLINTNEXTLINE(readability-identifier-naming)
1195+
static constexpr auto isZeroValueImpl = LLVMZeroValue::isLLVMZeroValue;
12201196

12211197
static void printEdgeFactImpl(llvm::raw_ostream &OS,
12221198
ByConstRef<l_t> EdgeFact) {
@@ -1244,10 +1220,10 @@ class IDEInstInteractionAnalysisT
12441220
}
12451221

12461222
static inline l_t joinImpl(ByConstRef<l_t> Lhs, ByConstRef<l_t> Rhs) {
1247-
if (Lhs.isTop() || Lhs.isBottom()) {
1223+
if (Lhs.isTop() || Rhs.isBottom()) {
12481224
return Rhs;
12491225
}
1250-
if (Rhs.isTop() || Rhs.isBottom()) {
1226+
if (Rhs.isTop() || Lhs.isBottom()) {
12511227
return Lhs;
12521228
}
12531229
const auto &LhsSet = std::get<BitVectorSet<e_t>>(Lhs);
@@ -1270,7 +1246,7 @@ class IDEInstInteractionAnalysisT
12701246
// at some point. Therefore, we only care for the variables and their
12711247
// associated values and ignore at which point a variable may holds as a
12721248
// data-flow fact.
1273-
const auto Variable = Result.getColumnKey();
1249+
const auto &Variable = Result.getColumnKey();
12741250
const auto &Value = Result.getValue();
12751251
// skip result entry if variable is not in the set of all variables
12761252
if (Variables.find(Variable) == Variables.end()) {

0 commit comments

Comments
 (0)