Keep one instance of KnowledgeBase for UnusedStoreEliminator.

This commit is contained in:
chriseth 2022-11-10 14:06:37 +01:00
parent 47aa1c65ae
commit 96e2a6d3fe
2 changed files with 39 additions and 32 deletions

View File

@ -92,6 +92,21 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast)
remover(_ast); remover(_ast);
} }
UnusedStoreEliminator::UnusedStoreEliminator(
Dialect const& _dialect,
map<YulString, SideEffects> const& _functionSideEffects,
map<YulString, ControlFlowSideEffects> _controlFlowSideEffects,
map<YulString, AssignedValue> const& _ssaValues,
bool _ignoreMemory
):
UnusedStoreBase(_dialect),
m_ignoreMemory(_ignoreMemory),
m_functionSideEffects(_functionSideEffects),
m_controlFlowSideEffects(_controlFlowSideEffects),
m_ssaValues(_ssaValues),
m_knowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); })
{}
void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall)
{ {
UnusedStoreBase::operator()(_functionCall); UnusedStoreBase::operator()(_functionCall);
@ -174,12 +189,11 @@ void UnusedStoreEliminator::visit(Statement const& _statement)
initialState = State::Used; initialState = State::Used;
auto startOffset = identifierNameIfSSA(funCall->arguments.at(1)); auto startOffset = identifierNameIfSSA(funCall->arguments.at(1));
auto length = identifierNameIfSSA(funCall->arguments.at(2)); auto length = identifierNameIfSSA(funCall->arguments.at(2));
KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); });
if (length && startOffset) if (length && startOffset)
{ {
FunctionCall const* lengthCall = get_if<FunctionCall>(m_ssaValues.at(*length).value); FunctionCall const* lengthCall = get_if<FunctionCall>(m_ssaValues.at(*length).value);
if ( if (
knowledge.knownToBeZero(*startOffset) && m_knowledgeBase.knownToBeZero(*startOffset) &&
lengthCall && lengthCall &&
toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE
) )
@ -267,8 +281,6 @@ bool UnusedStoreEliminator::knownUnrelated(
UnusedStoreEliminator::Operation const& _op2 UnusedStoreEliminator::Operation const& _op2
) const ) const
{ {
KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); });
if (_op1.location != _op2.location) if (_op1.location != _op2.location)
return true; return true;
if (_op1.location == Location::Storage) if (_op1.location == Location::Storage)
@ -278,26 +290,26 @@ bool UnusedStoreEliminator::knownUnrelated(
yulAssert( yulAssert(
_op1.length && _op1.length &&
_op2.length && _op2.length &&
knowledge.valueIfKnownConstant(*_op1.length) == 1 && m_knowledgeBase.valueIfKnownConstant(*_op1.length) == 1 &&
knowledge.valueIfKnownConstant(*_op2.length) == 1 m_knowledgeBase.valueIfKnownConstant(*_op2.length) == 1
); );
return knowledge.knownToBeDifferent(*_op1.start, *_op2.start); return m_knowledgeBase.knownToBeDifferent(*_op1.start, *_op2.start);
} }
} }
else else
{ {
yulAssert(_op1.location == Location::Memory, ""); yulAssert(_op1.location == Location::Memory, "");
if ( if (
(_op1.length && knowledge.knownToBeZero(*_op1.length)) || (_op1.length && m_knowledgeBase.knownToBeZero(*_op1.length)) ||
(_op2.length && knowledge.knownToBeZero(*_op2.length)) (_op2.length && m_knowledgeBase.knownToBeZero(*_op2.length))
) )
return true; return true;
if (_op1.start && _op1.length && _op2.start) if (_op1.start && _op1.length && _op2.start)
{ {
optional<u256> length1 = knowledge.valueIfKnownConstant(*_op1.length); optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length);
optional<u256> start1 = knowledge.valueIfKnownConstant(*_op1.start); optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start);
optional<u256> start2 = knowledge.valueIfKnownConstant(*_op2.start); optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start);
if ( if (
(length1 && start1 && start2) && (length1 && start1 && start2) &&
*start1 + *length1 >= *start1 && // no overflow *start1 + *length1 >= *start1 && // no overflow
@ -307,9 +319,9 @@ bool UnusedStoreEliminator::knownUnrelated(
} }
if (_op2.start && _op2.length && _op1.start) if (_op2.start && _op2.length && _op1.start)
{ {
optional<u256> length2 = knowledge.valueIfKnownConstant(*_op2.length); optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length);
optional<u256> start2 = knowledge.valueIfKnownConstant(*_op2.start); optional<u256> start2 = m_knowledgeBase.valueIfKnownConstant(*_op2.start);
optional<u256> start1 = knowledge.valueIfKnownConstant(*_op1.start); optional<u256> start1 = m_knowledgeBase.valueIfKnownConstant(*_op1.start);
if ( if (
(length2 && start2 && start1) && (length2 && start2 && start1) &&
*start2 + *length2 >= *start2 && // no overflow *start2 + *length2 >= *start2 && // no overflow
@ -320,12 +332,12 @@ bool UnusedStoreEliminator::knownUnrelated(
if (_op1.start && _op1.length && _op2.start && _op2.length) if (_op1.start && _op1.length && _op2.start && _op2.length)
{ {
optional<u256> length1 = knowledge.valueIfKnownConstant(*_op1.length); optional<u256> length1 = m_knowledgeBase.valueIfKnownConstant(*_op1.length);
optional<u256> length2 = knowledge.valueIfKnownConstant(*_op2.length); optional<u256> length2 = m_knowledgeBase.valueIfKnownConstant(*_op2.length);
if ( if (
(length1 && *length1 <= 32) && (length1 && *length1 <= 32) &&
(length2 && *length2 <= 32) && (length2 && *length2 <= 32) &&
knowledge.knownToBeDifferentByAtLeast32(*_op1.start, *_op2.start) m_knowledgeBase.knownToBeDifferentByAtLeast32(*_op1.start, *_op2.start)
) )
return true; return true;
} }
@ -348,22 +360,20 @@ bool UnusedStoreEliminator::knownCovered(
return true; return true;
if (_covered.location == Location::Memory) if (_covered.location == Location::Memory)
{ {
KnowledgeBase knowledge([this](YulString _var) { return util::valueOrNullptr(m_ssaValues, _var); }); if (_covered.length && m_knowledgeBase.knownToBeZero(*_covered.length))
if (_covered.length && knowledge.knownToBeZero(*_covered.length))
return true; return true;
// Condition (i = cover_i_ng, e = cover_e_d): // Condition (i = cover_i_ng, e = cover_e_d):
// i.start <= e.start && e.start + e.length <= i.start + i.length // i.start <= e.start && e.start + e.length <= i.start + i.length
if (!_covered.start || !_covering.start || !_covered.length || !_covering.length) if (!_covered.start || !_covering.start || !_covered.length || !_covering.length)
return false; return false;
optional<u256> coveredLength = knowledge.valueIfKnownConstant(*_covered.length); optional<u256> coveredLength = m_knowledgeBase.valueIfKnownConstant(*_covered.length);
optional<u256> coveringLength = knowledge.valueIfKnownConstant(*_covering.length); optional<u256> coveringLength = m_knowledgeBase.valueIfKnownConstant(*_covering.length);
if (*_covered.start == *_covering.start) if (*_covered.start == *_covering.start)
if (coveredLength && coveringLength && *coveredLength <= *coveringLength) if (coveredLength && coveringLength && *coveredLength <= *coveringLength)
return true; return true;
optional<u256> coveredStart = knowledge.valueIfKnownConstant(*_covered.start); optional<u256> coveredStart = m_knowledgeBase.valueIfKnownConstant(*_covered.start);
optional<u256> coveringStart = knowledge.valueIfKnownConstant(*_covering.start); optional<u256> coveringStart = m_knowledgeBase.valueIfKnownConstant(*_covering.start);
if (coveredStart && coveringStart && coveredLength && coveringLength) if (coveredStart && coveringStart && coveredLength && coveringLength)
if ( if (
*coveringStart <= *coveredStart && *coveringStart <= *coveredStart &&

View File

@ -27,6 +27,7 @@
#include <libyul/optimiser/OptimiserStep.h> #include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/Semantics.h> #include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/UnusedStoreBase.h> #include <libyul/optimiser/UnusedStoreBase.h>
#include <libyul/optimiser/KnowledgeBase.h>
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
@ -68,13 +69,7 @@ public:
std::map<YulString, ControlFlowSideEffects> _controlFlowSideEffects, std::map<YulString, ControlFlowSideEffects> _controlFlowSideEffects,
std::map<YulString, AssignedValue> const& _ssaValues, std::map<YulString, AssignedValue> const& _ssaValues,
bool _ignoreMemory bool _ignoreMemory
): );
UnusedStoreBase(_dialect),
m_ignoreMemory(_ignoreMemory),
m_functionSideEffects(_functionSideEffects),
m_controlFlowSideEffects(_controlFlowSideEffects),
m_ssaValues(_ssaValues)
{}
using UnusedStoreBase::operator(); using UnusedStoreBase::operator();
void operator()(FunctionCall const& _functionCall) override; void operator()(FunctionCall const& _functionCall) override;
@ -121,6 +116,8 @@ private:
std::map<YulString, AssignedValue> const& m_ssaValues; std::map<YulString, AssignedValue> const& m_ssaValues;
std::map<Statement const*, Operation> m_storeOperations; std::map<Statement const*, Operation> m_storeOperations;
KnowledgeBase mutable m_knowledgeBase;
}; };
} }