mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul Optimizer: Simplify start offset of zero-length operations.
This commit is contained in:
parent
fbef27233c
commit
e996fe6247
@ -8,6 +8,7 @@ Language Features:
|
|||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Code Generator: More efficient overflow checks for multiplication.
|
* Code Generator: More efficient overflow checks for multiplication.
|
||||||
|
* Yul Optimizer: Simplify the starting offset of zero-length operations to zero.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -411,7 +411,7 @@ bool DataFlowAnalyzer::inScope(YulString _variableName) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<u256> DataFlowAnalyzer::valueOfIdentifier(YulString const& _name)
|
optional<u256> DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) const
|
||||||
{
|
{
|
||||||
if (AssignedValue const* value = variableValue(_name))
|
if (AssignedValue const* value = variableValue(_name))
|
||||||
if (Literal const* literal = get_if<Literal>(value->value))
|
if (Literal const* literal = get_if<Literal>(value->value))
|
||||||
|
@ -148,7 +148,7 @@ protected:
|
|||||||
bool inScope(YulString _variableName) const;
|
bool inScope(YulString _variableName) const;
|
||||||
|
|
||||||
/// Returns the literal value of the identifier, if it exists.
|
/// Returns the literal value of the identifier, if it exists.
|
||||||
std::optional<u256> valueOfIdentifier(YulString const& _name);
|
std::optional<u256> valueOfIdentifier(YulString const& _name) const;
|
||||||
|
|
||||||
enum class StoreLoadLocation {
|
enum class StoreLoadLocation {
|
||||||
Memory = 0,
|
Memory = 0,
|
||||||
|
@ -23,7 +23,11 @@
|
|||||||
|
|
||||||
#include <libyul/optimiser/SimplificationRules.h>
|
#include <libyul/optimiser/SimplificationRules.h>
|
||||||
#include <libyul/optimiser/OptimiserStep.h>
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
#include <libyul/optimiser/OptimizerUtilities.h>
|
||||||
#include <libyul/AST.h>
|
#include <libyul/AST.h>
|
||||||
|
#include <libyul/Utilities.h>
|
||||||
|
|
||||||
|
#include <libevmasm/SemanticInformation.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
@ -44,4 +48,29 @@ void ExpressionSimplifier::visit(Expression& _expression)
|
|||||||
[this](YulString _var) { return variableValue(_var); }
|
[this](YulString _var) { return variableValue(_var); }
|
||||||
))
|
))
|
||||||
_expression = match->action().toExpression(debugDataOf(_expression));
|
_expression = match->action().toExpression(debugDataOf(_expression));
|
||||||
|
|
||||||
|
if (auto* functionCall = get_if<FunctionCall>(&_expression))
|
||||||
|
if (optional<evmasm::Instruction> instruction = toEVMInstruction(m_dialect, functionCall->functionName.name))
|
||||||
|
for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction))
|
||||||
|
if (op.startParameter && op.lengthParameter)
|
||||||
|
{
|
||||||
|
Expression& startArgument = functionCall->arguments.at(*op.startParameter);
|
||||||
|
Expression const& lengthArgument = functionCall->arguments.at(*op.lengthParameter);
|
||||||
|
if (
|
||||||
|
knownToBeZero(lengthArgument) &&
|
||||||
|
!knownToBeZero(startArgument) &&
|
||||||
|
!holds_alternative<FunctionCall>(startArgument)
|
||||||
|
)
|
||||||
|
startArgument = Literal{debugDataOf(startArgument), LiteralKind::Number, "0"_yulstring, {}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpressionSimplifier::knownToBeZero(Expression const& _expression) const
|
||||||
|
{
|
||||||
|
if (auto const* literal = get_if<Literal>(&_expression))
|
||||||
|
return valueOfLiteral(*literal) == 0;
|
||||||
|
else if (auto const* identifier = get_if<Identifier>(&_expression))
|
||||||
|
return valueOfIdentifier(identifier->name) == 0;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ private:
|
|||||||
explicit ExpressionSimplifier(Dialect const& _dialect):
|
explicit ExpressionSimplifier(Dialect const& _dialect):
|
||||||
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore)
|
DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore)
|
||||||
{}
|
{}
|
||||||
|
bool knownToBeZero(Expression const& _expression) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
for {} div(create(0, 1, 0), shl(msize(), 1)) {}
|
for {} div(create(0, 1, 1), shl(msize(), 1)) {}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,7 +10,7 @@
|
|||||||
//
|
//
|
||||||
// {
|
// {
|
||||||
// {
|
// {
|
||||||
// for { } div(create(0, 1, 0), shl(msize(), 1)) { }
|
// for { } div(create(0, 1, 1), shl(msize(), 1)) { }
|
||||||
// { }
|
// { }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
revert(calldataload(0), 0)
|
||||||
|
revert(call(0,0,0,0,0,0,0), 0)
|
||||||
|
calldatacopy(calldataload(1), calldataload(2), 0)
|
||||||
|
return(calldataload(3), 0)
|
||||||
|
codecopy(calldataload(4), calldataload(5), sub(42,42))
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// step: expressionSimplifier
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// let _1 := 0
|
||||||
|
// revert(0, _1)
|
||||||
|
// pop(call(_1, _1, _1, _1, _1, _1, _1))
|
||||||
|
// revert(0, _1)
|
||||||
|
// calldatacopy(0, calldataload(2), _1)
|
||||||
|
// return(0, _1)
|
||||||
|
// codecopy(0, calldataload(5), 0)
|
||||||
|
// }
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user