Skip to content

Commit 0ee185d

Browse files
committed
Branchless opt
1 parent bff24e8 commit 0ee185d

File tree

3 files changed

+30
-40
lines changed

3 files changed

+30
-40
lines changed

.gas-snapshot

+22-22
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ AuthTest:testSetOwnerWithPermissiveAuthority(address,address) (runs: 256, μ: 13
2828
Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223)
2929
Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191)
3030
CREATE3Test:testDeployERC20() (gas: 853111)
31-
CREATE3Test:testDeployERC20(bytes32,string,string,uint8) (runs: 256, μ: 923845, ~: 921961)
31+
CREATE3Test:testDeployERC20(bytes32,string,string,uint8) (runs: 256, μ: 924106, ~: 921961)
3232
CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778914174)
33-
CREATE3Test:testFailDoubleDeployDifferentBytecode(bytes32,bytes,bytes) (runs: 256, μ: 5062195514745832485, ~: 8937393460516727435)
33+
CREATE3Test:testFailDoubleDeployDifferentBytecode(bytes32,bytes,bytes) (runs: 256, μ: 5097107207950975695, ~: 8937393460516727446)
3434
CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218)
35-
CREATE3Test:testFailDoubleDeploySameBytecode(bytes32,bytes) (runs: 256, μ: 5027837975401088877, ~: 8937393460516728677)
35+
CREATE3Test:testFailDoubleDeploySameBytecode(bytes32,bytes) (runs: 256, μ: 5062749668606232091, ~: 8937393460516728689)
3636
DSTestPlusTest:testBound() (gas: 14214)
3737
DSTestPlusTest:testBound(uint256,uint256,uint256) (runs: 256, μ: 2787, ~: 2793)
3838
DSTestPlusTest:testBrutalizeMemory() (gas: 823)
@@ -115,8 +115,8 @@ ERC1155Test:testSafeTransferFromToEOA() (gas: 93167)
115115
ERC1155Test:testSafeTransferFromToEOA(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 93478, ~: 97450)
116116
ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 739583)
117117
ERC1155Test:testSafeTransferFromToERC1155Recipient(uint256,uint256,bytes,uint256,bytes) (runs: 256, μ: 769591, ~: 765729)
118-
ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2388)
119-
ERC20Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2606)
118+
ERC20Invariants:invariantBalanceSum (runs: 256, calls: 3840, reverts: 2388)
119+
ERC20Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2560)
120120
ERC20Test:testApprove() (gas: 31058)
121121
ERC20Test:testApprove(address,uint256) (runs: 256, μ: 30424, ~: 31280)
122122
ERC20Test:testBurn() (gas: 56970)
@@ -137,16 +137,16 @@ ERC20Test:testFailTransferFromInsufficientBalance(address,uint256,uint256) (runs
137137
ERC20Test:testFailTransferInsufficientBalance() (gas: 52806)
138138
ERC20Test:testFailTransferInsufficientBalance(address,uint256,uint256) (runs: 256, μ: 51720, ~: 55310)
139139
ERC20Test:testInfiniteApproveTransferFrom() (gas: 89793)
140-
ERC20Test:testMetadata(string,string,uint8) (runs: 256, μ: 870618, ~: 863277)
140+
ERC20Test:testMetadata(string,string,uint8) (runs: 256, μ: 868512, ~: 863173)
141141
ERC20Test:testMint() (gas: 53746)
142142
ERC20Test:testMint(address,uint256) (runs: 256, μ: 52214, ~: 53925)
143143
ERC20Test:testPermit() (gas: 63193)
144144
ERC20Test:testPermit(uint248,address,uint256,uint256) (runs: 256, μ: 62584, ~: 63517)
145145
ERC20Test:testTransfer() (gas: 60272)
146146
ERC20Test:testTransfer(address,uint256) (runs: 256, μ: 58773, ~: 60484)
147147
ERC20Test:testTransferFrom() (gas: 83777)
148-
ERC20Test:testTransferFrom(address,uint256,uint256) (runs: 256, μ: 86464, ~: 92841)
149-
ERC4626Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2881)
148+
ERC20Test:testTransferFrom(address,uint256,uint256) (runs: 256, μ: 86308, ~: 92841)
149+
ERC4626Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2881)
150150
ERC4626Test:testFailDepositWithNoApproval() (gas: 13357)
151151
ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86993)
152152
ERC4626Test:testFailDepositZero() (gas: 7780)
@@ -163,7 +163,7 @@ ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 201569, ~: 201579
163163
ERC4626Test:testSingleMintRedeem(uint128) (runs: 256, μ: 201484, ~: 201494)
164164
ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286247)
165165
ERC4626Test:testWithdrawZero() (gas: 52462)
166-
ERC721Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2170)
166+
ERC721Test:invariantMetadata (runs: 256, calls: 3840, reverts: 2170)
167167
ERC721Test:testApprove() (gas: 78427)
168168
ERC721Test:testApprove(address,uint256) (runs: 256, μ: 78637, ~: 78637)
169169
ERC721Test:testApproveAll() (gas: 31063)
@@ -240,17 +240,17 @@ ERC721Test:testTransferFromApproveAll() (gas: 92898)
240240
ERC721Test:testTransferFromApproveAll(uint256,address) (runs: 256, μ: 93182, ~: 93182)
241241
ERC721Test:testTransferFromSelf() (gas: 64776)
242242
ERC721Test:testTransferFromSelf(uint256,address) (runs: 256, μ: 65061, ~: 65061)
243-
FixedPointMathLibTest:testDifferentiallyFuzzSqrt(uint256) (runs: 256, μ: 13827, ~: 4181)
243+
FixedPointMathLibTest:testDifferentiallyFuzzSqrt(uint256) (runs: 256, μ: 13819, ~: 4231)
244244
FixedPointMathLibTest:testDivWadDown() (gas: 841)
245-
FixedPointMathLibTest:testDivWadDown(uint256,uint256) (runs: 256, μ: 718, ~: 820)
245+
FixedPointMathLibTest:testDivWadDown(uint256,uint256) (runs: 256, μ: 717, ~: 820)
246246
FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 446)
247247
FixedPointMathLibTest:testDivWadUp() (gas: 1003)
248-
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 809, ~: 972)
248+
FixedPointMathLibTest:testDivWadUp(uint256,uint256) (runs: 256, μ: 807, ~: 972)
249249
FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 462)
250-
FixedPointMathLibTest:testFailDivWadDownOverflow(uint256,uint256) (runs: 256, μ: 443, ~: 419)
250+
FixedPointMathLibTest:testFailDivWadDownOverflow(uint256,uint256) (runs: 256, μ: 444, ~: 419)
251251
FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 342)
252252
FixedPointMathLibTest:testFailDivWadDownZeroDenominator(uint256) (runs: 256, μ: 397, ~: 397)
253-
FixedPointMathLibTest:testFailDivWadUpOverflow(uint256,uint256) (runs: 256, μ: 398, ~: 374)
253+
FixedPointMathLibTest:testFailDivWadUpOverflow(uint256,uint256) (runs: 256, μ: 399, ~: 374)
254254
FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 342)
255255
FixedPointMathLibTest:testFailDivWadUpZeroDenominator(uint256) (runs: 256, μ: 396, ~: 396)
256256
FixedPointMathLibTest:testFailMulDivDownOverflow(uint256,uint256,uint256) (runs: 256, μ: 437, ~: 414)
@@ -274,12 +274,12 @@ FixedPointMathLibTest:testMulWadUp() (gas: 981)
274274
FixedPointMathLibTest:testMulWadUp(uint256,uint256) (runs: 256, μ: 835, ~: 1073)
275275
FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 959)
276276
FixedPointMathLibTest:testRPow() (gas: 2164)
277-
FixedPointMathLibTest:testSqrt() (gas: 2580)
278-
FixedPointMathLibTest:testSqrt(uint256) (runs: 256, μ: 997, ~: 1013)
279-
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 15210, ~: 340)
280-
FixedPointMathLibTest:testSqrtBackHashed(uint256) (runs: 256, μ: 59040, ~: 59500)
281-
FixedPointMathLibTest:testSqrtBackHashedSingle() (gas: 58937)
282-
LibStringTest:testDifferentiallyFuzzToString(uint256,bytes) (runs: 256, μ: 20749, ~: 8925)
277+
FixedPointMathLibTest:testSqrt() (gas: 600)
278+
FixedPointMathLibTest:testSqrt(uint256) (runs: 256, μ: 990, ~: 1038)
279+
FixedPointMathLibTest:testSqrtBack(uint256) (runs: 256, μ: 14665, ~: 340)
280+
FixedPointMathLibTest:testSqrtBackHashed(uint256) (runs: 256, μ: 56528, ~: 56940)
281+
FixedPointMathLibTest:testSqrtBackHashedSingle() (gas: 56448)
282+
LibStringTest:testDifferentiallyFuzzToString(uint256,bytes) (runs: 256, μ: 21006, ~: 9531)
283283
LibStringTest:testToString() (gas: 10047)
284284
LibStringTest:testToStringDirty() (gas: 8123)
285285
LibStringTest:testToStringOverwrite() (gas: 484)
@@ -310,7 +310,7 @@ OwnedTest:testCallFunctionAsNonOwner(address) (runs: 256, μ: 16238, ~: 16257)
310310
OwnedTest:testCallFunctionAsOwner() (gas: 10479)
311311
OwnedTest:testSetOwner() (gas: 13035)
312312
OwnedTest:testSetOwner(address) (runs: 256, μ: 13151, ~: 13170)
313-
ReentrancyGuardTest:invariantReentrancyStatusAlways1() (runs: 256, calls: 3840, reverts: 319)
313+
ReentrancyGuardTest:invariantReentrancyStatusAlways1 (runs: 256, calls: 3840, reverts: 319)
314314
ReentrancyGuardTest:testFailUnprotectedCall() (gas: 46147)
315315
ReentrancyGuardTest:testNoReentrancy() (gas: 7515)
316316
ReentrancyGuardTest:testProtectedCall() (gas: 33467)
@@ -446,7 +446,7 @@ SignedWadMathTest:testFailWadDivZeroDenominator(int256) (runs: 256, μ: 296, ~:
446446
SignedWadMathTest:testFailWadMulOverflow(int256,int256) (runs: 256, μ: 323, ~: 296)
447447
SignedWadMathTest:testWadDiv(uint256,uint256,bool,bool) (runs: 256, μ: 5696, ~: 5664)
448448
SignedWadMathTest:testWadMul(uint256,uint256,bool,bool) (runs: 256, μ: 5720, ~: 5688)
449-
WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 256, calls: 3840, reverts: 1908)
449+
WETHInvariants:invariantTotalSupplyEqualsBalance (runs: 256, calls: 3840, reverts: 1908)
450450
WETHTest:testDeposit() (gas: 63535)
451451
WETHTest:testDeposit(uint256) (runs: 256, μ: 62792, ~: 65880)
452452
WETHTest:testFallbackDeposit() (gas: 63249)

