Skip to content

Commit 0c7b979

Browse files
authored
EF SemiRing in Problem (#722)
* Tie the EF semi-ring to the problem + integrate into solver * Incorporate combine and extend into IIA * minor * Fix IIA * apply review comment
1 parent 59f257a commit 0c7b979

File tree

6 files changed

+163
-114
lines changed

6 files changed

+163
-114
lines changed

include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,23 @@ defaultComposeOrNull(EdgeFunctionRef<ConcreteEF> This,
132132
return nullptr;
133133
}
134134

135+
template <typename L>
136+
EdgeFunction<L>
137+
defaultComposeOrNull(const EdgeFunction<L> &This,
138+
const EdgeFunction<L> &SecondFunction) noexcept {
139+
if (llvm::isa<EdgeIdentity<L>>(SecondFunction)) {
140+
return This;
141+
}
142+
if (SecondFunction.isConstant() || llvm::isa<AllTop<L>>(This) ||
143+
llvm::isa<EdgeIdentity<L>>(This)) {
144+
return SecondFunction;
145+
}
146+
if (llvm::isa<AllBottom<L>>(This)) {
147+
return This;
148+
}
149+
return nullptr;
150+
}
151+
135152
template <typename L> struct ConstantEdgeFunction {
136153
using l_t = L;
137154
using JLattice = JoinLatticeTraits<L>;
@@ -409,6 +426,26 @@ EdgeFunction<L> defaultJoinOrNull(EdgeFunctionRef<ConcreteEF> This,
409426
return nullptr;
410427
}
411428

429+
template <typename L, uint8_t N = 0>
430+
EdgeFunction<L> defaultJoinOrNull(const EdgeFunction<L> &This,
431+
const EdgeFunction<L> &OtherFunction) {
432+
if (llvm::isa<AllBottom<L>>(OtherFunction) || llvm::isa<AllTop<L>>(This)) {
433+
return OtherFunction;
434+
}
435+
if (llvm::isa<AllTop<L>>(OtherFunction) || OtherFunction == This ||
436+
llvm::isa<AllBottom<L>>(This)) {
437+
return This;
438+
}
439+
if (llvm::isa<EdgeIdentity<L>>(OtherFunction)) {
440+
if constexpr (N > 0) {
441+
return JoinEdgeFunction<L, N>::create(This, OtherFunction);
442+
} else if constexpr (HasJoinLatticeTraits<L>) {
443+
return AllBottom<L>{};
444+
}
445+
}
446+
return nullptr;
447+
}
448+
412449
template <typename L>
413450
EdgeFunction<L> EdgeIdentity<L>::join(EdgeFunctionRef<EdgeIdentity> This,
414451
const EdgeFunction<L> &OtherFunction) {

include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "phasar/Utils/JoinLattice.h"
2323
#include "phasar/Utils/NullAnalysisPrinter.h"
2424
#include "phasar/Utils/Printer.h"
25+
#include "phasar/Utils/SemiRing.h"
2526
#include "phasar/Utils/Soundness.h"
2627

2728
#include "llvm/ADT/StringRef.h"
@@ -62,6 +63,7 @@ template <typename AnalysisDomainTy,
6263
class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
6364
public EdgeFunctions<AnalysisDomainTy>,
6465
public JoinLattice<AnalysisDomainTy>,
66+
public SemiRing<AnalysisDomainTy>,
6567
public AllTopFnProvider<AnalysisDomainTy> {
6668
public:
6769
using ProblemAnalysisDomain = AnalysisDomainTy;

include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ class IDESolver
406406
PHASAR_LOG_LEVEL(DEBUG,
407407
"Compose: " << SumEdgFnE << " * " << f << '\n');
408408
WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)),
409-
f.composeWith(SumEdgFnE));
409+
IDEProblem.extend(f, SumEdgFnE));
410410
}
411411
}
412412
} else {
@@ -498,15 +498,15 @@ class IDESolver
498498
<< f4);
499499
PHASAR_LOG_LEVEL(DEBUG,
500500
" (return * calleeSummary * call)");
501-
EdgeFunction<l_t> fPrime =
502-
f4.composeWith(fCalleeSummary).composeWith(f5);
501+
EdgeFunction<l_t> fPrime = IDEProblem.extend(
502+
IDEProblem.extend(f4, fCalleeSummary), f5);
503503
PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime);
504504
d_t d5_restoredCtx = restoreContextOnReturnedFact(n, d2, d5);
505505
// propagte the effects of the entire call
506506
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f);
507507
WorkList.emplace_back(
508508
PathEdge(d1, RetSiteN, std::move(d5_restoredCtx)),
509-
f.composeWith(fPrime));
509+
IDEProblem.extend(f, fPrime));
510510
}
511511
}
512512
}
@@ -538,7 +538,7 @@ class IDESolver
538538
.push_back(EdgeFnE);
539539
}
540540
INC_COUNTER("EF Queries", 1, Full);
541-
auto fPrime = f.composeWith(EdgeFnE);
541+
auto fPrime = IDEProblem.extend(f, EdgeFnE);
542542
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << EdgeFnE << " * " << f << " = "
543543
<< fPrime);
544544
WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)),
@@ -570,7 +570,7 @@ class IDESolver
570570
EdgeFunction<l_t> g =
571571
CachedFlowEdgeFunctions.getNormalEdgeFunction(n, d2, nPrime, d3);
572572
PHASAR_LOG_LEVEL(DEBUG, "Queried Normal Edge Function: " << g);
573-
EdgeFunction<l_t> fPrime = f.composeWith(g);
573+
EdgeFunction<l_t> fPrime = IDEProblem.extend(f, g);
574574
if (SolverConfig.emitESG()) {
575575
IntermediateEdgeFunctions[std::make_tuple(n, d2, nPrime, d3)]
576576
.push_back(g);
@@ -950,7 +950,8 @@ class IDESolver
950950
PHASAR_LOG_LEVEL(DEBUG,
951951
"Compose: " << f5 << " * " << f << " * " << f4);
952952
PHASAR_LOG_LEVEL(DEBUG, " (return * function * call)");
953-
EdgeFunction<l_t> fPrime = f4.composeWith(f).composeWith(f5);
953+
EdgeFunction<l_t> fPrime =
954+
IDEProblem.extend(IDEProblem.extend(f4, f), f5);
954955
PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime);
955956
// for each jump function coming into the call, propagate to
956957
// return site using the composed function
@@ -965,7 +966,7 @@ class IDESolver
965966
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f3);
966967
WorkList.emplace_back(PathEdge(std::move(d3), RetSiteC,
967968
std::move(d5_restoredCtx)),
968-
f3.composeWith(fPrime));
969+
IDEProblem.extend(f3, fPrime));
969970
}
970971
}
971972
}
@@ -1004,7 +1005,7 @@ class IDESolver
10041005
}
10051006
INC_COUNTER("EF Queries", 1, Full);
10061007
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << f5 << " * " << f);
1007-
propagteUnbalancedReturnFlow(RetSiteC, d5, f.composeWith(f5),
1008+
propagteUnbalancedReturnFlow(RetSiteC, d5, IDEProblem.extend(f, f5),
10081009
Caller);
10091010
// register for value processing (2nd IDE phase)
10101011
UnbalancedRetSites.insert(RetSiteC);
@@ -1153,7 +1154,7 @@ class IDESolver
11531154
// was found
11541155
return AllTop;
11551156
}();
1156-
EdgeFunction<l_t> fPrime = JumpFnE.joinWith(f);
1157+
EdgeFunction<l_t> fPrime = IDEProblem.combine(JumpFnE, f);
11571158
bool NewFunction = fPrime != JumpFnE;
11581159

