mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move AND with constant inside OR.
This commit is contained in:
parent
1d95f95635
commit
40c27ccc22
@ -4,6 +4,7 @@ Language Features:
|
|||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Optimizer: Try to move ``and`` with constant inside ``or`` to improve storage writes of small types.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -507,6 +507,23 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combine alternating AND/OR/AND with constant,
|
||||||
|
// AND(OR(AND(X, A), Y), B) -> OR(AND(X, A & B), AND(Y, B))
|
||||||
|
// Many versions due to commutativity.
|
||||||
|
for (auto const& inner: {Builtins::AND(X, A), Builtins::AND(A, X)})
|
||||||
|
for (auto const& second: {Builtins::OR(inner, Y), Builtins::OR(Y, inner)})
|
||||||
|
{
|
||||||
|
// We might swap X and Y but this is not an issue anymore.
|
||||||
|
rules.push_back({
|
||||||
|
Builtins::AND(second, B),
|
||||||
|
[=]() -> Pattern { return Builtins::OR(Builtins::AND(X, A.d() & B.d()), Builtins::AND(Y, B)); }
|
||||||
|
});
|
||||||
|
rules.push_back({
|
||||||
|
Builtins::AND(B, second),
|
||||||
|
[=]() -> Pattern { return Builtins::OR(Builtins::AND(X, A.d() & B.d()), Builtins::AND(Y, B)); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
rules.push_back({
|
rules.push_back({
|
||||||
// MUL(X, SHL(Y, 1)) -> SHL(Y, X)
|
// MUL(X, SHL(Y, 1)) -> SHL(Y, X)
|
||||||
Builtins::MUL(X, Builtins::SHL(Y, Word(1))),
|
Builtins::MUL(X, Builtins::SHL(Y, Word(1))),
|
||||||
|
1
test/cmdlineTests/optimize_full_storage_write/args
Normal file
1
test/cmdlineTests/optimize_full_storage_write/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--optimize --asm --metadata-hash none
|
12
test/cmdlineTests/optimize_full_storage_write/input.sol
Normal file
12
test/cmdlineTests/optimize_full_storage_write/input.sol
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
contract OptimizeFullSlotWrite {
|
||||||
|
uint64[4] nums;
|
||||||
|
function f() public {
|
||||||
|
nums[0] = 11111;
|
||||||
|
nums[1] = 22222;
|
||||||
|
nums[2] = 33333;
|
||||||
|
nums[3] = 44444;
|
||||||
|
}
|
||||||
|
}
|
64
test/cmdlineTests/optimize_full_storage_write/output
Normal file
64
test/cmdlineTests/optimize_full_storage_write/output
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
======= optimize_full_storage_write/input.sol:OptimizeFullSlotWrite =======
|
||||||
|
EVM assembly:
|
||||||
|
/* "optimize_full_storage_write/input.sol":60:213 contract OptimizeFullSlotWrite {... */
|
||||||
|
mstore(0x40, 0x80)
|
||||||
|
callvalue
|
||||||
|
dup1
|
||||||
|
iszero
|
||||||
|
tag_1
|
||||||
|
jumpi
|
||||||
|
0x00
|
||||||
|
dup1
|
||||||
|
revert
|
||||||
|
tag_1:
|
||||||
|
pop
|
||||||
|
dataSize(sub_0)
|
||||||
|
dup1
|
||||||
|
dataOffset(sub_0)
|
||||||
|
0x00
|
||||||
|
codecopy
|
||||||
|
0x00
|
||||||
|
return
|
||||||
|
stop
|
||||||
|
|
||||||
|
sub_0: assembly {
|
||||||
|
/* "optimize_full_storage_write/input.sol":60:213 contract OptimizeFullSlotWrite {... */
|
||||||
|
mstore(0x40, 0x80)
|
||||||
|
callvalue
|
||||||
|
dup1
|
||||||
|
iszero
|
||||||
|
tag_1
|
||||||
|
jumpi
|
||||||
|
0x00
|
||||||
|
dup1
|
||||||
|
revert
|
||||||
|
tag_1:
|
||||||
|
pop
|
||||||
|
jumpi(tag_2, lt(calldatasize, 0x04))
|
||||||
|
shr(0xe0, calldataload(0x00))
|
||||||
|
dup1
|
||||||
|
0x26121ff0
|
||||||
|
eq
|
||||||
|
tag_3
|
||||||
|
jumpi
|
||||||
|
tag_2:
|
||||||
|
0x00
|
||||||
|
dup1
|
||||||
|
revert
|
||||||
|
/* "optimize_full_storage_write/input.sol":111:211 function f() public {... */
|
||||||
|
tag_3:
|
||||||
|
tag_4
|
||||||
|
/* "optimize_full_storage_write/input.sol":192:207 nums[3] = 44444 */
|
||||||
|
0xad9c000000000000823500000000000056ce0000000000002b67
|
||||||
|
/* "optimize_full_storage_write/input.sol":135:139 nums */
|
||||||
|
0x00
|
||||||
|
/* "optimize_full_storage_write/input.sol":192:207 nums[3] = 44444 */
|
||||||
|
sstore
|
||||||
|
/* "optimize_full_storage_write/input.sol":111:211 function f() public {... */
|
||||||
|
jump
|
||||||
|
tag_4:
|
||||||
|
stop
|
||||||
|
|
||||||
|
auxdata: <AUXDATA REMOVED>
|
||||||
|
}
|
32
test/formal/move_and_inside_or.py
Normal file
32
test/formal/move_and_inside_or.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from rule import Rule
|
||||||
|
from opcodes import *
|
||||||
|
|
||||||
|
"""
|
||||||
|
Rule:
|
||||||
|
AND(OR(AND(X, A), Y), B) -> OR(AND(X, A & B), AND(Y, B))
|
||||||
|
"""
|
||||||
|
|
||||||
|
rule = Rule()
|
||||||
|
|
||||||
|
# bit width is irrelevant
|
||||||
|
n_bits = 128
|
||||||
|
|
||||||
|
# Input vars
|
||||||
|
X = BitVec('X', n_bits)
|
||||||
|
Y = BitVec('Y', n_bits)
|
||||||
|
A = BitVec('A', n_bits)
|
||||||
|
B = BitVec('B', n_bits)
|
||||||
|
|
||||||
|
# Non optimized result, explicit form
|
||||||
|
nonopt = AND(OR(AND(X, A), Y), B)
|
||||||
|
|
||||||
|
# Optimized result
|
||||||
|
opt = OR(AND(X, A & B), AND(Y, B))
|
||||||
|
|
||||||
|
rule.check(nonopt, opt)
|
||||||
|
|
||||||
|
# Now the forms as they are constructod in the code.
|
||||||
|
for inner in [AND(X, A), AND(A, X)]:
|
||||||
|
for second in [OR(inner, Y), OR(Y, inner)]:
|
||||||
|
rule.check(AND(second, B), opt)
|
||||||
|
rule.check(AND(B, second), opt)
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
// Tests that masks that "add" up to
|
||||||
|
// the full bit width are removed.
|
||||||
|
let a := sload(0)
|
||||||
|
let x := sload(a)
|
||||||
|
let mask := 0xffffffffffffffff
|
||||||
|
x := or(and(x, not(mask)), 0x2b67)
|
||||||
|
mask := shl(64, mask)
|
||||||
|
x := or(and(x, not(mask)), 0x56ce0000000000000000)
|
||||||
|
mask := shl(64, mask)
|
||||||
|
x := or(and(x, not(mask)), shl(0x80, 0x8235))
|
||||||
|
mask := shl(64, mask)
|
||||||
|
x := or(and(x, not(mask)), shl(0xc2, 0x2b67))
|
||||||
|
sstore(a, x)
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >byzantium
|
||||||
|
// ----
|
||||||
|
// step: fullSuite
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// sstore(sload(0), 0xad9c000000000000823500000000000056ce0000000000002b67)
|
||||||
|
// }
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user