aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/SolidityOptimizer.cpp
diff options
context:
space:
mode:
authorPaweł Bylica <chfast@gmail.com>2015-06-11 00:01:03 +0800
committerPaweł Bylica <chfast@gmail.com>2015-06-11 00:01:03 +0800
commit5d534416b1115e54e86aaa04e248f88f6d34cd41 (patch)
tree8adb81f80ff0099c836618cfd200df0a3f2bd48d /libsolidity/SolidityOptimizer.cpp
parent7557e4b73f66aaf03e7f274036bac18792a480f4 (diff)
parentbcecae082219abb99157aca5afe9440fac20b516 (diff)
downloaddexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar.gz
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar.bz2
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar.lz
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar.xz
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.tar.zst
dexon-solidity-5d534416b1115e54e86aaa04e248f88f6d34cd41.zip
Merge remote-tracking branch 'upstream/develop' into evmjit-develop
Conflicts: evmjit/libevmjit-cpp/JitVM.cpp evmjit/libevmjit-cpp/JitVM.h
Diffstat (limited to 'libsolidity/SolidityOptimizer.cpp')
-rw-r--r--libsolidity/SolidityOptimizer.cpp115
1 files changed, 114 insertions, 1 deletions
diff --git a/libsolidity/SolidityOptimizer.cpp b/libsolidity/SolidityOptimizer.cpp
index 744fc48a..397ee631 100644
--- a/libsolidity/SolidityOptimizer.cpp
+++ b/libsolidity/SolidityOptimizer.cpp
@@ -355,7 +355,8 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
if (_instr == eth::Instruction::SHA3)
numSHA3s++;
});
- BOOST_CHECK_EQUAL(2, numSHA3s);
+// TEST DISABLED UNTIL 93693404 IS IMPLEMENTED
+// BOOST_CHECK_EQUAL(2, numSHA3s);
}
BOOST_AUTO_TEST_CASE(cse_intermediate_swap)
@@ -440,6 +441,16 @@ BOOST_AUTO_TEST_CASE(cse_double_negation)
checkCSE({Instruction::DUP5, Instruction::NOT, Instruction::NOT}, {Instruction::DUP5});
}
+BOOST_AUTO_TEST_CASE(cse_double_iszero)
+{
+ checkCSE({Instruction::GT, Instruction::ISZERO, Instruction::ISZERO}, {Instruction::GT});
+ checkCSE({Instruction::GT, Instruction::ISZERO}, {Instruction::GT, Instruction::ISZERO});
+ checkCSE(
+ {Instruction::ISZERO, Instruction::ISZERO, Instruction::ISZERO},
+ {Instruction::ISZERO}
+ );
+}
+
BOOST_AUTO_TEST_CASE(cse_associativity)
{
AssemblyItems input{
@@ -908,6 +919,31 @@ BOOST_AUTO_TEST_CASE(cse_equality_on_initially_known_stack)
BOOST_CHECK(find(output.begin(), output.end(), AssemblyItem(u256(1))) != output.end());
}
+BOOST_AUTO_TEST_CASE(cse_access_previous_sequence)
+{
+ // Tests that the code generator detects whether it tries to access SLOAD instructions
+ // from a sequenced expression which is not in its scope.
+ eth::KnownState state = createInitialState(AssemblyItems{
+ u256(0),
+ Instruction::SLOAD,
+ u256(1),
+ Instruction::ADD,
+ u256(0),
+ Instruction::SSTORE
+ });
+ // now stored: val_1 + 1 (value at sequence 1)
+ // if in the following instructions, the SLOAD cresolves to "val_1 + 1",
+ // this cannot be generated because we cannot load from sequence 1 anymore.
+ AssemblyItems input{
+ u256(0),
+ Instruction::SLOAD,
+ };
+ BOOST_CHECK_THROW(getCSE(input, state), StackTooDeepException);
+ // @todo for now, this throws an exception, but it should recover to the following
+ // (or an even better version) at some point:
+ // 0, SLOAD, 1, ADD, SSTORE, 0 SLOAD
+}
+
BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused)
{
// remove parts of the code that are unused
@@ -1004,6 +1040,83 @@ BOOST_AUTO_TEST_CASE(block_deduplicator)
BOOST_CHECK_EQUAL(pushTags.size(), 2);
}
+BOOST_AUTO_TEST_CASE(block_deduplicator_loops)
+{
+ AssemblyItems input{
+ u256(0),
+ eth::Instruction::SLOAD,
+ AssemblyItem(PushTag, 1),
+ AssemblyItem(PushTag, 2),
+ eth::Instruction::JUMPI,
+ eth::Instruction::JUMP,
+ AssemblyItem(Tag, 1),
+ u256(5),
+ u256(6),
+ eth::Instruction::SSTORE,
+ AssemblyItem(PushTag, 1),
+ eth::Instruction::JUMP,
+ AssemblyItem(Tag, 2),
+ u256(5),
+ u256(6),
+ eth::Instruction::SSTORE,
+ AssemblyItem(PushTag, 2),
+ eth::Instruction::JUMP,
+ };
+ BlockDeduplicator dedup(input);
+ dedup.deduplicate();
+
+ set<u256> pushTags;
+ for (AssemblyItem const& item: input)
+ if (item.type() == PushTag)
+ pushTags.insert(item.data());
+ BOOST_CHECK_EQUAL(pushTags.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(computing_constants)
+{
+ char const* sourceCode = R"(
+ contract c {
+ uint a;
+ uint b;
+ uint c;
+ function set() returns (uint a, uint b, uint c) {
+ a = 0x77abc0000000000000000000000000000000000000000000000000000000001;
+ b = 0x817416927846239487123469187231298734162934871263941234127518276;
+ g();
+ }
+ function g() {
+ b = 0x817416927846239487123469187231298734162934871263941234127518276;
+ c = 0x817416927846239487123469187231298734162934871263941234127518276;
+ }
+ function get() returns (uint ra, uint rb, uint rc) {
+ ra = a;
+ rb = b;
+ rc = c ;
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("set()");
+ compareVersions("get()");
+
+ m_optimize = true;
+ m_optimizeRuns = 1;
+ bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c");
+ bytes complicatedConstant = toBigEndian(u256("0x817416927846239487123469187231298734162934871263941234127518276"));
+ unsigned occurrences = 0;
+ for (auto iter = optimizedBytecode.cbegin(); iter < optimizedBytecode.cend(); ++occurrences)
+ iter = search(iter, optimizedBytecode.cend(), complicatedConstant.cbegin(), complicatedConstant.cend()) + 1;
+ BOOST_CHECK_EQUAL(2, occurrences);
+
+ bytes constantWithZeros = toBigEndian(u256("0x77abc0000000000000000000000000000000000000000000000000000000001"));
+ BOOST_CHECK(search(
+ optimizedBytecode.cbegin(),
+ optimizedBytecode.cend(),
+ constantWithZeros.cbegin(),
+ constantWithZeros.cend()
+ ) == optimizedBytecode.cend());
+}
+
BOOST_AUTO_TEST_SUITE_END()
}