Skip to content

Commit

Permalink
Branchless opt
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Sep 12, 2022
1 parent bff24e8 commit 0ee185d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 40 deletions.
44 changes: 22 additions & 22 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ AuthTest:testSetOwnerWithPermissiveAuthority(address,address) (runs: 256, μ: 13
Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223)
Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191)
CREATE3Test:testDeployERC20() (gas: 853111)
CREATE3Test:testDeployERC20(bytes32,string,string,uint8) (runs: 256, μ: 923845, ~: 921961)
CREATE3Test:testDeployERC20(bytes32,string,string,uint8) (runs: 256, μ: 924106, ~: 921961)
CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778914174)
CREATE3Test:testFailDoubleDeployDifferentBytecode(bytes32,bytes,bytes) (runs: 256, μ: 5062195514745832485, ~: 8937393460516727435)
CREATE3Test:testFailDoubleDeployDifferentBytecode(bytes32,bytes,bytes) (runs: 256, μ: 5097107207950975695, ~: 8937393460516727446)
CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218)
CREATE3Test:testFailDoubleDeploySameBytecode(bytes32,bytes) (runs: 256, μ: 5027837975401088877, ~: 8937393460516728677)
CREATE3Test:testFailDoubleDeploySameBytecode(bytes32,bytes) (runs: 256, μ: 5062749668606232091, ~: 8937393460516728689)
DSTestPlusTest:testBound() (gas: 14214)
DSTestPlusTest:testBound(uint256,uint256,uint256) (runs: 256, μ: 2787, ~: 2793)
DSTestPlusTest:testBrutalizeMemory() (gas: 823)
Expand Down Expand Up @@ -115,8 +115,8 @@ ERC1155Test:testSafeTransferFromToEOA() (gas: 93167)
ERC1155Test:testSafeTransferFromToEOA(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 93478, ~: 97450)
ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 739583)
ERC1155Test:testSafeTransferFromToERC1155Recipient(uint256,uint256,bytes,uint256,bytes) (runs: 256, μ: 769591, ~: 765729)
ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2388)
ERC20Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2606)
ERC20Invariants:invariantBalanceSum (runs: 256, calls: 3840, reverts: 2388)
ERC20Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2560)
ERC20Test:testApprove() (gas: 31058)
ERC20Test:testApprove(address,uint256) (runs: 256, μ: 30424, ~: 31280)
ERC20Test:testBurn() (gas: 56970)
Expand All @@ -137,16 +137,16 @@ ERC20Test:testFailTransferFromInsufficientBalance(address,uint256,uint256) (runs
ERC20Test:testFailTransferInsufficientBalance() (gas: 52806)
ERC20Test:testFailTransferInsufficientBalance(address,uint256,uint256) (runs: 256, μ: 51720, ~: 55310)
ERC20Test:testInfiniteApproveTransferFrom() (gas: 89793)
ERC20Test:testMetadata(string,string,uint8) (runs: 256, μ: 870618, ~: 863277)
ERC20Test:testMetadata(string,string,uint8) (runs: 256, μ: 868512, ~: 863173)
ERC20Test:testMint() (gas: 53746)
ERC20Test:testMint(address,uint256) (runs: 256, μ: 52214, ~: 53925)
ERC20Test:testPermit() (gas: 63193)
ERC20Test:testPermit(uint248,address,uint256,uint256) (runs: 256, μ: 62584, ~: 63517)
ERC20Test:testTransfer() (gas: 60272)
ERC20Test:testTransfer(address,uint256) (runs: 256, μ: 58773, ~: 60484)
ERC20Test:testTransferFrom() (gas: 83777)
ERC20Test:testTransferFrom(address,uint256,uint256) (runs: 256, μ: 86464, ~: 92841)
ERC4626Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2881)
ERC20Test:testTransferFrom(address,uint256,uint256) (runs: 256, μ: 86308, ~: 92841)
ERC4626Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2881)
ERC4626Test:testFailDepositWithNoApproval() (gas: 13357)
ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86993)
ERC4626Test:testFailDepositZero() (gas: 7780)
Expand All @@ -163,7 +163,7 @@ ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 201569, ~: 201579
ERC4626Test:testSingleMintRedeem(uint128) (runs: 256, μ: 201484, ~: 201494)
ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286247)
ERC4626Test:testWithdrawZero() (gas: 52462)
ERC721Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2170)
ERC721Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2170)
ERC721Test:testApprove() (gas: 78427)
ERC721Test:testApprove(address,uint256) (runs: 256, μ: 78637, ~: 78637)
ERC721Test:testApproveAll() (gas: 31063)
Expand Down Expand Up @@ -240,17 +240,17 @@ ERC721Test:testTransferFromApproveAll() (gas: 92898)
ERC721Test:testTransferFromApproveAll(uint256,address) (runs: 256, μ: 93182, ~: 93182)
ERC721Test:testTransferFromSelf() (gas: 64776)
ERC721Test:testTransferFromSelf(uint256,address) (runs: 256, μ: 65061, ~: 65061)
FixedPointMathLibTest:testDifferentiallyFuzzSqrt(uint256) (runs: 256, μ: 13827, ~: 4181)
FixedPointMathLibTest:testDifferentiallyFuzzSqrt(uint256) (runs: 256, μ: 13819, ~: 4231)
FixedPointMathLibTest:testDivWadDown() (gas: 841)
FixedPointMathLibTest:testDivWadDown(uint256,uint256) (runs: 256, μ: 718, ~: 820)
FixedPointMathLibTest:testDivWadDown(uint256,uint256) (runs: 256, μ: 717, ~: 820)
FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 446)
FixedPointMathLibTest:testDivWadUp() (gas: 1003)
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 809, ~: 972)
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 807, ~: 972)
FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 462)
FixedPointMathLibTest:testFailDivWadDownOverflow(uint256,uint256) (runs: 256, μ: 443, ~: 419)
FixedPointMathLibTest:testFailDivWadDownOverflow(uint256,uint256) (runs: 256, μ: 444, ~: 419)
FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 342)
FixedPointMathLibTest:testFailDivWadDownZeroDenominator(uint256) (runs: 256, μ: 397, ~: 397)
FixedPointMathLibTest:testFailDivWadUpOverflow(uint256,uint256) (runs: 256, μ: 398, ~: 374)
FixedPointMathLibTest:testFailDivWadUpOverflow(uint256,uint256) (runs: 256, μ: 399, ~: 374)
FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 342)
FixedPointMathLibTest:testFailDivWadUpZeroDenominator(uint256) (runs: 256, μ: 396, ~: 396)
FixedPointMathLibTest:testFailMulDivDownOverflow(uint256,uint256,uint256) (runs: 256, μ: 437, ~: 414)
Expand All @@ -274,12 +274,12 @@ FixedPointMathLibTest:testMulWadUp() (gas: 981)
FixedPointMathLibTest:testMulWadUp(uint256,uint256) (runs: 256, μ: 835, ~: 1073)
FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 959)
FixedPointMathLibTest:testRPow() (gas: 2164)
FixedPointMathLibTest:testSqrt() (gas: 2580)
FixedPointMathLibTest:testSqrt(uint256) (runs: 256, μ: 997, ~: 1013)
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 15210, ~: 340)
FixedPointMathLibTest:testSqrtBackHashed(uint256) (runs: 256, μ: 59040, ~: 59500)
FixedPointMathLibTest:testSqrtBackHashedSingle() (gas: 58937)
LibStringTest:testDifferentiallyFuzzToString(uint256,bytes) (runs: 256, μ: 20749, ~: 8925)
FixedPointMathLibTest:testSqrt() (gas: 600)
FixedPointMathLibTest:testSqrt(uint256) (runs: 256, μ: 990, ~: 1038)
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 14665, ~: 340)
FixedPointMathLibTest:testSqrtBackHashed(uint256) (runs: 256, μ: 56528, ~: 56940)
FixedPointMathLibTest:testSqrtBackHashedSingle() (gas: 56448)
LibStringTest:testDifferentiallyFuzzToString(uint256,bytes) (runs: 256, μ: 21006, ~: 9531)
LibStringTest:testToString() (gas: 10047)
LibStringTest:testToStringDirty() (gas: 8123)
LibStringTest:testToStringOverwrite() (gas: 484)
Expand Down Expand Up @@ -310,7 +310,7 @@ OwnedTest:testCallFunctionAsNonOwner(address) (runs: 256, μ: 16238, ~: 16257)
OwnedTest:testCallFunctionAsOwner() (gas: 10479)
OwnedTest:testSetOwner() (gas: 13035)
OwnedTest:testSetOwner(address) (runs: 256, μ: 13151, ~: 13170)
ReentrancyGuardTest:invariantReentrancyStatusAlways1() (runs: 256, calls: 3840, reverts: 319)
ReentrancyGuardTest:invariantReentrancyStatusAlways1 (runs: 256, calls: 3840, reverts: 319)
ReentrancyGuardTest:testFailUnprotectedCall() (gas: 46147)
ReentrancyGuardTest:testNoReentrancy() (gas: 7515)
ReentrancyGuardTest:testProtectedCall() (gas: 33467)
Expand Down Expand Up @@ -446,7 +446,7 @@ SignedWadMathTest:testFailWadDivZeroDenominator(int256) (runs: 256, μ: 296, ~:
SignedWadMathTest:testFailWadMulOverflow(int256,int256) (runs: 256, μ: 323, ~: 296)
SignedWadMathTest:testWadDiv(uint256,uint256,bool,bool) (runs: 256, μ: 5696, ~: 5664)
SignedWadMathTest:testWadMul(uint256,uint256,bool,bool) (runs: 256, μ: 5720, ~: 5688)
WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 256, calls: 3840, reverts: 1908)
WETHInvariants:invariantTotalSupplyEqualsBalance (runs: 256, calls: 3840, reverts: 1908)
WETHTest:testDeposit() (gas: 63535)
WETHTest:testDeposit(uint256) (runs: 256, μ: 62792, ~: 65880)
WETHTest:testFallbackDeposit() (gas: 63249)
Expand Down
2 changes: 1 addition & 1 deletion lib/ds-test
Submodule ds-test updated 2 files
+22 −21 demo/demo.sol
+4 −4 src/test.sol
24 changes: 7 additions & 17 deletions src/utils/FixedPointMathLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -172,24 +172,14 @@ library FixedPointMathLib {
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

// Let y = x / 2**r, where r = lg2(x/65536).
// We check y >= 2^(k + 8) but shift right by k bits
// each branch to ensure that if x >= 256, then y >= 256.
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
let r := shl(7, gt(x, 0xffffffffffffffffffffffffffffffffff))
r := or(r, shl(6, gt(shr(r, x), 0xffffffffffffffffff)))
r := or(r, shl(5, gt(shr(r, x), 0xffffffffff)))
r := or(r, shl(4, gt(shr(r, x), 0xffffff)))
z := shl(shr(1, r), z)

// Goal was to get z*z*y within a small factor of x. More iterations could
// get y in a tighter range. Currently, we will have y in [256, 256*2^16).
Expand All @@ -207,7 +197,7 @@ library FixedPointMathLib {
// sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

// There is no overflow risk here since y < 2^136 after the first branch above.
z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.
z := shr(18, mul(z, add(shr(r, x), 65536))) // A mul() is saved from starting z at 181.

// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
z := shr(1, add(z, div(x, z)))
Expand Down

0 comments on commit 0ee185d

Please sign in to comment.