26
26
#include < libyul/optimiser/KnowledgeBase.h>
27
27
#include < libyul/optimiser/SSAValueTracker.h>
28
28
#include < libyul/optimiser/DataFlowAnalyzer.h>
29
+ #include < libyul/optimiser/NameDispenser.h>
30
+ #include < libyul/optimiser/CommonSubexpressionEliminator.h>
29
31
#include < libyul/backends/evm/EVMDialect.h>
30
32
31
33
#include < liblangutil/ErrorReporter.h>
@@ -44,20 +46,25 @@ class KnowledgeBaseTest
44
46
KnowledgeBase constructKnowledgeBase (string const & _source)
45
47
{
46
48
ErrorList errorList;
47
- shared_ptr<Object> object;
48
49
shared_ptr<AsmAnalysisInfo> analysisInfo;
49
- std::tie (object , analysisInfo) = yul::test::parse (_source, m_dialect, errorList);
50
- BOOST_REQUIRE (object && errorList.empty () && object ->code );
50
+ std::tie (m_object , analysisInfo) = yul::test::parse (_source, m_dialect, errorList);
51
+ BOOST_REQUIRE (m_object && errorList.empty () && m_object ->code );
51
52
52
- SSAValueTracker ssaValues;
53
- ssaValues (*object->code );
54
- for (auto const & [name, expression]: ssaValues.values ())
53
+ NameDispenser dispenser (m_dialect, *m_object->code );
54
+ std::set<YulString> reserved;
55
+ OptimiserStepContext context{m_dialect, dispenser, reserved, 0 };
56
+ CommonSubexpressionEliminator::run (context, *m_object->code );
57
+
58
+ m_ssaValues (*m_object->code );
59
+ for (auto const & [name, expression]: m_ssaValues.values ())
55
60
m_values[name].value = expression;
56
61
57
62
return KnowledgeBase (m_dialect, m_values);
58
63
}
59
64
60
65
EVMDialect m_dialect{EVMVersion{}, true };
66
+ shared_ptr<Object> m_object;
67
+ SSAValueTracker m_ssaValues;
61
68
map<YulString, AssignedValue> m_values;
62
69
};
63
70
@@ -75,10 +82,51 @@ BOOST_AUTO_TEST_CASE(basic)
75
82
})" );
76
83
77
84
BOOST_CHECK (!kb.knownToBeDifferent (" a" _yulstring, " b" _yulstring));
85
+ // This only works if the variable names are the same.
86
+ // It assumes that SSA+CSE+Simplifier actually replaces the variables.
87
+ BOOST_CHECK (!kb.knownToBeEqual (" a" _yulstring, " b" _yulstring));
88
+ BOOST_CHECK (!kb.valueIfKnownConstant (" a" _yulstring));
78
89
BOOST_CHECK (kb.valueIfKnownConstant (" zero" _yulstring) == u256 (0 ));
90
+ }
91
+
92
+ BOOST_AUTO_TEST_CASE (difference)
93
+ {
94
+ yul::KnowledgeBase kb = constructKnowledgeBase (R"( {
95
+ let a := calldataload(0)
96
+ let b := add(a, 200)
97
+ let c := add(a, 220)
98
+ let d := add(c, 12)
99
+ let e := sub(c, 12)
100
+ })" );
79
101
102
+ BOOST_CHECK (
103
+ kb.differenceIfKnownConstant (" c" _yulstring, " b" _yulstring) ==
104
+ u256 (20 )
105
+ );
106
+ BOOST_CHECK (
107
+ kb.differenceIfKnownConstant (" b" _yulstring, " c" _yulstring) ==
108
+ u256 (-20 )
109
+ );
110
+ BOOST_CHECK (!kb.knownToBeDifferentByAtLeast32 (" b" _yulstring, " c" _yulstring));
111
+ BOOST_CHECK (kb.knownToBeDifferentByAtLeast32 (" b" _yulstring, " d" _yulstring));
112
+ BOOST_CHECK (kb.knownToBeDifferentByAtLeast32 (" a" _yulstring, " b" _yulstring));
113
+ BOOST_CHECK (kb.knownToBeDifferentByAtLeast32 (" b" _yulstring, " a" _yulstring));
114
+
115
+ BOOST_CHECK (
116
+ kb.differenceIfKnownConstant (" e" _yulstring, " a" _yulstring) == u256 (208 )
117
+ );
118
+ BOOST_CHECK (
119
+ kb.differenceIfKnownConstant (" e" _yulstring, " b" _yulstring) == u256 (8 )
120
+ );
121
+ BOOST_CHECK (
122
+ kb.differenceIfKnownConstant (" a" _yulstring, " e" _yulstring) == u256 (-208 )
123
+ );
124
+ BOOST_CHECK (
125
+ kb.differenceIfKnownConstant (" b" _yulstring, " e" _yulstring) == u256 (-8 )
126
+ );
80
127
}
81
128
129
+
82
130
BOOST_AUTO_TEST_SUITE_END ()
83
131
84
132
}
0 commit comments