mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Common subexpression elimination ready for using pre-known state.
This commit is contained in:
parent
3ebb7d99c4
commit
867101e409
@ -40,9 +40,8 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
|
|||||||
int minHeight = m_state.stackHeight() + 1;
|
int minHeight = m_state.stackHeight() + 1;
|
||||||
if (!m_state.stackElements().empty())
|
if (!m_state.stackElements().empty())
|
||||||
minHeight = min(minHeight, m_state.stackElements().begin()->first);
|
minHeight = min(minHeight, m_state.stackElements().begin()->first);
|
||||||
for (int height = minHeight; height <= 0; ++height)
|
for (int height = minHeight; height <= m_initialState.stackHeight(); ++height)
|
||||||
//@todo this is not nice as it is here - should be "unknownStackElement" - but is it really unknown?
|
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
|
||||||
initialStackContents[height] = m_state.initialStackElement(height, SourceLocation());
|
|
||||||
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
|
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
|
||||||
targetStackContents[height] = m_state.stackElement(height, SourceLocation());
|
targetStackContents[height] = m_state.stackElement(height, SourceLocation());
|
||||||
|
|
||||||
@ -50,6 +49,7 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
|
|||||||
//stream(cout, initialStackContents, targetStackContents);
|
//stream(cout, initialStackContents, targetStackContents);
|
||||||
|
|
||||||
AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode(
|
AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode(
|
||||||
|
m_initialState.stackHeight(),
|
||||||
initialStackContents,
|
initialStackContents,
|
||||||
targetStackContents
|
targetStackContents
|
||||||
);
|
);
|
||||||
@ -106,10 +106,12 @@ CSECodeGenerator::CSECodeGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItems CSECodeGenerator::generateCode(
|
AssemblyItems CSECodeGenerator::generateCode(
|
||||||
|
int _initialStackHeight,
|
||||||
map<int, Id> const& _initialStack,
|
map<int, Id> const& _initialStack,
|
||||||
map<int, Id> const& _targetStackContents
|
map<int, Id> const& _targetStackContents
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
m_stackHeight = _initialStackHeight;
|
||||||
m_stack = _initialStack;
|
m_stack = _initialStack;
|
||||||
for (auto const& item: m_stack)
|
for (auto const& item: m_stack)
|
||||||
if (!m_classPositions.count(item.second))
|
if (!m_classPositions.count(item.second))
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
using Id = ExpressionClasses::Id;
|
using Id = ExpressionClasses::Id;
|
||||||
using StoreOperation = KnownState::StoreOperation;
|
using StoreOperation = KnownState::StoreOperation;
|
||||||
|
|
||||||
CommonSubexpressionEliminator(KnownState const& _state): m_state(_state) {}
|
CommonSubexpressionEliminator(KnownState const& _state): m_initialState(_state), m_state(_state) {}
|
||||||
|
|
||||||
/// Feeds AssemblyItems into the eliminator and @returns the iterator pointing at the first
|
/// Feeds AssemblyItems into the eliminator and @returns the iterator pointing at the first
|
||||||
/// item that must be fed into a new instance of the eliminator.
|
/// item that must be fed into a new instance of the eliminator.
|
||||||
@ -85,6 +85,7 @@ private:
|
|||||||
/// Tries to optimize the item that breaks the basic block at the end.
|
/// Tries to optimize the item that breaks the basic block at the end.
|
||||||
void optimizeBreakingItem();
|
void optimizeBreakingItem();
|
||||||
|
|
||||||
|
KnownState m_initialState;
|
||||||
KnownState m_state;
|
KnownState m_state;
|
||||||
/// Keeps information about which storage or memory slots were written to at which sequence
|
/// Keeps information about which storage or memory slots were written to at which sequence
|
||||||
/// number with what instruction.
|
/// number with what instruction.
|
||||||
@ -115,6 +116,7 @@ public:
|
|||||||
/// @param _targetStackContents final contents of the stack, by stack height relative to initial
|
/// @param _targetStackContents final contents of the stack, by stack height relative to initial
|
||||||
/// @note should only be called once on each object.
|
/// @note should only be called once on each object.
|
||||||
AssemblyItems generateCode(
|
AssemblyItems generateCode(
|
||||||
|
int _initialStackHeight,
|
||||||
std::map<int, Id> const& _initialStack,
|
std::map<int, Id> const& _initialStack,
|
||||||
std::map<int, Id> const& _targetStackContents
|
std::map<int, Id> const& _targetStackContents
|
||||||
);
|
);
|
||||||
@ -150,7 +152,7 @@ private:
|
|||||||
|
|
||||||
AssemblyItems m_generatedItems;
|
AssemblyItems m_generatedItems;
|
||||||
/// Current height of the stack relative to the start.
|
/// Current height of the stack relative to the start.
|
||||||
int m_stackHeight = 0;
|
int m_stackHeight;
|
||||||
/// If (b, a) is in m_requests then b is needed to compute a.
|
/// If (b, a) is in m_requests then b is needed to compute a.
|
||||||
std::multimap<Id, Id> m_neededBy;
|
std::multimap<Id, Id> m_neededBy;
|
||||||
/// Current content of the stack.
|
/// Current content of the stack.
|
||||||
|
@ -79,15 +79,6 @@ ExpressionClasses::Id ExpressionClasses::find(
|
|||||||
return exp.id;
|
return exp.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionClasses::Id ExpressionClasses::newId()
|
|
||||||
{
|
|
||||||
// Note that we cannot insert it in m_expressions because this requires item to be set.
|
|
||||||
Expression exp;
|
|
||||||
exp.id = m_representatives.size();
|
|
||||||
m_representatives.push_back(exp);
|
|
||||||
return exp.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
|
bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b)
|
||||||
{
|
{
|
||||||
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.
|
// Try to simplify "_a - _b" and return true iff the value is a non-zero constant.
|
||||||
|
@ -68,10 +68,6 @@ public:
|
|||||||
bool _copyItem = true,
|
bool _copyItem = true,
|
||||||
unsigned _sequenceNumber = 0
|
unsigned _sequenceNumber = 0
|
||||||
);
|
);
|
||||||
/// @returns a new unique class id which does not and will never have a representative containing
|
|
||||||
/// an AssemblyItem, i.e. its value cannot be generated, instead it has to be assumed to be
|
|
||||||
/// already present.
|
|
||||||
Id newId();
|
|
||||||
/// @returns the canonical representative of an expression class.
|
/// @returns the canonical representative of an expression class.
|
||||||
Expression const& representative(Id _id) const { return m_representatives.at(_id); }
|
Expression const& representative(Id _id) const { return m_representatives.at(_id); }
|
||||||
/// @returns the number of classes.
|
/// @returns the number of classes.
|
||||||
|
@ -135,8 +135,10 @@ ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation
|
|||||||
{
|
{
|
||||||
if (m_stackElements.count(_stackHeight))
|
if (m_stackElements.count(_stackHeight))
|
||||||
return m_stackElements.at(_stackHeight);
|
return m_stackElements.at(_stackHeight);
|
||||||
// Stack element not found (not assigned yet), create new equivalence class.
|
// Stack element not found (not assigned yet), create new unknown equivalence class.
|
||||||
return m_stackElements[_stackHeight] = m_expressionClasses->newId();
|
//@todo check that we do not infer incorrect equivalences when the stack is cleared partially
|
||||||
|
//in between.
|
||||||
|
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionClasses::Id KnownState::initialStackElement(
|
ExpressionClasses::Id KnownState::initialStackElement(
|
||||||
@ -144,10 +146,8 @@ ExpressionClasses::Id KnownState::initialStackElement(
|
|||||||
SourceLocation const& _location
|
SourceLocation const& _location
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested.");
|
|
||||||
assertThrow(_stackHeight > -16, StackTooDeepException, "");
|
|
||||||
// This is a special assembly item that refers to elements pre-existing on the initial stack.
|
// This is a special assembly item that refers to elements pre-existing on the initial stack.
|
||||||
return m_expressionClasses->find(AssemblyItem(dupInstruction(1 - _stackHeight), _location));
|
return m_expressionClasses->find(AssemblyItem(UndefinedItem, u256(_stackHeight), _location));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KnownState::setStackElement(int _stackHeight, Id _class)
|
void KnownState::setStackElement(int _stackHeight, Id _class)
|
||||||
|
Loading…
Reference in New Issue
Block a user