From c97447fbd8480d0532ee8227bf0c1811b4947da2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 18 Mar 2015 16:50:59 +0100 Subject: [PATCH] code generator stub --- libevmcore/CommonSubexpressionEliminator.cpp | 58 ++++++++++++-------- libevmcore/CommonSubexpressionEliminator.h | 39 ++++++++++--- 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/libevmcore/CommonSubexpressionEliminator.cpp b/libevmcore/CommonSubexpressionEliminator.cpp index 117f823ce..c442425a4 100644 --- a/libevmcore/CommonSubexpressionEliminator.cpp +++ b/libevmcore/CommonSubexpressionEliminator.cpp @@ -29,14 +29,14 @@ using namespace std; using namespace dev; using namespace dev::eth; -vector CommonSubexpressionEliminator::getOptimizedItems() const +vector 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 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 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(); + 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 arguments(info.args); + vector 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(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> const arithmetics = { @@ -232,3 +233,14 @@ unsigned CommonSubexpressionEliminator::getNextStackElementSequence(int _stackHe else return 0; } + + +AssemblyItems CSECodeGenerator::generateCode( + int _targetStackHeight, + map const& _targetStackContents, + vector> const& _equivalenceClasses) +{ + m_generatedItems.clear(); + m_classRequestCount.clear(); + return m_generatedItems; +} diff --git a/libevmcore/CommonSubexpressionEliminator.h b/libevmcore/CommonSubexpressionEliminator.h index 2f932ba49..c15b3efad 100644 --- a/libevmcore/CommonSubexpressionEliminator.h +++ b/libevmcore/CommonSubexpressionEliminator.h @@ -33,6 +33,10 @@ namespace eth { class AssemblyItem; +using AssemblyItems = std::vector; + +using EquivalenceClassId = unsigned; +using EquivalenceClassIds = std::vector; /** * 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 getOptimizedItems() const; + AssemblyItems getOptimizedItems(); private: - using EquivalenceClass = unsigned; - using EquivalenceClasses = std::vector; - /// @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, EquivalenceClass> m_stackElements; + std::map, 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> m_equivalenceClasses; + std::vector> m_equivalenceClasses; /// List of items generated during analysis. std::vector> 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 const& _targetStackContents, + std::vector> const& _equivalenceClasses + ); + +private: + AssemblyItems m_generatedItems; + /// Number of requests for an equivalence class, used as a reference counter. + std::map m_classRequestCount; }; template