mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11316 from ethereum/verbatimdata-tests
Added a few optimizer tests for Verbatim
This commit is contained in:
commit
2cd0bb11dc
@ -93,6 +93,45 @@ namespace
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||
}
|
||||
|
||||
/// In contrast to the function `CSE`, this function doesn't finish the CSE optimization on an
|
||||
/// instruction that breaks CSE Analysis block. Copied from Assembly.cpp
|
||||
AssemblyItems fullCSE(AssemblyItems const& _input)
|
||||
{
|
||||
AssemblyItems optimisedItems;
|
||||
|
||||
bool usesMSize = ranges::any_of(_input, [](AssemblyItem const& _i) {
|
||||
return _i == AssemblyItem{Instruction::MSIZE} || _i.type() == VerbatimBytecode;
|
||||
});
|
||||
|
||||
auto iter = _input.begin();
|
||||
while (iter != _input.end())
|
||||
{
|
||||
KnownState emptyState;
|
||||
CommonSubexpressionEliminator eliminator{emptyState};
|
||||
auto orig = iter;
|
||||
iter = eliminator.feedItems(iter, _input.end(), usesMSize);
|
||||
bool shouldReplace = false;
|
||||
AssemblyItems optimisedChunk;
|
||||
optimisedChunk = eliminator.getOptimizedItems();
|
||||
shouldReplace = (optimisedChunk.size() < static_cast<size_t>(iter - orig));
|
||||
if (shouldReplace)
|
||||
optimisedItems += optimisedChunk;
|
||||
else
|
||||
copy(orig, iter, back_inserter(optimisedItems));
|
||||
}
|
||||
|
||||
return optimisedItems;
|
||||
}
|
||||
|
||||
void checkFullCSE(
|
||||
AssemblyItems const& _input,
|
||||
AssemblyItems const& _expectation
|
||||
)
|
||||
{
|
||||
AssemblyItems output = fullCSE(_input);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
||||
}
|
||||
|
||||
AssemblyItems CFG(AssemblyItems const& _input)
|
||||
{
|
||||
AssemblyItems output = _input;
|
||||
@ -1292,6 +1331,135 @@ BOOST_AUTO_TEST_CASE(cse_sub_zero)
|
||||
});
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_simple_verbatim)
|
||||
{
|
||||
auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0};
|
||||
AssemblyItems input{verbatim};
|
||||
checkCSE(input, input);
|
||||
checkFullCSE(input, input);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_mload_pop)
|
||||
{
|
||||
AssemblyItems input{
|
||||
u256(1000),
|
||||
Instruction::MLOAD,
|
||||
Instruction::POP,
|
||||
};
|
||||
|
||||
AssemblyItems output{
|
||||
};
|
||||
|
||||
checkCSE(input, output);
|
||||
checkFullCSE(input, output);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_verbatim_mload)
|
||||
{
|
||||
auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0};
|
||||
AssemblyItems input{
|
||||
u256(1000),
|
||||
Instruction::MLOAD, // Should not be removed
|
||||
Instruction::POP,
|
||||
verbatim,
|
||||
u256(1000),
|
||||
Instruction::MLOAD, // Should not be removed
|
||||
Instruction::POP,
|
||||
};
|
||||
|
||||
checkFullCSE(input, input);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_sload_verbatim_dup)
|
||||
{
|
||||
auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0};
|
||||
AssemblyItems input{
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
verbatim
|
||||
};
|
||||
|
||||
AssemblyItems output{
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
Instruction::DUP1,
|
||||
verbatim
|
||||
};
|
||||
|
||||
checkCSE(input, output);
|
||||
checkFullCSE(input, output);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_verbatim_sload_sideeffect)
|
||||
{
|
||||
auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0};
|
||||
AssemblyItems input{
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
verbatim,
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
};
|
||||
|
||||
checkFullCSE(input, input);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_verbatim_eq)
|
||||
{
|
||||
auto verbatim = AssemblyItem{bytes{1, 2, 3, 4, 5}, 0, 0};
|
||||
AssemblyItems input{
|
||||
u256(0),
|
||||
Instruction::SLOAD,
|
||||
verbatim,
|
||||
Instruction::DUP1,
|
||||
Instruction::EQ
|
||||
};
|
||||
|
||||
checkFullCSE(input, input);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(verbatim_knownstate)
|
||||
{
|
||||
KnownState state = createInitialState(AssemblyItems{
|
||||
Instruction::DUP1,
|
||||
Instruction::DUP2,
|
||||
Instruction::DUP3,
|
||||
Instruction::DUP4
|
||||
});
|
||||
map<int, unsigned> const& stackElements = state.stackElements();
|
||||
|
||||
BOOST_CHECK(state.stackHeight() == 4);
|
||||
// One more than stack height because of the initial unknown element.
|
||||
BOOST_CHECK(stackElements.size() == 5);
|
||||
BOOST_CHECK(stackElements.count(0));
|
||||
unsigned initialElement = stackElements.at(0);
|
||||
// Check if all the DUPs were correctly matched to the same class.
|
||||
for (auto const& height: {1, 2, 3, 4})
|
||||
BOOST_CHECK(stackElements.at(height) == initialElement);
|
||||
|
||||
auto verbatim2i5o = AssemblyItem{bytes{1, 2, 3, 4, 5}, 2, 5};
|
||||
state.feedItem(verbatim2i5o);
|
||||
|
||||
BOOST_CHECK(state.stackHeight() == 7);
|
||||
// Stack elements
|
||||
// Before verbatim: {{0, x}, {1, x}, {2, x}, {3, x}, {4, x}}
|
||||
// After verbatim: {{0, x}, {1, x}, {2, x}, {3, a}, {4, b}, {5, c}, {6, d}, {7, e}}
|
||||
BOOST_CHECK(stackElements.size() == 8);
|
||||
|
||||
for (auto const& height: {1, 2})
|
||||
BOOST_CHECK(stackElements.at(height) == initialElement);
|
||||
|
||||
for (auto const& height: {3, 4, 5, 6, 7})
|
||||
BOOST_CHECK(stackElements.at(height) != initialElement);
|
||||
|
||||
for (auto const& height1: {3, 4, 5, 6, 7})
|
||||
for (auto const& height2: {3, 4, 5, 6, 7})
|
||||
if (height1 < height2)
|
||||
BOOST_CHECK(stackElements.at(height1) != stackElements.at(height2));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cse_remove_redundant_shift_masking)
|
||||
{
|
||||
if (!solidity::test::CommonOptions::get().evmVersion().hasBitwiseShifting())
|
||||
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
mstore(10, 20)
|
||||
// cannot be resolved because of verbatim
|
||||
sstore(0, mload(10))
|
||||
verbatim_0i_0o("test")
|
||||
}
|
||||
// ----
|
||||
// step: loadResolver
|
||||
//
|
||||
// {
|
||||
// let _1 := 20
|
||||
// let _2 := 10
|
||||
// mstore(_2, _1)
|
||||
// sstore(0, mload(_2))
|
||||
// verbatim_0i_0o("test")
|
||||
// }
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
sstore(10, 20)
|
||||
// will be resolved
|
||||
sstore(30, sload(10))
|
||||
verbatim_0i_0o("test")
|
||||
// will not be resolved
|
||||
sstore(30, sload(10))
|
||||
}
|
||||
// ----
|
||||
// step: loadResolver
|
||||
//
|
||||
// {
|
||||
// let _1 := 20
|
||||
// let _2 := 10
|
||||
// sstore(_2, _1)
|
||||
// let _4 := _1
|
||||
// let _5 := 30
|
||||
// sstore(_5, _4)
|
||||
// verbatim_0i_0o("test")
|
||||
// sstore(_5, sload(_2))
|
||||
// }
|
17
test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul
Normal file
17
test/libyul/yulOptimizerTests/unusedPruner/verbatim.yul
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
// cannot be removed because of verbatim
|
||||
let a := mload(10)
|
||||
// cannot be removed because of verbatim
|
||||
let b := keccak256(10, 32)
|
||||
// can be removed
|
||||
let c := add(a, b)
|
||||
verbatim_0i_0o("test")
|
||||
}
|
||||
// ----
|
||||
// step: unusedPruner
|
||||
//
|
||||
// {
|
||||
// pop(mload(10))
|
||||
// pop(keccak256(10, 32))
|
||||
// verbatim_0i_0o("test")
|
||||
// }
|
Loading…
Reference in New Issue
Block a user