Merge pull request #9895 from ethereum/exp-negative-one

Optimize exp when base is -1
This commit is contained in:
chriseth 2020-09-30 11:54:22 +02:00 committed by GitHub
commit 7a86a61b08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 0 deletions

View File

@ -2,6 +2,7 @@
Compiler Features: Compiler Features:
* SMTChecker: Support ``addmod`` and ``mulmod``. * SMTChecker: Support ``addmod`` and ``mulmod``.
* Optimizer: Optimize ``exp`` when base is -1.
### 0.7.2 (2020-09-28) ### 0.7.2 (2020-09-28)

View File

@ -643,6 +643,16 @@ std::vector<SimplificationRule<Pattern>> evmRuleList(
Builtins::EXP(2, X), Builtins::EXP(2, X),
[=]() -> Pattern { return Builtins::SHL(X, 1); } [=]() -> Pattern { return Builtins::SHL(X, 1); }
); );
rules.emplace_back(
Builtins::EXP(Word(-1), X),
[=]() -> Pattern
{
return Builtins::SUB(
Builtins::ISZERO(Builtins::AND(X, Word(1))),
Builtins::AND(X, Word(1))
);
}
);
return rules; return rules;
} }

View File

@ -0,0 +1,16 @@
from rule import Rule
from opcodes import *
from util import *
"""
Checking conversion of exp(-1, X) to sub(isZero(and(X, 1)), and(X, 1))
"""
rule = Rule()
n_bits = 256
X = BitVec('X', n_bits)
exp_neg_one = If(MOD(X, 2) == 0, BitVecVal(1, n_bits), BVUnsignedMax(n_bits, n_bits))
rule.check(SUB(ISZERO(AND(X, 1)), AND(X, 1)), exp_neg_one)

View File

@ -0,0 +1,29 @@
pragma experimental ABIEncoderV2;
contract C {
function exp_neg_one(uint exponent) public returns(int) {
return (-1)**exponent;
}
function exp_two(uint exponent) public returns(uint) {
return 2**exponent;
}
function exp_zero(uint exponent) public returns(uint) {
return 0**exponent;
}
function exp_one(uint exponent) public returns(uint) {
return 1**exponent;
}
}
// ====
// optimize: false
// optimize-yul: false
// ----
// creation:
// codeDepositCost: 119800
// executionCost: 165
// totalCost: 119965
// external:
// exp_neg_one(uint256): 2259
// exp_one(uint256): infinite
// exp_two(uint256): infinite
// exp_zero(uint256): infinite

View File

@ -0,0 +1,29 @@
pragma experimental ABIEncoderV2;
contract C {
function exp_neg_one(uint exponent) public returns(int) {
return (-1)**exponent;
}
function exp_two(uint exponent) public returns(uint) {
return 2**exponent;
}
function exp_zero(uint exponent) public returns(uint) {
return 0**exponent;
}
function exp_one(uint exponent) public returns(uint) {
return 1**exponent;
}
}
// ====
// optimize: true
// optimize-yul: true
// ----
// creation:
// codeDepositCost: 53200
// executionCost: 105
// totalCost: 53305
// external:
// exp_neg_one(uint256): 1962
// exp_one(uint256): 1915
// exp_two(uint256): 1893
// exp_zero(uint256): 1937

View File

@ -5,6 +5,7 @@
sstore(2, exp(2, t)) sstore(2, exp(2, t))
// The following should not be simplified // The following should not be simplified
sstore(3, exp(8, t)) sstore(3, exp(8, t))
sstore(4, exp(115792089237316195423570985008687907853269984665640564039457584007913129639935, t))
} }
// ==== // ====
// EVMVersion: >=constantinople // EVMVersion: >=constantinople
@ -19,4 +20,5 @@
// let _8 := 2 // let _8 := 2
// sstore(_8, shl(t, 1)) // sstore(_8, shl(t, 1))
// sstore(3, exp(8, t)) // sstore(3, exp(8, t))
// sstore(4, sub(iszero(and(t, 1)), and(t, 1)))
// } // }