Move the second run of YulOptimizer to IRGenerator to make it more obvious we're running it twice

This commit is contained in:
Kamil Śliwak 2023-04-28 21:53:16 +02:00
parent 0cb279494a
commit 4296197d8e
6 changed files with 371 additions and 27 deletions

View File

@ -113,6 +113,7 @@ pair<string, string> IRGenerator::run(
solAssert(false, ir + "\n\nInvalid IR generated:\n" + errorMessage + "\n"); solAssert(false, ir + "\n\nInvalid IR generated:\n" + errorMessage + "\n");
} }
asmStack.optimize(); asmStack.optimize();
asmStack.optimize(); // FIXME: We should be getting good results without running this twice
return {std::move(ir), asmStack.print(m_context.soliditySourceProvider())}; return {std::move(ir), asmStack.print(m_context.soliditySourceProvider())};
} }

View File

@ -1467,7 +1467,6 @@ void CompilerStack::generateEVMFromIR(ContractDefinition const& _contract)
m_debugInfoSelection m_debugInfoSelection
); );
stack.parseAndAnalyze("", compiledContract.yulIROptimized); stack.parseAndAnalyze("", compiledContract.yulIROptimized);
stack.optimize();
//cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl; //cout << yul::AsmPrinter{}(*stack.parserResult()->code) << endl;

View File

@ -32,43 +32,43 @@ object "C_59" {
if gt(offset, _5) { revert(_3, _3) } if gt(offset, _5) { revert(_3, _3) }
if iszero(slt(add(offset, 35), calldatasize())) { revert(_3, _3) } if iszero(slt(add(offset, 35), calldatasize())) { revert(_3, _3) }
let _6 := calldataload(add(_2, offset)) let _6 := calldataload(add(_2, offset))
let _7 := 36
if gt(_6, _5) if gt(_6, _5)
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x41) mstore(_2, 0x41)
revert(_3, _7) revert(_3, 36)
} }
let _8 := shl(5, _6) let _7 := shl(5, _6)
let _9 := not(31) let _8 := not(31)
let newFreePtr := add(_1, and(add(_8, 63), _9)) let newFreePtr := add(_1, and(add(_7, 63), _8))
if or(gt(newFreePtr, _5), lt(newFreePtr, _1)) if or(gt(newFreePtr, _5), lt(newFreePtr, _1))
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x41) mstore(_2, 0x41)
revert(_3, _7) revert(_3, 36)
} }
let _10 := 64 let _9 := 64
mstore(_10, newFreePtr) mstore(_9, newFreePtr)
let dst := _1 let dst := _1
mstore(_1, _6) mstore(_1, _6)
dst := add(_1, _4) dst := add(_1, _4)
let dst_1 := dst let dst_1 := dst
let srcEnd := add(add(offset, _8), _7) let _10 := 36
let srcEnd := add(add(offset, _7), _10)
if gt(srcEnd, calldatasize()) { revert(_3, _3) } if gt(srcEnd, calldatasize()) { revert(_3, _3) }
let src := add(offset, _7) let src := add(offset, _10)
for { } lt(src, srcEnd) { src := add(src, _4) } for { } lt(src, srcEnd) { src := add(src, _4) }
{ {
if slt(sub(calldatasize(), src), _4) { revert(_3, _3) } if slt(sub(calldatasize(), src), _4) { revert(_3, _3) }
let memPtr := mload(_10) let memPtr := mload(_9)
let newFreePtr_1 := add(memPtr, _4) let newFreePtr_1 := add(memPtr, _4)
if or(gt(newFreePtr_1, _5), lt(newFreePtr_1, memPtr)) if or(gt(newFreePtr_1, _5), lt(newFreePtr_1, memPtr))
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x41) mstore(_2, 0x41)
revert(_3, _7) revert(_3, _10)
} }
mstore(_10, newFreePtr_1) mstore(_9, newFreePtr_1)
mstore(memPtr, calldataload(src)) mstore(memPtr, calldataload(src))
mstore(dst, memPtr) mstore(dst, memPtr)
dst := add(dst, _4) dst := add(dst, _4)
@ -77,7 +77,7 @@ object "C_59" {
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x32) mstore(_2, 0x32)
revert(_3, _7) revert(_3, _10)
} }
sstore(_3, mload(/** @src 0:469:474 "_s[0]" */ mload(dst_1))) sstore(_3, mload(/** @src 0:469:474 "_s[0]" */ mload(dst_1)))
/// @src 0:346:625 "contract C {..." /// @src 0:346:625 "contract C {..."
@ -85,37 +85,37 @@ object "C_59" {
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x32) mstore(_2, 0x32)
revert(_3, _7) revert(_3, _10)
} }
let _11 := mload(/** @src 0:489:494 "_s[1]" */ mload(/** @src 0:346:625 "contract C {..." */ add(_1, _10))) let _11 := mload(/** @src 0:489:494 "_s[1]" */ mload(/** @src 0:346:625 "contract C {..." */ add(_1, _9)))
sstore(0x02, _11) sstore(0x02, _11)
let memPtr_1 := mload(_10) let memPtr_1 := mload(_9)
let newFreePtr_2 := add(memPtr_1, 160) let newFreePtr_2 := add(memPtr_1, 160)
if or(gt(newFreePtr_2, _5), lt(newFreePtr_2, memPtr_1)) if or(gt(newFreePtr_2, _5), lt(newFreePtr_2, memPtr_1))
{ {
mstore(_3, shl(224, 0x4e487b71)) mstore(_3, shl(224, 0x4e487b71))
mstore(_2, 0x41) mstore(_2, 0x41)
revert(_3, _7) revert(_3, _10)
} }
mstore(_10, newFreePtr_2) mstore(_9, newFreePtr_2)
mstore(memPtr_1, 100) mstore(memPtr_1, 100)
mstore(add(memPtr_1, _4), "longstringlongstringlongstringlo") mstore(add(memPtr_1, _4), "longstringlongstringlongstringlo")
mstore(add(memPtr_1, _10), "ngstringlongstringlongstringlong") mstore(add(memPtr_1, _9), "ngstringlongstringlongstringlong")
let _12 := 96 let _12 := 96
mstore(add(memPtr_1, _12), "stringlongstringlongstringlongst") mstore(add(memPtr_1, _12), "stringlongstringlongstringlongst")
mstore(add(memPtr_1, 128), "ring") mstore(add(memPtr_1, 128), "ring")
let memPos := mload(_10) let memPos := mload(_9)
mstore(memPos, _11) mstore(memPos, _11)
mstore(add(memPos, _4), _10) mstore(add(memPos, _4), _9)
let length := mload(memPtr_1) let length := mload(memPtr_1)
mstore(add(memPos, _10), length) mstore(add(memPos, _9), length)
let i := _3 let i := _3
for { } lt(i, length) { i := add(i, _4) } for { } lt(i, length) { i := add(i, _4) }
{ {
mstore(add(add(memPos, i), _12), mload(add(add(memPtr_1, i), _4))) mstore(add(add(memPos, i), _12), mload(add(add(memPtr_1, i), _4)))
} }
mstore(add(add(memPos, length), _12), _3) mstore(add(add(memPos, length), _12), _3)
return(memPos, add(sub(add(memPos, and(add(length, 31), _9)), memPos), _12)) return(memPos, add(sub(add(memPos, and(add(length, 31), _8)), memPos), _12))
} }
} }
revert(0, 0) revert(0, 0)

