Skip to content

Instantly share code, notes, and snippets.

Optimized IR:
/*******************************************************
,* WARNING *
,* Solidity to Yul compilation is still EXPERIMENTAL *
,* It can result in LOSS OF FUNDS or worse *
,* !USE AT YOUR OWN RISK! *
,*******************************************************/
object "C_164" {
code {
@hrkrshnn
hrkrshnn / proof.py
Last active September 24, 2020 14:49
from rule import Rule
from opcodes import *
rule = Rule()
for i in range(1, 25):
X = BitVec('X', 8*i)
Y = BitVec('Y', 8*i)
max = 2**(8*i) - 1
rule.check(
@hrkrshnn
hrkrshnn / after.yul
Last active October 6, 2020 17:51 — forked from ekpyron/after.yul
{
{
mstore(64, memoryguard(0x0120))
if iszero(lt(calldatasize(), 4))
{
switch shift_right_224_unsigned(calldataload(0))
case 0x13d1aa2e {
let param_0, param_1 := abi_decode_tuple_t_uint256t_uint256(4, calldatasize())
let ret_0 := fun_f_23(param_0, param_1)
let memPos := allocateMemory(0)
@hrkrshnn
hrkrshnn / optional-move.cpp
Created November 3, 2020 19:43
A test to see if objects can be moved out of optional
#include <iostream>
#include <optional>
struct A
{
A() { }
A(A const& a) { std::cout << "move construction failed!\n"; }
A(A&& o) { std::cout << "moved construction worked!\n"; }
A& operator=(A const& other) {
std::cout << "move assignment failed!\n";

When you're looping over an array from front to back, does it make sense to cache arr.length in a stack variable, or will it SLOAD/MLOAD that only once if it sees it won't change in the loop body

In the Yul optimizer (for the new code generator), there is an optimization step LoopInvariantCodeMotion designed to detect expressions that remain invariant in the loop and move them outside the loop. Take the following solidity example that finds the sum of a dynamic integer array in storage.

        uint sum = 0;
        for (uint i = 0; i < arr.length; ++i)
        {
            sum += arr[i];
 }
modified test/libyul/YulOptimizerTest.cpp
@@ -300,17 +300,17 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
}
else if (m_optimizerStep == "loadResolver")
{
- disambiguate();
- ForLoopInitRewriter::run(*m_context, *m_object->code);
- ExpressionSplitter::run(*m_context, *m_object->code);
- CommonSubexpressionEliminator::run(*m_context, *m_object->code);
- ExpressionSimplifier::run(*m_context, *m_object->code);
000- 1-1
31-110
31101

Fix the first column

62000
31-110
{
let _2296 := 128
let _2297 := 64
mstore(_2297, _2296)
let _4 := calldatasize()
let _2298 := 4
let _2299 := lt(_4, _2298)
let _2300 := iszero(_2299)
if _2300
{
pragma experimental SMTChecker;
contract A {
int public x;
event Ee(string);
function f() public virtual {
x = 1;
emit Ee(type(A).name);
}
}
diff -u /tmp/old.txt /tmp/new.txt
--- /tmp/old.txt 2021-02-01 20:13:33.637282924 +0100
+++ /tmp/new.txt 2021-02-01 20:14:02.415177046 +0100
@@ -1,7 +1,7 @@
-======= <stdin>:C =======
+======= optimizer_inliner_inc/input.sol:C =======
EVM assembly:
- /* "<stdin>":157:279 contract C {... */
+ /* "optimizer_inliner_inc/input.sol":157:279 contract C {... */