Skip to content

Commit a47f136

Browse files
committed
Add comparison cache to avoid repeating checks between varnodes
1 parent 346b160 commit a47f136

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

include/ppc2cpp/analysis/ProgramComparator.hpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,35 @@
11

22
#pragma once
33

4+
#include <functional>
5+
#include <unordered_map>
6+
47
#include "ppc2cpp/program_loader/ProgramLoader.hpp"
58
#include "ppc2cpp/model/Function.hpp"
69

710
namespace ppc2cpp {
11+
// Caches the result of comparison between varnodes
12+
class VarNodeComparisonCache {
13+
using NodePair = std::pair<VarNodePtr, VarNodePtr>;
14+
struct VarNodeCacheHash {
15+
std::size_t operator()(const NodePair& pair) const {
16+
return (std::hash<VarNode*>{}(pair.first.get())) ^ (std::hash<VarNode*>{}(pair.second.get()));
17+
}
18+
19+
};
20+
std::unordered_map<NodePair, bool, VarNodeCacheHash> _cache;
21+
22+
public:
23+
void set(VarNodePtr node1, VarNodePtr node2, bool equal) {
24+
_cache.insert_or_assign({node1, node2}, equal);
25+
}
26+
std::optional<bool> check(VarNodePtr node1, VarNodePtr node2) {
27+
if (_cache.contains({node1, node2})) {
28+
return _cache.at({node1, node2});
29+
} else return std::nullopt;
30+
}
31+
};
32+
833
class ProgramComparator {
934
public:
1035
ProgramLoaderPtr pLoader1;
@@ -23,6 +48,6 @@ class ProgramComparator {
2348
uint32_t* func1ptr;
2449
uint32_t* func2ptr;
2550

26-
bool compareVarNodes(const Function& func1, const Function& func2, const VarNodePtr& var1, const VarNodePtr& var2);
51+
bool compareVarNodes(const Function& func1, const Function& func2, const VarNodePtr& var1, const VarNodePtr& var2, VarNodeComparisonCache& comparisonCache);
2752
};
2853
}

src/analysis/ProgramComparator.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ namespace ppc2cpp {
2020
#pragma clang diagnostic push
2121
#pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
2222
#endif
23-
bool ProgramComparator::compareVarNodes(const Function& func1, const Function& func2, const VarNodePtr& var1, const VarNodePtr& var2) {
23+
bool ProgramComparator::compareVarNodes(const Function& func1, const Function& func2, const VarNodePtr& var1, const VarNodePtr& var2, VarNodeComparisonCache& comparisonCache) {
24+
auto cacheResult = comparisonCache.check(var1, var2);
25+
if (cacheResult.has_value()) return cacheResult.value();
26+
2427
ppc_cpu_t dialect = ppc_750cl_dialect;
2528

2629
if (!dynamic_pointer_cast<DataFlowNode>(var1) || !dynamic_pointer_cast<DataFlowNode>(var2)) {
@@ -98,12 +101,13 @@ bool ProgramComparator::compareVarNodes(const Function& func1, const Function& f
98101
return false;
99102
}
100103

101-
if (!compareVarNodes(func1, func2, var1->inputs[inputIdx], var2->inputs[inputIdx])) {
104+
if (!compareVarNodes(func1, func2, var1->inputs[inputIdx], var2->inputs[inputIdx], comparisonCache)) {
105+
comparisonCache.set(var1, var2, false);
102106
#ifndef NDEBUG
103107
std::cout << "Nonmatching child at index " << inputIdx << std::endl;
104108
#endif
105109
return false;
106-
}
110+
} else comparisonCache.set(var1, var2, true);
107111
}
108112
if (var2->inputs.size() > var1->inputs.size()) {
109113
std::cout << "Expected existence of input " << var1->inputs.size() << " in first variable" << "\n";
@@ -138,6 +142,7 @@ bool ProgramComparator::compareFunctionFlows(const Function& func1, const Functi
138142

139143
// TODO: More helpful non-equivalence messages, and in the "order of occurence" as much as possible.
140144
// Maybe come up with a system where the types of differences are aggregates and reported in an organized manner
145+
VarNodeComparisonCache comparisonCache;
141146

142147
// basic block equivalence checking
143148
for (int bblockIdx = 0; bblockIdx < cfg1.blocks.size(); bblockIdx++) {
@@ -158,7 +163,8 @@ bool ProgramComparator::compareFunctionFlows(const Function& func1, const Functi
158163
const SinkNodePtr& sink1 = sinks1[sinkIdx];
159164
const SinkNodePtr& sink2 = sinks2[sinkIdx];
160165

161-
if (!compareVarNodes(func1, func2, sink1, sink2)) {
166+
if (!compareVarNodes(func1, func2, sink1, sink2, comparisonCache)) {
167+
comparisonCache.set(sink1, sink2, true);
162168
std::cout << "Sinks at index " + std::to_string(sinkIdx) + " of block " + std::to_string(bblockIdx) + " did not match" << "\n";
163169
return false;
164170
}

0 commit comments

Comments
 (0)