Title: Create_a_new_opcode_for_counting_leading_zeros__CL
Category: EIPs

Author: Vectorized
Date: 2022-09-11T02:50:57.517Z

Count leading zeros (CLZ) is a native instruction in many processor architectures
(even in RISC architectures like ARM).
It is a basic building block used in many important fixed point and binary operations:

lnWad
powWad (due to lnWad)
sqrt
log2
most significant bit (msb)
least significant bit (lsb)
(can be easily implemented with CLZ by isolating the smallest bit via x & -x)

Code examples:

solady/FixedPointMathLib.sol at main · Vectorized/solady · GitHub
solady/LibBit.sol at main · Vectorized/solady · GitHub

For more applications see: Find first set - Wikipedia
Emulating this opcode is very wasteful in terms of runtime gas and bytecode size
(due to the need to store large constants like 0xffffffffffffffffffffffffffffffff or De Bruijn lookups like 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f).
Given that most processors have this opcode implemented natively, which can be used to efficiently implement the opcode in EVM, it feels even more wasteful not to have it available in the EVM.
Having this opcode in the EVM will enable cheaper runtime gas, cheaper validator computation, and smaller bytecode.

For the implementation of CLZ, I’d propose a gas cost of 3
(to keep in line with the gas cost of shl, shr, not, xor, etc).
This CLZ opcode will take in a single variable on the stack, and output a single variable onto the stack.
For the case of 0 as the input, CLZ returns 256 (the bit width of the input) to stay consistent with how it behaves in most processors, and for lesser bytecode required to handle the output.

CLZ has the following advantages over other bit counting operations:


log2(x) can be computed via 255 - clz(x), which automatically reverts for the case of 0 if using checked arithmetic. This makes it preferred over find first set (FFS).


Count trailing zeros (CTZ) is way cheaper to emulate with current Yul opcodes compared to CLZ. See the LibBit.sol. Inclusion of CLZ will make CTZ easy to compute, but not vice versa.


Basically, CLZ is the most common bit counting operation in processors because other bit counting operations can be easily implemented with CLZ.

Author: axic
Date: 2022-11-11T17:57:16.624Z

Can you leave an example of an efficient ctz implementation using clz?



 Vectorized:

log2(x) can be computed via 255 - clz(x), which automatically reverts for the case of 0 if using checked arithmetic. This makes it preferred over find first set (FFS).


Well, not automatically, but with code generated by the compiler 
Would you be able to rewrite the solady code using the hypothetical clz opcode? It would be a good way to see the complexity reduction.

Author: Zoltan
Date: 2024-09-02T21:16:59.923Z

Here is a lookup table for that.
521 bytes long.
Test it on evm.codes !
You just need to open an instruction’s info, then click on " Reproduce in playground", because if you click on the menu’s playground link it will only accept Solidity code.


drive.google.com



LZCNT_via_lookup_table.txt
Google Drive file.





Here is the raw table in hex:
0000010002ea0000038bebab0099000004008c00ec36ac0000d09a000078004a050000008dd60000ed003700ad7100dd00e5d1429ba4009100fe796000004b00067f0000004700da8e00d70000000000ee12003d38000000ae0072000000de000025e632d2a043009c1ca5000000920000c7ff007a2061f1005200f84cb600150766800000a90000000048000000db408f5e0000d800003b0000003000000000eff6130000003e00392e000000000000af000000730000b100bc0000dfc1000000002600e7963375d36ea100440000009d001db3a6000000000000be930000000057c800000000e17b0e21c3625af2000000530000cbf9004d00b7000000162808006700810000e9008aaa980000003500cf0077490000d500000070dce441a390fd5f00007e0046d900000000113c00000000000024319f001b000000c6001ff051f7b5146500a8000000003f5d00003a002f0000f50000002d000000000000b0bb00c000000095746d00000000b2000000bd0000560000e00dc259000000ca0000000027000000e889970034ce7600d4006fe3a2fc007d45000010000000239e1a00c51e50b464a700005c000000f4002c000000babf00946c000000000055000c5800c9000000008800cd0000e2fb7c000f002219c44f63005b00f32b00b9006b0000540b00000087cc00fa0000184e00002ab86a000a0086000017002969098500006884008382

Author: Zoltan
Date: 2024-09-02T22:47:38.691Z

Please put this EIP onto the table on Github!
https://github.com/search?q=repo%3Aethereum%2FEIPs%20zeroes&type=code
https://github.com/search?q=repo%3Aethereum%2FEIPs+leading+zeroes&type=code
https://github.com/search?q=repo%3Aethereum%2FEIPs+clz&type=code

Author: Vectorized
Date: 2024-09-04T13:03:25.888Z

Some updates.
As of the latest Solady at the time of writing, solady/src/utils/LibBit.sol at 24b6272d83fba9a4233bafafbcd7f879e3b0948b · Vectorized/solady · GitHub
CLZ: 184 gas
FFS: 136 gas
Having a specialized CLZ opcode can reduce the amount of gas to about 8 gas for CLZ, and about 30 gas for FFS (due to the need to isolate the least significant bit before CLZ).
CLZ will be useful in sqrt, cbrt, logarithms, bitmap lookups.
As of now, the codebase that will benefit the most if CLZ were to be shipped immediately will be Uniswap V4. But since the Uniswap V4 codebase has already been submitted for final audits, and the singleton will be launched soon, the benefits of having this opcode in EVM may be limited going forward.
After considering the amount of EVM fragmentation this may cause, I am hesistant on pushing core devs to implement this opcode.

Author: benaadams
Date: 2025-04-27T22:34:14.153Z

Would be less work than an ADD, but have some stack work so I’d suggest CLZ would be 3 gas as NOT is also 3 gas

Author: Vectorized
Date: 2025-04-27T22:34:27.606Z

I’ve changed my mind.
I’m in full support of clz now.
I have recently found a very good use case of using clz for generalized calldata compression (Solady LibZip.cdCompress and LibZip.cdDecompress). Having clz will greatly speed up this algorithm, as well as many other related bytes/string algorithms. I expect many future contracts to use LibZip.cdCompress and LibZip.cdDecompress for compressing/decompressing variables to and from storage.


github.com/Vectorized/solady


src/utils/LibZip.sol

main

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for compressing and decompressing bytes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol)
/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor)
/// @author FastLZ by ariya (https://github.com/ariya/FastLZ)
///
/// @dev Note:
/// The accompanying solady.js library includes implementations of
/// FastLZ and calldata operations for convenience.
library LibZip {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     FAST LZ OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // LZ77 implementation based on FastLZ.
    // Equivalent to level 1 compression and decompression at the following commit:
    // https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42
    // Decompression is backwards compatible.




  This file has been truncated. show original





X thread on how to use it to automagically pack storage variables.
https://x.com/optimizoor/status/1914238227386704053?s=61

Author: benaadams
Date: 2025-05-10T00:46:03.258Z

Why is 0 256 rather than 255?
Since 1 would be 254?

Author: benaadams
Date: 2025-05-11T03:07:37.229Z

Ignore this I can’t count