68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 /* Operations on HOST_WIDE_INT.
|
145
|
2 Copyright (C) 1987-2020 Free Software Foundation, Inc.
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4 This file is part of GCC.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 GCC is free software; you can redistribute it and/or modify it under
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 the terms of the GNU General Public License as published by the Free
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 Software Foundation; either version 3, or (at your option) any later
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 version.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14 for more details.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 You should have received a copy of the GNU General Public License
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 along with GCC; see the file COPYING3. If not see
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 <http://www.gnu.org/licenses/>. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20 #include "config.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21 #include "system.h"
|
111
|
22 #include "coretypes.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 #if GCC_VERSION < 3004
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
25
|
111
|
26 /* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
|
|
27 and exact_log2 are defined as inline functions in hwint.h
|
|
28 if GCC_VERSION >= 3004.
|
|
29 The definitions here are used for older versions of GCC and
|
|
30 non-GCC bootstrap compilers. */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
31
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33 If X is 0, return -1. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 floor_log2 (unsigned HOST_WIDE_INT x)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38 int t = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 if (x == 0)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41 return -1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 if (HOST_BITS_PER_WIDE_INT > 64)
|
111
|
44 if (x >= HOST_WIDE_INT_1U << (t + 64))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 t += 64;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
46 if (HOST_BITS_PER_WIDE_INT > 32)
|
111
|
47 if (x >= HOST_WIDE_INT_1U << (t + 32))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
48 t += 32;
|
111
|
49 if (x >= HOST_WIDE_INT_1U << (t + 16))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
50 t += 16;
|
111
|
51 if (x >= HOST_WIDE_INT_1U << (t + 8))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
52 t += 8;
|
111
|
53 if (x >= HOST_WIDE_INT_1U << (t + 4))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
54 t += 4;
|
111
|
55 if (x >= HOST_WIDE_INT_1U << (t + 2))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
56 t += 2;
|
111
|
57 if (x >= HOST_WIDE_INT_1U << (t + 1))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
58 t += 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
59
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
60 return t;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62
|
131
|
63 /* Given X, an unsigned number, return the least Y such that 2**Y >= X. */
|
111
|
64
|
|
65 int
|
|
66 ceil_log2 (unsigned HOST_WIDE_INT x)
|
|
67 {
|
131
|
68 return x == 0 ? 0 : floor_log2 (x - 1) + 1;
|
111
|
69 }
|
|
70
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
71 /* Return the logarithm of X, base 2, considering X unsigned,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
72 if X is a power of 2. Otherwise, returns -1. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
73
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
74 int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
75 exact_log2 (unsigned HOST_WIDE_INT x)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76 {
|
111
|
77 if (!pow2p_hwi (x))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
78 return -1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
79 return floor_log2 (x);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
80 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
81
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
82 /* Given X, an unsigned number, return the number of least significant bits
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
83 that are zero. When X == 0, the result is the word size. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
84
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
85 int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86 ctz_hwi (unsigned HOST_WIDE_INT x)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
87 {
|
111
|
88 return x ? floor_log2 (least_bit_hwi (x)) : HOST_BITS_PER_WIDE_INT;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
90
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
91 /* Similarly for most significant bits. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
92
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
93 int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
94 clz_hwi (unsigned HOST_WIDE_INT x)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
95 {
|
111
|
96 return HOST_BITS_PER_WIDE_INT - 1 - floor_log2 (x);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
97 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
98
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
99 /* Similar to ctz_hwi, except that the least significant bit is numbered
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
100 starting from 1, and X == 0 yields 0. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
101
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102 int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
103 ffs_hwi (unsigned HOST_WIDE_INT x)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
104 {
|
111
|
105 return 1 + floor_log2 (least_bit_hwi (x));
|
|
106 }
|
|
107
|
|
108 /* Return the number of set bits in X. */
|
|
109
|
|
110 int
|
|
111 popcount_hwi (unsigned HOST_WIDE_INT x)
|
|
112 {
|
|
113 int i, ret = 0;
|
|
114 size_t bits = sizeof (x) * CHAR_BIT;
|
|
115
|
|
116 for (i = 0; i < bits; i += 1)
|
|
117 {
|
|
118 ret += x & 1;
|
|
119 x >>= 1;
|
|
120 }
|
|
121
|
|
122 return ret;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
123 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
124
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
125 #endif /* GCC_VERSION < 3004 */
|
111
|
126
|
|
127
|
|
128 /* Compute the greatest common divisor of two numbers A and B using
|
|
129 Euclid's algorithm. */
|
|
130
|
|
131 HOST_WIDE_INT
|
|
132 gcd (HOST_WIDE_INT a, HOST_WIDE_INT b)
|
|
133 {
|
|
134 HOST_WIDE_INT x, y, z;
|
|
135
|
|
136 x = abs_hwi (a);
|
|
137 y = abs_hwi (b);
|
|
138
|
|
139 while (x > 0)
|
|
140 {
|
|
141 z = y % x;
|
|
142 y = x;
|
|
143 x = z;
|
|
144 }
|
|
145
|
|
146 return y;
|
|
147 }
|
|
148
|
|
149 /* For X and Y positive integers, return X multiplied by Y and check
|
|
150 that the result does not overflow. */
|
|
151
|
|
152 HOST_WIDE_INT
|
|
153 pos_mul_hwi (HOST_WIDE_INT x, HOST_WIDE_INT y)
|
|
154 {
|
|
155 if (x != 0)
|
|
156 gcc_checking_assert ((HOST_WIDE_INT_MAX) / x >= y);
|
|
157
|
|
158 return x * y;
|
|
159 }
|
|
160
|
|
161 /* Return X multiplied by Y and check that the result does not
|
|
162 overflow. */
|
|
163
|
|
164 HOST_WIDE_INT
|
|
165 mul_hwi (HOST_WIDE_INT x, HOST_WIDE_INT y)
|
|
166 {
|
|
167 gcc_checking_assert (x != HOST_WIDE_INT_MIN
|
|
168 && y != HOST_WIDE_INT_MIN);
|
|
169
|
|
170 if (x >= 0)
|
|
171 {
|
|
172 if (y >= 0)
|
|
173 return pos_mul_hwi (x, y);
|
|
174
|
|
175 return -pos_mul_hwi (x, -y);
|
|
176 }
|
|
177
|
|
178 if (y >= 0)
|
|
179 return -pos_mul_hwi (-x, y);
|
|
180
|
|
181 return pos_mul_hwi (-x, -y);
|
|
182 }
|
|
183
|
|
184 /* Compute the least common multiple of two numbers A and B . */
|
|
185
|
|
186 HOST_WIDE_INT
|
|
187 least_common_multiple (HOST_WIDE_INT a, HOST_WIDE_INT b)
|
|
188 {
|
|
189 return mul_hwi (abs_hwi (a) / gcd (a, b), abs_hwi (b));
|
|
190 }
|