mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1736 from ethereum/boundoptimizer
Add upper bound for computing constants.
This commit is contained in:
commit
85411f4f67
@ -18,6 +18,7 @@ Bugfixes:
|
|||||||
* Type system: Correctly convert function argument types to pointers for member functions.
|
* Type system: Correctly convert function argument types to pointers for member functions.
|
||||||
* Inline assembly: Charge one stack slot for non-value types during analysis.
|
* Inline assembly: Charge one stack slot for non-value types during analysis.
|
||||||
* Assembly output: Print source location before the operation it refers to instead of after.
|
* Assembly output: Print source location before the operation it refers to instead of after.
|
||||||
|
* Optimizer: Stop trying to optimize tricky constants after a while.
|
||||||
|
|
||||||
### 0.4.9 (2017-01-31)
|
### 0.4.9 (2017-01-31)
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
|||||||
// Is not always better, try literal and decomposition method.
|
// Is not always better, try literal and decomposition method.
|
||||||
AssemblyItems routine{u256(_value)};
|
AssemblyItems routine{u256(_value)};
|
||||||
bigint bestGas = gasNeeded(routine);
|
bigint bestGas = gasNeeded(routine);
|
||||||
for (unsigned bits = 255; bits > 8; --bits)
|
for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits)
|
||||||
{
|
{
|
||||||
unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff;
|
unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff;
|
||||||
if (gapDetector != 0xff && gapDetector != 0x100)
|
if (gapDetector != 0xff && gapDetector != 0x100)
|
||||||
@ -219,6 +219,8 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
|||||||
else if (lowerPart < 0)
|
else if (lowerPart < 0)
|
||||||
newRoutine.push_back(Instruction::SUB);
|
newRoutine.push_back(Instruction::SUB);
|
||||||
|
|
||||||
|
if (m_maxSteps > 0)
|
||||||
|
m_maxSteps--;
|
||||||
bigint newGas = gasNeeded(newRoutine);
|
bigint newGas = gasNeeded(newRoutine);
|
||||||
if (newGas < bestGas)
|
if (newGas < bestGas)
|
||||||
{
|
{
|
||||||
|
@ -143,6 +143,8 @@ protected:
|
|||||||
AssemblyItems findRepresentation(u256 const& _value);
|
AssemblyItems findRepresentation(u256 const& _value);
|
||||||
bigint gasNeeded(AssemblyItems const& _routine);
|
bigint gasNeeded(AssemblyItems const& _routine);
|
||||||
|
|
||||||
|
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
||||||
|
size_t m_maxSteps = 10000;
|
||||||
AssemblyItems m_routine;
|
AssemblyItems m_routine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -1234,6 +1235,67 @@ BOOST_AUTO_TEST_CASE(computing_constants)
|
|||||||
) == optimizedBytecode.cend());
|
) == optimizedBytecode.cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(constant_optimization_early_exit)
|
||||||
|
{
|
||||||
|
// This tests that the constant optimizer does not try to find the best representation
|
||||||
|
// indefinitely but instead stops after some number of iterations.
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
|
contract HexEncoding {
|
||||||
|
function hexEncodeTest(address addr) returns (bytes32 ret) {
|
||||||
|
uint x = uint(addr) / 2**32;
|
||||||
|
|
||||||
|
// Nibble interleave
|
||||||
|
x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
|
||||||
|
x = (x | (x * 2**64)) & 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff;
|
||||||
|
x = (x | (x * 2**32)) & 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff;
|
||||||
|
x = (x | (x * 2**16)) & 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff;
|
||||||
|
x = (x | (x * 2** 8)) & 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff;
|
||||||
|
x = (x | (x * 2** 4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
|
||||||
|
|
||||||
|
// Hex encode
|
||||||
|
uint h = (x & 0x0808080808080808080808080808080808080808080808080808080808080808) / 8;
|
||||||
|
uint i = (x & 0x0404040404040404040404040404040404040404040404040404040404040404) / 4;
|
||||||
|
uint j = (x & 0x0202020202020202020202020202020202020202020202020202020202020202) / 2;
|
||||||
|
x = x + (h & (i | j)) * 0x27 + 0x3030303030303030303030303030303030303030303030303030303030303030;
|
||||||
|
|
||||||
|
// Store and load next batch
|
||||||
|
assembly {
|
||||||
|
mstore(0, x)
|
||||||
|
}
|
||||||
|
x = uint(addr) * 2**96;
|
||||||
|
|
||||||
|
// Nibble interleave
|
||||||
|
x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
|
||||||
|
x = (x | (x * 2**64)) & 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff;
|
||||||
|
x = (x | (x * 2**32)) & 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff;
|
||||||
|
x = (x | (x * 2**16)) & 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff;
|
||||||
|
x = (x | (x * 2** 8)) & 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff;
|
||||||
|
x = (x | (x * 2** 4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
|
||||||
|
|
||||||
|
// Hex encode
|
||||||
|
h = (x & 0x0808080808080808080808080808080808080808080808080808080808080808) / 8;
|
||||||
|
i = (x & 0x0404040404040404040404040404040404040404040404040404040404040404) / 4;
|
||||||
|
j = (x & 0x0202020202020202020202020202020202020202020202020202020202020202) / 2;
|
||||||
|
x = x + (h & (i | j)) * 0x27 + 0x3030303030303030303030303030303030303030303030303030303030303030;
|
||||||
|
|
||||||
|
// Store and hash
|
||||||
|
assembly {
|
||||||
|
mstore(32, x)
|
||||||
|
ret := sha3(0, 40)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
compileBothVersions(sourceCode);
|
||||||
|
double duration = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
|
||||||
|
BOOST_CHECK_MESSAGE(duration < 20, "Compilation of constants took longer than 20 seconds.");
|
||||||
|
compareVersions("hexEncodeTest(address)", u256(0x123456789));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inconsistency)
|
BOOST_AUTO_TEST_CASE(inconsistency)
|
||||||
{
|
{
|
||||||
// This is a test of a bug in the optimizer.
|
// This is a test of a bug in the optimizer.
|
||||||
|
Loading…
Reference in New Issue
Block a user