lib/ds-test

src/utils/FixedPointMathLib.sol

+7-17
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,14 @@ library FixedPointMathLib {
172172
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
173173
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
174174

175+
// Let y = x / 2**r, where r = lg2(x/65536).
175176
// We check y >= 2^(k + 8) but shift right by k bits
176177
// each branch to ensure that if x >= 256, then y >= 256.
177-
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
178-
y := shr(128, y)
179-
z := shl(64, z)
180-
}
181-
if iszero(lt(y, 0x1000000000000000000)) {
182-
y := shr(64, y)
183-
z := shl(32, z)
184-
}
185-
if iszero(lt(y, 0x10000000000)) {
186-
y := shr(32, y)
187-
z := shl(16, z)
188-
}
189-
if iszero(lt(y, 0x1000000)) {
190-
y := shr(16, y)
191-
z := shl(8, z)
192-
}
178+
let r := shl(7, gt(x, 0xffffffffffffffffffffffffffffffffff))
179+
r := or(r, shl(6, gt(shr(r, x), 0xffffffffffffffffff)))
180+
r := or(r, shl(5, gt(shr(r, x), 0xffffffffff)))
181+
r := or(r, shl(4, gt(shr(r, x), 0xffffff)))
182+
z := shl(shr(1, r), z)
193183

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

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

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

0 commit comments

Comments
 (0)