11591160
IF_LOG_LEVEL_ENABLED(DEBUG, {

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

Lines changed: 74 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDEINSTINTERACTIONANALYSIS_H
1212

1313
#include "phasar/DataFlow/IfdsIde/DefaultEdgeFunctionSingletonCache.h"
14+
#include "phasar/DataFlow/IfdsIde/EdgeFunction.h"
1415
#include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h"
1516
#include "phasar/DataFlow/IfdsIde/FlowFunctions.h"
1617
#include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h"
@@ -949,59 +950,15 @@ class IDEInstInteractionAnalysisT
949950

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

952-
static EdgeFunction<l_t> compose(EdgeFunctionRef<IIAAKillOrReplaceEF> This,
953-
const EdgeFunction<l_t> SecondFunction) {
954-
955-
if (auto Default = defaultComposeOrNull(This, SecondFunction)) {
956-
return Default;
957-
}
958-
959-
auto Cache = This.getCacheOrNull();
960-
assert(Cache != nullptr && "We expect a cache, because "
961-
"IIAAKillOrReplaceEF is too large for SOO");
962-
963-
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(SecondFunction)) {
964-
auto Union =
965-
IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data);
966-
return Cache->createEdgeFunction(std::move(Union));
967-
}
968-
969-
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
970-
return SecondFunction;
971-
}
972-
llvm::report_fatal_error(
973-
"found unexpected edge function in 'IIAAKillOrReplaceEF'");
953+
static EdgeFunction<l_t>
954+
compose(EdgeFunctionRef<IIAAKillOrReplaceEF> /*This*/,
955+
const EdgeFunction<l_t> /*SecondFunction*/) {
956+
llvm::report_fatal_error("Implemented in 'extend'");
974957
}
975958

