1 | //===-- ctzsi2.c - Implement __ctzsi2 -------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements __ctzsi2 for the compiler_rt library. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "int_lib.h" |
14 | |
15 | // Returns: the number of trailing 0-bits |
16 | |
17 | // Precondition: a != 0 |
18 | |
19 | COMPILER_RT_ABI int __ctzsi2(si_int a) { |
20 | su_int x = (su_int)a; |
21 | si_int t = ((x & 0x0000FFFF) == 0) |
22 | << 4; // if (x has no small bits) t = 16 else 0 |
23 | x >>= t; // x = [0 - 0xFFFF] + higher garbage bits |
24 | su_int r = t; // r = [0, 16] |
25 | // return r + ctz(x) |
26 | t = ((x & 0x00FF) == 0) << 3; |
27 | x >>= t; // x = [0 - 0xFF] + higher garbage bits |
28 | r += t; // r = [0, 8, 16, 24] |
29 | // return r + ctz(x) |
30 | t = ((x & 0x0F) == 0) << 2; |
31 | x >>= t; // x = [0 - 0xF] + higher garbage bits |
32 | r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] |
33 | // return r + ctz(x) |
34 | t = ((x & 0x3) == 0) << 1; |
35 | x >>= t; |
36 | x &= 3; // x = [0 - 3] |
37 | r += t; // r = [0 - 30] and is even |
38 | // return r + ctz(x) |
39 | |
40 | // The branch-less return statement below is equivalent |
41 | // to the following switch statement: |
42 | // switch (x) |
43 | // { |
44 | // case 0: |
45 | // return r + 2; |
46 | // case 2: |
47 | // return r + 1; |
48 | // case 1: |
49 | // case 3: |
50 | // return r; |
51 | // } |
52 | return r + ((2 - (x >> 1)) & -((x & 1) == 0)); |
53 | } |
54 | |