mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Added a few optimizer tests for Verbatim
This commit is contained in:
parent
2e99a56be2
commit
8b4eaeabbf
@ -93,6 +93,45 @@ namespace
|
|||||||
BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end());
|
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 CFG(AssemblyItems const& _input)
|
||||||
{
|
{
|
||||||
AssemblyItems output = _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)
|
BOOST_AUTO_TEST_CASE(cse_remove_redundant_shift_masking)
|
||||||
{
|
{
|
||||||
if (!solidity::test::CommonOptions::get().evmVersion().hasBitwiseShifting())
|
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