View File

@ -102,6 +102,92 @@ object "C_6" {
let memPtr_84 := memPtr_1 let memPtr_84 := memPtr_1
let memPtr_85 := memPtr_1 let memPtr_85 := memPtr_1
let memPtr_86 := memPtr_1 let memPtr_86 := memPtr_1
let memPtr_87 := memPtr_1
let memPtr_88 := memPtr_1
let memPtr_89 := memPtr_1
let memPtr_90 := memPtr_1
let memPtr_91 := memPtr_1
let memPtr_92 := memPtr_1
let memPtr_93 := memPtr_1
let memPtr_94 := memPtr_1
let memPtr_95 := memPtr_1
let memPtr_96 := memPtr_1
let memPtr_97 := memPtr_1
let memPtr_98 := memPtr_1
let memPtr_99 := memPtr_1
let memPtr_100 := memPtr_1
let memPtr_101 := memPtr_1
let memPtr_102 := memPtr_1
let memPtr_103 := memPtr_1
let memPtr_104 := memPtr_1
let memPtr_105 := memPtr_1
let memPtr_106 := memPtr_1
let memPtr_107 := memPtr_1
let memPtr_108 := memPtr_1
let memPtr_109 := memPtr_1
let memPtr_110 := memPtr_1
let memPtr_111 := memPtr_1
let memPtr_112 := memPtr_1
let memPtr_113 := memPtr_1
let memPtr_114 := memPtr_1
let memPtr_115 := memPtr_1
let memPtr_116 := memPtr_1
let memPtr_117 := memPtr_1
let memPtr_118 := memPtr_1
let memPtr_119 := memPtr_1
let memPtr_120 := memPtr_1
let memPtr_121 := memPtr_1
let memPtr_122 := memPtr_1
let memPtr_123 := memPtr_1
let memPtr_124 := memPtr_1
let memPtr_125 := memPtr_1
let memPtr_126 := memPtr_1
let memPtr_127 := memPtr_1
let memPtr_128 := memPtr_1
let memPtr_129 := memPtr_1
let memPtr_130 := memPtr_1
let memPtr_131 := memPtr_1
let memPtr_132 := memPtr_1
let memPtr_133 := memPtr_1
let memPtr_134 := memPtr_1
let memPtr_135 := memPtr_1
let memPtr_136 := memPtr_1
let memPtr_137 := memPtr_1
let memPtr_138 := memPtr_1
let memPtr_139 := memPtr_1
let memPtr_140 := memPtr_1
let memPtr_141 := memPtr_1
let memPtr_142 := memPtr_1
let memPtr_143 := memPtr_1
let memPtr_144 := memPtr_1
let memPtr_145 := memPtr_1
let memPtr_146 := memPtr_1
let memPtr_147 := memPtr_1
let memPtr_148 := memPtr_1
let memPtr_149 := memPtr_1
let memPtr_150 := memPtr_1
let memPtr_151 := memPtr_1
let memPtr_152 := memPtr_1
let memPtr_153 := memPtr_1
let memPtr_154 := memPtr_1
let memPtr_155 := memPtr_1
let memPtr_156 := memPtr_1
let memPtr_157 := memPtr_1
let memPtr_158 := memPtr_1
let memPtr_159 := memPtr_1
let memPtr_160 := memPtr_1
let memPtr_161 := memPtr_1
let memPtr_162 := memPtr_1
let memPtr_163 := memPtr_1
let memPtr_164 := memPtr_1
let memPtr_165 := memPtr_1
let memPtr_166 := memPtr_1
let memPtr_167 := memPtr_1
let memPtr_168 := memPtr_1
let memPtr_169 := memPtr_1
let memPtr_170 := memPtr_1
let memPtr_171 := memPtr_1
let memPtr_172 := memPtr_1
memPtr := memPtr_1 memPtr := memPtr_1
} }
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
@ -210,6 +296,92 @@ object "C_6" {
let newValue_84 := newValue_1 let newValue_84 := newValue_1
let newValue_85 := newValue_1 let newValue_85 := newValue_1
let newValue_86 := newValue_1 let newValue_86 := newValue_1
let newValue_87 := newValue_1
let newValue_88 := newValue_1
let newValue_89 := newValue_1
let newValue_90 := newValue_1
let newValue_91 := newValue_1
let newValue_92 := newValue_1
let newValue_93 := newValue_1
let newValue_94 := newValue_1
let newValue_95 := newValue_1
let newValue_96 := newValue_1
let newValue_97 := newValue_1
let newValue_98 := newValue_1
let newValue_99 := newValue_1
let newValue_100 := newValue_1
let newValue_101 := newValue_1
let newValue_102 := newValue_1
let newValue_103 := newValue_1
let newValue_104 := newValue_1
let newValue_105 := newValue_1
let newValue_106 := newValue_1
let newValue_107 := newValue_1
let newValue_108 := newValue_1
let newValue_109 := newValue_1
let newValue_110 := newValue_1
let newValue_111 := newValue_1
let newValue_112 := newValue_1
let newValue_113 := newValue_1
let newValue_114 := newValue_1
let newValue_115 := newValue_1
let newValue_116 := newValue_1
let newValue_117 := newValue_1
let newValue_118 := newValue_1
let newValue_119 := newValue_1
let newValue_120 := newValue_1
let newValue_121 := newValue_1
let newValue_122 := newValue_1
let newValue_123 := newValue_1
let newValue_124 := newValue_1
let newValue_125 := newValue_1
let newValue_126 := newValue_1
let newValue_127 := newValue_1
let newValue_128 := newValue_1
let newValue_129 := newValue_1
let newValue_130 := newValue_1
let newValue_131 := newValue_1
let newValue_132 := newValue_1
let newValue_133 := newValue_1
let newValue_134 := newValue_1
let newValue_135 := newValue_1
let newValue_136 := newValue_1
let newValue_137 := newValue_1
let newValue_138 := newValue_1
let newValue_139 := newValue_1
let newValue_140 := newValue_1
let newValue_141 := newValue_1
let newValue_142 := newValue_1
let newValue_143 := newValue_1
let newValue_144 := newValue_1
let newValue_145 := newValue_1
let newValue_146 := newValue_1
let newValue_147 := newValue_1
let newValue_148 := newValue_1
let newValue_149 := newValue_1
let newValue_150 := newValue_1
let newValue_151 := newValue_1
let newValue_152 := newValue_1
let newValue_153 := newValue_1
let newValue_154 := newValue_1
let newValue_155 := newValue_1
let newValue_156 := newValue_1
let newValue_157 := newValue_1
let newValue_158 := newValue_1
let newValue_159 := newValue_1
let newValue_160 := newValue_1
let newValue_161 := newValue_1
let newValue_162 := newValue_1
let newValue_163 := newValue_1
let newValue_164 := newValue_1
let newValue_165 := newValue_1
let newValue_166 := newValue_1
let newValue_167 := newValue_1
let newValue_168 := newValue_1
let newValue_169 := newValue_1
let newValue_170 := newValue_1
let newValue_171 := newValue_1
let newValue_172 := newValue_1
newValue := newValue_1 newValue := newValue_1
} }
function allocate_unbounded() -> memPtr function allocate_unbounded() -> memPtr
@ -300,6 +472,92 @@ object "C_6" {
let memPtr_84 := memPtr_1 let memPtr_84 := memPtr_1
let memPtr_85 := memPtr_1 let memPtr_85 := memPtr_1
let memPtr_86 := memPtr_1 let memPtr_86 := memPtr_1
let memPtr_87 := memPtr_1
let memPtr_88 := memPtr_1
let memPtr_89 := memPtr_1
let memPtr_90 := memPtr_1
let memPtr_91 := memPtr_1
let memPtr_92 := memPtr_1
let memPtr_93 := memPtr_1
let memPtr_94 := memPtr_1
let memPtr_95 := memPtr_1
let memPtr_96 := memPtr_1
let memPtr_97 := memPtr_1
let memPtr_98 := memPtr_1
let memPtr_99 := memPtr_1
let memPtr_100 := memPtr_1
let memPtr_101 := memPtr_1
let memPtr_102 := memPtr_1
let memPtr_103 := memPtr_1
let memPtr_104 := memPtr_1
let memPtr_105 := memPtr_1
let memPtr_106 := memPtr_1
let memPtr_107 := memPtr_1
let memPtr_108 := memPtr_1
let memPtr_109 := memPtr_1
let memPtr_110 := memPtr_1
let memPtr_111 := memPtr_1
let memPtr_112 := memPtr_1
let memPtr_113 := memPtr_1
let memPtr_114 := memPtr_1
let memPtr_115 := memPtr_1
let memPtr_116 := memPtr_1
let memPtr_117 := memPtr_1
let memPtr_118 := memPtr_1
let memPtr_119 := memPtr_1
let memPtr_120 := memPtr_1
let memPtr_121 := memPtr_1
let memPtr_122 := memPtr_1
let memPtr_123 := memPtr_1
let memPtr_124 := memPtr_1
let memPtr_125 := memPtr_1
let memPtr_126 := memPtr_1
let memPtr_127 := memPtr_1
let memPtr_128 := memPtr_1
let memPtr_129 := memPtr_1
let memPtr_130 := memPtr_1
let memPtr_131 := memPtr_1
let memPtr_132 := memPtr_1
let memPtr_133 := memPtr_1
let memPtr_134 := memPtr_1
let memPtr_135 := memPtr_1
let memPtr_136 := memPtr_1
let memPtr_137 := memPtr_1
let memPtr_138 := memPtr_1
let memPtr_139 := memPtr_1
let memPtr_140 := memPtr_1
let memPtr_141 := memPtr_1
let memPtr_142 := memPtr_1
let memPtr_143 := memPtr_1
let memPtr_144 := memPtr_1
let memPtr_145 := memPtr_1
let memPtr_146 := memPtr_1
let memPtr_147 := memPtr_1
let memPtr_148 := memPtr_1
let memPtr_149 := memPtr_1
let memPtr_150 := memPtr_1
let memPtr_151 := memPtr_1
let memPtr_152 := memPtr_1
let memPtr_153 := memPtr_1
let memPtr_154 := memPtr_1
let memPtr_155 := memPtr_1
let memPtr_156 := memPtr_1
let memPtr_157 := memPtr_1
let memPtr_158 := memPtr_1
let memPtr_159 := memPtr_1
let memPtr_160 := memPtr_1
let memPtr_161 := memPtr_1
let memPtr_162 := memPtr_1
let memPtr_163 := memPtr_1
let memPtr_164 := memPtr_1
let memPtr_165 := memPtr_1
let memPtr_166 := memPtr_1
let memPtr_167 := memPtr_1
let memPtr_168 := memPtr_1
let memPtr_169 := memPtr_1
let memPtr_170 := memPtr_1
let memPtr_171 := memPtr_1
let memPtr_172 := memPtr_1
memPtr := memPtr_1 memPtr := memPtr_1
} }
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
@ -401,6 +659,92 @@ object "C_6" {
let tail_84 := tail_1 let tail_84 := tail_1
let tail_85 := tail_1 let tail_85 := tail_1
let tail_86 := tail_1 let tail_86 := tail_1
let tail_87 := tail_1
let tail_88 := tail_1
let tail_89 := tail_1
let tail_90 := tail_1
let tail_91 := tail_1
let tail_92 := tail_1
let tail_93 := tail_1
let tail_94 := tail_1
let tail_95 := tail_1
let tail_96 := tail_1
let tail_97 := tail_1
let tail_98 := tail_1
let tail_99 := tail_1
let tail_100 := tail_1
let tail_101 := tail_1
let tail_102 := tail_1
let tail_103 := tail_1
let tail_104 := tail_1
let tail_105 := tail_1
let tail_106 := tail_1
let tail_107 := tail_1
let tail_108 := tail_1
let tail_109 := tail_1
let tail_110 := tail_1
let tail_111 := tail_1
let tail_112 := tail_1
let tail_113 := tail_1
let tail_114 := tail_1
let tail_115 := tail_1
let tail_116 := tail_1
let tail_117 := tail_1
let tail_118 := tail_1
let tail_119 := tail_1
let tail_120 := tail_1
let tail_121 := tail_1
let tail_122 := tail_1
let tail_123 := tail_1
let tail_124 := tail_1
let tail_125 := tail_1
let tail_126 := tail_1
let tail_127 := tail_1
let tail_128 := tail_1
let tail_129 := tail_1
let tail_130 := tail_1
let tail_131 := tail_1
let tail_132 := tail_1
let tail_133 := tail_1
let tail_134 := tail_1
let tail_135 := tail_1
let tail_136 := tail_1
let tail_137 := tail_1
let tail_138 := tail_1
let tail_139 := tail_1
let tail_140 := tail_1
let tail_141 := tail_1
let tail_142 := tail_1
let tail_143 := tail_1
let tail_144 := tail_1
let tail_145 := tail_1
let tail_146 := tail_1
let tail_147 := tail_1
let tail_148 := tail_1
let tail_149 := tail_1
let tail_150 := tail_1
let tail_151 := tail_1
let tail_152 := tail_1
let tail_153 := tail_1
let tail_154 := tail_1
let tail_155 := tail_1
let tail_156 := tail_1
let tail_157 := tail_1
let tail_158 := tail_1
let tail_159 := tail_1
let tail_160 := tail_1
let tail_161 := tail_1
let tail_162 := tail_1
let tail_163 := tail_1
let tail_164 := tail_1
let tail_165 := tail_1
let tail_166 := tail_1
let tail_167 := tail_1
let tail_168 := tail_1
let tail_169 := tail_1
let tail_170 := tail_1
let tail_171 := tail_1
let tail_172 := tail_1
tail := tail_1 tail := tail_1
} }
function external_fun_f() function external_fun_f()

View File

@ -31,7 +31,7 @@ contract C {
// compileViaYul: true // compileViaYul: true
// ---- // ----
// test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 // test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29
// gas irOptimized: 304768 // gas irOptimized: 304765
// test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 // test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 116476 // gas irOptimized: 116476
// test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 // test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13

View File

@ -18,7 +18,7 @@ contract c {
} }
// ---- // ----
// test() -> 38, 28, 18 // test() -> 38, 28, 18
// gas irOptimized: 148520 // gas irOptimized: 148525
// gas legacy: 151594 // gas legacy: 151594
// gas legacyOptimized: 142655 // gas legacyOptimized: 142655
// storageEmpty -> 1 // storageEmpty -> 1