It can be done with a fairly simple log-depth circuit without resorting to such hacks that only really make sense in software.
The "position of most significant set bit" function pmsb
can be defined recursively:
$\begin{split}pmsb(``0") &= Nil \\
pmsb(``1") &= Nil \\
pmsb(a:b) &= ``0":pmsb(b) \text{ if a=0}\\
&= ``1":pmsb(a) \text{ otherwise}
\end{split}$
Where :
divides a power-of-two string down the middle or concatenates two strings, depending on its context.
This can already be implemented as a circuit, but it includes some annoying wide comparisons. They can be removed by returning a tuple with an extra bit that tracks the zero-ness of the whole string (it is applied to the halves so you get the result from the halves in the recursion):
$\begin{split}pmsb(``0") &= (Nil, T) \\
pmsb(``1") &= (Nil, F) \\
pmsb(a:b) &= \text{let } (pa, za) = pmsb(a) \\
&\phantom{=}\quad\quad (pb, zb) = pmsb(b) \\
&\phantom{=}\;\; \text{in if } za \text{ then } (``0":pb, zb)\\
&\phantom{=}\quad\quad\quad\quad\text{else } (``1":pa, F)
\end{split}$
This can then be evaluated bottom-up by a circuit of depth O(log n) and size O(n) where n is the length of the bit-string at the top level, which must be a power of two and not one. The zeroness bit circuit has the structure of an AND-reduction, but it is used at the intermediate nodes instead of only at the end. The main result is computed by a similar tree of MUXes that take those bits as control input.