976-
static EdgeFunction<l_t> join(EdgeFunctionRef<IIAAKillOrReplaceEF> This,
977-
const EdgeFunction<l_t> &OtherFunction) {
978-
/// XXX: Here, we underapproximate joins with EdgeIdentity
979-
if (llvm::isa<EdgeIdentity<l_t>>(OtherFunction)) {
980-
return This;
981-
}
982-
983-
if (auto Default = defaultJoinOrNull(This, OtherFunction)) {
984-
return Default;
985-
}
986-
987-
auto Cache = This.getCacheOrNull();
988-
assert(Cache != nullptr && "We expect a cache, because "
989-
"IIAAKillOrReplaceEF is too large for SOO");
990-
991-
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(OtherFunction)) {
992-
auto ADCache = OtherFunction.template getCacheOrNull<IIAAAddLabelsEF>();
993-
assert(ADCache);
994-
auto Union =
995-
IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data);
996-
return ADCache->createEdgeFunction(std::move(Union));
997-
}
998-
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(OtherFunction)) {
999-
auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement,
1000-
KR->Replacement);
1001-
return Cache->createEdgeFunction(std::move(Union));
1002-
}
1003-
llvm::report_fatal_error(
1004-
"found unexpected edge function in 'IIAAKillOrReplaceEF'");
959+
static EdgeFunction<l_t> join(EdgeFunctionRef<IIAAKillOrReplaceEF> /*This*/,
960+
const EdgeFunction<l_t> & /*OtherFunction*/) {
961+
llvm::report_fatal_error("Implemented in 'combine'");
1005962
}
1006963

1007964
bool operator==(const IIAAKillOrReplaceEF &Other) const noexcept {
@@ -1044,55 +1001,15 @@ class IDEInstInteractionAnalysisT
10441001
return IDEInstInteractionAnalysisT::joinImpl(Src, Data);
10451002
}
10461003

1047-
static EdgeFunction<l_t> compose(EdgeFunctionRef<IIAAAddLabelsEF> This,
1048-
const EdgeFunction<l_t> &SecondFunction) {
1049-
if (auto Default = defaultComposeOrNull(This, SecondFunction)) {
1050-
return Default;
1051-
}
1052-
1053-
auto Cache = This.getCacheOrNull();
1054-
assert(Cache != nullptr && "We expect a cache, because "
1055-
"IIAAAddLabelsEF is too large for SOO");
1056-
1057-
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(SecondFunction)) {
1058-
auto Union =
1059-
IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data);
1060-
return Cache->createEdgeFunction(std::move(Union));
1061-
}
1062-
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(SecondFunction)) {
1063-
return SecondFunction;
1064-
}
1065-
llvm::report_fatal_error(
1066-
"found unexpected edge function in 'IIAAAddLabelsEF'");
1004+
static EdgeFunction<l_t>
1005+
compose(EdgeFunctionRef<IIAAAddLabelsEF> /*This*/,
1006+
const EdgeFunction<l_t> & /*SecondFunction*/) {
1007+
llvm::report_fatal_error("Implemented in 'extend'");
10671008
}
10681009

1069-
static EdgeFunction<l_t> join(EdgeFunctionRef<IIAAAddLabelsEF> This,
1070-
const EdgeFunction<l_t> &OtherFunction) {
1071-
/// XXX: Here, we underapproximate joins with EdgeIdentity
1072-
if (llvm::isa<EdgeIdentity<l_t>>(OtherFunction)) {
1073-
return This;
1074-
}
1075-
1076-
if (auto Default = defaultJoinOrNull(This, OtherFunction)) {
1077-
return Default;
1078-
}
1079-
1080-
auto Cache = This.getCacheOrNull();
1081-
assert(Cache != nullptr && "We expect a cache, because "
1082-
"IIAAAddLabelsEF is too large for SOO");
1083-
1084-
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(OtherFunction)) {
1085-
auto Union =
1086-
IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data);
1087-
return Cache->createEdgeFunction(std::move(Union));
1088-
}
1089-
if (auto *KR = llvm::dyn_cast<IIAAKillOrReplaceEF>(OtherFunction)) {
1090-
auto Union =
1091-
IDEInstInteractionAnalysisT::joinImpl(This->Data, KR->Replacement);
1092-
return Cache->createEdgeFunction(std::move(Union));
1093-
}
1094-
llvm::report_fatal_error(
1095-
"found unexpected edge function in 'IIAAAddLabelsEF'");
1010+
static EdgeFunction<l_t> join(EdgeFunctionRef<IIAAAddLabelsEF> /*This*/,
1011+
const EdgeFunction<l_t> & /*OtherFunction*/) {
1012+
llvm::report_fatal_error("Implemented in 'combine'");
10961013
}
10971014

