Browse Source

code generator stub

cl-refactor
chriseth 10 years ago
parent
commit
c97447fbd8
  1. 58
      libevmcore/CommonSubexpressionEliminator.cpp
  2. 39
      libevmcore/CommonSubexpressionEliminator.h

58
libevmcore/CommonSubexpressionEliminator.cpp

@ -29,14 +29,14 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems() const
vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
{
auto streamEquivalenceClass = [this](ostream& _out, EquivalenceClass _id)
auto streamEquivalenceClass = [this](ostream& _out, EquivalenceClassId _id)
{
auto const& eqClass = m_equivalenceClasses[_id];
_out << " " << _id << ": " << *eqClass.first;
_out << "(";
for (EquivalenceClass arg: eqClass.second)
for (EquivalenceClassId arg: eqClass.second)
_out << dec << arg << ",";
_out << ")" << endl;
};
@ -52,19 +52,20 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems() const
streamEquivalenceClass(cout, it.second);
}
cout << "Equivalence classes: " << endl;
for (EquivalenceClass eqClass = 0; eqClass < m_equivalenceClasses.size(); ++eqClass)
for (EquivalenceClassId eqClass = 0; eqClass < m_equivalenceClasses.size(); ++eqClass)
streamEquivalenceClass(cout, eqClass);
cout << "----------------------------" << endl;
if (m_stackElements.size() == 0)
{
map<int, EquivalenceClassId> targetStackContents;
int minStackHeight = m_stackHeight;
if (m_stackElements.size() > 0)
minStackHeight = min(minStackHeight, m_stackElements.begin()->first.first);
for (int stackHeight = minStackHeight; stackHeight <= m_stackHeight; ++stackHeight)
targetStackContents[stackHeight] = getStackElement(stackHeight);
}
int stackHeight;
// m_stackElements
// for all stack elements from most neg to most pos:
//
return vector<AssemblyItem>();
CSECodeGenerator generator;
return generator.generateCode(m_stackHeight, targetStackContents, m_equivalenceClasses);
}
bool CommonSubexpressionEliminator::breaksBasicBlock(AssemblyItem const& _item)
@ -112,7 +113,7 @@ void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item)
);
else if (instruction != Instruction::POP)
{
vector<EquivalenceClass> arguments(info.args);
vector<EquivalenceClassId> arguments(info.args);
for (int i = 0; i < info.args; ++i)
arguments[i] = getStackElement(m_stackHeight - i);
setStackElement(m_stackHeight + info.ret - info.args, getClass(_item, arguments));
@ -121,7 +122,7 @@ void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item)
}
}
void CommonSubexpressionEliminator::setStackElement(int _stackHeight, EquivalenceClass _class)
void CommonSubexpressionEliminator::setStackElement(int _stackHeight, EquivalenceClassId _class)
{
unsigned nextSequence = getNextStackElementSequence(_stackHeight);
m_stackElements[make_pair(_stackHeight, nextSequence)] = _class;
@ -131,8 +132,8 @@ void CommonSubexpressionEliminator::swapStackElements(int _stackHeightA, int _st
{
if (_stackHeightA == _stackHeightB)
BOOST_THROW_EXCEPTION(OptimizerException() << errinfo_comment("Swap on same stack elements."));
EquivalenceClass classA = getStackElement(_stackHeightA);
EquivalenceClass classB = getStackElement(_stackHeightB);
EquivalenceClassId classA = getStackElement(_stackHeightA);
EquivalenceClassId classB = getStackElement(_stackHeightB);
unsigned nextSequenceA = getNextStackElementSequence(_stackHeightA);
unsigned nextSequenceB = getNextStackElementSequence(_stackHeightB);
@ -140,7 +141,7 @@ void CommonSubexpressionEliminator::swapStackElements(int _stackHeightA, int _st
m_stackElements[make_pair(_stackHeightB, nextSequenceB)] = classA;
}
CommonSubexpressionEliminator::EquivalenceClass CommonSubexpressionEliminator::getStackElement(int _stackHeight)
EquivalenceClassId CommonSubexpressionEliminator::getStackElement(int _stackHeight)
{
// retrieve class by last sequence number
unsigned nextSequence = getNextStackElementSequence(_stackHeight);
@ -154,13 +155,13 @@ CommonSubexpressionEliminator::EquivalenceClass CommonSubexpressionEliminator::g
BOOST_THROW_EXCEPTION(OptimizerException() << errinfo_comment("Stack too deep."));
// This is a special assembly item that refers to elements pre-existing on the initial stack.
m_spareAssemblyItem.push_back(make_shared<AssemblyItem>(dupInstruction(1 - _stackHeight)));
m_equivalenceClasses.push_back(make_pair(m_spareAssemblyItem.back().get(), EquivalenceClasses()));
return m_stackElements[make_pair(_stackHeight, nextSequence)] = EquivalenceClass(m_equivalenceClasses.size() - 1);
m_equivalenceClasses.push_back(make_pair(m_spareAssemblyItem.back().get(), EquivalenceClassIds()));
return m_stackElements[make_pair(_stackHeight, nextSequence)] = EquivalenceClassId(m_equivalenceClasses.size() - 1);
}
CommonSubexpressionEliminator::EquivalenceClass CommonSubexpressionEliminator::getClass(
EquivalenceClassId CommonSubexpressionEliminator::getClass(
const AssemblyItem& _item,
EquivalenceClasses const& _arguments
EquivalenceClassIds const& _arguments
)
{
// do a clever search, i.e.
@ -168,7 +169,7 @@ CommonSubexpressionEliminator::EquivalenceClass CommonSubexpressionEliminator::g
// - check whether the two items are equal for a SUB instruction
// - check whether 0 or 1 is in one of the classes for a MUL
// - for commutative opcodes, sort the arguments before searching
for (EquivalenceClass c = 0; c < m_equivalenceClasses.size(); ++c)
for (EquivalenceClassId c = 0; c < m_equivalenceClasses.size(); ++c)
{
AssemblyItem const& classItem = *m_equivalenceClasses[c].first;
if (classItem != _item)
@ -184,7 +185,7 @@ CommonSubexpressionEliminator::EquivalenceClass CommonSubexpressionEliminator::g
if (_item.type() == Operation && _arguments.size() == 2 && all_of(
_arguments.begin(),
_arguments.end(),
[this](EquivalenceClass eqc) { return m_equivalenceClasses[eqc].first->match(Push); }))
[this](EquivalenceClassId eqc) { return m_equivalenceClasses[eqc].first->match(Push); }))
{
map<Instruction, function<u256(u256, u256)>> const arithmetics =
{
@ -232,3 +233,14 @@ unsigned CommonSubexpressionEliminator::getNextStackElementSequence(int _stackHe
else
return 0;
}
AssemblyItems CSECodeGenerator::generateCode(
int _targetStackHeight,
map<int, EquivalenceClassId> const& _targetStackContents,
vector<pair<const AssemblyItem*, EquivalenceClassIds>> const& _equivalenceClasses)
{
m_generatedItems.clear();
m_classRequestCount.clear();
return m_generatedItems;
}

39
libevmcore/CommonSubexpressionEliminator.h

@ -33,6 +33,10 @@ namespace eth
{
class AssemblyItem;
using AssemblyItems = std::vector<AssemblyItem>;
using EquivalenceClassId = unsigned;
using EquivalenceClassIds = std::vector<EquivalenceClassId>;
/**
* Optimizer step that performs common subexpression elimination and stack reorginasation,
@ -56,27 +60,24 @@ public:
_AssemblyItemIterator feedItems(_AssemblyItemIterator _iterator, _AssemblyItemIterator _end);
/// @returns the resulting items after optimization.
std::vector<AssemblyItem> getOptimizedItems() const;
AssemblyItems getOptimizedItems();
private:
using EquivalenceClass = unsigned;
using EquivalenceClasses = std::vector<EquivalenceClass>;
/// @returns true if the given items starts a new basic block
bool breaksBasicBlock(AssemblyItem const& _item);
/// Feeds the item into the system for analysis.
void feedItem(AssemblyItem const& _item);
/// Assigns a new equivalence class to the next sequence number of the given stack element.
void setStackElement(int _stackHeight, EquivalenceClass _class);
void setStackElement(int _stackHeight, EquivalenceClassId _class);
/// Swaps the given stack elements in their next sequence number.
void swapStackElements(int _stackHeightA, int _stackHeightB);
/// Retrieves the current equivalence class fo the given stack element (or generates a new
/// one if it does not exist yet).
EquivalenceClass getStackElement(int _stackHeight);
EquivalenceClassId getStackElement(int _stackHeight);
/// Retrieves the equivalence class resulting from the given item applied to the given classes,
/// might also create a new one.
EquivalenceClass getClass(AssemblyItem const& _item, EquivalenceClasses const& _arguments = {});
EquivalenceClassId getClass(AssemblyItem const& _item, EquivalenceClassIds const& _arguments = {});
/// @returns the next sequence number of the given stack element.
unsigned getNextStackElementSequence(int _stackHeight);
@ -84,12 +85,32 @@ private:
/// Current stack height, can be negative.
int m_stackHeight = 0;
/// Mapping (stack height, sequence number) -> equivalence class
std::map<std::pair<int, unsigned>, EquivalenceClass> m_stackElements;
std::map<std::pair<int, unsigned>, EquivalenceClassId> m_stackElements;
/// Vector of equivalence class representatives - we only store one item of an equivalence
/// class and the index is used as identifier.
std::vector<std::pair<AssemblyItem const*, EquivalenceClasses>> m_equivalenceClasses;
std::vector<std::pair<AssemblyItem const*, EquivalenceClassIds>> m_equivalenceClasses;
/// List of items generated during analysis.
std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItem;
};
class CSECodeGenerator
{
public:
/// @returns the assembly items generated from the given requirements
/// @param _targetStackHeight target stack height starting from an assumed initial stack height of zero
/// @param _targetStackContents final contents of the stack, by stack height relative to initial
/// @param _equivalenceClasses equivalence classes as expressions of how to compute them
AssemblyItems generateCode(
int _targetStackHeight,
std::map<int, EquivalenceClassId> const& _targetStackContents,
std::vector<std::pair<AssemblyItem const*, EquivalenceClassIds>> const& _equivalenceClasses
);
private:
AssemblyItems m_generatedItems;
/// Number of requests for an equivalence class, used as a reference counter.
std::map<EquivalenceClassId, unsigned> m_classRequestCount;
};
template <class _AssemblyItemIterator>

Loading…
Cancel
Save