/src/php-src/ext/opcache/jit/ir/ir_private.h
Line | Count | Source |
1 | | /* |
2 | | * IR - Lightweight JIT Compilation Framework |
3 | | * (Common data structures and non public definitions) |
4 | | * Copyright (C) 2022 Zend by Perforce. |
5 | | * Authors: Dmitry Stogov <dmitry@php.net> |
6 | | */ |
7 | | |
8 | | #ifndef IR_PRIVATE_H |
9 | | #define IR_PRIVATE_H |
10 | | #include <string.h> |
11 | | #include <stdlib.h> |
12 | | #include <stddef.h> |
13 | | |
14 | | #ifdef IR_DEBUG |
15 | | # include <assert.h> |
16 | 0 | # define IR_ASSERT(x) assert(x) |
17 | | #else |
18 | | # define IR_ASSERT(x) |
19 | | #endif |
20 | | |
21 | | #ifdef _WIN32 |
22 | | # include <intrin.h> |
23 | | # ifdef _M_X64 |
24 | | # pragma intrinsic(_BitScanForward64) |
25 | | # pragma intrinsic(_BitScanReverse64) |
26 | | # endif |
27 | | # pragma intrinsic(_BitScanForward) |
28 | | # pragma intrinsic(_BitScanReverse) |
29 | | #endif |
30 | | |
31 | | #ifdef __has_builtin |
32 | | # if __has_builtin(__builtin_expect) |
33 | 0 | # define EXPECTED(condition) __builtin_expect(!!(condition), 1) |
34 | 0 | # define UNEXPECTED(condition) __builtin_expect(!!(condition), 0) |
35 | | # endif |
36 | | # if __has_attribute(__aligned__) |
37 | | # define IR_SET_ALIGNED(alignment, decl) decl __attribute__ ((__aligned__ (alignment))) |
38 | | # endif |
39 | | # if __has_attribute(__fallthrough__) |
40 | 0 | # define IR_FALLTHROUGH __attribute__((__fallthrough__)) |
41 | | # endif |
42 | | #elif defined(_WIN32) |
43 | | # define IR_SET_ALIGNED(alignment, decl) __declspec(align(alignment)) decl |
44 | | #else /* GCC prior to 10 or non-clang/msvc compilers */ |
45 | | #define __has_builtin(x) 0 |
46 | | #endif |
47 | | #ifndef EXPECTED |
48 | | # define EXPECTED(condition) (condition) |
49 | | # define UNEXPECTED(condition) (condition) |
50 | | #endif |
51 | | #ifndef IR_SET_ALIGNED |
52 | | # define IR_SET_ALIGNED(alignment, decl) decl |
53 | | #endif |
54 | | #ifndef IR_FALLTHROUGH |
55 | | # define IR_FALLTHROUGH ((void)0) |
56 | | #endif |
57 | | |
58 | | /*** Helper routines ***/ |
59 | | |
60 | | #define IR_ALIGNED_SIZE(size, alignment) \ |
61 | 0 | (((size) + ((alignment) - 1)) & ~((alignment) - 1)) |
62 | | |
63 | 0 | #define IR_MAX(a, b) (((a) > (b)) ? (a) : (b)) |
64 | 0 | #define IR_MIN(a, b) (((a) < (b)) ? (a) : (b)) |
65 | | |
66 | 0 | #define IR_IS_POWER_OF_TWO(x) ((x) && (!((x) & ((x) - 1)))) |
67 | | |
68 | 0 | #define IR_LOG2(x) ir_ntzl(x) |
69 | | |
70 | | IR_ALWAYS_INLINE uint8_t ir_rol8(uint8_t op1, uint8_t op2) |
71 | 0 | { |
72 | 0 | return (op1 << op2) | (op1 >> (8 - op2)); |
73 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_rol8 Unexecuted instantiation: ir_check.c:ir_rol8 Unexecuted instantiation: ir_dump.c:ir_rol8 Unexecuted instantiation: ir_emit.c:ir_rol8 Unexecuted instantiation: ir_gcm.c:ir_rol8 Unexecuted instantiation: ir_gdb.c:ir_rol8 Unexecuted instantiation: ir_patch.c:ir_rol8 Unexecuted instantiation: ir_ra.c:ir_rol8 Unexecuted instantiation: ir_save.c:ir_rol8 Unexecuted instantiation: ir_sccp.c:ir_rol8 Unexecuted instantiation: ir_strtab.c:ir_rol8 Unexecuted instantiation: ir.c:ir_rol8 |
74 | | |
75 | | IR_ALWAYS_INLINE uint16_t ir_rol16(uint16_t op1, uint16_t op2) |
76 | 0 | { |
77 | 0 | return (op1 << op2) | (op1 >> (16 - op2)); |
78 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_rol16 Unexecuted instantiation: ir_check.c:ir_rol16 Unexecuted instantiation: ir_dump.c:ir_rol16 Unexecuted instantiation: ir_emit.c:ir_rol16 Unexecuted instantiation: ir_gcm.c:ir_rol16 Unexecuted instantiation: ir_gdb.c:ir_rol16 Unexecuted instantiation: ir_patch.c:ir_rol16 Unexecuted instantiation: ir_ra.c:ir_rol16 Unexecuted instantiation: ir_save.c:ir_rol16 Unexecuted instantiation: ir_sccp.c:ir_rol16 Unexecuted instantiation: ir_strtab.c:ir_rol16 Unexecuted instantiation: ir.c:ir_rol16 |
79 | | |
80 | | IR_ALWAYS_INLINE uint32_t ir_rol32(uint32_t op1, uint32_t op2) |
81 | 0 | { |
82 | 0 | return (op1 << op2) | (op1 >> (32 - op2)); |
83 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_rol32 Unexecuted instantiation: ir_check.c:ir_rol32 Unexecuted instantiation: ir_dump.c:ir_rol32 Unexecuted instantiation: ir_emit.c:ir_rol32 Unexecuted instantiation: ir_gcm.c:ir_rol32 Unexecuted instantiation: ir_gdb.c:ir_rol32 Unexecuted instantiation: ir_patch.c:ir_rol32 Unexecuted instantiation: ir_ra.c:ir_rol32 Unexecuted instantiation: ir_save.c:ir_rol32 Unexecuted instantiation: ir_sccp.c:ir_rol32 Unexecuted instantiation: ir_strtab.c:ir_rol32 Unexecuted instantiation: ir.c:ir_rol32 |
84 | | |
85 | | IR_ALWAYS_INLINE uint64_t ir_rol64(uint64_t op1, uint64_t op2) |
86 | 0 | { |
87 | 0 | return (op1 << op2) | (op1 >> (64 - op2)); |
88 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_rol64 Unexecuted instantiation: ir_check.c:ir_rol64 Unexecuted instantiation: ir_dump.c:ir_rol64 Unexecuted instantiation: ir_emit.c:ir_rol64 Unexecuted instantiation: ir_gcm.c:ir_rol64 Unexecuted instantiation: ir_gdb.c:ir_rol64 Unexecuted instantiation: ir_patch.c:ir_rol64 Unexecuted instantiation: ir_ra.c:ir_rol64 Unexecuted instantiation: ir_save.c:ir_rol64 Unexecuted instantiation: ir_sccp.c:ir_rol64 Unexecuted instantiation: ir_strtab.c:ir_rol64 Unexecuted instantiation: ir.c:ir_rol64 |
89 | | |
90 | | IR_ALWAYS_INLINE uint8_t ir_ror8(uint8_t op1, uint8_t op2) |
91 | 0 | { |
92 | 0 | return (op1 >> op2) | (op1 << (8 - op2)); |
93 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ror8 Unexecuted instantiation: ir_check.c:ir_ror8 Unexecuted instantiation: ir_dump.c:ir_ror8 Unexecuted instantiation: ir_emit.c:ir_ror8 Unexecuted instantiation: ir_gcm.c:ir_ror8 Unexecuted instantiation: ir_gdb.c:ir_ror8 Unexecuted instantiation: ir_patch.c:ir_ror8 Unexecuted instantiation: ir_ra.c:ir_ror8 Unexecuted instantiation: ir_save.c:ir_ror8 Unexecuted instantiation: ir_sccp.c:ir_ror8 Unexecuted instantiation: ir_strtab.c:ir_ror8 Unexecuted instantiation: ir.c:ir_ror8 |
94 | | |
95 | | IR_ALWAYS_INLINE uint16_t ir_ror16(uint16_t op1, uint16_t op2) |
96 | 0 | { |
97 | 0 | return (op1 >> op2) | (op1 << (16 - op2)); |
98 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ror16 Unexecuted instantiation: ir_check.c:ir_ror16 Unexecuted instantiation: ir_dump.c:ir_ror16 Unexecuted instantiation: ir_emit.c:ir_ror16 Unexecuted instantiation: ir_gcm.c:ir_ror16 Unexecuted instantiation: ir_gdb.c:ir_ror16 Unexecuted instantiation: ir_patch.c:ir_ror16 Unexecuted instantiation: ir_ra.c:ir_ror16 Unexecuted instantiation: ir_save.c:ir_ror16 Unexecuted instantiation: ir_sccp.c:ir_ror16 Unexecuted instantiation: ir_strtab.c:ir_ror16 Unexecuted instantiation: ir.c:ir_ror16 |
99 | | |
100 | | IR_ALWAYS_INLINE uint32_t ir_ror32(uint32_t op1, uint32_t op2) |
101 | 0 | { |
102 | 0 | return (op1 >> op2) | (op1 << (32 - op2)); |
103 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ror32 Unexecuted instantiation: ir_check.c:ir_ror32 Unexecuted instantiation: ir_dump.c:ir_ror32 Unexecuted instantiation: ir_emit.c:ir_ror32 Unexecuted instantiation: ir_gcm.c:ir_ror32 Unexecuted instantiation: ir_gdb.c:ir_ror32 Unexecuted instantiation: ir_patch.c:ir_ror32 Unexecuted instantiation: ir_ra.c:ir_ror32 Unexecuted instantiation: ir_save.c:ir_ror32 Unexecuted instantiation: ir_sccp.c:ir_ror32 Unexecuted instantiation: ir_strtab.c:ir_ror32 Unexecuted instantiation: ir.c:ir_ror32 |
104 | | |
105 | | IR_ALWAYS_INLINE uint64_t ir_ror64(uint64_t op1, uint64_t op2) |
106 | 0 | { |
107 | 0 | return (op1 >> op2) | (op1 << (64 - op2)); |
108 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ror64 Unexecuted instantiation: ir_check.c:ir_ror64 Unexecuted instantiation: ir_dump.c:ir_ror64 Unexecuted instantiation: ir_emit.c:ir_ror64 Unexecuted instantiation: ir_gcm.c:ir_ror64 Unexecuted instantiation: ir_gdb.c:ir_ror64 Unexecuted instantiation: ir_patch.c:ir_ror64 Unexecuted instantiation: ir_ra.c:ir_ror64 Unexecuted instantiation: ir_save.c:ir_ror64 Unexecuted instantiation: ir_sccp.c:ir_ror64 Unexecuted instantiation: ir_strtab.c:ir_ror64 Unexecuted instantiation: ir.c:ir_ror64 |
109 | | |
110 | | /* Number of trailing zero bits (0x01 -> 0; 0x40 -> 6; 0x00 -> LEN) */ |
111 | | IR_ALWAYS_INLINE uint32_t ir_ntz(uint32_t num) |
112 | 0 | { |
113 | 0 | #if (defined(__GNUC__) || __has_builtin(__builtin_ctz)) |
114 | 0 | return __builtin_ctz(num); |
115 | | #elif defined(_WIN32) |
116 | | uint32_t index; |
117 | | |
118 | | if (!_BitScanForward(&index, num)) { |
119 | | /* undefined behavior */ |
120 | | return 32; |
121 | | } |
122 | | |
123 | | return index; |
124 | | #else |
125 | | int n; |
126 | | |
127 | | if (num == 0) return 32; |
128 | | |
129 | | n = 1; |
130 | | if ((num & 0x0000ffff) == 0) {n += 16; num = num >> 16;} |
131 | | if ((num & 0x000000ff) == 0) {n += 8; num = num >> 8;} |
132 | | if ((num & 0x0000000f) == 0) {n += 4; num = num >> 4;} |
133 | | if ((num & 0x00000003) == 0) {n += 2; num = num >> 2;} |
134 | | return n - (num & 1); |
135 | | #endif |
136 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ntz Unexecuted instantiation: ir_check.c:ir_ntz Unexecuted instantiation: ir_dump.c:ir_ntz Unexecuted instantiation: ir_emit.c:ir_ntz Unexecuted instantiation: ir_gcm.c:ir_ntz Unexecuted instantiation: ir_gdb.c:ir_ntz Unexecuted instantiation: ir_patch.c:ir_ntz Unexecuted instantiation: ir_ra.c:ir_ntz Unexecuted instantiation: ir_save.c:ir_ntz Unexecuted instantiation: ir_sccp.c:ir_ntz Unexecuted instantiation: ir_strtab.c:ir_ntz Unexecuted instantiation: ir.c:ir_ntz |
137 | | |
138 | | /* Number of trailing zero bits (0x01 -> 0; 0x40 -> 6; 0x00 -> LEN) */ |
139 | | IR_ALWAYS_INLINE uint32_t ir_ntzl(uint64_t num) |
140 | 0 | { |
141 | | // Note that the _WIN64 case should come before __has_builtin() below so that |
142 | | // clang-cl on Windows will use the uint64_t version, not the "long" uint32_t |
143 | | // version. |
144 | | #if defined(_WIN64) |
145 | | unsigned long index; |
146 | | |
147 | | if (!_BitScanForward64(&index, num)) { |
148 | | /* undefined behavior */ |
149 | | return 64; |
150 | | } |
151 | | |
152 | | return (uint32_t) index; |
153 | | #elif (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) |
154 | | return __builtin_ctzl(num); |
155 | | #else |
156 | | uint32_t n; |
157 | | |
158 | | if (num == 0) return 64; |
159 | | |
160 | | n = 1; |
161 | | if ((num & 0xffffffff) == 0) {n += 32; num = num >> 32;} |
162 | | if ((num & 0x0000ffff) == 0) {n += 16; num = num >> 16;} |
163 | | if ((num & 0x000000ff) == 0) {n += 8; num = num >> 8;} |
164 | | if ((num & 0x0000000f) == 0) {n += 4; num = num >> 4;} |
165 | | if ((num & 0x00000003) == 0) {n += 2; num = num >> 2;} |
166 | | return n - (uint32_t)(num & 1); |
167 | | #endif |
168 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ntzl Unexecuted instantiation: ir_check.c:ir_ntzl Unexecuted instantiation: ir_dump.c:ir_ntzl Unexecuted instantiation: ir_emit.c:ir_ntzl Unexecuted instantiation: ir_gcm.c:ir_ntzl Unexecuted instantiation: ir_gdb.c:ir_ntzl Unexecuted instantiation: ir_patch.c:ir_ntzl Unexecuted instantiation: ir_ra.c:ir_ntzl Unexecuted instantiation: ir_save.c:ir_ntzl Unexecuted instantiation: ir_sccp.c:ir_ntzl Unexecuted instantiation: ir_strtab.c:ir_ntzl Unexecuted instantiation: ir.c:ir_ntzl |
169 | | |
170 | | /* Number of leading zero bits (Undefined for zero) */ |
171 | | IR_ALWAYS_INLINE int ir_nlz(uint32_t num) |
172 | 0 | { |
173 | 0 | #if (defined(__GNUC__) || __has_builtin(__builtin_clz)) |
174 | 0 | return __builtin_clz(num); |
175 | 0 | #elif defined(_WIN32) |
176 | 0 | uint32_t index; |
177 | 0 |
|
178 | 0 | if (!_BitScanReverse(&index, num)) { |
179 | 0 | /* undefined behavior */ |
180 | 0 | return 32; |
181 | 0 | } |
182 | 0 |
|
183 | 0 | return (int) (32 - 1) - index; |
184 | 0 | #else |
185 | 0 | uint32_t x; |
186 | 0 | uint32_t n; |
187 | 0 |
|
188 | 0 | n = 32; |
189 | 0 | x = num >> 16; if (x != 0) {n -= 16; num = x;} |
190 | 0 | x = num >> 8; if (x != 0) {n -= 8; num = x;} |
191 | 0 | x = num >> 4; if (x != 0) {n -= 4; num = x;} |
192 | 0 | x = num >> 2; if (x != 0) {n -= 2; num = x;} |
193 | 0 | x = num >> 1; if (x != 0) return n - 2; |
194 | 0 | return n - num; |
195 | 0 | #endif |
196 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_nlz Unexecuted instantiation: ir_check.c:ir_nlz Unexecuted instantiation: ir_dump.c:ir_nlz Unexecuted instantiation: ir_emit.c:ir_nlz Unexecuted instantiation: ir_gcm.c:ir_nlz Unexecuted instantiation: ir_gdb.c:ir_nlz Unexecuted instantiation: ir_patch.c:ir_nlz Unexecuted instantiation: ir_ra.c:ir_nlz Unexecuted instantiation: ir_save.c:ir_nlz Unexecuted instantiation: ir_sccp.c:ir_nlz Unexecuted instantiation: ir_strtab.c:ir_nlz Unexecuted instantiation: ir.c:ir_nlz |
197 | | |
198 | | IR_ALWAYS_INLINE int ir_nlzl(uint64_t num) |
199 | 0 | { |
200 | 0 | #if (defined(__GNUC__) || __has_builtin(__builtin_clzll)) |
201 | 0 | return __builtin_clzll(num); |
202 | 0 | #elif defined(_WIN64) |
203 | 0 | unsigned long index; |
204 | 0 |
|
205 | 0 | if (!_BitScanReverse64(&index, num)) { |
206 | 0 | /* undefined behavior */ |
207 | 0 | return 64; |
208 | 0 | } |
209 | 0 |
|
210 | 0 | return (int) (64 - 1) - index; |
211 | 0 | #else |
212 | 0 | uint64_t x; |
213 | 0 | uint32_t n; |
214 | 0 |
|
215 | 0 | n = 64; |
216 | 0 | x = num >> 32; if (x != 0) {n -= 32; num = x;} |
217 | 0 | x = num >> 16; if (x != 0) {n -= 16; num = x;} |
218 | 0 | x = num >> 8; if (x != 0) {n -= 8; num = x;} |
219 | 0 | x = num >> 4; if (x != 0) {n -= 4; num = x;} |
220 | 0 | x = num >> 2; if (x != 0) {n -= 2; num = x;} |
221 | 0 | x = num >> 1; if (x != 0) return n - 2; |
222 | 0 | return n - (uint32_t)num; |
223 | 0 | #endif |
224 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_nlzl Unexecuted instantiation: ir_check.c:ir_nlzl Unexecuted instantiation: ir_dump.c:ir_nlzl Unexecuted instantiation: ir_emit.c:ir_nlzl Unexecuted instantiation: ir_gcm.c:ir_nlzl Unexecuted instantiation: ir_gdb.c:ir_nlzl Unexecuted instantiation: ir_patch.c:ir_nlzl Unexecuted instantiation: ir_ra.c:ir_nlzl Unexecuted instantiation: ir_save.c:ir_nlzl Unexecuted instantiation: ir_sccp.c:ir_nlzl Unexecuted instantiation: ir_strtab.c:ir_nlzl Unexecuted instantiation: ir.c:ir_nlzl |
225 | | |
226 | | /*** Helper data types ***/ |
227 | | |
228 | | /* Arena */ |
229 | | struct _ir_arena { |
230 | | char *ptr; |
231 | | char *end; |
232 | | ir_arena *prev; |
233 | | }; |
234 | | |
235 | | IR_ALWAYS_INLINE ir_arena* ir_arena_create(size_t size) |
236 | 0 | { |
237 | 0 | ir_arena *arena; |
238 | |
|
239 | 0 | IR_ASSERT(size >= IR_ALIGNED_SIZE(sizeof(ir_arena), 8)); |
240 | 0 | arena = (ir_arena*)ir_mem_malloc(size); |
241 | 0 | arena->ptr = (char*) arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8); |
242 | 0 | arena->end = (char*) arena + size; |
243 | 0 | arena->prev = NULL; |
244 | 0 | return arena; |
245 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_arena_create Unexecuted instantiation: ir_check.c:ir_arena_create Unexecuted instantiation: ir_dump.c:ir_arena_create Unexecuted instantiation: ir_emit.c:ir_arena_create Unexecuted instantiation: ir_gcm.c:ir_arena_create Unexecuted instantiation: ir_gdb.c:ir_arena_create Unexecuted instantiation: ir_patch.c:ir_arena_create Unexecuted instantiation: ir_ra.c:ir_arena_create Unexecuted instantiation: ir_save.c:ir_arena_create Unexecuted instantiation: ir_sccp.c:ir_arena_create Unexecuted instantiation: ir_strtab.c:ir_arena_create Unexecuted instantiation: ir.c:ir_arena_create |
246 | | |
247 | | IR_ALWAYS_INLINE void ir_arena_free(ir_arena *arena) |
248 | 0 | { |
249 | 0 | do { |
250 | 0 | ir_arena *prev = arena->prev; |
251 | 0 | ir_mem_free(arena); |
252 | 0 | arena = prev; |
253 | 0 | } while (arena); |
254 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_arena_free Unexecuted instantiation: ir_check.c:ir_arena_free Unexecuted instantiation: ir_dump.c:ir_arena_free Unexecuted instantiation: ir_emit.c:ir_arena_free Unexecuted instantiation: ir_gcm.c:ir_arena_free Unexecuted instantiation: ir_gdb.c:ir_arena_free Unexecuted instantiation: ir_patch.c:ir_arena_free Unexecuted instantiation: ir_ra.c:ir_arena_free Unexecuted instantiation: ir_save.c:ir_arena_free Unexecuted instantiation: ir_sccp.c:ir_arena_free Unexecuted instantiation: ir_strtab.c:ir_arena_free Unexecuted instantiation: ir.c:ir_arena_free |
255 | | |
256 | | IR_ALWAYS_INLINE void* ir_arena_alloc(ir_arena **arena_ptr, size_t size) |
257 | 0 | { |
258 | 0 | ir_arena *arena = *arena_ptr; |
259 | 0 | char *ptr = (char*)IR_ALIGNED_SIZE((uintptr_t)arena->ptr, 8); |
260 | |
|
261 | 0 | if (EXPECTED((ptrdiff_t)size <= (ptrdiff_t)(arena->end - ptr))) { |
262 | 0 | arena->ptr = ptr + size; |
263 | 0 | } else { |
264 | 0 | size_t arena_size = |
265 | 0 | UNEXPECTED((size + IR_ALIGNED_SIZE(sizeof(ir_arena), 8)) > (size_t)(arena->end - (char*) arena)) ? |
266 | 0 | (size + IR_ALIGNED_SIZE(sizeof(ir_arena), 8)) : |
267 | 0 | (size_t)(arena->end - (char*) arena); |
268 | 0 | ir_arena *new_arena = (ir_arena*)ir_mem_malloc(arena_size); |
269 | |
|
270 | 0 | ptr = (char*) new_arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8); |
271 | 0 | new_arena->ptr = (char*) new_arena + IR_ALIGNED_SIZE(sizeof(ir_arena), 8) + size; |
272 | 0 | new_arena->end = (char*) new_arena + arena_size; |
273 | 0 | new_arena->prev = arena; |
274 | 0 | *arena_ptr = new_arena; |
275 | 0 | } |
276 | |
|
277 | 0 | return (void*) ptr; |
278 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_arena_alloc Unexecuted instantiation: ir_check.c:ir_arena_alloc Unexecuted instantiation: ir_dump.c:ir_arena_alloc Unexecuted instantiation: ir_emit.c:ir_arena_alloc Unexecuted instantiation: ir_gcm.c:ir_arena_alloc Unexecuted instantiation: ir_gdb.c:ir_arena_alloc Unexecuted instantiation: ir_patch.c:ir_arena_alloc Unexecuted instantiation: ir_ra.c:ir_arena_alloc Unexecuted instantiation: ir_save.c:ir_arena_alloc Unexecuted instantiation: ir_sccp.c:ir_arena_alloc Unexecuted instantiation: ir_strtab.c:ir_arena_alloc Unexecuted instantiation: ir.c:ir_arena_alloc |
279 | | |
280 | | IR_ALWAYS_INLINE void* ir_arena_checkpoint(ir_arena *arena) |
281 | 0 | { |
282 | 0 | return arena->ptr; |
283 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_arena_checkpoint Unexecuted instantiation: ir_check.c:ir_arena_checkpoint Unexecuted instantiation: ir_dump.c:ir_arena_checkpoint Unexecuted instantiation: ir_emit.c:ir_arena_checkpoint Unexecuted instantiation: ir_gcm.c:ir_arena_checkpoint Unexecuted instantiation: ir_gdb.c:ir_arena_checkpoint Unexecuted instantiation: ir_patch.c:ir_arena_checkpoint Unexecuted instantiation: ir_ra.c:ir_arena_checkpoint Unexecuted instantiation: ir_save.c:ir_arena_checkpoint Unexecuted instantiation: ir_sccp.c:ir_arena_checkpoint Unexecuted instantiation: ir_strtab.c:ir_arena_checkpoint Unexecuted instantiation: ir.c:ir_arena_checkpoint |
284 | | |
285 | | IR_ALWAYS_INLINE void ir_arena_release(ir_arena **arena_ptr, void *checkpoint) |
286 | 0 | { |
287 | 0 | ir_arena *arena = *arena_ptr; |
288 | 0 |
|
289 | 0 | while (UNEXPECTED((char*)checkpoint > arena->end) || |
290 | 0 | UNEXPECTED((char*)checkpoint <= (char*)arena)) { |
291 | 0 | ir_arena *prev = arena->prev; |
292 | 0 | ir_mem_free(arena); |
293 | 0 | *arena_ptr = arena = prev; |
294 | 0 | } |
295 | 0 | IR_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end); |
296 | 0 | arena->ptr = (char*)checkpoint; |
297 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_arena_release Unexecuted instantiation: ir_check.c:ir_arena_release Unexecuted instantiation: ir_dump.c:ir_arena_release Unexecuted instantiation: ir_emit.c:ir_arena_release Unexecuted instantiation: ir_gcm.c:ir_arena_release Unexecuted instantiation: ir_gdb.c:ir_arena_release Unexecuted instantiation: ir_patch.c:ir_arena_release Unexecuted instantiation: ir_ra.c:ir_arena_release Unexecuted instantiation: ir_save.c:ir_arena_release Unexecuted instantiation: ir_sccp.c:ir_arena_release Unexecuted instantiation: ir_strtab.c:ir_arena_release Unexecuted instantiation: ir.c:ir_arena_release |
298 | | |
299 | | /* Bitsets */ |
300 | | #if defined(IR_TARGET_X86) |
301 | | # define IR_BITSET_BITS 32 |
302 | | # define IR_BITSET_ONE 1U |
303 | | # define ir_bitset_base_t uint32_t |
304 | | # define ir_bitset_ntz ir_ntz |
305 | | #else |
306 | 0 | # define IR_BITSET_BITS 64 |
307 | | # ifdef _M_X64 /* MSVC*/ |
308 | | # define IR_BITSET_ONE 1ui64 |
309 | | # else |
310 | 0 | # define IR_BITSET_ONE 1UL |
311 | | # endif |
312 | 0 | # define ir_bitset_base_t uint64_t |
313 | 0 | # define ir_bitset_ntz ir_ntzl |
314 | | #endif |
315 | | |
316 | | typedef ir_bitset_base_t *ir_bitset; |
317 | | |
318 | | IR_ALWAYS_INLINE uint32_t ir_bitset_len(uint32_t n) |
319 | 0 | { |
320 | 0 | return (n + (IR_BITSET_BITS - 1)) / IR_BITSET_BITS; |
321 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_len Unexecuted instantiation: ir_check.c:ir_bitset_len Unexecuted instantiation: ir_dump.c:ir_bitset_len Unexecuted instantiation: ir_emit.c:ir_bitset_len Unexecuted instantiation: ir_gcm.c:ir_bitset_len Unexecuted instantiation: ir_gdb.c:ir_bitset_len Unexecuted instantiation: ir_patch.c:ir_bitset_len Unexecuted instantiation: ir_ra.c:ir_bitset_len Unexecuted instantiation: ir_save.c:ir_bitset_len Unexecuted instantiation: ir_sccp.c:ir_bitset_len Unexecuted instantiation: ir_strtab.c:ir_bitset_len Unexecuted instantiation: ir.c:ir_bitset_len |
322 | | |
323 | | IR_ALWAYS_INLINE ir_bitset ir_bitset_malloc(uint32_t n) |
324 | 0 | { |
325 | 0 | return ir_mem_calloc(ir_bitset_len(n), IR_BITSET_BITS / 8); |
326 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_malloc Unexecuted instantiation: ir_check.c:ir_bitset_malloc Unexecuted instantiation: ir_dump.c:ir_bitset_malloc Unexecuted instantiation: ir_emit.c:ir_bitset_malloc Unexecuted instantiation: ir_gcm.c:ir_bitset_malloc Unexecuted instantiation: ir_gdb.c:ir_bitset_malloc Unexecuted instantiation: ir_patch.c:ir_bitset_malloc Unexecuted instantiation: ir_ra.c:ir_bitset_malloc Unexecuted instantiation: ir_save.c:ir_bitset_malloc Unexecuted instantiation: ir_sccp.c:ir_bitset_malloc Unexecuted instantiation: ir_strtab.c:ir_bitset_malloc Unexecuted instantiation: ir.c:ir_bitset_malloc |
327 | | |
328 | | IR_ALWAYS_INLINE void ir_bitset_incl(ir_bitset set, uint32_t n) |
329 | 0 | { |
330 | 0 | set[n / IR_BITSET_BITS] |= IR_BITSET_ONE << (n % IR_BITSET_BITS); |
331 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_incl Unexecuted instantiation: ir_check.c:ir_bitset_incl Unexecuted instantiation: ir_dump.c:ir_bitset_incl Unexecuted instantiation: ir_emit.c:ir_bitset_incl Unexecuted instantiation: ir_gcm.c:ir_bitset_incl Unexecuted instantiation: ir_gdb.c:ir_bitset_incl Unexecuted instantiation: ir_patch.c:ir_bitset_incl Unexecuted instantiation: ir_ra.c:ir_bitset_incl Unexecuted instantiation: ir_save.c:ir_bitset_incl Unexecuted instantiation: ir_sccp.c:ir_bitset_incl Unexecuted instantiation: ir_strtab.c:ir_bitset_incl Unexecuted instantiation: ir.c:ir_bitset_incl |
332 | | |
333 | | IR_ALWAYS_INLINE void ir_bitset_excl(ir_bitset set, uint32_t n) |
334 | 0 | { |
335 | 0 | set[n / IR_BITSET_BITS] &= ~(IR_BITSET_ONE << (n % IR_BITSET_BITS)); |
336 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_excl Unexecuted instantiation: ir_check.c:ir_bitset_excl Unexecuted instantiation: ir_dump.c:ir_bitset_excl Unexecuted instantiation: ir_emit.c:ir_bitset_excl Unexecuted instantiation: ir_gcm.c:ir_bitset_excl Unexecuted instantiation: ir_gdb.c:ir_bitset_excl Unexecuted instantiation: ir_patch.c:ir_bitset_excl Unexecuted instantiation: ir_ra.c:ir_bitset_excl Unexecuted instantiation: ir_save.c:ir_bitset_excl Unexecuted instantiation: ir_sccp.c:ir_bitset_excl Unexecuted instantiation: ir_strtab.c:ir_bitset_excl Unexecuted instantiation: ir.c:ir_bitset_excl |
337 | | |
338 | | IR_ALWAYS_INLINE bool ir_bitset_in(const ir_bitset set, uint32_t n) |
339 | 0 | { |
340 | 0 | return (set[(n / IR_BITSET_BITS)] & (IR_BITSET_ONE << (n % IR_BITSET_BITS))) != 0; |
341 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_in Unexecuted instantiation: ir_check.c:ir_bitset_in Unexecuted instantiation: ir_dump.c:ir_bitset_in Unexecuted instantiation: ir_emit.c:ir_bitset_in Unexecuted instantiation: ir_gcm.c:ir_bitset_in Unexecuted instantiation: ir_gdb.c:ir_bitset_in Unexecuted instantiation: ir_patch.c:ir_bitset_in Unexecuted instantiation: ir_ra.c:ir_bitset_in Unexecuted instantiation: ir_save.c:ir_bitset_in Unexecuted instantiation: ir_sccp.c:ir_bitset_in Unexecuted instantiation: ir_strtab.c:ir_bitset_in Unexecuted instantiation: ir.c:ir_bitset_in |
342 | | |
343 | | IR_ALWAYS_INLINE void ir_bitset_clear(ir_bitset set, uint32_t len) |
344 | 0 | { |
345 | 0 | memset(set, 0, len * (IR_BITSET_BITS / 8)); |
346 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_clear Unexecuted instantiation: ir_check.c:ir_bitset_clear Unexecuted instantiation: ir_dump.c:ir_bitset_clear Unexecuted instantiation: ir_emit.c:ir_bitset_clear Unexecuted instantiation: ir_gcm.c:ir_bitset_clear Unexecuted instantiation: ir_gdb.c:ir_bitset_clear Unexecuted instantiation: ir_patch.c:ir_bitset_clear Unexecuted instantiation: ir_ra.c:ir_bitset_clear Unexecuted instantiation: ir_save.c:ir_bitset_clear Unexecuted instantiation: ir_sccp.c:ir_bitset_clear Unexecuted instantiation: ir_strtab.c:ir_bitset_clear Unexecuted instantiation: ir.c:ir_bitset_clear |
347 | | |
348 | | IR_ALWAYS_INLINE void ir_bitset_fill(ir_bitset set, uint32_t len) |
349 | 0 | { |
350 | 0 | memset(set, 0xff, len * (IR_BITSET_BITS / 8)); |
351 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_fill Unexecuted instantiation: ir_check.c:ir_bitset_fill Unexecuted instantiation: ir_dump.c:ir_bitset_fill Unexecuted instantiation: ir_emit.c:ir_bitset_fill Unexecuted instantiation: ir_gcm.c:ir_bitset_fill Unexecuted instantiation: ir_gdb.c:ir_bitset_fill Unexecuted instantiation: ir_patch.c:ir_bitset_fill Unexecuted instantiation: ir_ra.c:ir_bitset_fill Unexecuted instantiation: ir_save.c:ir_bitset_fill Unexecuted instantiation: ir_sccp.c:ir_bitset_fill Unexecuted instantiation: ir_strtab.c:ir_bitset_fill Unexecuted instantiation: ir.c:ir_bitset_fill |
352 | | |
353 | | IR_ALWAYS_INLINE bool ir_bitset_empty(const ir_bitset set, uint32_t len) |
354 | 0 | { |
355 | 0 | uint32_t i; |
356 | 0 | for (i = 0; i < len; i++) { |
357 | 0 | if (set[i]) { |
358 | 0 | return 0; |
359 | 0 | } |
360 | 0 | } |
361 | 0 | return 1; |
362 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_empty Unexecuted instantiation: ir_check.c:ir_bitset_empty Unexecuted instantiation: ir_dump.c:ir_bitset_empty Unexecuted instantiation: ir_emit.c:ir_bitset_empty Unexecuted instantiation: ir_gcm.c:ir_bitset_empty Unexecuted instantiation: ir_gdb.c:ir_bitset_empty Unexecuted instantiation: ir_patch.c:ir_bitset_empty Unexecuted instantiation: ir_ra.c:ir_bitset_empty Unexecuted instantiation: ir_save.c:ir_bitset_empty Unexecuted instantiation: ir_sccp.c:ir_bitset_empty Unexecuted instantiation: ir_strtab.c:ir_bitset_empty Unexecuted instantiation: ir.c:ir_bitset_empty |
363 | | |
364 | | IR_ALWAYS_INLINE bool ir_bitset_equal(const ir_bitset set1, const ir_bitset set2, uint32_t len) |
365 | 0 | { |
366 | 0 | return memcmp(set1, set2, len * (IR_BITSET_BITS / 8)) == 0; |
367 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_equal Unexecuted instantiation: ir_check.c:ir_bitset_equal Unexecuted instantiation: ir_dump.c:ir_bitset_equal Unexecuted instantiation: ir_emit.c:ir_bitset_equal Unexecuted instantiation: ir_gcm.c:ir_bitset_equal Unexecuted instantiation: ir_gdb.c:ir_bitset_equal Unexecuted instantiation: ir_patch.c:ir_bitset_equal Unexecuted instantiation: ir_ra.c:ir_bitset_equal Unexecuted instantiation: ir_save.c:ir_bitset_equal Unexecuted instantiation: ir_sccp.c:ir_bitset_equal Unexecuted instantiation: ir_strtab.c:ir_bitset_equal Unexecuted instantiation: ir.c:ir_bitset_equal |
368 | | |
369 | | IR_ALWAYS_INLINE void ir_bitset_copy(ir_bitset set1, const ir_bitset set2, uint32_t len) |
370 | 0 | { |
371 | 0 | memcpy(set1, set2, len * (IR_BITSET_BITS / 8)); |
372 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_copy Unexecuted instantiation: ir_check.c:ir_bitset_copy Unexecuted instantiation: ir_dump.c:ir_bitset_copy Unexecuted instantiation: ir_emit.c:ir_bitset_copy Unexecuted instantiation: ir_gcm.c:ir_bitset_copy Unexecuted instantiation: ir_gdb.c:ir_bitset_copy Unexecuted instantiation: ir_patch.c:ir_bitset_copy Unexecuted instantiation: ir_ra.c:ir_bitset_copy Unexecuted instantiation: ir_save.c:ir_bitset_copy Unexecuted instantiation: ir_sccp.c:ir_bitset_copy Unexecuted instantiation: ir_strtab.c:ir_bitset_copy Unexecuted instantiation: ir.c:ir_bitset_copy |
373 | | |
374 | | IR_ALWAYS_INLINE void ir_bitset_intersection(ir_bitset set1, const ir_bitset set2, uint32_t len) |
375 | 0 | { |
376 | 0 | uint32_t i; |
377 | |
|
378 | 0 | for (i = 0; i < len; i++) { |
379 | 0 | set1[i] &= set2[i]; |
380 | 0 | } |
381 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_intersection Unexecuted instantiation: ir_check.c:ir_bitset_intersection Unexecuted instantiation: ir_dump.c:ir_bitset_intersection Unexecuted instantiation: ir_emit.c:ir_bitset_intersection Unexecuted instantiation: ir_gcm.c:ir_bitset_intersection Unexecuted instantiation: ir_gdb.c:ir_bitset_intersection Unexecuted instantiation: ir_patch.c:ir_bitset_intersection Unexecuted instantiation: ir_ra.c:ir_bitset_intersection Unexecuted instantiation: ir_save.c:ir_bitset_intersection Unexecuted instantiation: ir_sccp.c:ir_bitset_intersection Unexecuted instantiation: ir_strtab.c:ir_bitset_intersection Unexecuted instantiation: ir.c:ir_bitset_intersection |
382 | | |
383 | | IR_ALWAYS_INLINE void ir_bitset_union(ir_bitset set1, const ir_bitset set2, uint32_t len) |
384 | 0 | { |
385 | 0 | uint32_t i; |
386 | |
|
387 | 0 | for (i = 0; i < len; i++) { |
388 | 0 | set1[i] |= set2[i]; |
389 | 0 | } |
390 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_union Unexecuted instantiation: ir_check.c:ir_bitset_union Unexecuted instantiation: ir_dump.c:ir_bitset_union Unexecuted instantiation: ir_emit.c:ir_bitset_union Unexecuted instantiation: ir_gcm.c:ir_bitset_union Unexecuted instantiation: ir_gdb.c:ir_bitset_union Unexecuted instantiation: ir_patch.c:ir_bitset_union Unexecuted instantiation: ir_ra.c:ir_bitset_union Unexecuted instantiation: ir_save.c:ir_bitset_union Unexecuted instantiation: ir_sccp.c:ir_bitset_union Unexecuted instantiation: ir_strtab.c:ir_bitset_union Unexecuted instantiation: ir.c:ir_bitset_union |
391 | | |
392 | | IR_ALWAYS_INLINE void ir_bitset_difference(ir_bitset set1, const ir_bitset set2, uint32_t len) |
393 | 0 | { |
394 | 0 | uint32_t i; |
395 | |
|
396 | 0 | for (i = 0; i < len; i++) { |
397 | 0 | set1[i] = set1[i] & ~set2[i]; |
398 | 0 | } |
399 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_difference Unexecuted instantiation: ir_check.c:ir_bitset_difference Unexecuted instantiation: ir_dump.c:ir_bitset_difference Unexecuted instantiation: ir_emit.c:ir_bitset_difference Unexecuted instantiation: ir_gcm.c:ir_bitset_difference Unexecuted instantiation: ir_gdb.c:ir_bitset_difference Unexecuted instantiation: ir_patch.c:ir_bitset_difference Unexecuted instantiation: ir_ra.c:ir_bitset_difference Unexecuted instantiation: ir_save.c:ir_bitset_difference Unexecuted instantiation: ir_sccp.c:ir_bitset_difference Unexecuted instantiation: ir_strtab.c:ir_bitset_difference Unexecuted instantiation: ir.c:ir_bitset_difference |
400 | | |
401 | | IR_ALWAYS_INLINE bool ir_bitset_is_subset(const ir_bitset set1, const ir_bitset set2, uint32_t len) |
402 | 0 | { |
403 | 0 | uint32_t i; |
404 | 0 |
|
405 | 0 | for (i = 0; i < len; i++) { |
406 | 0 | if (set1[i] & ~set2[i]) { |
407 | 0 | return 0; |
408 | 0 | } |
409 | 0 | } |
410 | 0 | return 1; |
411 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_is_subset Unexecuted instantiation: ir_check.c:ir_bitset_is_subset Unexecuted instantiation: ir_dump.c:ir_bitset_is_subset Unexecuted instantiation: ir_emit.c:ir_bitset_is_subset Unexecuted instantiation: ir_gcm.c:ir_bitset_is_subset Unexecuted instantiation: ir_gdb.c:ir_bitset_is_subset Unexecuted instantiation: ir_patch.c:ir_bitset_is_subset Unexecuted instantiation: ir_ra.c:ir_bitset_is_subset Unexecuted instantiation: ir_save.c:ir_bitset_is_subset Unexecuted instantiation: ir_sccp.c:ir_bitset_is_subset Unexecuted instantiation: ir_strtab.c:ir_bitset_is_subset Unexecuted instantiation: ir.c:ir_bitset_is_subset |
412 | | |
413 | | IR_ALWAYS_INLINE int ir_bitset_first(const ir_bitset set, uint32_t len) |
414 | 0 | { |
415 | 0 | uint32_t i; |
416 | |
|
417 | 0 | for (i = 0; i < len; i++) { |
418 | 0 | if (set[i]) { |
419 | 0 | return IR_BITSET_BITS * i + ir_bitset_ntz(set[i]); |
420 | 0 | } |
421 | 0 | } |
422 | 0 | return -1; /* empty set */ |
423 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_first Unexecuted instantiation: ir_check.c:ir_bitset_first Unexecuted instantiation: ir_dump.c:ir_bitset_first Unexecuted instantiation: ir_emit.c:ir_bitset_first Unexecuted instantiation: ir_gcm.c:ir_bitset_first Unexecuted instantiation: ir_gdb.c:ir_bitset_first Unexecuted instantiation: ir_patch.c:ir_bitset_first Unexecuted instantiation: ir_ra.c:ir_bitset_first Unexecuted instantiation: ir_save.c:ir_bitset_first Unexecuted instantiation: ir_sccp.c:ir_bitset_first Unexecuted instantiation: ir_strtab.c:ir_bitset_first Unexecuted instantiation: ir.c:ir_bitset_first |
424 | | |
425 | | IR_ALWAYS_INLINE int ir_bitset_last(const ir_bitset set, uint32_t len) |
426 | 0 | { |
427 | 0 | uint32_t i = len; |
428 | 0 |
|
429 | 0 | while (i > 0) { |
430 | 0 | i--; |
431 | 0 | if (set[i]) { |
432 | 0 | uint32_t j = IR_BITSET_BITS * i - 1; |
433 | 0 | ir_bitset_base_t x = set[i]; |
434 | 0 | do { |
435 | 0 | x = x >> 1; |
436 | 0 | j++; |
437 | 0 | } while (x != 0); |
438 | 0 | return j; |
439 | 0 | } |
440 | 0 | } |
441 | 0 | return -1; /* empty set */ |
442 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_last Unexecuted instantiation: ir_check.c:ir_bitset_last Unexecuted instantiation: ir_dump.c:ir_bitset_last Unexecuted instantiation: ir_emit.c:ir_bitset_last Unexecuted instantiation: ir_gcm.c:ir_bitset_last Unexecuted instantiation: ir_gdb.c:ir_bitset_last Unexecuted instantiation: ir_patch.c:ir_bitset_last Unexecuted instantiation: ir_ra.c:ir_bitset_last Unexecuted instantiation: ir_save.c:ir_bitset_last Unexecuted instantiation: ir_sccp.c:ir_bitset_last Unexecuted instantiation: ir_strtab.c:ir_bitset_last Unexecuted instantiation: ir.c:ir_bitset_last |
443 | | |
444 | | IR_ALWAYS_INLINE int ir_bitset_pop_first(ir_bitset set, uint32_t len) |
445 | 0 | { |
446 | 0 | uint32_t i; |
447 | |
|
448 | 0 | for (i = 0; i < len; i++) { |
449 | 0 | ir_bitset_base_t x = set[i]; |
450 | |
|
451 | 0 | if (x) { |
452 | 0 | int bit = IR_BITSET_BITS * i + ir_bitset_ntz(x); |
453 | 0 | set[i] = x & (x - 1); |
454 | 0 | return bit; |
455 | 0 | } |
456 | 0 | } |
457 | 0 | return -1; /* empty set */ |
458 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitset_pop_first Unexecuted instantiation: ir_check.c:ir_bitset_pop_first Unexecuted instantiation: ir_dump.c:ir_bitset_pop_first Unexecuted instantiation: ir_emit.c:ir_bitset_pop_first Unexecuted instantiation: ir_gcm.c:ir_bitset_pop_first Unexecuted instantiation: ir_gdb.c:ir_bitset_pop_first Unexecuted instantiation: ir_patch.c:ir_bitset_pop_first Unexecuted instantiation: ir_ra.c:ir_bitset_pop_first Unexecuted instantiation: ir_save.c:ir_bitset_pop_first Unexecuted instantiation: ir_sccp.c:ir_bitset_pop_first Unexecuted instantiation: ir_strtab.c:ir_bitset_pop_first Unexecuted instantiation: ir.c:ir_bitset_pop_first |
459 | | |
460 | 0 | #define IR_BITSET_FOREACH(set, len, bit) do { \ |
461 | 0 | ir_bitset _set = (set); \ |
462 | 0 | uint32_t _i, _len = (len); \ |
463 | 0 | for (_i = 0; _i < _len; _set++, _i++) { \ |
464 | 0 | ir_bitset_base_t _x = *_set; \ |
465 | 0 | while (_x) { \ |
466 | 0 | (bit) = IR_BITSET_BITS * _i + ir_bitset_ntz(_x); \ |
467 | 0 | _x &= _x - 1; |
468 | | |
469 | 0 | #define IR_BITSET_FOREACH_DIFFERENCE(set1, set2, len, bit) do { \ |
470 | 0 | ir_bitset _set1 = (set1); \ |
471 | 0 | ir_bitset _set2 = (set2); \ |
472 | 0 | uint32_t _i, _len = (len); \ |
473 | 0 | for (_i = 0; _i < _len; _i++) { \ |
474 | 0 | ir_bitset_base_t _x = _set1[_i] & ~_set2[_i]; \ |
475 | 0 | while (_x) { \ |
476 | 0 | (bit) = IR_BITSET_BITS * _i + ir_bitset_ntz(_x); \ |
477 | 0 | _x &= _x - 1; |
478 | | |
479 | | #define IR_BITSET_FOREACH_END() \ |
480 | 0 | } \ |
481 | 0 | } \ |
482 | 0 | } while (0) |
483 | | |
484 | | /* Sparse Set */ |
485 | | typedef struct _ir_sparse_set { |
486 | | uint32_t size; |
487 | | uint32_t len; |
488 | | uint32_t *data; |
489 | | } ir_sparse_set; |
490 | | |
491 | 0 | #define IR_SPARSE_SET_DENSE(set, n) (set)->data[n] |
492 | 0 | #define IR_SPARSE_SET_SPARSE(set, n) (set)->data[-1 - ((int32_t)(n))] |
493 | | |
494 | | IR_ALWAYS_INLINE void ir_sparse_set_init(ir_sparse_set *set, uint32_t size) |
495 | 0 | { |
496 | 0 | set->size = size; |
497 | 0 | set->len = 0; |
498 | 0 | set->data = (uint32_t*)ir_mem_malloc(sizeof(uint32_t) * 2 * size) + size; |
499 | 0 | #ifdef IR_DEBUG |
500 | | /* initialize sparse part to avoid valgrind warnings */ |
501 | 0 | memset(&IR_SPARSE_SET_SPARSE(set, size - 1), 0, size * sizeof(uint32_t)); |
502 | 0 | #endif |
503 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_init Unexecuted instantiation: ir_check.c:ir_sparse_set_init Unexecuted instantiation: ir_dump.c:ir_sparse_set_init Unexecuted instantiation: ir_emit.c:ir_sparse_set_init Unexecuted instantiation: ir_gcm.c:ir_sparse_set_init Unexecuted instantiation: ir_gdb.c:ir_sparse_set_init Unexecuted instantiation: ir_patch.c:ir_sparse_set_init Unexecuted instantiation: ir_ra.c:ir_sparse_set_init Unexecuted instantiation: ir_save.c:ir_sparse_set_init Unexecuted instantiation: ir_sccp.c:ir_sparse_set_init Unexecuted instantiation: ir_strtab.c:ir_sparse_set_init Unexecuted instantiation: ir.c:ir_sparse_set_init |
504 | | |
505 | | IR_ALWAYS_INLINE void ir_sparse_set_clear(ir_sparse_set *set) |
506 | 0 | { |
507 | 0 | set->len = 0; |
508 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_clear Unexecuted instantiation: ir_check.c:ir_sparse_set_clear Unexecuted instantiation: ir_dump.c:ir_sparse_set_clear Unexecuted instantiation: ir_emit.c:ir_sparse_set_clear Unexecuted instantiation: ir_gcm.c:ir_sparse_set_clear Unexecuted instantiation: ir_gdb.c:ir_sparse_set_clear Unexecuted instantiation: ir_patch.c:ir_sparse_set_clear Unexecuted instantiation: ir_ra.c:ir_sparse_set_clear Unexecuted instantiation: ir_save.c:ir_sparse_set_clear Unexecuted instantiation: ir_sccp.c:ir_sparse_set_clear Unexecuted instantiation: ir_strtab.c:ir_sparse_set_clear Unexecuted instantiation: ir.c:ir_sparse_set_clear |
509 | | |
510 | | IR_ALWAYS_INLINE void ir_sparse_set_free(ir_sparse_set *set) |
511 | 0 | { |
512 | 0 | ir_mem_free(set->data - set->size); |
513 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_free Unexecuted instantiation: ir_check.c:ir_sparse_set_free Unexecuted instantiation: ir_dump.c:ir_sparse_set_free Unexecuted instantiation: ir_emit.c:ir_sparse_set_free Unexecuted instantiation: ir_gcm.c:ir_sparse_set_free Unexecuted instantiation: ir_gdb.c:ir_sparse_set_free Unexecuted instantiation: ir_patch.c:ir_sparse_set_free Unexecuted instantiation: ir_ra.c:ir_sparse_set_free Unexecuted instantiation: ir_save.c:ir_sparse_set_free Unexecuted instantiation: ir_sccp.c:ir_sparse_set_free Unexecuted instantiation: ir_strtab.c:ir_sparse_set_free Unexecuted instantiation: ir.c:ir_sparse_set_free |
514 | | |
515 | | IR_ALWAYS_INLINE bool ir_sparse_set_empty(const ir_sparse_set *set) |
516 | 0 | { |
517 | 0 | return set->len == 0; |
518 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_empty Unexecuted instantiation: ir_check.c:ir_sparse_set_empty Unexecuted instantiation: ir_dump.c:ir_sparse_set_empty Unexecuted instantiation: ir_emit.c:ir_sparse_set_empty Unexecuted instantiation: ir_gcm.c:ir_sparse_set_empty Unexecuted instantiation: ir_gdb.c:ir_sparse_set_empty Unexecuted instantiation: ir_patch.c:ir_sparse_set_empty Unexecuted instantiation: ir_ra.c:ir_sparse_set_empty Unexecuted instantiation: ir_save.c:ir_sparse_set_empty Unexecuted instantiation: ir_sccp.c:ir_sparse_set_empty Unexecuted instantiation: ir_strtab.c:ir_sparse_set_empty Unexecuted instantiation: ir.c:ir_sparse_set_empty |
519 | | |
520 | | IR_ALWAYS_INLINE bool ir_sparse_set_in(const ir_sparse_set *set, uint32_t n) |
521 | 0 | { |
522 | 0 | uint32_t idx = IR_SPARSE_SET_SPARSE(set, n); |
523 | |
|
524 | 0 | return idx < set->len && IR_SPARSE_SET_DENSE(set, idx) == n; |
525 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_in Unexecuted instantiation: ir_check.c:ir_sparse_set_in Unexecuted instantiation: ir_dump.c:ir_sparse_set_in Unexecuted instantiation: ir_emit.c:ir_sparse_set_in Unexecuted instantiation: ir_gcm.c:ir_sparse_set_in Unexecuted instantiation: ir_gdb.c:ir_sparse_set_in Unexecuted instantiation: ir_patch.c:ir_sparse_set_in Unexecuted instantiation: ir_ra.c:ir_sparse_set_in Unexecuted instantiation: ir_save.c:ir_sparse_set_in Unexecuted instantiation: ir_sccp.c:ir_sparse_set_in Unexecuted instantiation: ir_strtab.c:ir_sparse_set_in Unexecuted instantiation: ir.c:ir_sparse_set_in |
526 | | |
527 | | IR_ALWAYS_INLINE void ir_sparse_set_add(ir_sparse_set *set, uint32_t n) |
528 | 0 | { |
529 | 0 | uint32_t idx; |
530 | |
|
531 | 0 | IR_ASSERT(!ir_sparse_set_in(set, n)); |
532 | 0 | idx = set->len++; |
533 | 0 | IR_SPARSE_SET_DENSE(set, idx) = n; |
534 | 0 | IR_SPARSE_SET_SPARSE(set, n) = idx; |
535 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_add Unexecuted instantiation: ir_check.c:ir_sparse_set_add Unexecuted instantiation: ir_dump.c:ir_sparse_set_add Unexecuted instantiation: ir_emit.c:ir_sparse_set_add Unexecuted instantiation: ir_gcm.c:ir_sparse_set_add Unexecuted instantiation: ir_gdb.c:ir_sparse_set_add Unexecuted instantiation: ir_patch.c:ir_sparse_set_add Unexecuted instantiation: ir_ra.c:ir_sparse_set_add Unexecuted instantiation: ir_save.c:ir_sparse_set_add Unexecuted instantiation: ir_sccp.c:ir_sparse_set_add Unexecuted instantiation: ir_strtab.c:ir_sparse_set_add Unexecuted instantiation: ir.c:ir_sparse_set_add |
536 | | |
537 | | IR_ALWAYS_INLINE void ir_sparse_set_del(ir_sparse_set *set, uint32_t n) |
538 | 0 | { |
539 | 0 | uint32_t last; |
540 | 0 |
|
541 | 0 | IR_ASSERT(ir_sparse_set_in(set, n)); |
542 | 0 | last = IR_SPARSE_SET_DENSE(set, set->len - 1); |
543 | 0 | if (last != n) { |
544 | 0 | uint32_t idx = IR_SPARSE_SET_SPARSE(set, n); |
545 | 0 |
|
546 | 0 | IR_SPARSE_SET_DENSE(set, idx) = last; |
547 | 0 | IR_SPARSE_SET_SPARSE(set, last) = idx; |
548 | 0 |
|
549 | 0 | } |
550 | 0 | set->len--; |
551 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_del Unexecuted instantiation: ir_check.c:ir_sparse_set_del Unexecuted instantiation: ir_dump.c:ir_sparse_set_del Unexecuted instantiation: ir_emit.c:ir_sparse_set_del Unexecuted instantiation: ir_gcm.c:ir_sparse_set_del Unexecuted instantiation: ir_gdb.c:ir_sparse_set_del Unexecuted instantiation: ir_patch.c:ir_sparse_set_del Unexecuted instantiation: ir_ra.c:ir_sparse_set_del Unexecuted instantiation: ir_save.c:ir_sparse_set_del Unexecuted instantiation: ir_sccp.c:ir_sparse_set_del Unexecuted instantiation: ir_strtab.c:ir_sparse_set_del Unexecuted instantiation: ir.c:ir_sparse_set_del |
552 | | |
553 | | IR_ALWAYS_INLINE uint32_t ir_sparse_set_pop(ir_sparse_set *set) |
554 | 0 | { |
555 | 0 | if (set->len > 0) { |
556 | 0 | set->len--; |
557 | 0 | return IR_SPARSE_SET_DENSE(set, set->len); |
558 | 0 | } |
559 | 0 | return -1; /* empty set */ |
560 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_sparse_set_pop Unexecuted instantiation: ir_check.c:ir_sparse_set_pop Unexecuted instantiation: ir_dump.c:ir_sparse_set_pop Unexecuted instantiation: ir_emit.c:ir_sparse_set_pop Unexecuted instantiation: ir_gcm.c:ir_sparse_set_pop Unexecuted instantiation: ir_gdb.c:ir_sparse_set_pop Unexecuted instantiation: ir_patch.c:ir_sparse_set_pop Unexecuted instantiation: ir_ra.c:ir_sparse_set_pop Unexecuted instantiation: ir_save.c:ir_sparse_set_pop Unexecuted instantiation: ir_sccp.c:ir_sparse_set_pop Unexecuted instantiation: ir_strtab.c:ir_sparse_set_pop Unexecuted instantiation: ir.c:ir_sparse_set_pop |
561 | | |
562 | 0 | #define IR_SPARSE_SET_FOREACH(set, bit) do { \ |
563 | 0 | ir_sparse_set *_set = (set); \ |
564 | 0 | uint32_t _i, _len = _set->len; \ |
565 | 0 | uint32_t *_p = _set->data; \ |
566 | 0 | for (_i = 0; _i < _len; _p++, _i++) { \ |
567 | 0 | (bit) = *_p; \ |
568 | | |
569 | | #define IR_SPARSE_SET_FOREACH_END() \ |
570 | 0 | } \ |
571 | 0 | } while (0) |
572 | | |
573 | | /* Bit Queue */ |
574 | | typedef struct _ir_bitqueue { |
575 | | uint32_t len; |
576 | | uint32_t pos; |
577 | | ir_bitset set; |
578 | | } ir_bitqueue; |
579 | | |
580 | | IR_ALWAYS_INLINE void ir_bitqueue_init(ir_bitqueue *q, uint32_t n) |
581 | 0 | { |
582 | 0 | q->len = ir_bitset_len(n); |
583 | 0 | q->pos = q->len - 1; |
584 | 0 | q->set = ir_bitset_malloc(n); |
585 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_init Unexecuted instantiation: ir_check.c:ir_bitqueue_init Unexecuted instantiation: ir_dump.c:ir_bitqueue_init Unexecuted instantiation: ir_emit.c:ir_bitqueue_init Unexecuted instantiation: ir_gcm.c:ir_bitqueue_init Unexecuted instantiation: ir_gdb.c:ir_bitqueue_init Unexecuted instantiation: ir_patch.c:ir_bitqueue_init Unexecuted instantiation: ir_ra.c:ir_bitqueue_init Unexecuted instantiation: ir_save.c:ir_bitqueue_init Unexecuted instantiation: ir_sccp.c:ir_bitqueue_init Unexecuted instantiation: ir_strtab.c:ir_bitqueue_init Unexecuted instantiation: ir.c:ir_bitqueue_init |
586 | | |
587 | | IR_ALWAYS_INLINE void ir_bitqueue_grow(ir_bitqueue *q, uint32_t n) |
588 | 0 | { |
589 | 0 | uint32_t len = ir_bitset_len(n); |
590 | 0 | IR_ASSERT(len >= q->len); |
591 | 0 | if (len > q->len) { |
592 | 0 | q->set = ir_mem_realloc(q->set, len * (IR_BITSET_BITS / 8)); |
593 | 0 | memset(q->set + q->len, 0, (len - q->len) * (IR_BITSET_BITS / 8)); |
594 | 0 | q->len = len; |
595 | 0 | } |
596 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_grow Unexecuted instantiation: ir_check.c:ir_bitqueue_grow Unexecuted instantiation: ir_dump.c:ir_bitqueue_grow Unexecuted instantiation: ir_emit.c:ir_bitqueue_grow Unexecuted instantiation: ir_gcm.c:ir_bitqueue_grow Unexecuted instantiation: ir_gdb.c:ir_bitqueue_grow Unexecuted instantiation: ir_patch.c:ir_bitqueue_grow Unexecuted instantiation: ir_ra.c:ir_bitqueue_grow Unexecuted instantiation: ir_save.c:ir_bitqueue_grow Unexecuted instantiation: ir_sccp.c:ir_bitqueue_grow Unexecuted instantiation: ir_strtab.c:ir_bitqueue_grow Unexecuted instantiation: ir.c:ir_bitqueue_grow |
597 | | |
598 | | IR_ALWAYS_INLINE void ir_bitqueue_free(ir_bitqueue *q) |
599 | 0 | { |
600 | 0 | ir_mem_free(q->set); |
601 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_free Unexecuted instantiation: ir_check.c:ir_bitqueue_free Unexecuted instantiation: ir_dump.c:ir_bitqueue_free Unexecuted instantiation: ir_emit.c:ir_bitqueue_free Unexecuted instantiation: ir_gcm.c:ir_bitqueue_free Unexecuted instantiation: ir_gdb.c:ir_bitqueue_free Unexecuted instantiation: ir_patch.c:ir_bitqueue_free Unexecuted instantiation: ir_ra.c:ir_bitqueue_free Unexecuted instantiation: ir_save.c:ir_bitqueue_free Unexecuted instantiation: ir_sccp.c:ir_bitqueue_free Unexecuted instantiation: ir_strtab.c:ir_bitqueue_free Unexecuted instantiation: ir.c:ir_bitqueue_free |
602 | | |
603 | | IR_ALWAYS_INLINE void ir_bitqueue_clear(ir_bitqueue *q) |
604 | 0 | { |
605 | 0 | q->pos = q->len - 1; |
606 | 0 | ir_bitset_clear(q->set, q->len); |
607 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_clear Unexecuted instantiation: ir_check.c:ir_bitqueue_clear Unexecuted instantiation: ir_dump.c:ir_bitqueue_clear Unexecuted instantiation: ir_emit.c:ir_bitqueue_clear Unexecuted instantiation: ir_gcm.c:ir_bitqueue_clear Unexecuted instantiation: ir_gdb.c:ir_bitqueue_clear Unexecuted instantiation: ir_patch.c:ir_bitqueue_clear Unexecuted instantiation: ir_ra.c:ir_bitqueue_clear Unexecuted instantiation: ir_save.c:ir_bitqueue_clear Unexecuted instantiation: ir_sccp.c:ir_bitqueue_clear Unexecuted instantiation: ir_strtab.c:ir_bitqueue_clear Unexecuted instantiation: ir.c:ir_bitqueue_clear |
608 | | |
609 | | IR_ALWAYS_INLINE int ir_bitqueue_pop(ir_bitqueue *q) |
610 | 0 | { |
611 | 0 | uint32_t i = q->pos; |
612 | 0 | ir_bitset_base_t x, *p = q->set + i; |
613 | 0 | do { |
614 | 0 | x = *p; |
615 | 0 | if (x) { |
616 | 0 | int bit = IR_BITSET_BITS * i + ir_bitset_ntz(x); |
617 | 0 | *p = x & (x - 1); |
618 | 0 | q->pos = i; |
619 | 0 | return bit; |
620 | 0 | } |
621 | 0 | p++; |
622 | 0 | i++; |
623 | 0 | } while (i < q->len); |
624 | 0 | q->pos = q->len - 1; |
625 | 0 | return -1; /* empty set */ |
626 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_pop Unexecuted instantiation: ir_check.c:ir_bitqueue_pop Unexecuted instantiation: ir_dump.c:ir_bitqueue_pop Unexecuted instantiation: ir_emit.c:ir_bitqueue_pop Unexecuted instantiation: ir_gcm.c:ir_bitqueue_pop Unexecuted instantiation: ir_gdb.c:ir_bitqueue_pop Unexecuted instantiation: ir_patch.c:ir_bitqueue_pop Unexecuted instantiation: ir_ra.c:ir_bitqueue_pop Unexecuted instantiation: ir_save.c:ir_bitqueue_pop Unexecuted instantiation: ir_sccp.c:ir_bitqueue_pop Unexecuted instantiation: ir_strtab.c:ir_bitqueue_pop Unexecuted instantiation: ir.c:ir_bitqueue_pop |
627 | | |
628 | | IR_ALWAYS_INLINE void ir_bitqueue_add(ir_bitqueue *q, uint32_t n) |
629 | 0 | { |
630 | 0 | uint32_t i = n / IR_BITSET_BITS; |
631 | 0 | q->set[i] |= IR_BITSET_ONE << (n % IR_BITSET_BITS); |
632 | 0 | if (i < q->pos) { |
633 | 0 | q->pos = i; |
634 | 0 | } |
635 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_add Unexecuted instantiation: ir_check.c:ir_bitqueue_add Unexecuted instantiation: ir_dump.c:ir_bitqueue_add Unexecuted instantiation: ir_emit.c:ir_bitqueue_add Unexecuted instantiation: ir_gcm.c:ir_bitqueue_add Unexecuted instantiation: ir_gdb.c:ir_bitqueue_add Unexecuted instantiation: ir_patch.c:ir_bitqueue_add Unexecuted instantiation: ir_ra.c:ir_bitqueue_add Unexecuted instantiation: ir_save.c:ir_bitqueue_add Unexecuted instantiation: ir_sccp.c:ir_bitqueue_add Unexecuted instantiation: ir_strtab.c:ir_bitqueue_add Unexecuted instantiation: ir.c:ir_bitqueue_add |
636 | | |
637 | | IR_ALWAYS_INLINE void ir_bitqueue_del(ir_bitqueue *q, uint32_t n) |
638 | 0 | { |
639 | 0 | ir_bitset_excl(q->set, n); |
640 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_del Unexecuted instantiation: ir_check.c:ir_bitqueue_del Unexecuted instantiation: ir_dump.c:ir_bitqueue_del Unexecuted instantiation: ir_emit.c:ir_bitqueue_del Unexecuted instantiation: ir_gcm.c:ir_bitqueue_del Unexecuted instantiation: ir_gdb.c:ir_bitqueue_del Unexecuted instantiation: ir_patch.c:ir_bitqueue_del Unexecuted instantiation: ir_ra.c:ir_bitqueue_del Unexecuted instantiation: ir_save.c:ir_bitqueue_del Unexecuted instantiation: ir_sccp.c:ir_bitqueue_del Unexecuted instantiation: ir_strtab.c:ir_bitqueue_del Unexecuted instantiation: ir.c:ir_bitqueue_del |
641 | | |
642 | | IR_ALWAYS_INLINE bool ir_bitqueue_in(const ir_bitqueue *q, uint32_t n) |
643 | 0 | { |
644 | 0 | return ir_bitset_in(q->set, n); |
645 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_bitqueue_in Unexecuted instantiation: ir_check.c:ir_bitqueue_in Unexecuted instantiation: ir_dump.c:ir_bitqueue_in Unexecuted instantiation: ir_emit.c:ir_bitqueue_in Unexecuted instantiation: ir_gcm.c:ir_bitqueue_in Unexecuted instantiation: ir_gdb.c:ir_bitqueue_in Unexecuted instantiation: ir_patch.c:ir_bitqueue_in Unexecuted instantiation: ir_ra.c:ir_bitqueue_in Unexecuted instantiation: ir_save.c:ir_bitqueue_in Unexecuted instantiation: ir_sccp.c:ir_bitqueue_in Unexecuted instantiation: ir_strtab.c:ir_bitqueue_in Unexecuted instantiation: ir.c:ir_bitqueue_in |
646 | | |
647 | | /* Dynamic array of numeric references */ |
648 | | typedef struct _ir_array { |
649 | | ir_ref *refs; |
650 | | uint32_t size; |
651 | | } ir_array; |
652 | | |
653 | | void ir_array_grow(ir_array *a, uint32_t size); |
654 | | void ir_array_insert(ir_array *a, uint32_t i, ir_ref val); |
655 | | void ir_array_remove(ir_array *a, uint32_t i); |
656 | | |
657 | | IR_ALWAYS_INLINE void ir_array_init(ir_array *a, uint32_t size) |
658 | 0 | { |
659 | 0 | a->refs = ir_mem_malloc(size * sizeof(ir_ref)); |
660 | 0 | a->size = size; |
661 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_init Unexecuted instantiation: ir_check.c:ir_array_init Unexecuted instantiation: ir_dump.c:ir_array_init Unexecuted instantiation: ir_emit.c:ir_array_init Unexecuted instantiation: ir_gcm.c:ir_array_init Unexecuted instantiation: ir_gdb.c:ir_array_init Unexecuted instantiation: ir_patch.c:ir_array_init Unexecuted instantiation: ir_ra.c:ir_array_init Unexecuted instantiation: ir_save.c:ir_array_init Unexecuted instantiation: ir_sccp.c:ir_array_init Unexecuted instantiation: ir_strtab.c:ir_array_init Unexecuted instantiation: ir.c:ir_array_init |
662 | | |
663 | | IR_ALWAYS_INLINE void ir_array_free(ir_array *a) |
664 | 0 | { |
665 | 0 | ir_mem_free(a->refs); |
666 | 0 | a->refs = NULL; |
667 | 0 | a->size = 0; |
668 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_free Unexecuted instantiation: ir_check.c:ir_array_free Unexecuted instantiation: ir_dump.c:ir_array_free Unexecuted instantiation: ir_emit.c:ir_array_free Unexecuted instantiation: ir_gcm.c:ir_array_free Unexecuted instantiation: ir_gdb.c:ir_array_free Unexecuted instantiation: ir_patch.c:ir_array_free Unexecuted instantiation: ir_ra.c:ir_array_free Unexecuted instantiation: ir_save.c:ir_array_free Unexecuted instantiation: ir_sccp.c:ir_array_free Unexecuted instantiation: ir_strtab.c:ir_array_free Unexecuted instantiation: ir.c:ir_array_free |
669 | | |
670 | | IR_ALWAYS_INLINE uint32_t ir_array_size(const ir_array *a) |
671 | 0 | { |
672 | 0 | return a->size; |
673 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_size Unexecuted instantiation: ir_check.c:ir_array_size Unexecuted instantiation: ir_dump.c:ir_array_size Unexecuted instantiation: ir_emit.c:ir_array_size Unexecuted instantiation: ir_gcm.c:ir_array_size Unexecuted instantiation: ir_gdb.c:ir_array_size Unexecuted instantiation: ir_patch.c:ir_array_size Unexecuted instantiation: ir_ra.c:ir_array_size Unexecuted instantiation: ir_save.c:ir_array_size Unexecuted instantiation: ir_sccp.c:ir_array_size Unexecuted instantiation: ir_strtab.c:ir_array_size Unexecuted instantiation: ir.c:ir_array_size |
674 | | |
675 | | IR_ALWAYS_INLINE ir_ref ir_array_get(const ir_array *a, uint32_t i) |
676 | 0 | { |
677 | 0 | return (i < a->size) ? a->refs[i] : IR_UNUSED; |
678 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_get Unexecuted instantiation: ir_check.c:ir_array_get Unexecuted instantiation: ir_dump.c:ir_array_get Unexecuted instantiation: ir_emit.c:ir_array_get Unexecuted instantiation: ir_gcm.c:ir_array_get Unexecuted instantiation: ir_gdb.c:ir_array_get Unexecuted instantiation: ir_patch.c:ir_array_get Unexecuted instantiation: ir_ra.c:ir_array_get Unexecuted instantiation: ir_save.c:ir_array_get Unexecuted instantiation: ir_sccp.c:ir_array_get Unexecuted instantiation: ir_strtab.c:ir_array_get Unexecuted instantiation: ir.c:ir_array_get |
679 | | |
680 | | IR_ALWAYS_INLINE ir_ref ir_array_at(const ir_array *a, uint32_t i) |
681 | 0 | { |
682 | 0 | IR_ASSERT(i < a->size); |
683 | 0 | return a->refs[i]; |
684 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_at Unexecuted instantiation: ir_check.c:ir_array_at Unexecuted instantiation: ir_dump.c:ir_array_at Unexecuted instantiation: ir_emit.c:ir_array_at Unexecuted instantiation: ir_gcm.c:ir_array_at Unexecuted instantiation: ir_gdb.c:ir_array_at Unexecuted instantiation: ir_patch.c:ir_array_at Unexecuted instantiation: ir_ra.c:ir_array_at Unexecuted instantiation: ir_save.c:ir_array_at Unexecuted instantiation: ir_sccp.c:ir_array_at Unexecuted instantiation: ir_strtab.c:ir_array_at Unexecuted instantiation: ir.c:ir_array_at |
685 | | |
686 | | IR_ALWAYS_INLINE void ir_array_set(ir_array *a, uint32_t i, ir_ref val) |
687 | 0 | { |
688 | 0 | if (i >= a->size) { |
689 | 0 | ir_array_grow(a, i + 1); |
690 | 0 | } |
691 | 0 | a->refs[i] = val; |
692 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_set Unexecuted instantiation: ir_check.c:ir_array_set Unexecuted instantiation: ir_dump.c:ir_array_set Unexecuted instantiation: ir_emit.c:ir_array_set Unexecuted instantiation: ir_gcm.c:ir_array_set Unexecuted instantiation: ir_gdb.c:ir_array_set Unexecuted instantiation: ir_patch.c:ir_array_set Unexecuted instantiation: ir_ra.c:ir_array_set Unexecuted instantiation: ir_save.c:ir_array_set Unexecuted instantiation: ir_sccp.c:ir_array_set Unexecuted instantiation: ir_strtab.c:ir_array_set Unexecuted instantiation: ir.c:ir_array_set |
693 | | |
694 | | IR_ALWAYS_INLINE void ir_array_set_unchecked(ir_array *a, uint32_t i, ir_ref val) |
695 | 0 | { |
696 | 0 | IR_ASSERT(i < a->size); |
697 | 0 | a->refs[i] = val; |
698 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_array_set_unchecked Unexecuted instantiation: ir_check.c:ir_array_set_unchecked Unexecuted instantiation: ir_dump.c:ir_array_set_unchecked Unexecuted instantiation: ir_emit.c:ir_array_set_unchecked Unexecuted instantiation: ir_gcm.c:ir_array_set_unchecked Unexecuted instantiation: ir_gdb.c:ir_array_set_unchecked Unexecuted instantiation: ir_patch.c:ir_array_set_unchecked Unexecuted instantiation: ir_ra.c:ir_array_set_unchecked Unexecuted instantiation: ir_save.c:ir_array_set_unchecked Unexecuted instantiation: ir_sccp.c:ir_array_set_unchecked Unexecuted instantiation: ir_strtab.c:ir_array_set_unchecked Unexecuted instantiation: ir.c:ir_array_set_unchecked |
699 | | |
700 | | /* List/Stack of numeric references */ |
701 | | typedef struct _ir_list { |
702 | | ir_array a; |
703 | | uint32_t len; |
704 | | } ir_list; |
705 | | |
706 | | uint32_t ir_list_find(const ir_list *l, ir_ref val); |
707 | | void ir_list_insert(ir_list *l, uint32_t i, ir_ref val); |
708 | | void ir_list_remove(ir_list *l, uint32_t i); |
709 | | |
710 | | IR_ALWAYS_INLINE void ir_list_init(ir_list *l, uint32_t size) |
711 | 0 | { |
712 | 0 | ir_array_init(&l->a, size); |
713 | 0 | l->len = 0; |
714 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_init Unexecuted instantiation: ir_check.c:ir_list_init Unexecuted instantiation: ir_dump.c:ir_list_init Unexecuted instantiation: ir_emit.c:ir_list_init Unexecuted instantiation: ir_gcm.c:ir_list_init Unexecuted instantiation: ir_gdb.c:ir_list_init Unexecuted instantiation: ir_patch.c:ir_list_init Unexecuted instantiation: ir_ra.c:ir_list_init Unexecuted instantiation: ir_save.c:ir_list_init Unexecuted instantiation: ir_sccp.c:ir_list_init Unexecuted instantiation: ir_strtab.c:ir_list_init Unexecuted instantiation: ir.c:ir_list_init |
715 | | |
716 | | IR_ALWAYS_INLINE void ir_list_free(ir_list *l) |
717 | 0 | { |
718 | 0 | ir_array_free(&l->a); |
719 | 0 | l->len = 0; |
720 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_free Unexecuted instantiation: ir_check.c:ir_list_free Unexecuted instantiation: ir_dump.c:ir_list_free Unexecuted instantiation: ir_emit.c:ir_list_free Unexecuted instantiation: ir_gcm.c:ir_list_free Unexecuted instantiation: ir_gdb.c:ir_list_free Unexecuted instantiation: ir_patch.c:ir_list_free Unexecuted instantiation: ir_ra.c:ir_list_free Unexecuted instantiation: ir_save.c:ir_list_free Unexecuted instantiation: ir_sccp.c:ir_list_free Unexecuted instantiation: ir_strtab.c:ir_list_free Unexecuted instantiation: ir.c:ir_list_free |
721 | | |
722 | | IR_ALWAYS_INLINE void ir_list_clear(ir_list *l) |
723 | 0 | { |
724 | 0 | l->len = 0; |
725 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_clear Unexecuted instantiation: ir_check.c:ir_list_clear Unexecuted instantiation: ir_dump.c:ir_list_clear Unexecuted instantiation: ir_emit.c:ir_list_clear Unexecuted instantiation: ir_gcm.c:ir_list_clear Unexecuted instantiation: ir_gdb.c:ir_list_clear Unexecuted instantiation: ir_patch.c:ir_list_clear Unexecuted instantiation: ir_ra.c:ir_list_clear Unexecuted instantiation: ir_save.c:ir_list_clear Unexecuted instantiation: ir_sccp.c:ir_list_clear Unexecuted instantiation: ir_strtab.c:ir_list_clear Unexecuted instantiation: ir.c:ir_list_clear |
726 | | |
727 | | IR_ALWAYS_INLINE uint32_t ir_list_len(const ir_list *l) |
728 | 0 | { |
729 | 0 | return l->len; |
730 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_len Unexecuted instantiation: ir_check.c:ir_list_len Unexecuted instantiation: ir_dump.c:ir_list_len Unexecuted instantiation: ir_emit.c:ir_list_len Unexecuted instantiation: ir_gcm.c:ir_list_len Unexecuted instantiation: ir_gdb.c:ir_list_len Unexecuted instantiation: ir_patch.c:ir_list_len Unexecuted instantiation: ir_ra.c:ir_list_len Unexecuted instantiation: ir_save.c:ir_list_len Unexecuted instantiation: ir_sccp.c:ir_list_len Unexecuted instantiation: ir_strtab.c:ir_list_len Unexecuted instantiation: ir.c:ir_list_len |
731 | | |
732 | | IR_ALWAYS_INLINE uint32_t ir_list_capasity(const ir_list *l) |
733 | 0 | { |
734 | 0 | return ir_array_size(&l->a); |
735 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_capasity Unexecuted instantiation: ir_check.c:ir_list_capasity Unexecuted instantiation: ir_dump.c:ir_list_capasity Unexecuted instantiation: ir_emit.c:ir_list_capasity Unexecuted instantiation: ir_gcm.c:ir_list_capasity Unexecuted instantiation: ir_gdb.c:ir_list_capasity Unexecuted instantiation: ir_patch.c:ir_list_capasity Unexecuted instantiation: ir_ra.c:ir_list_capasity Unexecuted instantiation: ir_save.c:ir_list_capasity Unexecuted instantiation: ir_sccp.c:ir_list_capasity Unexecuted instantiation: ir_strtab.c:ir_list_capasity Unexecuted instantiation: ir.c:ir_list_capasity |
736 | | |
737 | | IR_ALWAYS_INLINE void ir_list_push(ir_list *l, ir_ref val) |
738 | 0 | { |
739 | 0 | ir_array_set(&l->a, l->len++, val); |
740 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_push Unexecuted instantiation: ir_check.c:ir_list_push Unexecuted instantiation: ir_dump.c:ir_list_push Unexecuted instantiation: ir_emit.c:ir_list_push Unexecuted instantiation: ir_gcm.c:ir_list_push Unexecuted instantiation: ir_gdb.c:ir_list_push Unexecuted instantiation: ir_patch.c:ir_list_push Unexecuted instantiation: ir_ra.c:ir_list_push Unexecuted instantiation: ir_save.c:ir_list_push Unexecuted instantiation: ir_sccp.c:ir_list_push Unexecuted instantiation: ir_strtab.c:ir_list_push Unexecuted instantiation: ir.c:ir_list_push |
741 | | |
742 | | IR_ALWAYS_INLINE void ir_list_push_unchecked(ir_list *l, ir_ref val) |
743 | 0 | { |
744 | 0 | ir_array_set_unchecked(&l->a, l->len++, val); |
745 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_push_unchecked Unexecuted instantiation: ir_check.c:ir_list_push_unchecked Unexecuted instantiation: ir_dump.c:ir_list_push_unchecked Unexecuted instantiation: ir_emit.c:ir_list_push_unchecked Unexecuted instantiation: ir_gcm.c:ir_list_push_unchecked Unexecuted instantiation: ir_gdb.c:ir_list_push_unchecked Unexecuted instantiation: ir_patch.c:ir_list_push_unchecked Unexecuted instantiation: ir_ra.c:ir_list_push_unchecked Unexecuted instantiation: ir_save.c:ir_list_push_unchecked Unexecuted instantiation: ir_sccp.c:ir_list_push_unchecked Unexecuted instantiation: ir_strtab.c:ir_list_push_unchecked Unexecuted instantiation: ir.c:ir_list_push_unchecked |
746 | | |
747 | | IR_ALWAYS_INLINE ir_ref ir_list_pop(ir_list *l) |
748 | 0 | { |
749 | 0 | IR_ASSERT(l->len > 0); |
750 | 0 | return ir_array_at(&l->a, --l->len); |
751 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_pop Unexecuted instantiation: ir_check.c:ir_list_pop Unexecuted instantiation: ir_dump.c:ir_list_pop Unexecuted instantiation: ir_emit.c:ir_list_pop Unexecuted instantiation: ir_gcm.c:ir_list_pop Unexecuted instantiation: ir_gdb.c:ir_list_pop Unexecuted instantiation: ir_patch.c:ir_list_pop Unexecuted instantiation: ir_ra.c:ir_list_pop Unexecuted instantiation: ir_save.c:ir_list_pop Unexecuted instantiation: ir_sccp.c:ir_list_pop Unexecuted instantiation: ir_strtab.c:ir_list_pop Unexecuted instantiation: ir.c:ir_list_pop |
752 | | |
753 | | IR_ALWAYS_INLINE ir_ref ir_list_peek(const ir_list *l) |
754 | 0 | { |
755 | 0 | IR_ASSERT(l->len > 0); |
756 | 0 | return ir_array_at(&l->a, l->len - 1); |
757 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_peek Unexecuted instantiation: ir_check.c:ir_list_peek Unexecuted instantiation: ir_dump.c:ir_list_peek Unexecuted instantiation: ir_emit.c:ir_list_peek Unexecuted instantiation: ir_gcm.c:ir_list_peek Unexecuted instantiation: ir_gdb.c:ir_list_peek Unexecuted instantiation: ir_patch.c:ir_list_peek Unexecuted instantiation: ir_ra.c:ir_list_peek Unexecuted instantiation: ir_save.c:ir_list_peek Unexecuted instantiation: ir_sccp.c:ir_list_peek Unexecuted instantiation: ir_strtab.c:ir_list_peek Unexecuted instantiation: ir.c:ir_list_peek |
758 | | |
759 | | IR_ALWAYS_INLINE ir_ref ir_list_at(const ir_list *l, uint32_t i) |
760 | 0 | { |
761 | 0 | IR_ASSERT(i < l->len); |
762 | 0 | return ir_array_at(&l->a, i); |
763 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_at Unexecuted instantiation: ir_check.c:ir_list_at Unexecuted instantiation: ir_dump.c:ir_list_at Unexecuted instantiation: ir_emit.c:ir_list_at Unexecuted instantiation: ir_gcm.c:ir_list_at Unexecuted instantiation: ir_gdb.c:ir_list_at Unexecuted instantiation: ir_patch.c:ir_list_at Unexecuted instantiation: ir_ra.c:ir_list_at Unexecuted instantiation: ir_save.c:ir_list_at Unexecuted instantiation: ir_sccp.c:ir_list_at Unexecuted instantiation: ir_strtab.c:ir_list_at Unexecuted instantiation: ir.c:ir_list_at |
764 | | |
765 | | IR_ALWAYS_INLINE void ir_list_set(ir_list *l, uint32_t i, ir_ref val) |
766 | 0 | { |
767 | 0 | IR_ASSERT(i < l->len); |
768 | 0 | ir_array_set_unchecked(&l->a, i, val); |
769 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_set Unexecuted instantiation: ir_check.c:ir_list_set Unexecuted instantiation: ir_dump.c:ir_list_set Unexecuted instantiation: ir_emit.c:ir_list_set Unexecuted instantiation: ir_gcm.c:ir_list_set Unexecuted instantiation: ir_gdb.c:ir_list_set Unexecuted instantiation: ir_patch.c:ir_list_set Unexecuted instantiation: ir_ra.c:ir_list_set Unexecuted instantiation: ir_save.c:ir_list_set Unexecuted instantiation: ir_sccp.c:ir_list_set Unexecuted instantiation: ir_strtab.c:ir_list_set Unexecuted instantiation: ir.c:ir_list_set |
770 | | |
771 | | /* Doesn't preserve order */ |
772 | | IR_ALWAYS_INLINE void ir_list_del(ir_list *l, uint32_t i) |
773 | 0 | { |
774 | 0 | IR_ASSERT(i < l->len); |
775 | 0 | l->len--; |
776 | 0 | ir_array_set_unchecked(&l->a, i, ir_array_at(&l->a, l->len)); |
777 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_del Unexecuted instantiation: ir_check.c:ir_list_del Unexecuted instantiation: ir_dump.c:ir_list_del Unexecuted instantiation: ir_emit.c:ir_list_del Unexecuted instantiation: ir_gcm.c:ir_list_del Unexecuted instantiation: ir_gdb.c:ir_list_del Unexecuted instantiation: ir_patch.c:ir_list_del Unexecuted instantiation: ir_ra.c:ir_list_del Unexecuted instantiation: ir_save.c:ir_list_del Unexecuted instantiation: ir_sccp.c:ir_list_del Unexecuted instantiation: ir_strtab.c:ir_list_del Unexecuted instantiation: ir.c:ir_list_del |
778 | | |
779 | | IR_ALWAYS_INLINE bool ir_list_contains(const ir_list *l, ir_ref val) |
780 | 0 | { |
781 | 0 | return ir_list_find(l, val) != (uint32_t)-1; |
782 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_list_contains Unexecuted instantiation: ir_check.c:ir_list_contains Unexecuted instantiation: ir_dump.c:ir_list_contains Unexecuted instantiation: ir_emit.c:ir_list_contains Unexecuted instantiation: ir_gcm.c:ir_list_contains Unexecuted instantiation: ir_gdb.c:ir_list_contains Unexecuted instantiation: ir_patch.c:ir_list_contains Unexecuted instantiation: ir_ra.c:ir_list_contains Unexecuted instantiation: ir_save.c:ir_list_contains Unexecuted instantiation: ir_sccp.c:ir_list_contains Unexecuted instantiation: ir_strtab.c:ir_list_contains Unexecuted instantiation: ir.c:ir_list_contains |
783 | | |
784 | | /* Worklist (unique list) */ |
785 | | typedef struct _ir_worklist { |
786 | | ir_list l; |
787 | | ir_bitset visited; |
788 | | } ir_worklist; |
789 | | |
790 | | IR_ALWAYS_INLINE void ir_worklist_init(ir_worklist *w, uint32_t size) |
791 | 0 | { |
792 | 0 | ir_list_init(&w->l, size); |
793 | 0 | w->visited = ir_bitset_malloc(size); |
794 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_init Unexecuted instantiation: ir_check.c:ir_worklist_init Unexecuted instantiation: ir_dump.c:ir_worklist_init Unexecuted instantiation: ir_emit.c:ir_worklist_init Unexecuted instantiation: ir_gcm.c:ir_worklist_init Unexecuted instantiation: ir_gdb.c:ir_worklist_init Unexecuted instantiation: ir_patch.c:ir_worklist_init Unexecuted instantiation: ir_ra.c:ir_worklist_init Unexecuted instantiation: ir_save.c:ir_worklist_init Unexecuted instantiation: ir_sccp.c:ir_worklist_init Unexecuted instantiation: ir_strtab.c:ir_worklist_init Unexecuted instantiation: ir.c:ir_worklist_init |
795 | | |
796 | | IR_ALWAYS_INLINE void ir_worklist_free(ir_worklist *w) |
797 | 0 | { |
798 | 0 | ir_list_free(&w->l); |
799 | 0 | ir_mem_free(w->visited); |
800 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_free Unexecuted instantiation: ir_check.c:ir_worklist_free Unexecuted instantiation: ir_dump.c:ir_worklist_free Unexecuted instantiation: ir_emit.c:ir_worklist_free Unexecuted instantiation: ir_gcm.c:ir_worklist_free Unexecuted instantiation: ir_gdb.c:ir_worklist_free Unexecuted instantiation: ir_patch.c:ir_worklist_free Unexecuted instantiation: ir_ra.c:ir_worklist_free Unexecuted instantiation: ir_save.c:ir_worklist_free Unexecuted instantiation: ir_sccp.c:ir_worklist_free Unexecuted instantiation: ir_strtab.c:ir_worklist_free Unexecuted instantiation: ir.c:ir_worklist_free |
801 | | |
802 | | IR_ALWAYS_INLINE uint32_t ir_worklist_len(const ir_worklist *w) |
803 | 0 | { |
804 | 0 | return ir_list_len(&w->l); |
805 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_len Unexecuted instantiation: ir_check.c:ir_worklist_len Unexecuted instantiation: ir_dump.c:ir_worklist_len Unexecuted instantiation: ir_emit.c:ir_worklist_len Unexecuted instantiation: ir_gcm.c:ir_worklist_len Unexecuted instantiation: ir_gdb.c:ir_worklist_len Unexecuted instantiation: ir_patch.c:ir_worklist_len Unexecuted instantiation: ir_ra.c:ir_worklist_len Unexecuted instantiation: ir_save.c:ir_worklist_len Unexecuted instantiation: ir_sccp.c:ir_worklist_len Unexecuted instantiation: ir_strtab.c:ir_worklist_len Unexecuted instantiation: ir.c:ir_worklist_len |
806 | | |
807 | | IR_ALWAYS_INLINE uint32_t ir_worklist_capasity(const ir_worklist *w) |
808 | 0 | { |
809 | 0 | return ir_list_capasity(&w->l); |
810 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_capasity Unexecuted instantiation: ir_check.c:ir_worklist_capasity Unexecuted instantiation: ir_dump.c:ir_worklist_capasity Unexecuted instantiation: ir_emit.c:ir_worklist_capasity Unexecuted instantiation: ir_gcm.c:ir_worklist_capasity Unexecuted instantiation: ir_gdb.c:ir_worklist_capasity Unexecuted instantiation: ir_patch.c:ir_worklist_capasity Unexecuted instantiation: ir_ra.c:ir_worklist_capasity Unexecuted instantiation: ir_save.c:ir_worklist_capasity Unexecuted instantiation: ir_sccp.c:ir_worklist_capasity Unexecuted instantiation: ir_strtab.c:ir_worklist_capasity Unexecuted instantiation: ir.c:ir_worklist_capasity |
811 | | |
812 | | IR_ALWAYS_INLINE void ir_worklist_clear(ir_worklist *w) |
813 | 0 | { |
814 | 0 | ir_list_clear(&w->l); |
815 | 0 | ir_bitset_clear(w->visited, ir_bitset_len(ir_worklist_capasity(w))); |
816 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_clear Unexecuted instantiation: ir_check.c:ir_worklist_clear Unexecuted instantiation: ir_dump.c:ir_worklist_clear Unexecuted instantiation: ir_emit.c:ir_worklist_clear Unexecuted instantiation: ir_gcm.c:ir_worklist_clear Unexecuted instantiation: ir_gdb.c:ir_worklist_clear Unexecuted instantiation: ir_patch.c:ir_worklist_clear Unexecuted instantiation: ir_ra.c:ir_worklist_clear Unexecuted instantiation: ir_save.c:ir_worklist_clear Unexecuted instantiation: ir_sccp.c:ir_worklist_clear Unexecuted instantiation: ir_strtab.c:ir_worklist_clear Unexecuted instantiation: ir.c:ir_worklist_clear |
817 | | |
818 | | IR_ALWAYS_INLINE bool ir_worklist_push(ir_worklist *w, ir_ref val) |
819 | 0 | { |
820 | 0 | IR_ASSERT(val >= 0 && (uint32_t)val < ir_worklist_capasity(w)); |
821 | 0 | if (ir_bitset_in(w->visited, val)) { |
822 | 0 | return 0; |
823 | 0 | } |
824 | 0 | ir_bitset_incl(w->visited, val); |
825 | 0 | IR_ASSERT(ir_list_len(&w->l) < ir_list_capasity(&w->l)); |
826 | 0 | ir_list_push_unchecked(&w->l, val); |
827 | 0 | return 1; |
828 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_push Unexecuted instantiation: ir_check.c:ir_worklist_push Unexecuted instantiation: ir_dump.c:ir_worklist_push Unexecuted instantiation: ir_emit.c:ir_worklist_push Unexecuted instantiation: ir_gcm.c:ir_worklist_push Unexecuted instantiation: ir_gdb.c:ir_worklist_push Unexecuted instantiation: ir_patch.c:ir_worklist_push Unexecuted instantiation: ir_ra.c:ir_worklist_push Unexecuted instantiation: ir_save.c:ir_worklist_push Unexecuted instantiation: ir_sccp.c:ir_worklist_push Unexecuted instantiation: ir_strtab.c:ir_worklist_push Unexecuted instantiation: ir.c:ir_worklist_push |
829 | | |
830 | | IR_ALWAYS_INLINE ir_ref ir_worklist_pop(ir_worklist *w) |
831 | 0 | { |
832 | 0 | return ir_list_pop(&w->l); |
833 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_pop Unexecuted instantiation: ir_check.c:ir_worklist_pop Unexecuted instantiation: ir_dump.c:ir_worklist_pop Unexecuted instantiation: ir_emit.c:ir_worklist_pop Unexecuted instantiation: ir_gcm.c:ir_worklist_pop Unexecuted instantiation: ir_gdb.c:ir_worklist_pop Unexecuted instantiation: ir_patch.c:ir_worklist_pop Unexecuted instantiation: ir_ra.c:ir_worklist_pop Unexecuted instantiation: ir_save.c:ir_worklist_pop Unexecuted instantiation: ir_sccp.c:ir_worklist_pop Unexecuted instantiation: ir_strtab.c:ir_worklist_pop Unexecuted instantiation: ir.c:ir_worklist_pop |
834 | | |
835 | | IR_ALWAYS_INLINE ir_ref ir_worklist_peek(const ir_worklist *w) |
836 | 0 | { |
837 | 0 | return ir_list_peek(&w->l); |
838 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_worklist_peek Unexecuted instantiation: ir_check.c:ir_worklist_peek Unexecuted instantiation: ir_dump.c:ir_worklist_peek Unexecuted instantiation: ir_emit.c:ir_worklist_peek Unexecuted instantiation: ir_gcm.c:ir_worklist_peek Unexecuted instantiation: ir_gdb.c:ir_worklist_peek Unexecuted instantiation: ir_patch.c:ir_worklist_peek Unexecuted instantiation: ir_ra.c:ir_worklist_peek Unexecuted instantiation: ir_save.c:ir_worklist_peek Unexecuted instantiation: ir_sccp.c:ir_worklist_peek Unexecuted instantiation: ir_strtab.c:ir_worklist_peek Unexecuted instantiation: ir.c:ir_worklist_peek |
839 | | |
840 | | /* IR Hash Table */ |
841 | 0 | #define IR_INVALID_IDX 0xffffffff |
842 | 0 | #define IR_INVALID_VAL 0x80000000 |
843 | | |
844 | | typedef struct _ir_hashtab_bucket { |
845 | | uint32_t key; |
846 | | ir_ref val; |
847 | | uint32_t next; |
848 | | } ir_hashtab_bucket; |
849 | | |
850 | | typedef struct _ir_hashtab { |
851 | | void *data; |
852 | | uint32_t mask; |
853 | | uint32_t size; |
854 | | uint32_t count; |
855 | | uint32_t pos; |
856 | | } ir_hashtab; |
857 | | |
858 | | void ir_hashtab_init(ir_hashtab *tab, uint32_t size); |
859 | | void ir_hashtab_free(ir_hashtab *tab); |
860 | | ir_ref ir_hashtab_find(const ir_hashtab *tab, uint32_t key); |
861 | | bool ir_hashtab_add(ir_hashtab *tab, uint32_t key, ir_ref val); |
862 | | void ir_hashtab_key_sort(ir_hashtab *tab); |
863 | | |
864 | | /* IR Addr Table */ |
865 | | typedef struct _ir_addrtab_bucket { |
866 | | uint64_t key; |
867 | | ir_ref val; |
868 | | uint32_t next; |
869 | | } ir_addrtab_bucket; |
870 | | |
871 | | void ir_addrtab_init(ir_hashtab *tab, uint32_t size); |
872 | | void ir_addrtab_free(ir_hashtab *tab); |
873 | | ir_ref ir_addrtab_find(const ir_hashtab *tab, uint64_t key); |
874 | | void ir_addrtab_set(ir_hashtab *tab, uint64_t key, ir_ref val); |
875 | | |
876 | | /*** IR OP info ***/ |
877 | | extern const uint8_t ir_type_flags[IR_LAST_TYPE]; |
878 | | extern const char *ir_type_name[IR_LAST_TYPE]; |
879 | | extern const char *ir_type_cname[IR_LAST_TYPE]; |
880 | | extern const uint8_t ir_type_size[IR_LAST_TYPE]; |
881 | | extern const uint32_t ir_op_flags[IR_LAST_OP]; |
882 | | extern const char *ir_op_name[IR_LAST_OP]; |
883 | | |
884 | | void ir_print_escaped_str(const char *s, size_t len, FILE *f); |
885 | | |
886 | 0 | #define IR_IS_CONST_OP(op) ((op) > IR_NOP && (op) <= IR_C_FLOAT) |
887 | 0 | #define IR_IS_FOLDABLE_OP(op) ((op) <= IR_LAST_FOLDABLE_OP) |
888 | 0 | #define IR_IS_SYM_CONST(op) ((op) == IR_STR || (op) == IR_SYM || (op) == IR_FUNC) |
889 | | |
890 | | ir_ref ir_const_ex(ir_ctx *ctx, ir_val val, uint8_t type, uint32_t optx); |
891 | | |
892 | | IR_ALWAYS_INLINE bool ir_const_is_true(const ir_insn *v) |
893 | 0 | { |
894 | 0 | if (IR_IS_SYM_CONST(v->op)) { |
895 | 0 | return 1; |
896 | 0 | } else if (v->type == IR_BOOL) { |
897 | 0 | return v->val.b; |
898 | 0 | } else if (IR_IS_TYPE_INT(v->type)) { |
899 | 0 | return v->val.i64 != 0; |
900 | 0 | } else if (v->type == IR_DOUBLE) { |
901 | 0 | return v->val.d != 0.0; |
902 | 0 | } else { |
903 | 0 | IR_ASSERT(v->type == IR_FLOAT); |
904 | 0 | return v->val.f != 0.0; |
905 | 0 | } |
906 | 0 | return 0; |
907 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_const_is_true Unexecuted instantiation: ir_check.c:ir_const_is_true Unexecuted instantiation: ir_dump.c:ir_const_is_true Unexecuted instantiation: ir_emit.c:ir_const_is_true Unexecuted instantiation: ir_gcm.c:ir_const_is_true Unexecuted instantiation: ir_gdb.c:ir_const_is_true Unexecuted instantiation: ir_patch.c:ir_const_is_true Unexecuted instantiation: ir_ra.c:ir_const_is_true Unexecuted instantiation: ir_save.c:ir_const_is_true Unexecuted instantiation: ir_sccp.c:ir_const_is_true Unexecuted instantiation: ir_strtab.c:ir_const_is_true Unexecuted instantiation: ir.c:ir_const_is_true |
908 | | |
909 | | IR_ALWAYS_INLINE bool ir_ref_is_true(ir_ctx *ctx, ir_ref ref) |
910 | 0 | { |
911 | 0 | if (ref == IR_TRUE) { |
912 | 0 | return 1; |
913 | 0 | } else if (ref == IR_FALSE) { |
914 | 0 | return 0; |
915 | 0 | } else { |
916 | 0 | IR_ASSERT(IR_IS_CONST_REF(ref)); |
917 | 0 | return ir_const_is_true(&ctx->ir_base[ref]); |
918 | 0 | } |
919 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_ref_is_true Unexecuted instantiation: ir_check.c:ir_ref_is_true Unexecuted instantiation: ir_dump.c:ir_ref_is_true Unexecuted instantiation: ir_emit.c:ir_ref_is_true Unexecuted instantiation: ir_gcm.c:ir_ref_is_true Unexecuted instantiation: ir_gdb.c:ir_ref_is_true Unexecuted instantiation: ir_patch.c:ir_ref_is_true Unexecuted instantiation: ir_ra.c:ir_ref_is_true Unexecuted instantiation: ir_save.c:ir_ref_is_true Unexecuted instantiation: ir_sccp.c:ir_ref_is_true Unexecuted instantiation: ir_strtab.c:ir_ref_is_true Unexecuted instantiation: ir.c:ir_ref_is_true |
920 | | |
921 | | /* IR OP flags */ |
922 | 0 | #define IR_OP_FLAG_OPERANDS_SHIFT 3 |
923 | | |
924 | 0 | #define IR_OP_FLAG_EDGES_MASK 0x03 |
925 | 0 | #define IR_OP_FLAG_VAR_INPUTS 0x04 |
926 | 0 | #define IR_OP_FLAG_OPERANDS_MASK 0x18 |
927 | | #define IR_OP_FLAG_MEM_MASK ((1<<6)|(1<<7)) |
928 | | |
929 | 0 | #define IR_OP_FLAG_DATA (1<<8) |
930 | 0 | #define IR_OP_FLAG_CONTROL (1<<9) |
931 | 0 | #define IR_OP_FLAG_MEM (1<<10) |
932 | 0 | #define IR_OP_FLAG_COMMUTATIVE (1<<11) |
933 | 0 | #define IR_OP_FLAG_BB_START (1<<12) |
934 | 0 | #define IR_OP_FLAG_BB_END (1<<13) |
935 | 0 | #define IR_OP_FLAG_TERMINATOR (1<<14) |
936 | 0 | #define IR_OP_FLAG_PINNED (1<<15) |
937 | | |
938 | 0 | #define IR_OP_FLAG_MEM_LOAD ((0<<6)|(0<<7)) |
939 | | #define IR_OP_FLAG_MEM_STORE ((0<<6)|(1<<7)) |
940 | | #define IR_OP_FLAG_MEM_CALL ((1<<6)|(0<<7)) |
941 | | #define IR_OP_FLAG_MEM_ALLOC ((1<<6)|(1<<7)) |
942 | 0 | #define IR_OP_FLAG_MEM_MASK ((1<<6)|(1<<7)) |
943 | | |
944 | 0 | #define IR_OPND_UNUSED 0x0 |
945 | 0 | #define IR_OPND_DATA 0x1 |
946 | 0 | #define IR_OPND_CONTROL 0x2 |
947 | 0 | #define IR_OPND_CONTROL_DEP 0x3 |
948 | 0 | #define IR_OPND_CONTROL_REF 0x4 |
949 | 0 | #define IR_OPND_STR 0x5 |
950 | 0 | #define IR_OPND_NUM 0x6 |
951 | 0 | #define IR_OPND_PROB 0x7 |
952 | 0 | #define IR_OPND_PROTO 0x8 |
953 | | |
954 | | #define IR_OP_FLAGS(op_flags, op1_flags, op2_flags, op3_flags) \ |
955 | | ((op_flags) | ((op1_flags) << 20) | ((op2_flags) << 24) | ((op3_flags) << 28)) |
956 | | |
957 | 0 | #define IR_INPUT_EDGES_COUNT(flags) (flags & IR_OP_FLAG_EDGES_MASK) |
958 | 0 | #define IR_OPERANDS_COUNT(flags) ((flags & IR_OP_FLAG_OPERANDS_MASK) >> IR_OP_FLAG_OPERANDS_SHIFT) |
959 | | |
960 | 0 | #define IR_OP_HAS_VAR_INPUTS(flags) ((flags) & IR_OP_FLAG_VAR_INPUTS) |
961 | | |
962 | | #define IR_OPND_KIND(flags, i) \ |
963 | 0 | (((flags) >> (16 + (4 * (((i) > 3) ? 3 : (i))))) & 0xf) |
964 | | |
965 | | #define IR_IS_REF_OPND_KIND(kind) \ |
966 | 0 | ((kind) >= IR_OPND_DATA && (kind) <= IR_OPND_CONTROL_REF) |
967 | | |
968 | | IR_ALWAYS_INLINE ir_ref ir_operands_count(const ir_ctx *ctx, const ir_insn *insn) |
969 | 0 | { |
970 | 0 | uint32_t flags = ir_op_flags[insn->op]; |
971 | 0 | uint32_t n = IR_OPERANDS_COUNT(flags); |
972 | |
|
973 | 0 | if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) { |
974 | | /* MERGE, PHI, CALL, etc */ |
975 | 0 | n = insn->inputs_count; |
976 | 0 | } |
977 | 0 | return n; |
978 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_operands_count Unexecuted instantiation: ir_check.c:ir_operands_count Unexecuted instantiation: ir_dump.c:ir_operands_count Unexecuted instantiation: ir_emit.c:ir_operands_count Unexecuted instantiation: ir_gcm.c:ir_operands_count Unexecuted instantiation: ir_gdb.c:ir_operands_count Unexecuted instantiation: ir_patch.c:ir_operands_count Unexecuted instantiation: ir_ra.c:ir_operands_count Unexecuted instantiation: ir_save.c:ir_operands_count Unexecuted instantiation: ir_sccp.c:ir_operands_count Unexecuted instantiation: ir_strtab.c:ir_operands_count Unexecuted instantiation: ir.c:ir_operands_count |
979 | | |
980 | | IR_ALWAYS_INLINE ir_ref ir_input_edges_count(const ir_ctx *ctx, const ir_insn *insn) |
981 | 0 | { |
982 | 0 | uint32_t flags = ir_op_flags[insn->op]; |
983 | 0 | uint32_t n = IR_INPUT_EDGES_COUNT(flags); |
984 | 0 | if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) { |
985 | | /* MERGE, PHI, CALL, etc */ |
986 | 0 | n = insn->inputs_count; |
987 | 0 | } |
988 | 0 | return n; |
989 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_input_edges_count Unexecuted instantiation: ir_check.c:ir_input_edges_count Unexecuted instantiation: ir_dump.c:ir_input_edges_count Unexecuted instantiation: ir_emit.c:ir_input_edges_count Unexecuted instantiation: ir_gcm.c:ir_input_edges_count Unexecuted instantiation: ir_gdb.c:ir_input_edges_count Unexecuted instantiation: ir_patch.c:ir_input_edges_count Unexecuted instantiation: ir_ra.c:ir_input_edges_count Unexecuted instantiation: ir_save.c:ir_input_edges_count Unexecuted instantiation: ir_sccp.c:ir_input_edges_count Unexecuted instantiation: ir_strtab.c:ir_input_edges_count Unexecuted instantiation: ir.c:ir_input_edges_count |
990 | | |
991 | | IR_ALWAYS_INLINE uint32_t ir_insn_inputs_to_len(uint32_t inputs_count) |
992 | 0 | { |
993 | 0 | return 1 + (inputs_count >> 2); |
994 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_check.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_dump.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_emit.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_gcm.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_gdb.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_patch.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_ra.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_save.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_sccp.c:ir_insn_inputs_to_len Unexecuted instantiation: ir_strtab.c:ir_insn_inputs_to_len Unexecuted instantiation: ir.c:ir_insn_inputs_to_len |
995 | | |
996 | | IR_ALWAYS_INLINE uint32_t ir_insn_len(const ir_insn *insn) |
997 | 0 | { |
998 | 0 | return ir_insn_inputs_to_len(insn->inputs_count); |
999 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_insn_len Unexecuted instantiation: ir_check.c:ir_insn_len Unexecuted instantiation: ir_dump.c:ir_insn_len Unexecuted instantiation: ir_emit.c:ir_insn_len Unexecuted instantiation: ir_gcm.c:ir_insn_len Unexecuted instantiation: ir_gdb.c:ir_insn_len Unexecuted instantiation: ir_patch.c:ir_insn_len Unexecuted instantiation: ir_ra.c:ir_insn_len Unexecuted instantiation: ir_save.c:ir_insn_len Unexecuted instantiation: ir_sccp.c:ir_insn_len Unexecuted instantiation: ir_strtab.c:ir_insn_len Unexecuted instantiation: ir.c:ir_insn_len |
1000 | | |
1001 | | /*** IR Context Private Flags (ir_ctx->flags2) ***/ |
1002 | 0 | #define IR_CFG_HAS_LOOPS (1<<0) |
1003 | 0 | #define IR_IRREDUCIBLE_CFG (1<<1) |
1004 | 0 | #define IR_HAS_ALLOCA (1<<2) |
1005 | 0 | #define IR_HAS_CALLS (1<<3) |
1006 | 0 | #define IR_OPT_IN_SCCP (1<<4) |
1007 | 0 | #define IR_LINEAR (1<<5) |
1008 | 0 | #define IR_HAS_VA_START (1<<6) |
1009 | 0 | #define IR_HAS_VA_COPY (1<<7) |
1010 | 0 | #define IR_HAS_VA_ARG_GP (1<<8) |
1011 | 0 | #define IR_HAS_VA_ARG_FP (1<<9) |
1012 | | #define IR_HAS_FP_RET_SLOT (1<<10) |
1013 | 0 | #define IR_16B_FRAME_ALIGNMENT (1<<11) |
1014 | | |
1015 | | /* Temporary: MEM2SSA -> SCCP */ |
1016 | 0 | #define IR_MEM2SSA_VARS (1<<25) |
1017 | | |
1018 | | /* Temporary: SCCP -> CFG */ |
1019 | 0 | #define IR_CFG_REACHABLE (1<<26) |
1020 | | |
1021 | | /* Temporary: Dominators -> Loops */ |
1022 | 0 | #define IR_NO_LOOPS (1<<25) |
1023 | | |
1024 | | /* Temporary: Live Ranges */ |
1025 | 0 | #define IR_LR_HAVE_DESSA_MOVES (1<<25) |
1026 | | |
1027 | | /* Temporary: Register Allocator */ |
1028 | 0 | #define IR_RA_HAVE_SPLITS (1<<25) |
1029 | 0 | #define IR_RA_HAVE_SPILLS (1<<26) |
1030 | | |
1031 | | #define IR_RESERVED_FLAG_1 (1U<<31) |
1032 | | |
1033 | | /*** IR Use Lists ***/ |
1034 | | struct _ir_use_list { |
1035 | | ir_ref refs; /* index in ir_ctx->use_edges[] array */ |
1036 | | ir_ref count; |
1037 | | }; |
1038 | | |
1039 | | void ir_use_list_remove_all(ir_ctx *ctx, ir_ref def, ir_ref use); |
1040 | | void ir_use_list_remove_one(ir_ctx *ctx, ir_ref def, ir_ref use); |
1041 | | void ir_use_list_replace_all(ir_ctx *ctx, ir_ref def, ir_ref use, ir_ref new_use); |
1042 | | void ir_use_list_replace_one(ir_ctx *ctx, ir_ref def, ir_ref use, ir_ref new_use); |
1043 | | bool ir_use_list_add(ir_ctx *ctx, ir_ref def, ir_ref use); |
1044 | | void ir_use_list_sort(ir_ctx *ctx, ir_ref def); |
1045 | | |
1046 | | IR_ALWAYS_INLINE ir_ref ir_next_control(const ir_ctx *ctx, ir_ref ref) |
1047 | 0 | { |
1048 | 0 | ir_use_list *use_list = &ctx->use_lists[ref]; |
1049 | 0 | ir_ref n = use_list->count; |
1050 | 0 | ir_ref *p; |
1051 | |
|
1052 | 0 | IR_ASSERT(ir_op_flags[ctx->ir_base[ref].op] & IR_OP_FLAG_CONTROL); |
1053 | 0 | for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) { |
1054 | 0 | ir_ref next = *p; |
1055 | 0 | ir_insn *insn = &ctx->ir_base[next]; |
1056 | |
|
1057 | 0 | if ((ir_op_flags[insn->op] & IR_OP_FLAG_CONTROL) && insn->op1 == ref) { |
1058 | 0 | return next; |
1059 | 0 | } |
1060 | 0 | } |
1061 | 0 | IR_ASSERT(0); |
1062 | 0 | return IR_UNUSED; |
1063 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_next_control Unexecuted instantiation: ir_check.c:ir_next_control Unexecuted instantiation: ir_dump.c:ir_next_control Unexecuted instantiation: ir_emit.c:ir_next_control Unexecuted instantiation: ir_gcm.c:ir_next_control Unexecuted instantiation: ir_gdb.c:ir_next_control Unexecuted instantiation: ir_patch.c:ir_next_control Unexecuted instantiation: ir_ra.c:ir_next_control Unexecuted instantiation: ir_save.c:ir_next_control Unexecuted instantiation: ir_sccp.c:ir_next_control Unexecuted instantiation: ir_strtab.c:ir_next_control Unexecuted instantiation: ir.c:ir_next_control |
1064 | | |
1065 | | /*** Modification helpers ***/ |
1066 | 0 | #define MAKE_NOP(_insn) do { \ |
1067 | 0 | ir_insn *__insn = _insn; \ |
1068 | 0 | __insn->optx = IR_NOP; \ |
1069 | 0 | __insn->op1 = __insn->op2 = __insn->op3 = IR_UNUSED; \ |
1070 | 0 | } while (0) |
1071 | | |
1072 | 0 | #define CLEAR_USES(_ref) do { \ |
1073 | 0 | ir_use_list *__use_list = &ctx->use_lists[_ref]; \ |
1074 | 0 | __use_list->count = 0; \ |
1075 | 0 | } while (0) |
1076 | | |
1077 | 0 | #define SWAP_REFS(_ref1, _ref2) do { \ |
1078 | 0 | ir_ref _tmp = _ref1; \ |
1079 | 0 | _ref1 = _ref2; \ |
1080 | 0 | _ref2 = _tmp; \ |
1081 | 0 | } while (0) |
1082 | | |
1083 | 0 | #define SWAP_INSNS(_insn1, _insn2) do { \ |
1084 | 0 | ir_insn *_tmp = _insn1; \ |
1085 | 0 | _insn1 = _insn2; \ |
1086 | 0 | _insn2 = _tmp; \ |
1087 | 0 | } while (0) |
1088 | | |
1089 | | void ir_replace(ir_ctx *ctx, ir_ref ref, ir_ref new_ref); |
1090 | | void ir_update_op(ir_ctx *ctx, ir_ref ref, uint32_t idx, ir_ref new_val); |
1091 | | |
1092 | | /*** Iterative Optimization ***/ |
1093 | | void ir_iter_replace(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist); |
1094 | | void ir_iter_update_op(ir_ctx *ctx, ir_ref ref, uint32_t idx, ir_ref new_val, ir_bitqueue *worklist); |
1095 | | void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist); |
1096 | | |
1097 | | /*** IR Basic Blocks info ***/ |
1098 | | #define IR_IS_BB_START(op) \ |
1099 | 0 | ((ir_op_flags[op] & IR_OP_FLAG_BB_START) != 0) |
1100 | | |
1101 | | #define IR_IS_BB_MERGE(op) \ |
1102 | | ((op) == IR_MERGE || (op) == IR_LOOP_BEGIN) |
1103 | | |
1104 | | #define IR_IS_BB_END(op) \ |
1105 | 0 | ((ir_op_flags[op] & IR_OP_FLAG_BB_END) != 0) |
1106 | | |
1107 | 0 | #define IR_BB_UNREACHABLE (1<<0) |
1108 | 0 | #define IR_BB_START (1<<1) |
1109 | 0 | #define IR_BB_ENTRY (1<<2) |
1110 | 0 | #define IR_BB_LOOP_HEADER (1<<3) |
1111 | 0 | #define IR_BB_IRREDUCIBLE_LOOP (1<<4) |
1112 | 0 | #define IR_BB_DESSA_MOVES (1<<5) /* translation out of SSA requires MOVEs */ |
1113 | 0 | #define IR_BB_EMPTY (1<<6) |
1114 | 0 | #define IR_BB_PREV_EMPTY_ENTRY (1<<7) |
1115 | 0 | #define IR_BB_OSR_ENTRY_LOADS (1<<8) /* OSR Entry-point with register LOADs */ |
1116 | 0 | #define IR_BB_LOOP_WITH_ENTRY (1<<9) /* set together with LOOP_HEADER if there is an ENTRY in the loop */ |
1117 | | |
1118 | | /* The following flags are set by GCM */ |
1119 | 0 | #define IR_BB_HAS_PHI (1<<10) |
1120 | 0 | #define IR_BB_HAS_PI (1<<11) |
1121 | 0 | #define IR_BB_HAS_PARAM (1<<12) |
1122 | 0 | #define IR_BB_HAS_VAR (1<<13) |
1123 | | |
1124 | | /* The following flags are set by BB scheduler */ |
1125 | 0 | #define IR_BB_ALIGN_LOOP (1<<14) |
1126 | | |
1127 | | struct _ir_block { |
1128 | | uint32_t flags; |
1129 | | ir_ref start; /* index of first instruction */ |
1130 | | ir_ref end; /* index of last instruction */ |
1131 | | uint32_t successors; /* index in ir_ctx->cfg_edges[] array */ |
1132 | | uint32_t successors_count; |
1133 | | uint32_t predecessors; /* index in ir_ctx->cfg_edges[] array */ |
1134 | | uint32_t predecessors_count; |
1135 | | union { |
1136 | | uint32_t dom_parent; /* immediate dominator block */ |
1137 | | uint32_t idom; /* immediate dominator block */ |
1138 | | }; |
1139 | | union { |
1140 | | uint32_t dom_depth; /* depth from the root of the dominators tree */ |
1141 | | uint32_t postnum; /* used temporary during tree constructon */ |
1142 | | }; |
1143 | | uint32_t dom_child; /* first dominated blocks */ |
1144 | | uint32_t dom_next_child; /* next dominated block (linked list) */ |
1145 | | uint32_t loop_header; |
1146 | | uint32_t loop_depth; |
1147 | | }; |
1148 | | |
1149 | | void ir_build_prev_refs(ir_ctx *ctx); |
1150 | | uint32_t ir_skip_empty_target_blocks(const ir_ctx *ctx, uint32_t b); |
1151 | | uint32_t ir_next_block(const ir_ctx *ctx, uint32_t b); |
1152 | | void ir_get_true_false_blocks(const ir_ctx *ctx, uint32_t b, uint32_t *true_block, uint32_t *false_block); |
1153 | | |
1154 | | IR_ALWAYS_INLINE uint32_t ir_phi_input_number(const ir_ctx *ctx, const ir_block *bb, uint32_t from) |
1155 | 0 | { |
1156 | 0 | uint32_t n, *p; |
1157 | |
|
1158 | 0 | for (n = 0, p = &ctx->cfg_edges[bb->predecessors]; n < bb->predecessors_count; p++, n++) { |
1159 | 0 | if (*p == from) { |
1160 | 0 | return n + 2; /* first input is a reference to MERGE */ |
1161 | 0 | } |
1162 | 0 | } |
1163 | 0 | IR_ASSERT(0); |
1164 | 0 | return 0; |
1165 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_phi_input_number Unexecuted instantiation: ir_check.c:ir_phi_input_number Unexecuted instantiation: ir_dump.c:ir_phi_input_number Unexecuted instantiation: ir_emit.c:ir_phi_input_number Unexecuted instantiation: ir_gcm.c:ir_phi_input_number Unexecuted instantiation: ir_gdb.c:ir_phi_input_number Unexecuted instantiation: ir_patch.c:ir_phi_input_number Unexecuted instantiation: ir_ra.c:ir_phi_input_number Unexecuted instantiation: ir_save.c:ir_phi_input_number Unexecuted instantiation: ir_sccp.c:ir_phi_input_number Unexecuted instantiation: ir_strtab.c:ir_phi_input_number Unexecuted instantiation: ir.c:ir_phi_input_number |
1166 | | |
1167 | | /*** Folding Engine (see ir.c and ir_fold.h) ***/ |
1168 | | typedef enum _ir_fold_action { |
1169 | | IR_FOLD_DO_RESTART, |
1170 | | IR_FOLD_DO_CSE, |
1171 | | IR_FOLD_DO_EMIT, |
1172 | | IR_FOLD_DO_COPY, |
1173 | | IR_FOLD_DO_CONST |
1174 | | } ir_fold_action; |
1175 | | |
1176 | | ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3, ir_insn *op1_insn, ir_insn *op2_insn, ir_insn *op3_insn); |
1177 | | |
1178 | | /*** Alias Analyzes (see ir.c) ***/ |
1179 | | ir_ref ir_find_aliasing_load(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr); |
1180 | | ir_ref ir_find_aliasing_vload(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var); |
1181 | | ir_ref ir_find_aliasing_store(ir_ctx *ctx, ir_ref ref, ir_ref addr, ir_ref val); |
1182 | | ir_ref ir_find_aliasing_vstore(ir_ctx *ctx, ir_ref ref, ir_ref addr, ir_ref val); |
1183 | | |
1184 | | /*** Predicates (see ir.c) ***/ |
1185 | | ir_ref ir_check_dominating_predicates(ir_ctx *ctx, ir_ref ref, ir_ref condition); |
1186 | | |
1187 | | /*** IR Live Info ***/ |
1188 | | typedef ir_ref ir_live_pos; |
1189 | | typedef struct _ir_use_pos ir_use_pos; |
1190 | | |
1191 | 0 | #define IR_SUB_REFS_COUNT 4 |
1192 | | |
1193 | 0 | #define IR_LOAD_SUB_REF 0 |
1194 | 0 | #define IR_USE_SUB_REF 1 |
1195 | 0 | #define IR_DEF_SUB_REF 2 |
1196 | 0 | #define IR_SAVE_SUB_REF 3 |
1197 | | |
1198 | 0 | #define IR_LIVE_POS_TO_REF(pos) ((pos) / IR_SUB_REFS_COUNT) |
1199 | 0 | #define IR_LIVE_POS_TO_SUB_REF(pos) ((pos) % IR_SUB_REFS_COUNT) |
1200 | | |
1201 | | #define IR_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT) |
1202 | | |
1203 | 0 | #define IR_START_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT) |
1204 | 0 | #define IR_LOAD_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT + IR_LOAD_SUB_REF) |
1205 | 0 | #define IR_USE_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT + IR_USE_SUB_REF) |
1206 | 0 | #define IR_DEF_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT + IR_DEF_SUB_REF) |
1207 | 0 | #define IR_SAVE_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT + IR_SAVE_SUB_REF) |
1208 | 0 | #define IR_END_LIVE_POS_FROM_REF(ref) ((ref) * IR_SUB_REFS_COUNT + IR_SUB_REFS_COUNT) |
1209 | | |
1210 | | /* ir_use_pos.flags bits */ |
1211 | 0 | #define IR_USE_MUST_BE_IN_REG (1<<0) |
1212 | 0 | #define IR_USE_SHOULD_BE_IN_REG (1<<1) |
1213 | 0 | #define IR_DEF_REUSES_OP1_REG (1<<2) |
1214 | 0 | #define IR_DEF_CONFLICTS_WITH_INPUT_REGS (1<<3) |
1215 | | |
1216 | 0 | #define IR_FUSED_USE (1<<6) |
1217 | 0 | #define IR_PHI_USE (1<<7) |
1218 | | |
1219 | 0 | #define IR_OP1_MUST_BE_IN_REG (1<<8) |
1220 | 0 | #define IR_OP1_SHOULD_BE_IN_REG (1<<9) |
1221 | 0 | #define IR_OP2_MUST_BE_IN_REG (1<<10) |
1222 | 0 | #define IR_OP2_SHOULD_BE_IN_REG (1<<11) |
1223 | 0 | #define IR_OP3_MUST_BE_IN_REG (1<<12) |
1224 | 0 | #define IR_OP3_SHOULD_BE_IN_REG (1<<13) |
1225 | | |
1226 | 0 | #define IR_USE_FLAGS(def_flags, op_num) (((def_flags) >> (6 + (IR_MIN((op_num), 3) * 2))) & 3) |
1227 | | |
1228 | | struct _ir_use_pos { |
1229 | | uint16_t op_num; /* 0 - means result */ |
1230 | | int8_t hint; |
1231 | | uint8_t flags; |
1232 | | ir_ref hint_ref; /* negative references are used for FUSION anf PHI */ |
1233 | | ir_live_pos pos; |
1234 | | ir_use_pos *next; |
1235 | | }; |
1236 | | |
1237 | | struct _ir_live_range { |
1238 | | ir_live_pos start; /* inclusive */ |
1239 | | ir_live_pos end; /* exclusive */ |
1240 | | ir_live_range *next; |
1241 | | }; |
1242 | | |
1243 | | /* ir_live_interval.flags bits (two low bits are reserved for temporary register number) */ |
1244 | 0 | #define IR_LIVE_INTERVAL_FIXED (1<<0) |
1245 | 0 | #define IR_LIVE_INTERVAL_TEMP (1<<1) |
1246 | 0 | #define IR_LIVE_INTERVAL_HAS_HINT_REGS (1<<2) |
1247 | 0 | #define IR_LIVE_INTERVAL_HAS_HINT_REFS (1<<3) |
1248 | 0 | #define IR_LIVE_INTERVAL_MEM_PARAM (1<<4) |
1249 | 0 | #define IR_LIVE_INTERVAL_MEM_LOAD (1<<5) |
1250 | 0 | #define IR_LIVE_INTERVAL_COALESCED (1<<6) |
1251 | 0 | #define IR_LIVE_INTERVAL_SPILL_SPECIAL (1<<7) /* spill slot is pre-allocated in a special area (see ir_ctx.spill_reserved_base) */ |
1252 | 0 | #define IR_LIVE_INTERVAL_SPILLED (1<<8) |
1253 | 0 | #define IR_LIVE_INTERVAL_SPLIT_CHILD (1<<9) |
1254 | | |
1255 | | struct _ir_live_interval { |
1256 | | uint8_t type; |
1257 | | int8_t reg; |
1258 | | uint16_t flags; |
1259 | | union { |
1260 | | int32_t vreg; |
1261 | | int32_t tmp_ref; |
1262 | | }; |
1263 | | union { |
1264 | | int32_t stack_spill_pos; |
1265 | | ir_ref tmp_op_num; |
1266 | | }; |
1267 | | ir_live_pos end; /* end of the last live range (cahce of ival.range.{next->}end) */ |
1268 | | ir_live_range range; |
1269 | | ir_live_range *current_range; |
1270 | | ir_use_pos *use_pos; |
1271 | | ir_live_interval *next; |
1272 | | ir_live_interval *list_next; /* linked list of active, inactive or unhandled intervals */ |
1273 | | }; |
1274 | | |
1275 | | typedef int (*emit_copy_t)(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to); |
1276 | | |
1277 | | int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy); |
1278 | | |
1279 | | #if defined(IR_REGSET_64BIT) |
1280 | | |
1281 | | /*typedef enum _ir_reg ir_reg;*/ |
1282 | | typedef int8_t ir_reg; |
1283 | | |
1284 | | /*** Register Sets ***/ |
1285 | | #if IR_REGSET_64BIT |
1286 | | typedef uint64_t ir_regset; |
1287 | | #else |
1288 | | typedef uint32_t ir_regset; |
1289 | | #endif |
1290 | | |
1291 | 0 | #define IR_REGSET_EMPTY 0 |
1292 | | |
1293 | | #define IR_REGSET_IS_EMPTY(regset) \ |
1294 | 0 | (regset == IR_REGSET_EMPTY) |
1295 | | |
1296 | | #define IR_REGSET_IS_SINGLETON(regset) \ |
1297 | | (regset && !(regset & (regset - 1))) |
1298 | | |
1299 | | #if IR_REGSET_64BIT |
1300 | | # define IR_REGSET(reg) \ |
1301 | | (1ull << (reg)) |
1302 | | #else |
1303 | | # define IR_REGSET(reg) \ |
1304 | 0 | (1u << (reg)) |
1305 | | #endif |
1306 | | |
1307 | | #if IR_REGSET_64BIT |
1308 | | # define IR_REGSET_INTERVAL(reg1, reg2) \ |
1309 | | (((1ull << ((reg2) - (reg1) + 1)) - 1) << (reg1)) |
1310 | | #else |
1311 | | # define IR_REGSET_INTERVAL(reg1, reg2) \ |
1312 | 0 | (((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1)) |
1313 | | #endif |
1314 | | |
1315 | | #define IR_REGSET_IN(regset, reg) \ |
1316 | 0 | (((regset) & IR_REGSET(reg)) != 0) |
1317 | | |
1318 | | #define IR_REGSET_INCL(regset, reg) \ |
1319 | 0 | (regset) |= IR_REGSET(reg) |
1320 | | |
1321 | | #define IR_REGSET_EXCL(regset, reg) \ |
1322 | 0 | (regset) &= ~IR_REGSET(reg) |
1323 | | |
1324 | | #define IR_REGSET_UNION(set1, set2) \ |
1325 | 0 | ((set1) | (set2)) |
1326 | | |
1327 | | #define IR_REGSET_INTERSECTION(set1, set2) \ |
1328 | 0 | ((set1) & (set2)) |
1329 | | |
1330 | | #define IR_REGSET_DIFFERENCE(set1, set2) \ |
1331 | 0 | ((set1) & ~(set2)) |
1332 | | |
1333 | | #if IR_REGSET_64BIT |
1334 | | # define IR_REGSET_FIRST(set) ((ir_reg)ir_ntzl(set)) |
1335 | | # define ir_REGSET_LAST(set) ((ir_reg)(ir_nlzl(set)(set)^63)) |
1336 | | #else |
1337 | 0 | # define IR_REGSET_FIRST(set) ((ir_reg)ir_ntz(set)) |
1338 | | # define IR_REGSET_LAST(set) ((ir_reg)(ir_nlz(set)^31)) |
1339 | | #endif |
1340 | | |
1341 | | IR_ALWAYS_INLINE ir_reg ir_regset_pop_first(ir_regset *set) |
1342 | 0 | { |
1343 | 0 | ir_reg reg; |
1344 | |
|
1345 | 0 | IR_ASSERT(!IR_REGSET_IS_EMPTY(*set)); |
1346 | 0 | reg = IR_REGSET_FIRST(*set); |
1347 | 0 | *set = (*set) & ((*set) - 1); |
1348 | 0 | return reg; |
1349 | 0 | } Unexecuted instantiation: ir_emit.c:ir_regset_pop_first Unexecuted instantiation: ir_ra.c:ir_regset_pop_first |
1350 | | |
1351 | | #define IR_REGSET_FOREACH(set, reg) \ |
1352 | 0 | do { \ |
1353 | 0 | ir_regset _tmp = (set); \ |
1354 | 0 | while (!IR_REGSET_IS_EMPTY(_tmp)) { \ |
1355 | 0 | reg = ir_regset_pop_first(&_tmp); |
1356 | | |
1357 | | #define IR_REGSET_FOREACH_END() \ |
1358 | 0 | } \ |
1359 | 0 | } while (0) |
1360 | | |
1361 | | #endif /* defined(IR_REGSET_64BIT) */ |
1362 | | |
1363 | | /*** IR Register Allocation ***/ |
1364 | | /* Flags for ctx->regs[][] (low bits are used for register number itself) */ |
1365 | | typedef struct _ir_reg_alloc_data { |
1366 | | int32_t unused_slot_4; |
1367 | | int32_t unused_slot_2; |
1368 | | int32_t unused_slot_1; |
1369 | | ir_live_interval **handled; |
1370 | | } ir_reg_alloc_data; |
1371 | | |
1372 | | int32_t ir_allocate_spill_slot(ir_ctx *ctx, ir_type type, ir_reg_alloc_data *data); |
1373 | | |
1374 | | IR_ALWAYS_INLINE void ir_set_alocated_reg(ir_ctx *ctx, ir_ref ref, int op_num, int8_t reg) |
1375 | 0 | { |
1376 | 0 | int8_t *regs = ctx->regs[ref]; |
1377 | |
|
1378 | 0 | if (op_num > 0) { |
1379 | | /* regs[] is not limited by the declared boundary 4, the real boundary checked below */ |
1380 | 0 | IR_ASSERT(op_num <= IR_MAX(3, ctx->ir_base[ref].inputs_count)); |
1381 | 0 | } |
1382 | 0 | regs[op_num] = reg; |
1383 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_set_alocated_reg Unexecuted instantiation: ir_check.c:ir_set_alocated_reg Unexecuted instantiation: ir_dump.c:ir_set_alocated_reg Unexecuted instantiation: ir_emit.c:ir_set_alocated_reg Unexecuted instantiation: ir_gcm.c:ir_set_alocated_reg Unexecuted instantiation: ir_gdb.c:ir_set_alocated_reg Unexecuted instantiation: ir_patch.c:ir_set_alocated_reg Unexecuted instantiation: ir_ra.c:ir_set_alocated_reg Unexecuted instantiation: ir_save.c:ir_set_alocated_reg Unexecuted instantiation: ir_sccp.c:ir_set_alocated_reg Unexecuted instantiation: ir_strtab.c:ir_set_alocated_reg Unexecuted instantiation: ir.c:ir_set_alocated_reg |
1384 | | |
1385 | | IR_ALWAYS_INLINE int8_t ir_get_alocated_reg(const ir_ctx *ctx, ir_ref ref, int op_num) |
1386 | 0 | { |
1387 | 0 | int8_t *regs = ctx->regs[ref]; |
1388 | | |
1389 | | /* regs[] is not limited by the declared boundary 4, the real boundary checked below */ |
1390 | 0 | IR_ASSERT(op_num <= IR_MAX(3, ctx->ir_base[ref].inputs_count)); |
1391 | 0 | return regs[op_num]; |
1392 | 0 | } Unexecuted instantiation: ir_cfg.c:ir_get_alocated_reg Unexecuted instantiation: ir_check.c:ir_get_alocated_reg Unexecuted instantiation: ir_dump.c:ir_get_alocated_reg Unexecuted instantiation: ir_emit.c:ir_get_alocated_reg Unexecuted instantiation: ir_gcm.c:ir_get_alocated_reg Unexecuted instantiation: ir_gdb.c:ir_get_alocated_reg Unexecuted instantiation: ir_patch.c:ir_get_alocated_reg Unexecuted instantiation: ir_ra.c:ir_get_alocated_reg Unexecuted instantiation: ir_save.c:ir_get_alocated_reg Unexecuted instantiation: ir_sccp.c:ir_get_alocated_reg Unexecuted instantiation: ir_strtab.c:ir_get_alocated_reg Unexecuted instantiation: ir.c:ir_get_alocated_reg |
1393 | | |
1394 | | /*** IR Target Interface ***/ |
1395 | | |
1396 | | /* ctx->rules[] flags */ |
1397 | 0 | #define IR_FUSED (1U<<31) /* Insn is fused into others (code is generated as part of the fusion root) */ |
1398 | 0 | #define IR_SKIPPED (1U<<30) /* Insn is skipped (code is not generated) */ |
1399 | 0 | #define IR_SIMPLE (1U<<29) /* Insn doesn't have any target constraints */ |
1400 | 0 | #define IR_FUSED_REG (1U<<28) /* Register assignemnt may be stored in ctx->fused_regs instead of ctx->regs */ |
1401 | 0 | #define IR_MAY_SWAP (1U<<27) /* Allow swapping operands for better register allocation */ |
1402 | 0 | #define IR_MAY_REUSE (1U<<26) /* Result may reuse register of the source */ |
1403 | | |
1404 | 0 | #define IR_RULE_MASK 0xff |
1405 | | |
1406 | | extern const char *ir_rule_name[]; |
1407 | | |
1408 | | typedef struct _ir_target_constraints ir_target_constraints; |
1409 | | |
1410 | | #define IR_TMP_REG(_num, _type, _start, _end) \ |
1411 | 0 | (ir_tmp_reg){.num=(_num), .type=(_type), .start=(_start), .end=(_end)} |
1412 | | #define IR_SCRATCH_REG(_reg, _start, _end) \ |
1413 | 0 | (ir_tmp_reg){.reg=(_reg), .type=IR_VOID, .start=(_start), .end=(_end)} |
1414 | | |
1415 | | int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints); |
1416 | | |
1417 | | void ir_fix_stack_frame(ir_ctx *ctx); |
1418 | | |
1419 | | /* Utility */ |
1420 | | ir_type ir_get_return_type(ir_ctx *ctx); |
1421 | | bool ir_is_fastcall(const ir_ctx *ctx, const ir_insn *insn); |
1422 | | bool ir_is_vararg(const ir_ctx *ctx, ir_insn *insn); |
1423 | | |
1424 | | //#define IR_BITSET_LIVENESS |
1425 | | |
1426 | | #endif /* IR_PRIVATE_H */ |