10981015
bool operator==(const IIAAAddLabelsEF &Other) const noexcept {
@@ -1112,6 +1029,64 @@ class IDEInstInteractionAnalysisT
11121029
}
11131030
};
11141031

1032+
const auto &getData(const EdgeFunction<l_t> &EF) {
1033+
if (const auto *AddLabels = llvm::dyn_cast<IIAAAddLabelsEF>(EF)) {
1034+
return AddLabels->Data;
1035+
}
1036+
if (const auto *KillOrReplace = llvm::dyn_cast<IIAAKillOrReplaceEF>(EF)) {
1037+
return KillOrReplace->Replacement;
1038+
}
1039+
llvm::report_fatal_error(
1040+
"found unexpected first edge function in 'getData': " +
1041+
llvm::Twine(to_string(EF)));
1042+
}
1043+
1044+
EdgeFunction<l_t> extend(const EdgeFunction<l_t> &FirstFunction,
1045+
const EdgeFunction<l_t> &SecondFunction) override {
1046+
if (auto Default = defaultComposeOrNull(FirstFunction, SecondFunction)) {
1047+
return Default;
1048+
}
1049+
1050+
const auto &ThisData = getData(FirstFunction);
1051+
1052+
if (auto *AD = llvm::dyn_cast<IIAAAddLabelsEF>(SecondFunction)) {
1053+
auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, AD->Data);
1054+
return llvm::isa<IIAAAddLabelsEF>(FirstFunction)
1055+
? IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union))
1056+
: IIAAKillOrReplaceEFCache.createEdgeFunction(
1057+
std::move(Union));
1058+
}
1059+
1060+
llvm::report_fatal_error(
1061+
"found unexpected second edge function in 'extend'");
1062+
}
1063+
1064+
EdgeFunction<l_t> combine(const EdgeFunction<l_t> &FirstFunction,
1065+
const EdgeFunction<l_t> &OtherFunction) override {
1066+
/// XXX: Here, we underapproximate joins with EdgeIdentity
1067+
if (llvm::isa<EdgeIdentity<l_t>>(FirstFunction)) {
1068+
return OtherFunction;
1069+
}
1070+
if (llvm::isa<EdgeIdentity<l_t>>(OtherFunction) &&
1071+
!llvm::isa<AllTop<l_t>>(FirstFunction)) {
1072+
return FirstFunction;
1073+
}
1074+
1075+
if (auto Default = defaultJoinOrNull(FirstFunction, OtherFunction)) {
1076+
return Default;
1077+
}
1078+
1079+
const auto &ThisData = getData(FirstFunction);
1080+
const auto &OtherData = getData(OtherFunction);
1081+
auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, OtherData);
1082+
1083+
if (llvm::isa<IIAAKillOrReplaceEF>(FirstFunction) &&
1084+
llvm::isa<IIAAKillOrReplaceEF>(OtherFunction)) {
1085+
return IIAAKillOrReplaceEFCache.createEdgeFunction(std::move(Union));
1086+
}
1087+
return IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union));
1088+
}
1089+
11151090
// Provide functionalities for printing things and emitting text reports.
11161091

11171092
static void stripBottomResults(std::unordered_map<d_t, l_t> &Res) {
@@ -1173,7 +1148,7 @@ class IDEInstInteractionAnalysisT
11731148
}
11741149
if (const auto *H = llvm::dyn_cast<llvm::CallBase>(I)) {
11751150
if (!H->isIndirectCall() && H->getCalledFunction() &&
1176-
this->ICF->isHeapAllocatingFunction(H->getCalledFunction())) {
1151+
psr::isHeapAllocatingFunction(H->getCalledFunction())) {
11771152
Variables.insert(H);
11781153
}
11791154
}

include/phasar/Utils/BitVectorSet.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ template <typename T> class BitVectorSet {
177177
}
178178

179179
[[nodiscard]] BitVectorSet<T> setUnion(const BitVectorSet<T> &Other) const {
180-
size_t MaxSize = std::max(Bits.size(), Other.Bits.size());
181-
BitVectorSet<T> Res;
182-
Res.Bits.reserve(MaxSize);
183-
Res.Bits = Bits;
184-
Res.Bits |= Other.Bits;
180+
const bool ThisSetIsSmaller = Bits.size() < Other.Bits.size();
181+
BitVectorSet<T> Res = ThisSetIsSmaller ? Other : *this;
182+
const BitVectorSet &Smaller = ThisSetIsSmaller ? *this : Other;
183+
184+
Res.Bits |= Smaller.Bits;
185185
return Res;
186186
}
187187

0 commit comments

Comments
 (0)