Skip to content

Commit 643140e

Browse files
authored
Merge pull request #11349 from ethereum/create-solver-class-from-reasoning-based-simplifier
Create solver class from reasoning based simplifier
2 parents 58bec9f + 39b2342 commit 643140e

File tree

5 files changed

+271
-146
lines changed

5 files changed

+271
-146
lines changed

libyul/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ add_library(yul
166166
optimiser/RedundantAssignEliminator.h
167167
optimiser/Rematerialiser.cpp
168168
optimiser/Rematerialiser.h
169+
optimiser/SMTSolver.cpp
170+
optimiser/SMTSolver.h
169171
optimiser/SSAReverser.cpp
170172
optimiser/SSAReverser.h
171173
optimiser/SSATransform.cpp

libyul/optimiser/ReasoningBasedSimplifier.cpp

Lines changed: 13 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
*/
1717

1818
#include <libyul/optimiser/ReasoningBasedSimplifier.h>
19+
#include <libyul/optimiser/SMTSolver.h>
1920

20-
#include <libyul/optimiser/OptimizerUtilities.h>
2121
#include <libyul/optimiser/SSAValueTracker.h>
2222
#include <libyul/optimiser/Semantics.h>
2323
#include <libyul/AST.h>
@@ -56,14 +56,7 @@ std::optional<string> ReasoningBasedSimplifier::invalidInCurrentEnvironment()
5656

5757
void ReasoningBasedSimplifier::operator()(VariableDeclaration& _varDecl)
5858
{
59-
if (_varDecl.variables.size() != 1 || !_varDecl.value)
60-
return;
61-
YulString varName = _varDecl.variables.front().name;
62-
if (!m_ssaVariables.count(varName))
63-
return;
64-
bool const inserted = m_variables.insert({varName, m_solver->newVariable("yul_" + varName.str(), defaultSort())}).second;
65-
yulAssert(inserted, "");
66-
m_solver->addAssertion(m_variables.at(varName) == encodeExpression(*_varDecl.value));
59+
SMTSolver::encodeVariableDeclaration(_varDecl);
6760
}
6861

6962
void ReasoningBasedSimplifier::operator()(If& _if)
@@ -111,37 +104,11 @@ ReasoningBasedSimplifier::ReasoningBasedSimplifier(
111104
Dialect const& _dialect,
112105
set<YulString> const& _ssaVariables
113106
):
114-
m_dialect(_dialect),
115-
m_ssaVariables(_ssaVariables),
116-
m_solver(make_unique<smtutil::SMTPortfolio>())
107+
SMTSolver(_ssaVariables, _dialect),
108+
m_dialect(_dialect)
117109
{
118110
}
119111

120-
smtutil::Expression ReasoningBasedSimplifier::encodeExpression(yul::Expression const& _expression)
121-
{
122-
return std::visit(GenericVisitor{
123-
[&](FunctionCall const& _functionCall)
124-
{
125-
if (auto instruction = toEVMInstruction(m_dialect, _functionCall.functionName.name))
126-
return encodeEVMBuiltin(*instruction, _functionCall.arguments);
127-
return newRestrictedVariable();
128-
},
129-
[&](Identifier const& _identifier)
130-
{
131-
if (
132-
m_ssaVariables.count(_identifier.name) &&
133-
m_variables.count(_identifier.name)
134-
)
135-
return m_variables.at(_identifier.name);
136-
else
137-
return newRestrictedVariable();
138-
},
139-
[&](Literal const& _literal)
140-
{
141-
return literalValue(_literal);
142-
}
143-
}, _expression);
144-
}
145112

146113
smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
147114
evmasm::Instruction _instruction,
@@ -172,10 +139,10 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
172139
constantValue(0),
173140
// No `wrap()` needed here, because -2**255 / -1 results
174141
// in 2**255 which is "converted" to its two's complement
175-
// representation 2**255 in `signedToUnsigned`
176-
signedToUnsigned(smtutil::signedDivisionEVM(
177-
unsignedToSigned(arguments.at(0)),
178-
unsignedToSigned(arguments.at(1))
142+
// representation 2**255 in `signedToTwosComplement`
143+
signedToTwosComplement(smtutil::signedDivisionEVM(
144+
twosComplementToSigned(arguments.at(0)),
145+
twosComplementToSigned(arguments.at(1))
179146
))
180147
);
181148
case evmasm::Instruction::MOD:
@@ -188,19 +155,19 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
188155
return smtutil::Expression::ite(
189156
arguments.at(1) == constantValue(0),
190157
constantValue(0),
191-
signedToUnsigned(signedModuloEVM(
192-
unsignedToSigned(arguments.at(0)),
193-
unsignedToSigned(arguments.at(1))
158+
signedToTwosComplement(signedModuloEVM(
159+
twosComplementToSigned(arguments.at(0)),
160+
twosComplementToSigned(arguments.at(1))
194161
))
195162
);
196163
case evmasm::Instruction::LT:
197164
return booleanValue(arguments.at(0) < arguments.at(1));
198165
case evmasm::Instruction::SLT:
199-
return booleanValue(unsignedToSigned(arguments.at(0)) < unsignedToSigned(arguments.at(1)));
166+
return booleanValue(twosComplementToSigned(arguments.at(0)) < twosComplementToSigned(arguments.at(1)));
200167
case evmasm::Instruction::GT:
201168
return booleanValue(arguments.at(0) > arguments.at(1));
202169
case evmasm::Instruction::SGT:
203-
return booleanValue(unsignedToSigned(arguments.at(0)) > unsignedToSigned(arguments.at(1)));
170+
return booleanValue(twosComplementToSigned(arguments.at(0)) > twosComplementToSigned(arguments.at(1)));
204171
case evmasm::Instruction::EQ:
205172
return booleanValue(arguments.at(0) == arguments.at(1));
206173
case evmasm::Instruction::ISZERO:
@@ -259,76 +226,3 @@ smtutil::Expression ReasoningBasedSimplifier::encodeEVMBuiltin(
259226
}
260227
return newRestrictedVariable();
261228
}
262-
263-
smtutil::Expression ReasoningBasedSimplifier::int2bv(smtutil::Expression _arg) const
264-
{
265-
return smtutil::Expression::int2bv(std::move(_arg), 256);
266-
}
267-
268-
smtutil::Expression ReasoningBasedSimplifier::bv2int(smtutil::Expression _arg) const
269-
{
270-
return smtutil::Expression::bv2int(std::move(_arg));
271-
}
272-
273-
smtutil::Expression ReasoningBasedSimplifier::newVariable()
274-
{
275-
return m_solver->newVariable(uniqueName(), defaultSort());
276-
}
277-
278-
smtutil::Expression ReasoningBasedSimplifier::newRestrictedVariable()
279-
{
280-
smtutil::Expression var = newVariable();
281-
m_solver->addAssertion(0 <= var && var < smtutil::Expression(bigint(1) << 256));
282-
return var;
283-
}
284-
285-
string ReasoningBasedSimplifier::uniqueName()
286-
{
287-
return "expr_" + to_string(m_varCounter++);
288-
}
289-
290-
shared_ptr<Sort> ReasoningBasedSimplifier::defaultSort() const
291-
{
292-
return SortProvider::intSort();
293-
}
294-
295-
smtutil::Expression ReasoningBasedSimplifier::booleanValue(smtutil::Expression _value) const
296-
{
297-
return smtutil::Expression::ite(_value, constantValue(1), constantValue(0));
298-
}
299-
300-
smtutil::Expression ReasoningBasedSimplifier::constantValue(size_t _value) const
301-
{
302-
return _value;
303-
}
304-
305-
smtutil::Expression ReasoningBasedSimplifier::literalValue(Literal const& _literal) const
306-
{
307-
return smtutil::Expression(valueOfLiteral(_literal));
308-
}
309-
310-
smtutil::Expression ReasoningBasedSimplifier::unsignedToSigned(smtutil::Expression _value)
311-
{
312-
return smtutil::Expression::ite(
313-
_value < smtutil::Expression(bigint(1) << 255),
314-
_value,
315-
_value - smtutil::Expression(bigint(1) << 256)
316-
);
317-
}
318-
319-
smtutil::Expression ReasoningBasedSimplifier::signedToUnsigned(smtutil::Expression _value)
320-
{
321-
return smtutil::Expression::ite(
322-
_value >= 0,
323-
_value,
324-
_value + smtutil::Expression(bigint(1) << 256)
325-
);
326-
}
327-
328-
smtutil::Expression ReasoningBasedSimplifier::wrap(smtutil::Expression _value)
329-
{
330-
smtutil::Expression rest = newRestrictedVariable();
331-
smtutil::Expression multiplier = newVariable();
332-
m_solver->addAssertion(_value == multiplier * smtutil::Expression(bigint(1) << 256) + rest);
333-
return rest;
334-
}

libyul/optimiser/ReasoningBasedSimplifier.h

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
#pragma once
1818

19+
#include <libyul/optimiser/SMTSolver.h>
1920
#include <libyul/optimiser/ASTWalker.h>
2021
#include <libyul/optimiser/OptimiserStep.h>
2122
#include <libyul/Dialect.h>
@@ -46,7 +47,7 @@ namespace solidity::yul
4647
*
4748
* Prerequisite: Disambiguator, SSATransform.
4849
*/
49-
class ReasoningBasedSimplifier: public ASTModifier
50+
class ReasoningBasedSimplifier: public ASTModifier, SMTSolver
5051
{
5152
public:
5253
static constexpr char const* name{"ReasoningBasedSimplifier"};
@@ -63,36 +64,12 @@ class ReasoningBasedSimplifier: public ASTModifier
6364
std::set<YulString> const& _ssaVariables
6465
);
6566

66-
smtutil::Expression encodeExpression(
67-
Expression const& _expression
68-
);
69-
70-
virtual smtutil::Expression encodeEVMBuiltin(
67+
smtutil::Expression encodeEVMBuiltin(
7168
evmasm::Instruction _instruction,
7269
std::vector<Expression> const& _arguments
73-
);
74-
75-
smtutil::Expression int2bv(smtutil::Expression _arg) const;
76-
smtutil::Expression bv2int(smtutil::Expression _arg) const;
77-
78-
smtutil::Expression newVariable();
79-
virtual smtutil::Expression newRestrictedVariable();
80-
std::string uniqueName();
81-
82-
virtual std::shared_ptr<smtutil::Sort> defaultSort() const;
83-
virtual smtutil::Expression booleanValue(smtutil::Expression _value) const;
84-
virtual smtutil::Expression constantValue(size_t _value) const;
85-
virtual smtutil::Expression literalValue(Literal const& _literal) const;
86-
virtual smtutil::Expression unsignedToSigned(smtutil::Expression _value);
87-
virtual smtutil::Expression signedToUnsigned(smtutil::Expression _value);
88-
virtual smtutil::Expression wrap(smtutil::Expression _value);
70+
) override;
8971

9072
Dialect const& m_dialect;
91-
std::set<YulString> const& m_ssaVariables;
92-
std::unique_ptr<smtutil::SolverInterface> m_solver;
93-
std::map<YulString, smtutil::Expression> m_variables;
94-
95-
size_t m_varCounter = 0;
9673
};
9774

9875
}

0 commit comments

Comments
 (0)