diff --git a/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol b/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol index 47d8bd3f6..4dff7f916 100644 --- a/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol +++ b/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol @@ -52,8 +52,15 @@ library strings { src += 32; } + // The following masking would overflow in the case of len=0 + // and the code path in that case is useless, albeit correct. + // This shortcut avoids it and saves gas. + if (len == 0) + return; + // Copy remaining bytes - uint mask = 256 ** (32 - len) - 1; + uint mask; + unchecked { mask = 256 ** (32 - len) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) @@ -215,7 +222,9 @@ library strings { if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } - uint256 diff = (a & mask) - (b & mask); + uint256 diff; + // This depends on potential underflow. + unchecked { diff = (a & mask) - (b & mask); } if (diff != 0) return int(diff); } diff --git a/test/libsolidity/semanticTests/externalContracts/strings.sol b/test/libsolidity/semanticTests/externalContracts/strings.sol index 6c16e205d..1f209ef6f 100644 --- a/test/libsolidity/semanticTests/externalContracts/strings.sol +++ b/test/libsolidity/semanticTests/externalContracts/strings.sol @@ -51,26 +51,26 @@ contract test { // compileViaYul: also // ---- // constructor() -// gas irOptimized: 926170 -// gas legacy: 1192776 -// gas legacyOptimized: 777238 +// gas irOptimized: 912777 +// gas legacy: 1188228 +// gas legacyOptimized: 771634 // toSlice(string): 0x20, 11, "hello world" -> 11, 0xa0 // gas irOptimized: 22877 // gas legacy: 23190 // gas legacyOptimized: 22508 // roundtrip(string): 0x20, 11, "hello world" -> 0x20, 11, "hello world" -// gas irOptimized: 23783 -// gas legacy: 24560 -// gas legacyOptimized: 23481 +// gas irOptimized: 23676 +// gas legacy: 23820 +// gas legacyOptimized: 23123 // utf8len(string): 0x20, 16, "\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83\xf0\x9f\x98\x83" -> 4 # Input: "😃😃😃😃" # // gas irOptimized: 24779 // gas legacy: 25716 // gas legacyOptimized: 24115 // multiconcat(string,uint256): 0x40, 3, 11, "hello world" -> 0x20, 0x58, 0x68656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f726c, 0x6468656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f72, 49027192869463622675296414541903001712009715982962058146354235762728281047040 # concatenating 3 times # -// gas irOptimized: 30478 -// gas legacy: 36801 -// gas legacyOptimized: 30420 -// benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> FAILURE, hex"4e487b71", 0x11 -// gas irOptimized: 27298 +// gas irOptimized: 29729 // gas legacy: 31621 -// gas legacyOptimized: 27668 +// gas legacyOptimized: 27914 +// benchmark(string,bytes32): 0x40, 0x0842021, 8, "solidity" -> 0x2020 +// gas irOptimized: 2903627 +// gas legacy: 4381235 +// gas legacyOptimized: 2317529