Use builtin iszero for for loop condition rewriting.

This commit is contained in:
chriseth
2019-09-12 10:26:16 +02:00
committed by Daniel Kirchner
parent 324cc71b13
commit 4f80117eef
12 changed files with 111 additions and 16 deletions
+1
View File
@@ -61,6 +61,7 @@ struct Dialect: boost::noncopyable
virtual BuiltinFunction const* discardFunction() const { return nullptr; }
virtual BuiltinFunction const* equalityFunction() const { return nullptr; }
virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; }
virtual std::set<YulString> fixedFunctionNames() const { return {}; }
+1
View File
@@ -70,6 +70,7 @@ struct EVMDialect: public Dialect
BuiltinFunctionForEVM const* discardFunction() const override { return builtin("pop"_yulstring); }
BuiltinFunctionForEVM const* equalityFunction() const override { return builtin("eq"_yulstring); }
BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); }
static EVMDialect const& looseAssemblyForEVM(langutil::EVMVersion _version);
static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version);
+1
View File
@@ -47,6 +47,7 @@ struct WasmDialect: public Dialect
BuiltinFunction const* builtin(YulString _name) const override;
BuiltinFunction const* discardFunction() const override { return builtin("drop"_yulstring); }
BuiltinFunction const* equalityFunction() const override { return builtin("i64.eq"_yulstring); }
BuiltinFunction const* booleanNegationFunction() const override { return builtin("i64.eqz"_yulstring); }
std::set<YulString> fixedFunctionNames() const override { return {"main"_yulstring}; }
@@ -25,7 +25,7 @@ using namespace yul;
void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
{
if (_forLoop.condition->type() != typeid(Literal))
if (m_dialect.booleanNegationFunction() && _forLoop.condition->type() != typeid(Literal))
{
langutil::SourceLocation loc = locationOf(*_forLoop.condition);
_forLoop.body.statements.insert(
@@ -33,9 +33,9 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop)
If {
loc,
make_unique<Expression>(
FunctionalInstruction {
FunctionCall {
loc,
eth::Instruction::ISZERO,
{loc, m_dialect.booleanNegationFunction()->name},
make_vector<Expression>(std::move(*_forLoop.condition))
}
),
+7 -1
View File
@@ -17,6 +17,7 @@
#pragma once
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/Dialect.h>
namespace yul
{
@@ -29,17 +30,22 @@ namespace yul
* By moving the iteration check part into the ForLoop body, we can apply expression splitter
* to the condition expression.
*
* This rewritter will skip loops that already have literal constant as iteration condition.
* This rewriter will skip loops that already have literal constant as iteration condition.
*
* Requirements:
* - The Disambiguator must be run upfront.
* - To avoid unnecessary rewrite, it is recommended to run this rewriter after StructuralSimplifier.
* - Only works for dialects with a builtin boolean negation function.
*/
class ForLoopConditionIntoBody: public ASTModifier
{
public:
ForLoopConditionIntoBody(Dialect const& _dialect): m_dialect(_dialect) {}
using ASTModifier::operator();
void operator()(ForLoop& _forLoop) override;
private:
Dialect const& m_dialect;
};
}
+2
View File
@@ -33,6 +33,7 @@
#include <libyul/optimiser/ExpressionJoiner.h>
#include <libyul/optimiser/ExpressionInliner.h>
#include <libyul/optimiser/FullInliner.h>
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
#include <libyul/optimiser/ForLoopInitRewriter.h>
#include <libyul/optimiser/Rematerialiser.h>
#include <libyul/optimiser/UnusedPruner.h>
@@ -94,6 +95,7 @@ void OptimiserSuite::run(
LiteralRematerialiser{_dialect}(ast);
StructuralSimplifier{}(ast);
ControlFlowSimplifier{_dialect}(ast);
ForLoopConditionIntoBody{_dialect}(ast);
BlockFlattener{}(ast);
// None of the above can make stack problems worse.