mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6213 from ethereum/iszeroJump
Peephole optimizer for "iszero iszero <tag> jumpi".
This commit is contained in:
commit
5c4a3aa270
@ -5,6 +5,7 @@ Language Features:
|
|||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Peephole Optimizer: Remove double ``iszero`` before ``jumpi``.
|
||||||
* SMTChecker: Support enums without typecast.
|
* SMTChecker: Support enums without typecast.
|
||||||
* SMTChecker: Support one-dimensional arrays.
|
* SMTChecker: Support one-dimensional arrays.
|
||||||
* Yul Optimizer: Add rule to remove empty default switch cases
|
* Yul Optimizer: Add rule to remove empty default switch cases
|
||||||
|
@ -45,6 +45,14 @@ struct ApplyRule
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
template <class Method>
|
template <class Method>
|
||||||
|
struct ApplyRule<Method, 4>
|
||||||
|
{
|
||||||
|
static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
|
||||||
|
{
|
||||||
|
return Method::applySimple(_in[0], _in[1], _in[2], _in[3], _out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <class Method>
|
||||||
struct ApplyRule<Method, 3>
|
struct ApplyRule<Method, 3>
|
||||||
{
|
{
|
||||||
static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
|
static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
|
||||||
@ -197,6 +205,32 @@ struct SwapComparison: SimplePeepholeOptimizerMethod<SwapComparison, 2>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI, 4>
|
||||||
|
{
|
||||||
|
static size_t applySimple(
|
||||||
|
AssemblyItem const& _iszero1,
|
||||||
|
AssemblyItem const& _iszero2,
|
||||||
|
AssemblyItem const& _pushTag,
|
||||||
|
AssemblyItem const& _jumpi,
|
||||||
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
_iszero1 == Instruction::ISZERO &&
|
||||||
|
_iszero2 == Instruction::ISZERO &&
|
||||||
|
_pushTag.type() == PushTag &&
|
||||||
|
_jumpi == Instruction::JUMPI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*_out = _pushTag;
|
||||||
|
*_out = _jumpi;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext, 3>
|
struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext, 3>
|
||||||
{
|
{
|
||||||
static size_t applySimple(
|
static size_t applySimple(
|
||||||
@ -320,7 +354,12 @@ bool PeepholeOptimiser::optimise()
|
|||||||
{
|
{
|
||||||
OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)};
|
OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)};
|
||||||
while (state.i < m_items.size())
|
while (state.i < m_items.size())
|
||||||
applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), JumpToNext(), UnreachableCode(), TagConjunctions(), TruthyAnd(), Identity());
|
applyMethods(
|
||||||
|
state,
|
||||||
|
PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(),
|
||||||
|
IsZeroIsZeroJumpI(), JumpToNext(), UnreachableCode(),
|
||||||
|
TagConjunctions(), TruthyAnd(), Identity()
|
||||||
|
);
|
||||||
if (m_optimisedItems.size() < m_items.size() || (
|
if (m_optimisedItems.size() < m_items.size() || (
|
||||||
m_optimisedItems.size() == m_items.size() && (
|
m_optimisedItems.size() == m_items.size() && (
|
||||||
eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) ||
|
eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) ||
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
======= data_storage/input.sol:C =======
|
======= data_storage/input.sol:C =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
300 + 258600 = 258900
|
294 + 255000 = 255294
|
||||||
external:
|
external:
|
||||||
f(): 258
|
f(): 252
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
======= gas_test_abiv2/input.sol:C =======
|
======= gas_test_abiv2/input.sol:C =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
1147 + 1103000 = 1104147
|
1140 + 1096600 = 1097740
|
||||||
external:
|
external:
|
||||||
a(): 530
|
a(): 530
|
||||||
b(uint256): 1124
|
b(uint256): 1118
|
||||||
f1(uint256): 586
|
f1(uint256): 586
|
||||||
f2(uint256[],string[],uint16,address): infinite
|
f2(uint256[],string[],uint16,address): infinite
|
||||||
f3(uint16[],string[],uint16,address): infinite
|
f3(uint16[],string[],uint16,address): infinite
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
======= gas_test_abiv2_optimize_yul/input.sol:C =======
|
======= gas_test_abiv2_optimize_yul/input.sol:C =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
651 + 617400 = 618051
|
651 + 617200 = 617851
|
||||||
external:
|
external:
|
||||||
a(): 429
|
a(): 429
|
||||||
b(uint256): 887
|
b(uint256): 884
|
||||||
f1(uint256): 351
|
f1(uint256): 351
|
||||||
f2(uint256[],string[],uint16,address): infinite
|
f2(uint256[],string[],uint16,address): infinite
|
||||||
f3(uint16[],string[],uint16,address): infinite
|
f3(uint16[],string[],uint16,address): infinite
|
||||||
|
@ -2,52 +2,52 @@
|
|||||||
======= gas_test_dispatch/input.sol:Large =======
|
======= gas_test_dispatch/input.sol:Large =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
683 + 650600 = 651283
|
670 + 635000 = 635670
|
||||||
external:
|
external:
|
||||||
a(): 451
|
a(): 451
|
||||||
b(uint256): 852
|
b(uint256): 846
|
||||||
f0(uint256): 433
|
f0(uint256): 427
|
||||||
f1(uint256): 40764
|
f1(uint256): 40752
|
||||||
f2(uint256): 20705
|
f2(uint256): 20693
|
||||||
f3(uint256): 20793
|
f3(uint256): 20781
|
||||||
f4(uint256): 20771
|
f4(uint256): 20759
|
||||||
f5(uint256): 20749
|
f5(uint256): 20737
|
||||||
f6(uint256): 20772
|
f6(uint256): 20760
|
||||||
f7(uint256): 20684
|
f7(uint256): 20672
|
||||||
f8(uint256): 20684
|
f8(uint256): 20672
|
||||||
f9(uint256): 20706
|
f9(uint256): 20694
|
||||||
g0(uint256): 319
|
g0(uint256): 313
|
||||||
g1(uint256): 40719
|
g1(uint256): 40707
|
||||||
g2(uint256): 20682
|
g2(uint256): 20670
|
||||||
g3(uint256): 20770
|
g3(uint256): 20758
|
||||||
g4(uint256): 20748
|
g4(uint256): 20736
|
||||||
g5(uint256): 20704
|
g5(uint256): 20692
|
||||||
g6(uint256): 20727
|
g6(uint256): 20715
|
||||||
g7(uint256): 20726
|
g7(uint256): 20714
|
||||||
g8(uint256): 20704
|
g8(uint256): 20692
|
||||||
g9(uint256): 20661
|
g9(uint256): 20649
|
||||||
|
|
||||||
======= gas_test_dispatch/input.sol:Medium =======
|
======= gas_test_dispatch/input.sol:Medium =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
300 + 256800 = 257100
|
294 + 251200 = 251494
|
||||||
external:
|
external:
|
||||||
a(): 428
|
a(): 428
|
||||||
b(uint256): 852
|
b(uint256): 846
|
||||||
f1(uint256): 40675
|
f1(uint256): 40663
|
||||||
f2(uint256): 20705
|
f2(uint256): 20693
|
||||||
f3(uint256): 20749
|
f3(uint256): 20737
|
||||||
g0(uint256): 319
|
g0(uint256): 313
|
||||||
g7(uint256): 20704
|
g7(uint256): 20692
|
||||||
g8(uint256): 20682
|
g8(uint256): 20670
|
||||||
g9(uint256): 20638
|
g9(uint256): 20626
|
||||||
|
|
||||||
======= gas_test_dispatch/input.sol:Small =======
|
======= gas_test_dispatch/input.sol:Small =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
129 + 83000 = 83129
|
129 + 81800 = 81929
|
||||||
external:
|
external:
|
||||||
fallback: 118
|
fallback: 118
|
||||||
a(): 383
|
a(): 383
|
||||||
b(uint256): 808
|
b(uint256): 802
|
||||||
f1(uint256): 40675
|
f1(uint256): 40663
|
||||||
|
@ -2,52 +2,52 @@
|
|||||||
======= gas_test_dispatch_optimize/input.sol:Large =======
|
======= gas_test_dispatch_optimize/input.sol:Large =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
300 + 259200 = 259500
|
300 + 260400 = 260700
|
||||||
external:
|
external:
|
||||||
a(): 398
|
a(): 398
|
||||||
b(uint256): 1108
|
b(uint256): 1105
|
||||||
f0(uint256): 334
|
f0(uint256): 334
|
||||||
f1(uint256): 40898
|
f1(uint256): 40892
|
||||||
f2(uint256): 20958
|
f2(uint256): 20952
|
||||||
f3(uint256): 21046
|
f3(uint256): 21040
|
||||||
f4(uint256): 21024
|
f4(uint256): 21018
|
||||||
f5(uint256): 21002
|
f5(uint256): 20996
|
||||||
f6(uint256): 20914
|
f6(uint256): 20908
|
||||||
f7(uint256): 20694
|
f7(uint256): 20688
|
||||||
f8(uint256): 20826
|
f8(uint256): 20820
|
||||||
f9(uint256): 20848
|
f9(uint256): 20842
|
||||||
g0(uint256): 574
|
g0(uint256): 574
|
||||||
g1(uint256): 40610
|
g1(uint256): 40604
|
||||||
g2(uint256): 20692
|
g2(uint256): 20686
|
||||||
g3(uint256): 20780
|
g3(uint256): 20774
|
||||||
g4(uint256): 20758
|
g4(uint256): 20752
|
||||||
g5(uint256): 20846
|
g5(uint256): 20840
|
||||||
g6(uint256): 20626
|
g6(uint256): 20620
|
||||||
g7(uint256): 20736
|
g7(uint256): 20730
|
||||||
g8(uint256): 20714
|
g8(uint256): 20708
|
||||||
g9(uint256): 20560
|
g9(uint256): 20554
|
||||||
|
|
||||||
======= gas_test_dispatch_optimize/input.sol:Medium =======
|
======= gas_test_dispatch_optimize/input.sol:Medium =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
183 + 140200 = 140383
|
183 + 140800 = 140983
|
||||||
external:
|
external:
|
||||||
a(): 398
|
a(): 398
|
||||||
b(uint256): 866
|
b(uint256): 863
|
||||||
f1(uint256): 40678
|
f1(uint256): 40672
|
||||||
f2(uint256): 20716
|
f2(uint256): 20710
|
||||||
f3(uint256): 20760
|
f3(uint256): 20754
|
||||||
g0(uint256): 332
|
g0(uint256): 332
|
||||||
g7(uint256): 20626
|
g7(uint256): 20620
|
||||||
g8(uint256): 20604
|
g8(uint256): 20598
|
||||||
g9(uint256): 20560
|
g9(uint256): 20554
|
||||||
|
|
||||||
======= gas_test_dispatch_optimize/input.sol:Small =======
|
======= gas_test_dispatch_optimize/input.sol:Small =======
|
||||||
Gas estimation:
|
Gas estimation:
|
||||||
construction:
|
construction:
|
||||||
117 + 64600 = 64717
|
111 + 64000 = 64111
|
||||||
external:
|
external:
|
||||||
fallback: 118
|
fallback: 118
|
||||||
a(): 376
|
a(): 376
|
||||||
b(uint256): 756
|
b(uint256): 753
|
||||||
f1(uint256): 40612
|
f1(uint256): 40606
|
||||||
|
@ -969,27 +969,60 @@ BOOST_AUTO_TEST_CASE(peephole_swap_comparison)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(peephole_truthy_and)
|
BOOST_AUTO_TEST_CASE(peephole_truthy_and)
|
||||||
{
|
{
|
||||||
AssemblyItems items{
|
AssemblyItems items{
|
||||||
AssemblyItem(Tag, 1),
|
AssemblyItem(Tag, 1),
|
||||||
Instruction::BALANCE,
|
Instruction::BALANCE,
|
||||||
u256(0),
|
u256(0),
|
||||||
Instruction::NOT,
|
Instruction::NOT,
|
||||||
Instruction::AND,
|
Instruction::AND,
|
||||||
AssemblyItem(PushTag, 1),
|
AssemblyItem(PushTag, 1),
|
||||||
Instruction::JUMPI
|
Instruction::JUMPI
|
||||||
};
|
};
|
||||||
AssemblyItems expectation{
|
AssemblyItems expectation{
|
||||||
AssemblyItem(Tag, 1),
|
AssemblyItem(Tag, 1),
|
||||||
Instruction::BALANCE,
|
Instruction::BALANCE,
|
||||||
AssemblyItem(PushTag, 1),
|
AssemblyItem(PushTag, 1),
|
||||||
Instruction::JUMPI
|
Instruction::JUMPI
|
||||||
};
|
};
|
||||||
PeepholeOptimiser peepOpt(items);
|
PeepholeOptimiser peepOpt(items);
|
||||||
BOOST_REQUIRE(peepOpt.optimise());
|
BOOST_REQUIRE(peepOpt.optimise());
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(
|
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||||
items.begin(), items.end(),
|
items.begin(), items.end(),
|
||||||
expectation.begin(), expectation.end()
|
expectation.begin(), expectation.end()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(peephole_iszero_iszero_jumpi)
|
||||||
|
{
|
||||||
|
AssemblyItems items{
|
||||||
|
AssemblyItem(Tag, 1),
|
||||||
|
u256(0),
|
||||||
|
Instruction::CALLDATALOAD,
|
||||||
|
Instruction::ISZERO,
|
||||||
|
Instruction::ISZERO,
|
||||||
|
AssemblyItem(PushTag, 1),
|
||||||
|
Instruction::JUMPI,
|
||||||
|
u256(0),
|
||||||
|
u256(0x20),
|
||||||
|
Instruction::RETURN
|
||||||
|
};
|
||||||
|
AssemblyItems expectation{
|
||||||
|
AssemblyItem(Tag, 1),
|
||||||
|
u256(0),
|
||||||
|
Instruction::CALLDATALOAD,
|
||||||
|
AssemblyItem(PushTag, 1),
|
||||||
|
Instruction::JUMPI,
|
||||||
|
u256(0),
|
||||||
|
u256(0x20),
|
||||||
|
Instruction::RETURN
|
||||||
|
};
|
||||||
|
PeepholeOptimiser peepOpt(items);
|
||||||
|
BOOST_REQUIRE(peepOpt.optimise());
|
||||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||||
|
items.begin(), items.end(),
|
||||||
|
expectation.begin(), expectation.end()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(jumpdest_removal)
|
BOOST_AUTO_TEST_CASE(jumpdest_removal)
|
||||||
|
@ -69,12 +69,12 @@ BOOST_AUTO_TEST_CASE(string_storage)
|
|||||||
compileAndRun(sourceCode);
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
if (Options::get().evmVersion() <= EVMVersion::byzantium())
|
if (Options::get().evmVersion() <= EVMVersion::byzantium())
|
||||||
CHECK_GAS(134435, 130591, 100);
|
CHECK_GAS(133899, 130591, 100);
|
||||||
// This is only correct on >=Constantinople.
|
// This is only correct on >=Constantinople.
|
||||||
else if (Options::get().useABIEncoderV2)
|
else if (Options::get().useABIEncoderV2)
|
||||||
CHECK_GAS(151819, 136003, 100);
|
CHECK_GAS(151283, 136003, 100);
|
||||||
else
|
else
|
||||||
CHECK_GAS(127225, 120159, 100);
|
CHECK_GAS(126689, 120159, 100);
|
||||||
if (Options::get().evmVersion() >= EVMVersion::byzantium())
|
if (Options::get().evmVersion() >= EVMVersion::byzantium())
|
||||||
{
|
{
|
||||||
callContractFunction("f()");
|
callContractFunction("f()");
|
||||||
|
Loading…
Reference in New Issue
Block a user