aboutsummaryrefslogtreecommitdiffstats
path: root/CommonSubexpressionEliminator.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-05-08 00:31:21 +0800
committerchriseth <c@ethdev.com>2015-05-11 18:56:40 +0800
commit2fbcb5b9c81e7922e7cc58a4d75da12ec600e536 (patch)
tree13dac605ff6ba3a7f31337bebd8e86eb44ad208f /CommonSubexpressionEliminator.cpp
parent9d3f0de31bb82217a5fc5f2daf933d21b18774a0 (diff)
downloaddexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar.gz
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar.bz2
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar.lz
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar.xz
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.tar.zst
dexon-solidity-2fbcb5b9c81e7922e7cc58a4d75da12ec600e536.zip
Store alternative stack locations during code generation.
Diffstat (limited to 'CommonSubexpressionEliminator.cpp')
-rw-r--r--CommonSubexpressionEliminator.cpp80
1 files changed, 42 insertions, 38 deletions
diff --git a/CommonSubexpressionEliminator.cpp b/CommonSubexpressionEliminator.cpp
index 5beb7966..e369c9db 100644
--- a/CommonSubexpressionEliminator.cpp
+++ b/CommonSubexpressionEliminator.cpp
@@ -121,10 +121,7 @@ AssemblyItems CSECodeGenerator::generateCode(
m_stack = _initialStack;
m_targetStack = _targetStackContents;
for (auto const& item: m_stack)
- if (!m_classPositions.count(item.second))
- m_classPositions[item.second] = item.first;
-
- // @todo: provide information about the positions of copies of class elements
+ m_classPositions[item.second].insert(item.first);
// generate the dependency graph starting from final storage and memory writes and target stack contents
for (auto const& p: m_storeOperations)
@@ -152,11 +149,12 @@ AssemblyItems CSECodeGenerator::generateCode(
{
if (m_stack.count(targetItem.first) && m_stack.at(targetItem.first) == targetItem.second)
continue; // already there
- int position = generateClassElement(targetItem.second);
- assertThrow(position != c_invalidPosition, OptimizerException, "");
- if (position == targetItem.first)
+ generateClassElement(targetItem.second);
+ assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, "");
+ if (m_classPositions[targetItem.second].count(targetItem.first))
continue;
SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation();
+ int position = classElementPosition(targetItem.second);
if (position < targetItem.first)
// it is already at its target, we need another copy
appendDup(position, location);
@@ -266,19 +264,23 @@ void CSECodeGenerator::addDependencies(Id _c)
}
}
-int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
+void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
{
+ for (auto it: m_classPositions)
+ for (auto p: it.second)
+ if (p > m_stackHeight)
+ assertThrow(false, OptimizerException, "");
// do some cleanup
removeStackTopIfPossible();
if (m_classPositions.count(_c))
{
assertThrow(
- m_classPositions[_c] != c_invalidPosition,
+ !m_classPositions[_c].empty(),
OptimizerException,
"Element already removed but still needed."
);
- return m_classPositions[_c];
+ return;
}
ExpressionClasses::Expression const& expr = m_expressionClasses.representative(_c);
assertThrow(
@@ -351,16 +353,16 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
// this will not append a swap but remove the one that is already there
appendOrRemoveSwap(m_stackHeight - 1, location);
- for (auto arg: arguments)
- if (m_classPositions[arg] != c_invalidPosition && canBeRemoved(arg, _c))
- m_classPositions[arg] = c_invalidPosition;
for (size_t i = 0; i < arguments.size(); ++i)
+ {
+ m_classPositions[m_stack[m_stackHeight - i]].erase(m_stackHeight - i);
m_stack.erase(m_stackHeight - i);
+ }
appendItem(*expr.item);
if (expr.item->type() != Operation || instructionInfo(expr.item->instruction()).ret == 1)
{
m_stack[m_stackHeight] = _c;
- return m_classPositions[_c] = m_stackHeight;
+ m_classPositions[_c].insert(m_stackHeight);
}
else
{
@@ -369,18 +371,18 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
OptimizerException,
"Invalid number of return values."
);
- return m_classPositions[_c] = c_invalidPosition;
+ m_classPositions[_c]; // ensure it is created to mark the expression as generated
}
}
int CSECodeGenerator::classElementPosition(Id _id) const
{
assertThrow(
- m_classPositions.count(_id) && m_classPositions.at(_id) != c_invalidPosition,
+ m_classPositions.count(_id) && !m_classPositions.at(_id).empty(),
OptimizerException,
"Element requested but is not present."
);
- return m_classPositions.at(_id);
+ return *max_element(m_classPositions.at(_id).begin(), m_classPositions.at(_id).end());
}
bool CSECodeGenerator::canBeRemoved(Id _element, Id _result, int _fromPosition)
@@ -389,20 +391,19 @@ bool CSECodeGenerator::canBeRemoved(Id _element, Id _result, int _fromPosition)
if (_fromPosition == c_invalidPosition)
_fromPosition = classElementPosition(_element);
- bool isCopy = _fromPosition != classElementPosition(_element);
+ bool haveCopy = m_classPositions.at(_element).size() > 1;
if (m_finalClasses.count(_element))
// It is part of the target stack. It can be removed if it is a copy that is not in the target position.
- return isCopy && (!m_targetStack.count(_fromPosition) || m_targetStack[_fromPosition] != _element);
- else if (isCopy)
- // It is only a copy, can be removed.
- return true;
-
- // Can be removed unless it is needed by a class that has not been computed yet.
- // Note that m_classPositions also includes classes that were deleted in the meantime.
- auto range = m_neededBy.equal_range(_element);
- for (auto it = range.first; it != range.second; ++it)
- if (it->second != _result && !m_classPositions.count(it->second))
- return false;
+ return haveCopy && (!m_targetStack.count(_fromPosition) || m_targetStack[_fromPosition] != _element);
+ else if (!haveCopy)
+ {
+ // Can be removed unless it is needed by a class that has not been computed yet.
+ // Note that m_classPositions also includes classes that were deleted in the meantime.
+ auto range = m_neededBy.equal_range(_element);
+ for (auto it = range.first; it != range.second; ++it)
+ if (it->second != _result && !m_classPositions.count(it->second))
+ return false;
+ }
return true;
}
@@ -414,9 +415,9 @@ bool CSECodeGenerator::removeStackTopIfPossible()
Id top = m_stack[m_stackHeight];
if (!canBeRemoved(top, Id(-1), m_stackHeight))
return false;
- m_generatedItems.push_back(AssemblyItem(Instruction::POP));
+ m_classPositions[m_stack[m_stackHeight]].erase(m_stackHeight);
m_stack.erase(m_stackHeight);
- m_stackHeight--;
+ appendItem(AssemblyItem(Instruction::POP));
return true;
}
@@ -428,6 +429,7 @@ void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _locat
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(dupInstruction(instructionNum), _location));
m_stack[m_stackHeight] = m_stack[_fromPosition];
+ m_classPositions[m_stack[m_stackHeight]].insert(m_stackHeight);
}
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location)
@@ -439,13 +441,15 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(swapInstruction(instructionNum), _location));
- // The value of a class can be present in multiple locations on the stack. We only update the
- // "canonical" one that is tracked by m_classPositions
- if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight)
- m_classPositions[m_stack[m_stackHeight]] = _fromPosition;
- if (m_classPositions[m_stack[_fromPosition]] == _fromPosition)
- m_classPositions[m_stack[_fromPosition]] = m_stackHeight;
- swap(m_stack[m_stackHeight], m_stack[_fromPosition]);
+
+ if (m_stack[m_stackHeight] != m_stack[_fromPosition])
+ {
+ m_classPositions[m_stack[m_stackHeight]].erase(m_stackHeight);
+ m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition);
+ m_classPositions[m_stack[_fromPosition]].erase(_fromPosition);
+ m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight);
+ swap(m_stack[m_stackHeight], m_stack[_fromPosition]);
+ }
if (m_generatedItems.size() >= 2 &&
SemanticInformation::isSwapInstruction(m_generatedItems.back()) &&
*(m_generatedItems.end() - 2) == m_generatedItems.back())