File: | build/gcc/machmode.h |
Warning: | line 422, column 60 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Rtl-level induction variable analysis. | ||||
2 | Copyright (C) 2004-2023 Free Software Foundation, Inc. | ||||
3 | |||||
4 | This file is part of GCC. | ||||
5 | |||||
6 | GCC is free software; you can redistribute it and/or modify it | ||||
7 | under the terms of the GNU General Public License as published by the | ||||
8 | Free Software Foundation; either version 3, or (at your option) any | ||||
9 | later version. | ||||
10 | |||||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT | ||||
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||||
14 | for more details. | ||||
15 | |||||
16 | You should have received a copy of the GNU General Public License | ||||
17 | along with GCC; see the file COPYING3. If not see | ||||
18 | <http://www.gnu.org/licenses/>. */ | ||||
19 | |||||
20 | /* This is a simple analysis of induction variables of the loop. The major use | ||||
21 | is for determining the number of iterations of a loop for loop unrolling, | ||||
22 | doloop optimization and branch prediction. The iv information is computed | ||||
23 | on demand. | ||||
24 | |||||
25 | Induction variables are analyzed by walking the use-def chains. When | ||||
26 | a basic induction variable (biv) is found, it is cached in the bivs | ||||
27 | hash table. When register is proved to be a biv, its description | ||||
28 | is stored to DF_REF_DATA of the def reference. | ||||
29 | |||||
30 | The analysis works always with one loop -- you must call | ||||
31 | iv_analysis_loop_init (loop) for it. All the other functions then work with | ||||
32 | this loop. When you need to work with another loop, just call | ||||
33 | iv_analysis_loop_init for it. When you no longer need iv analysis, call | ||||
34 | iv_analysis_done () to clean up the memory. | ||||
35 | |||||
36 | The available functions are: | ||||
37 | |||||
38 | iv_analyze (insn, mode, reg, iv): Stores the description of the induction | ||||
39 | variable corresponding to the use of register REG in INSN to IV, given | ||||
40 | that REG has mode MODE. Returns true if REG is an induction variable | ||||
41 | in INSN. false otherwise. If a use of REG is not found in INSN, | ||||
42 | the following insns are scanned (so that we may call this function | ||||
43 | on insns returned by get_condition). | ||||
44 | iv_analyze_result (insn, def, iv): Stores to IV the description of the iv | ||||
45 | corresponding to DEF, which is a register defined in INSN. | ||||
46 | iv_analyze_expr (insn, mode, expr, iv): Stores to IV the description of iv | ||||
47 | corresponding to expression EXPR evaluated at INSN. All registers used by | ||||
48 | EXPR must also be used in INSN. MODE is the mode of EXPR. | ||||
49 | */ | ||||
50 | |||||
51 | #include "config.h" | ||||
52 | #include "system.h" | ||||
53 | #include "coretypes.h" | ||||
54 | #include "backend.h" | ||||
55 | #include "rtl.h" | ||||
56 | #include "df.h" | ||||
57 | #include "memmodel.h" | ||||
58 | #include "emit-rtl.h" | ||||
59 | #include "diagnostic-core.h" | ||||
60 | #include "cfgloop.h" | ||||
61 | #include "intl.h" | ||||
62 | #include "dumpfile.h" | ||||
63 | #include "rtl-iter.h" | ||||
64 | #include "tree-ssa-loop-niter.h" | ||||
65 | #include "regs.h" | ||||
66 | #include "function-abi.h" | ||||
67 | |||||
68 | /* Possible return values of iv_get_reaching_def. */ | ||||
69 | |||||
70 | enum iv_grd_result | ||||
71 | { | ||||
72 | /* More than one reaching def, or reaching def that does not | ||||
73 | dominate the use. */ | ||||
74 | GRD_INVALID, | ||||
75 | |||||
76 | /* The use is trivial invariant of the loop, i.e. is not changed | ||||
77 | inside the loop. */ | ||||
78 | GRD_INVARIANT, | ||||
79 | |||||
80 | /* The use is reached by initial value and a value from the | ||||
81 | previous iteration. */ | ||||
82 | GRD_MAYBE_BIV, | ||||
83 | |||||
84 | /* The use has single dominating def. */ | ||||
85 | GRD_SINGLE_DOM | ||||
86 | }; | ||||
87 | |||||
88 | /* Information about a biv. */ | ||||
89 | |||||
90 | class biv_entry | ||||
91 | { | ||||
92 | public: | ||||
93 | unsigned regno; /* The register of the biv. */ | ||||
94 | class rtx_iv iv; /* Value of the biv. */ | ||||
95 | }; | ||||
96 | |||||
97 | static bool clean_slate = true; | ||||
98 | |||||
99 | static unsigned int iv_ref_table_size = 0; | ||||
100 | |||||
101 | /* Table of rtx_ivs indexed by the df_ref uid field. */ | ||||
102 | static class rtx_iv ** iv_ref_table; | ||||
103 | |||||
104 | /* Induction variable stored at the reference. */ | ||||
105 | #define DF_REF_IV(REF)iv_ref_table[((REF)->base.id)] iv_ref_table[DF_REF_ID (REF)((REF)->base.id)] | ||||
106 | #define DF_REF_IV_SET(REF, IV)iv_ref_table[((REF)->base.id)] = (IV) iv_ref_table[DF_REF_ID (REF)((REF)->base.id)] = (IV) | ||||
107 | |||||
108 | /* The current loop. */ | ||||
109 | |||||
110 | static class loop *current_loop; | ||||
111 | |||||
112 | /* Hashtable helper. */ | ||||
113 | |||||
114 | struct biv_entry_hasher : free_ptr_hash <biv_entry> | ||||
115 | { | ||||
116 | typedef rtx_def *compare_type; | ||||
117 | static inline hashval_t hash (const biv_entry *); | ||||
118 | static inline bool equal (const biv_entry *, const rtx_def *); | ||||
119 | }; | ||||
120 | |||||
121 | /* Returns hash value for biv B. */ | ||||
122 | |||||
123 | inline hashval_t | ||||
124 | biv_entry_hasher::hash (const biv_entry *b) | ||||
125 | { | ||||
126 | return b->regno; | ||||
127 | } | ||||
128 | |||||
129 | /* Compares biv B and register R. */ | ||||
130 | |||||
131 | inline bool | ||||
132 | biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r) | ||||
133 | { | ||||
134 | return b->regno == REGNO (r)(rhs_regno(r)); | ||||
135 | } | ||||
136 | |||||
137 | /* Bivs of the current loop. */ | ||||
138 | |||||
139 | static hash_table<biv_entry_hasher> *bivs; | ||||
140 | |||||
141 | static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *); | ||||
142 | |||||
143 | /* Return the RTX code corresponding to the IV extend code EXTEND. */ | ||||
144 | static inline enum rtx_code | ||||
145 | iv_extend_to_rtx_code (enum iv_extend_code extend) | ||||
146 | { | ||||
147 | switch (extend) | ||||
148 | { | ||||
149 | case IV_SIGN_EXTEND: | ||||
150 | return SIGN_EXTEND; | ||||
151 | case IV_ZERO_EXTEND: | ||||
152 | return ZERO_EXTEND; | ||||
153 | case IV_UNKNOWN_EXTEND: | ||||
154 | return UNKNOWN; | ||||
155 | } | ||||
156 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 156, __FUNCTION__)); | ||||
157 | } | ||||
158 | |||||
159 | /* Dumps information about IV to FILE. */ | ||||
160 | |||||
161 | extern void dump_iv_info (FILE *, class rtx_iv *); | ||||
162 | void | ||||
163 | dump_iv_info (FILE *file, class rtx_iv *iv) | ||||
164 | { | ||||
165 | if (!iv->base) | ||||
166 | { | ||||
167 | fprintf (file, "not simple"); | ||||
168 | return; | ||||
169 | } | ||||
170 | |||||
171 | if (iv->step == const0_rtx(const_int_rtx[64]) | ||||
172 | && !iv->first_special) | ||||
173 | fprintf (file, "invariant "); | ||||
174 | |||||
175 | print_rtl (file, iv->base); | ||||
176 | if (iv->step != const0_rtx(const_int_rtx[64])) | ||||
177 | { | ||||
178 | fprintf (file, " + "); | ||||
179 | print_rtl (file, iv->step); | ||||
180 | fprintf (file, " * iteration"); | ||||
181 | } | ||||
182 | fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode)mode_name[iv->mode]); | ||||
183 | |||||
184 | if (iv->mode != iv->extend_mode) | ||||
185 | fprintf (file, " %s to %s", | ||||
186 | rtx_name[iv_extend_to_rtx_code (iv->extend)], | ||||
187 | GET_MODE_NAME (iv->extend_mode)mode_name[iv->extend_mode]); | ||||
188 | |||||
189 | if (iv->mult != const1_rtx(const_int_rtx[64 +1])) | ||||
190 | { | ||||
191 | fprintf (file, " * "); | ||||
192 | print_rtl (file, iv->mult); | ||||
193 | } | ||||
194 | if (iv->delta != const0_rtx(const_int_rtx[64])) | ||||
195 | { | ||||
196 | fprintf (file, " + "); | ||||
197 | print_rtl (file, iv->delta); | ||||
198 | } | ||||
199 | if (iv->first_special) | ||||
200 | fprintf (file, " (first special)"); | ||||
201 | } | ||||
202 | |||||
203 | static void | ||||
204 | check_iv_ref_table_size (void) | ||||
205 | { | ||||
206 | if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ()(df->def_info.table_size)) | ||||
207 | { | ||||
208 | unsigned int new_size = DF_DEFS_TABLE_SIZE ()(df->def_info.table_size) + (DF_DEFS_TABLE_SIZE ()(df->def_info.table_size) / 4); | ||||
209 | iv_ref_table = XRESIZEVEC (class rtx_iv *, iv_ref_table, new_size)((class rtx_iv * *) xrealloc ((void *) (iv_ref_table), sizeof (class rtx_iv *) * (new_size))); | ||||
210 | memset (&iv_ref_table[iv_ref_table_size], 0, | ||||
211 | (new_size - iv_ref_table_size) * sizeof (class rtx_iv *)); | ||||
212 | iv_ref_table_size = new_size; | ||||
213 | } | ||||
214 | } | ||||
215 | |||||
216 | |||||
217 | /* Checks whether REG is a well-behaved register. */ | ||||
218 | |||||
219 | static bool | ||||
220 | simple_reg_p (rtx reg) | ||||
221 | { | ||||
222 | unsigned r; | ||||
223 | |||||
224 | if (GET_CODE (reg)((enum rtx_code) (reg)->code) == SUBREG) | ||||
225 | { | ||||
226 | if (!subreg_lowpart_p (reg)) | ||||
227 | return false; | ||||
228 | reg = SUBREG_REG (reg)(((reg)->u.fld[0]).rt_rtx); | ||||
229 | } | ||||
230 | |||||
231 | if (!REG_P (reg)(((enum rtx_code) (reg)->code) == REG)) | ||||
232 | return false; | ||||
233 | |||||
234 | r = REGNO (reg)(rhs_regno(reg)); | ||||
235 | if (HARD_REGISTER_NUM_P (r)((r) < 76)) | ||||
236 | return false; | ||||
237 | |||||
238 | if (GET_MODE_CLASS (GET_MODE (reg))((enum mode_class) mode_class[((machine_mode) (reg)->mode) ]) != MODE_INT) | ||||
239 | return false; | ||||
240 | |||||
241 | return true; | ||||
242 | } | ||||
243 | |||||
244 | /* Clears the information about ivs stored in df. */ | ||||
245 | |||||
246 | static void | ||||
247 | clear_iv_info (void) | ||||
248 | { | ||||
249 | unsigned i, n_defs = DF_DEFS_TABLE_SIZE ()(df->def_info.table_size); | ||||
250 | class rtx_iv *iv; | ||||
251 | |||||
252 | check_iv_ref_table_size (); | ||||
253 | for (i = 0; i < n_defs; i++) | ||||
254 | { | ||||
255 | iv = iv_ref_table[i]; | ||||
256 | if (iv) | ||||
257 | { | ||||
258 | free (iv); | ||||
259 | iv_ref_table[i] = NULL__null; | ||||
260 | } | ||||
261 | } | ||||
262 | |||||
263 | bivs->empty (); | ||||
264 | } | ||||
265 | |||||
266 | |||||
267 | /* Prepare the data for an induction variable analysis of a LOOP. */ | ||||
268 | |||||
269 | void | ||||
270 | iv_analysis_loop_init (class loop *loop) | ||||
271 | { | ||||
272 | current_loop = loop; | ||||
273 | |||||
274 | /* Clear the information from the analysis of the previous loop. */ | ||||
275 | if (clean_slate) | ||||
276 | { | ||||
277 | df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN); | ||||
278 | bivs = new hash_table<biv_entry_hasher> (10); | ||||
279 | clean_slate = false; | ||||
280 | } | ||||
281 | else | ||||
282 | clear_iv_info (); | ||||
283 | |||||
284 | /* Get rid of the ud chains before processing the rescans. Then add | ||||
285 | the problem back. */ | ||||
286 | df_remove_problem (df_chain(df->problems_by_index[DF_CHAIN])); | ||||
287 | df_process_deferred_rescans (); | ||||
288 | df_set_flags (DF_RD_PRUNE_DEAD_DEFS); | ||||
289 | df_chain_add_problem (DF_UD_CHAIN); | ||||
290 | df_note_add_problem (); | ||||
291 | df_analyze_loop (loop); | ||||
292 | if (dump_file) | ||||
293 | df_dump_region (dump_file); | ||||
294 | |||||
295 | check_iv_ref_table_size (); | ||||
296 | } | ||||
297 | |||||
298 | /* Finds the definition of REG that dominates loop latch and stores | ||||
299 | it to DEF. Returns false if there is not a single definition | ||||
300 | dominating the latch. If REG has no definition in loop, DEF | ||||
301 | is set to NULL and true is returned. */ | ||||
302 | |||||
303 | static bool | ||||
304 | latch_dominating_def (rtx reg, df_ref *def) | ||||
305 | { | ||||
306 | df_ref single_rd = NULL__null, adef; | ||||
307 | unsigned regno = REGNO (reg)(rhs_regno(reg)); | ||||
308 | class df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch)(df_rd_get_bb_info ((current_loop->latch)->index)); | ||||
309 | |||||
310 | for (adef = DF_REG_DEF_CHAIN (regno)(df->def_regs[(regno)]->reg_chain); adef; adef = DF_REF_NEXT_REG (adef)((adef)->base.next_reg)) | ||||
311 | { | ||||
312 | if (!bitmap_bit_p (df->blocks_to_analyze, DF_REF_BBNO (adef)(((((adef)->base.cl) == DF_REF_ARTIFICIAL) ? (adef)->artificial_ref .bb : BLOCK_FOR_INSN (((adef)->base.insn_info->insn)))-> index)) | ||||
313 | || !bitmap_bit_p (&bb_info->out, DF_REF_ID (adef)((adef)->base.id))) | ||||
314 | continue; | ||||
315 | |||||
316 | /* More than one reaching definition. */ | ||||
317 | if (single_rd) | ||||
318 | return false; | ||||
319 | |||||
320 | if (!just_once_each_iteration_p (current_loop, DF_REF_BB (adef)((((adef)->base.cl) == DF_REF_ARTIFICIAL) ? (adef)->artificial_ref .bb : BLOCK_FOR_INSN (((adef)->base.insn_info->insn))))) | ||||
321 | return false; | ||||
322 | |||||
323 | single_rd = adef; | ||||
324 | } | ||||
325 | |||||
326 | *def = single_rd; | ||||
327 | return true; | ||||
328 | } | ||||
329 | |||||
330 | /* Gets definition of REG reaching its use in INSN and stores it to DEF. */ | ||||
331 | |||||
332 | static enum iv_grd_result | ||||
333 | iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def) | ||||
334 | { | ||||
335 | df_ref use, adef; | ||||
336 | basic_block def_bb, use_bb; | ||||
337 | rtx_insn *def_insn; | ||||
338 | bool dom_p; | ||||
339 | |||||
340 | *def = NULL__null; | ||||
341 | if (!simple_reg_p (reg)) | ||||
342 | return GRD_INVALID; | ||||
343 | if (GET_CODE (reg)((enum rtx_code) (reg)->code) == SUBREG) | ||||
344 | reg = SUBREG_REG (reg)(((reg)->u.fld[0]).rt_rtx); | ||||
345 | gcc_assert (REG_P (reg))((void)(!((((enum rtx_code) (reg)->code) == REG)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 345, __FUNCTION__), 0 : 0)); | ||||
346 | |||||
347 | use = df_find_use (insn, reg); | ||||
348 | gcc_assert (use != NULL)((void)(!(use != __null) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 348, __FUNCTION__), 0 : 0)); | ||||
349 | |||||
350 | if (!DF_REF_CHAIN (use)((use)->base.chain)) | ||||
351 | return GRD_INVARIANT; | ||||
352 | |||||
353 | /* More than one reaching def. */ | ||||
354 | if (DF_REF_CHAIN (use)((use)->base.chain)->next) | ||||
355 | return GRD_INVALID; | ||||
356 | |||||
357 | adef = DF_REF_CHAIN (use)((use)->base.chain)->ref; | ||||
358 | |||||
359 | /* We do not handle setting only part of the register. */ | ||||
360 | if (DF_REF_FLAGS (adef)((adef)->base.flags) & DF_REF_READ_WRITE) | ||||
361 | return GRD_INVALID; | ||||
362 | |||||
363 | def_insn = DF_REF_INSN (adef)((adef)->base.insn_info->insn); | ||||
364 | def_bb = DF_REF_BB (adef)((((adef)->base.cl) == DF_REF_ARTIFICIAL) ? (adef)->artificial_ref .bb : BLOCK_FOR_INSN (((adef)->base.insn_info->insn))); | ||||
365 | use_bb = BLOCK_FOR_INSN (insn); | ||||
366 | |||||
367 | if (use_bb == def_bb) | ||||
368 | dom_p = (DF_INSN_LUID (def_insn)((((df->insns[(INSN_UID (def_insn))]))->luid)) < DF_INSN_LUID (insn)((((df->insns[(INSN_UID (insn))]))->luid))); | ||||
369 | else | ||||
370 | dom_p = dominated_by_p (CDI_DOMINATORS, use_bb, def_bb); | ||||
371 | |||||
372 | if (dom_p) | ||||
373 | { | ||||
374 | *def = adef; | ||||
375 | return GRD_SINGLE_DOM; | ||||
376 | } | ||||
377 | |||||
378 | /* The definition does not dominate the use. This is still OK if | ||||
379 | this may be a use of a biv, i.e. if the def_bb dominates loop | ||||
380 | latch. */ | ||||
381 | if (just_once_each_iteration_p (current_loop, def_bb)) | ||||
382 | return GRD_MAYBE_BIV; | ||||
383 | |||||
384 | return GRD_INVALID; | ||||
385 | } | ||||
386 | |||||
387 | /* Sets IV to invariant CST in MODE. Always returns true (just for | ||||
388 | consistency with other iv manipulation functions that may fail). */ | ||||
389 | |||||
390 | static bool | ||||
391 | iv_constant (class rtx_iv *iv, scalar_int_mode mode, rtx cst) | ||||
392 | { | ||||
393 | iv->mode = mode; | ||||
394 | iv->base = cst; | ||||
395 | iv->step = const0_rtx(const_int_rtx[64]); | ||||
396 | iv->first_special = false; | ||||
397 | iv->extend = IV_UNKNOWN_EXTEND; | ||||
398 | iv->extend_mode = iv->mode; | ||||
399 | iv->delta = const0_rtx(const_int_rtx[64]); | ||||
400 | iv->mult = const1_rtx(const_int_rtx[64 +1]); | ||||
401 | |||||
402 | return true; | ||||
403 | } | ||||
404 | |||||
405 | /* Evaluates application of subreg to MODE on IV. */ | ||||
406 | |||||
407 | static bool | ||||
408 | iv_subreg (class rtx_iv *iv, scalar_int_mode mode) | ||||
409 | { | ||||
410 | /* If iv is invariant, just calculate the new value. */ | ||||
411 | if (iv->step == const0_rtx(const_int_rtx[64]) | ||||
412 | && !iv->first_special) | ||||
413 | { | ||||
414 | rtx val = get_iv_value (iv, const0_rtx(const_int_rtx[64])); | ||||
415 | val = lowpart_subreg (mode, val, | ||||
416 | iv->extend == IV_UNKNOWN_EXTEND | ||||
417 | ? iv->mode : iv->extend_mode); | ||||
418 | |||||
419 | iv->base = val; | ||||
420 | iv->extend = IV_UNKNOWN_EXTEND; | ||||
421 | iv->mode = iv->extend_mode = mode; | ||||
422 | iv->delta = const0_rtx(const_int_rtx[64]); | ||||
423 | iv->mult = const1_rtx(const_int_rtx[64 +1]); | ||||
424 | return true; | ||||
425 | } | ||||
426 | |||||
427 | if (iv->extend_mode == mode) | ||||
428 | return true; | ||||
429 | |||||
430 | if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode)) | ||||
431 | return false; | ||||
432 | |||||
433 | iv->extend = IV_UNKNOWN_EXTEND; | ||||
434 | iv->mode = mode; | ||||
435 | |||||
436 | iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta, | ||||
437 | simplify_gen_binary (MULT, iv->extend_mode, | ||||
438 | iv->base, iv->mult)); | ||||
439 | iv->step = simplify_gen_binary (MULT, iv->extend_mode, iv->step, iv->mult); | ||||
440 | iv->mult = const1_rtx(const_int_rtx[64 +1]); | ||||
441 | iv->delta = const0_rtx(const_int_rtx[64]); | ||||
442 | iv->first_special = false; | ||||
443 | |||||
444 | return true; | ||||
445 | } | ||||
446 | |||||
447 | /* Evaluates application of EXTEND to MODE on IV. */ | ||||
448 | |||||
449 | static bool | ||||
450 | iv_extend (class rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) | ||||
451 | { | ||||
452 | /* If iv is invariant, just calculate the new value. */ | ||||
453 | if (iv->step == const0_rtx(const_int_rtx[64]) | ||||
454 | && !iv->first_special) | ||||
455 | { | ||||
456 | rtx val = get_iv_value (iv, const0_rtx(const_int_rtx[64])); | ||||
457 | if (iv->extend_mode != iv->mode | ||||
458 | && iv->extend != IV_UNKNOWN_EXTEND | ||||
459 | && iv->extend != extend) | ||||
460 | val = lowpart_subreg (iv->mode, val, iv->extend_mode); | ||||
461 | val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode, | ||||
462 | val, | ||||
463 | iv->extend == extend | ||||
464 | ? iv->extend_mode : iv->mode); | ||||
465 | iv->base = val; | ||||
466 | iv->extend = IV_UNKNOWN_EXTEND; | ||||
467 | iv->mode = iv->extend_mode = mode; | ||||
468 | iv->delta = const0_rtx(const_int_rtx[64]); | ||||
469 | iv->mult = const1_rtx(const_int_rtx[64 +1]); | ||||
470 | return true; | ||||
471 | } | ||||
472 | |||||
473 | if (mode != iv->extend_mode) | ||||
474 | return false; | ||||
475 | |||||
476 | if (iv->extend != IV_UNKNOWN_EXTEND | ||||
477 | && iv->extend != extend) | ||||
478 | return false; | ||||
479 | |||||
480 | iv->extend = extend; | ||||
481 | |||||
482 | return true; | ||||
483 | } | ||||
484 | |||||
485 | /* Evaluates negation of IV. */ | ||||
486 | |||||
487 | static bool | ||||
488 | iv_neg (class rtx_iv *iv) | ||||
489 | { | ||||
490 | if (iv->extend == IV_UNKNOWN_EXTEND) | ||||
491 | { | ||||
492 | iv->base = simplify_gen_unary (NEG, iv->extend_mode, | ||||
493 | iv->base, iv->extend_mode); | ||||
494 | iv->step = simplify_gen_unary (NEG, iv->extend_mode, | ||||
495 | iv->step, iv->extend_mode); | ||||
496 | } | ||||
497 | else | ||||
498 | { | ||||
499 | iv->delta = simplify_gen_unary (NEG, iv->extend_mode, | ||||
500 | iv->delta, iv->extend_mode); | ||||
501 | iv->mult = simplify_gen_unary (NEG, iv->extend_mode, | ||||
502 | iv->mult, iv->extend_mode); | ||||
503 | } | ||||
504 | |||||
505 | return true; | ||||
506 | } | ||||
507 | |||||
508 | /* Evaluates addition or subtraction (according to OP) of IV1 to IV0. */ | ||||
509 | |||||
510 | static bool | ||||
511 | iv_add (class rtx_iv *iv0, class rtx_iv *iv1, enum rtx_code op) | ||||
512 | { | ||||
513 | scalar_int_mode mode; | ||||
514 | rtx arg; | ||||
515 | |||||
516 | /* Extend the constant to extend_mode of the other operand if necessary. */ | ||||
517 | if (iv0->extend == IV_UNKNOWN_EXTEND | ||||
518 | && iv0->mode == iv0->extend_mode | ||||
519 | && iv0->step == const0_rtx(const_int_rtx[64]) | ||||
520 | && GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode)) | ||||
521 | { | ||||
522 | iv0->extend_mode = iv1->extend_mode; | ||||
523 | iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode, | ||||
524 | iv0->base, iv0->mode); | ||||
525 | } | ||||
526 | if (iv1->extend == IV_UNKNOWN_EXTEND | ||||
527 | && iv1->mode == iv1->extend_mode | ||||
528 | && iv1->step == const0_rtx(const_int_rtx[64]) | ||||
529 | && GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode)) | ||||
530 | { | ||||
531 | iv1->extend_mode = iv0->extend_mode; | ||||
532 | iv1->base = simplify_gen_unary (ZERO_EXTEND, iv1->extend_mode, | ||||
533 | iv1->base, iv1->mode); | ||||
534 | } | ||||
535 | |||||
536 | mode = iv0->extend_mode; | ||||
537 | if (mode != iv1->extend_mode) | ||||
538 | return false; | ||||
539 | |||||
540 | if (iv0->extend == IV_UNKNOWN_EXTEND | ||||
541 | && iv1->extend == IV_UNKNOWN_EXTEND) | ||||
542 | { | ||||
543 | if (iv0->mode != iv1->mode) | ||||
544 | return false; | ||||
545 | |||||
546 | iv0->base = simplify_gen_binary (op, mode, iv0->base, iv1->base); | ||||
547 | iv0->step = simplify_gen_binary (op, mode, iv0->step, iv1->step); | ||||
548 | |||||
549 | return true; | ||||
550 | } | ||||
551 | |||||
552 | /* Handle addition of constant. */ | ||||
553 | if (iv1->extend == IV_UNKNOWN_EXTEND | ||||
554 | && iv1->mode == mode | ||||
555 | && iv1->step == const0_rtx(const_int_rtx[64])) | ||||
556 | { | ||||
557 | iv0->delta = simplify_gen_binary (op, mode, iv0->delta, iv1->base); | ||||
558 | return true; | ||||
559 | } | ||||
560 | |||||
561 | if (iv0->extend == IV_UNKNOWN_EXTEND | ||||
562 | && iv0->mode == mode | ||||
563 | && iv0->step == const0_rtx(const_int_rtx[64])) | ||||
564 | { | ||||
565 | arg = iv0->base; | ||||
566 | *iv0 = *iv1; | ||||
567 | if (op == MINUS | ||||
568 | && !iv_neg (iv0)) | ||||
569 | return false; | ||||
570 | |||||
571 | iv0->delta = simplify_gen_binary (PLUS, mode, iv0->delta, arg); | ||||
572 | return true; | ||||
573 | } | ||||
574 | |||||
575 | return false; | ||||
576 | } | ||||
577 | |||||
578 | /* Evaluates multiplication of IV by constant CST. */ | ||||
579 | |||||
580 | static bool | ||||
581 | iv_mult (class rtx_iv *iv, rtx mby) | ||||
582 | { | ||||
583 | scalar_int_mode mode = iv->extend_mode; | ||||
584 | |||||
585 | if (GET_MODE (mby)((machine_mode) (mby)->mode) != VOIDmode((void) 0, E_VOIDmode) | ||||
586 | && GET_MODE (mby)((machine_mode) (mby)->mode) != mode) | ||||
587 | return false; | ||||
588 | |||||
589 | if (iv->extend == IV_UNKNOWN_EXTEND) | ||||
590 | { | ||||
591 | iv->base = simplify_gen_binary (MULT, mode, iv->base, mby); | ||||
592 | iv->step = simplify_gen_binary (MULT, mode, iv->step, mby); | ||||
593 | } | ||||
594 | else | ||||
595 | { | ||||
596 | iv->delta = simplify_gen_binary (MULT, mode, iv->delta, mby); | ||||
597 | iv->mult = simplify_gen_binary (MULT, mode, iv->mult, mby); | ||||
598 | } | ||||
599 | |||||
600 | return true; | ||||
601 | } | ||||
602 | |||||
603 | /* Evaluates shift of IV by constant CST. */ | ||||
604 | |||||
605 | static bool | ||||
606 | iv_shift (class rtx_iv *iv, rtx mby) | ||||
607 | { | ||||
608 | scalar_int_mode mode = iv->extend_mode; | ||||
609 | |||||
610 | if (GET_MODE (mby)((machine_mode) (mby)->mode) != VOIDmode((void) 0, E_VOIDmode) | ||||
611 | && GET_MODE (mby)((machine_mode) (mby)->mode) != mode) | ||||
612 | return false; | ||||
613 | |||||
614 | if (iv->extend == IV_UNKNOWN_EXTEND) | ||||
615 | { | ||||
616 | iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby); | ||||
617 | iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby); | ||||
618 | } | ||||
619 | else | ||||
620 | { | ||||
621 | iv->delta = simplify_gen_binary (ASHIFT, mode, iv->delta, mby); | ||||
622 | iv->mult = simplify_gen_binary (ASHIFT, mode, iv->mult, mby); | ||||
623 | } | ||||
624 | |||||
625 | return true; | ||||
626 | } | ||||
627 | |||||
628 | /* The recursive part of get_biv_step. Gets the value of the single value | ||||
629 | defined by DEF wrto initial value of REG inside loop, in shape described | ||||
630 | at get_biv_step. */ | ||||
631 | |||||
632 | static bool | ||||
633 | get_biv_step_1 (df_ref def, scalar_int_mode outer_mode, rtx reg, | ||||
634 | rtx *inner_step, scalar_int_mode *inner_mode, | ||||
635 | enum iv_extend_code *extend, | ||||
636 | rtx *outer_step) | ||||
637 | { | ||||
638 | rtx set, rhs, op0 = NULL_RTX(rtx) 0, op1 = NULL_RTX(rtx) 0; | ||||
639 | rtx next, nextr; | ||||
640 | enum rtx_code code; | ||||
641 | rtx_insn *insn = DF_REF_INSN (def)((def)->base.insn_info->insn); | ||||
642 | df_ref next_def; | ||||
643 | enum iv_grd_result res; | ||||
644 | |||||
645 | set = single_set (insn); | ||||
646 | if (!set) | ||||
647 | return false; | ||||
648 | |||||
649 | rhs = find_reg_equal_equiv_note (insn); | ||||
650 | if (rhs) | ||||
651 | rhs = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
652 | else | ||||
653 | rhs = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||
654 | |||||
655 | code = GET_CODE (rhs)((enum rtx_code) (rhs)->code); | ||||
656 | switch (code) | ||||
657 | { | ||||
658 | case SUBREG: | ||||
659 | case REG: | ||||
660 | next = rhs; | ||||
661 | break; | ||||
662 | |||||
663 | case PLUS: | ||||
664 | case MINUS: | ||||
665 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
666 | op1 = XEXP (rhs, 1)(((rhs)->u.fld[1]).rt_rtx); | ||||
667 | |||||
668 | if (code == PLUS && CONSTANT_P (op0)((rtx_class[(int) (((enum rtx_code) (op0)->code))]) == RTX_CONST_OBJ )) | ||||
669 | std::swap (op0, op1); | ||||
670 | |||||
671 | if (!simple_reg_p (op0) | ||||
672 | || !CONSTANT_P (op1)((rtx_class[(int) (((enum rtx_code) (op1)->code))]) == RTX_CONST_OBJ )) | ||||
673 | return false; | ||||
674 | |||||
675 | if (GET_MODE (rhs)((machine_mode) (rhs)->mode) != outer_mode) | ||||
676 | { | ||||
677 | /* ppc64 uses expressions like | ||||
678 | |||||
679 | (set x:SI (plus:SI (subreg:SI y:DI) 1)). | ||||
680 | |||||
681 | this is equivalent to | ||||
682 | |||||
683 | (set x':DI (plus:DI y:DI 1)) | ||||
684 | (set x:SI (subreg:SI (x':DI)). */ | ||||
685 | if (GET_CODE (op0)((enum rtx_code) (op0)->code) != SUBREG) | ||||
686 | return false; | ||||
687 | if (GET_MODE (SUBREG_REG (op0))((machine_mode) ((((op0)->u.fld[0]).rt_rtx))->mode) != outer_mode) | ||||
688 | return false; | ||||
689 | } | ||||
690 | |||||
691 | next = op0; | ||||
692 | break; | ||||
693 | |||||
694 | case SIGN_EXTEND: | ||||
695 | case ZERO_EXTEND: | ||||
696 | if (GET_MODE (rhs)((machine_mode) (rhs)->mode) != outer_mode) | ||||
697 | return false; | ||||
698 | |||||
699 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
700 | if (!simple_reg_p (op0)) | ||||
701 | return false; | ||||
702 | |||||
703 | next = op0; | ||||
704 | break; | ||||
705 | |||||
706 | default: | ||||
707 | return false; | ||||
708 | } | ||||
709 | |||||
710 | if (GET_CODE (next)((enum rtx_code) (next)->code) == SUBREG) | ||||
711 | { | ||||
712 | if (!subreg_lowpart_p (next)) | ||||
713 | return false; | ||||
714 | |||||
715 | nextr = SUBREG_REG (next)(((next)->u.fld[0]).rt_rtx); | ||||
716 | if (GET_MODE (nextr)((machine_mode) (nextr)->mode) != outer_mode) | ||||
717 | return false; | ||||
718 | } | ||||
719 | else | ||||
720 | nextr = next; | ||||
721 | |||||
722 | res = iv_get_reaching_def (insn, nextr, &next_def); | ||||
723 | |||||
724 | if (res == GRD_INVALID || res == GRD_INVARIANT) | ||||
725 | return false; | ||||
726 | |||||
727 | if (res == GRD_MAYBE_BIV) | ||||
728 | { | ||||
729 | if (!rtx_equal_p (nextr, reg)) | ||||
730 | return false; | ||||
731 | |||||
732 | *inner_step = const0_rtx(const_int_rtx[64]); | ||||
733 | *extend = IV_UNKNOWN_EXTEND; | ||||
734 | *inner_mode = outer_mode; | ||||
735 | *outer_step = const0_rtx(const_int_rtx[64]); | ||||
736 | } | ||||
737 | else if (!get_biv_step_1 (next_def, outer_mode, reg, | ||||
738 | inner_step, inner_mode, extend, | ||||
739 | outer_step)) | ||||
740 | return false; | ||||
741 | |||||
742 | if (GET_CODE (next)((enum rtx_code) (next)->code) == SUBREG) | ||||
743 | { | ||||
744 | scalar_int_mode amode; | ||||
745 | if (!is_a <scalar_int_mode> (GET_MODE (next)((machine_mode) (next)->mode), &amode) | ||||
746 | || GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode)) | ||||
747 | return false; | ||||
748 | |||||
749 | *inner_mode = amode; | ||||
750 | *inner_step = simplify_gen_binary (PLUS, outer_mode, | ||||
751 | *inner_step, *outer_step); | ||||
752 | *outer_step = const0_rtx(const_int_rtx[64]); | ||||
753 | *extend = IV_UNKNOWN_EXTEND; | ||||
754 | } | ||||
755 | |||||
756 | switch (code) | ||||
757 | { | ||||
758 | case REG: | ||||
759 | case SUBREG: | ||||
760 | break; | ||||
761 | |||||
762 | case PLUS: | ||||
763 | case MINUS: | ||||
764 | if (*inner_mode == outer_mode | ||||
765 | /* See comment in previous switch. */ | ||||
766 | || GET_MODE (rhs)((machine_mode) (rhs)->mode) != outer_mode) | ||||
767 | *inner_step = simplify_gen_binary (code, outer_mode, | ||||
768 | *inner_step, op1); | ||||
769 | else | ||||
770 | *outer_step = simplify_gen_binary (code, outer_mode, | ||||
771 | *outer_step, op1); | ||||
772 | break; | ||||
773 | |||||
774 | case SIGN_EXTEND: | ||||
775 | case ZERO_EXTEND: | ||||
776 | gcc_assert (GET_MODE (op0) == *inner_mode((void)(!(((machine_mode) (op0)->mode) == *inner_mode && *extend == IV_UNKNOWN_EXTEND && *outer_step == (const_int_rtx [64])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 778, __FUNCTION__), 0 : 0)) | ||||
777 | && *extend == IV_UNKNOWN_EXTEND((void)(!(((machine_mode) (op0)->mode) == *inner_mode && *extend == IV_UNKNOWN_EXTEND && *outer_step == (const_int_rtx [64])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 778, __FUNCTION__), 0 : 0)) | ||||
778 | && *outer_step == const0_rtx)((void)(!(((machine_mode) (op0)->mode) == *inner_mode && *extend == IV_UNKNOWN_EXTEND && *outer_step == (const_int_rtx [64])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 778, __FUNCTION__), 0 : 0)); | ||||
779 | |||||
780 | *extend = (code == SIGN_EXTEND) ? IV_SIGN_EXTEND : IV_ZERO_EXTEND; | ||||
781 | break; | ||||
782 | |||||
783 | default: | ||||
784 | return false; | ||||
785 | } | ||||
786 | |||||
787 | return true; | ||||
788 | } | ||||
789 | |||||
790 | /* Gets the operation on register REG inside loop, in shape | ||||
791 | |||||
792 | OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP)) | ||||
793 | |||||
794 | If the operation cannot be described in this shape, return false. | ||||
795 | LAST_DEF is the definition of REG that dominates loop latch. */ | ||||
796 | |||||
797 | static bool | ||||
798 | get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg, | ||||
799 | rtx *inner_step, scalar_int_mode *inner_mode, | ||||
800 | enum iv_extend_code *extend, rtx *outer_step) | ||||
801 | { | ||||
802 | if (!get_biv_step_1 (last_def, outer_mode, reg, | ||||
803 | inner_step, inner_mode, extend, | ||||
804 | outer_step)) | ||||
805 | return false; | ||||
806 | |||||
807 | gcc_assert ((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND))((void)(!((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 807, __FUNCTION__), 0 : 0)); | ||||
808 | gcc_assert (*inner_mode != outer_mode || *outer_step == const0_rtx)((void)(!(*inner_mode != outer_mode || *outer_step == (const_int_rtx [64])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 808, __FUNCTION__), 0 : 0)); | ||||
809 | |||||
810 | return true; | ||||
811 | } | ||||
812 | |||||
813 | /* Records information that DEF is induction variable IV. */ | ||||
814 | |||||
815 | static void | ||||
816 | record_iv (df_ref def, class rtx_iv *iv) | ||||
817 | { | ||||
818 | class rtx_iv *recorded_iv = XNEW (class rtx_iv)((class rtx_iv *) xmalloc (sizeof (class rtx_iv))); | ||||
819 | |||||
820 | *recorded_iv = *iv; | ||||
821 | check_iv_ref_table_size (); | ||||
822 | DF_REF_IV_SET (def, recorded_iv)iv_ref_table[((def)->base.id)] = (recorded_iv); | ||||
823 | } | ||||
824 | |||||
825 | /* If DEF was already analyzed for bivness, store the description of the biv to | ||||
826 | IV and return true. Otherwise return false. */ | ||||
827 | |||||
828 | static bool | ||||
829 | analyzed_for_bivness_p (rtx def, class rtx_iv *iv) | ||||
830 | { | ||||
831 | class biv_entry *biv = bivs->find_with_hash (def, REGNO (def)(rhs_regno(def))); | ||||
832 | |||||
833 | if (!biv) | ||||
834 | return false; | ||||
835 | |||||
836 | *iv = biv->iv; | ||||
837 | return true; | ||||
838 | } | ||||
839 | |||||
840 | static void | ||||
841 | record_biv (rtx def, class rtx_iv *iv) | ||||
842 | { | ||||
843 | class biv_entry *biv = XNEW (class biv_entry)((class biv_entry *) xmalloc (sizeof (class biv_entry))); | ||||
844 | biv_entry **slot = bivs->find_slot_with_hash (def, REGNO (def)(rhs_regno(def)), INSERT); | ||||
845 | |||||
846 | biv->regno = REGNO (def)(rhs_regno(def)); | ||||
847 | biv->iv = *iv; | ||||
848 | gcc_assert (!*slot)((void)(!(!*slot) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 848, __FUNCTION__), 0 : 0)); | ||||
849 | *slot = biv; | ||||
850 | } | ||||
851 | |||||
852 | /* Determines whether DEF is a biv and if so, stores its description | ||||
853 | to *IV. OUTER_MODE is the mode of DEF. */ | ||||
854 | |||||
855 | static bool | ||||
856 | iv_analyze_biv (scalar_int_mode outer_mode, rtx def, class rtx_iv *iv) | ||||
857 | { | ||||
858 | rtx inner_step, outer_step; | ||||
859 | scalar_int_mode inner_mode; | ||||
860 | enum iv_extend_code extend; | ||||
861 | df_ref last_def; | ||||
862 | |||||
863 | if (dump_file) | ||||
864 | { | ||||
865 | fprintf (dump_file, "Analyzing "); | ||||
866 | print_rtl (dump_file, def); | ||||
867 | fprintf (dump_file, " for bivness.\n"); | ||||
868 | } | ||||
869 | |||||
870 | if (!REG_P (def)(((enum rtx_code) (def)->code) == REG)) | ||||
871 | { | ||||
872 | if (!CONSTANT_P (def)((rtx_class[(int) (((enum rtx_code) (def)->code))]) == RTX_CONST_OBJ )) | ||||
873 | return false; | ||||
874 | |||||
875 | return iv_constant (iv, outer_mode, def); | ||||
876 | } | ||||
877 | |||||
878 | if (!latch_dominating_def (def, &last_def)) | ||||
879 | { | ||||
880 | if (dump_file) | ||||
881 | fprintf (dump_file, " not simple.\n"); | ||||
882 | return false; | ||||
883 | } | ||||
884 | |||||
885 | if (!last_def) | ||||
886 | return iv_constant (iv, outer_mode, def); | ||||
887 | |||||
888 | if (analyzed_for_bivness_p (def, iv)) | ||||
889 | { | ||||
890 | if (dump_file) | ||||
891 | fprintf (dump_file, " already analysed.\n"); | ||||
892 | return iv->base != NULL_RTX(rtx) 0; | ||||
893 | } | ||||
894 | |||||
895 | if (!get_biv_step (last_def, outer_mode, def, &inner_step, &inner_mode, | ||||
896 | &extend, &outer_step)) | ||||
897 | { | ||||
898 | iv->base = NULL_RTX(rtx) 0; | ||||
899 | goto end; | ||||
900 | } | ||||
901 | |||||
902 | /* Loop transforms base to es (base + inner_step) + outer_step, | ||||
903 | where es means extend of subreg between inner_mode and outer_mode. | ||||
904 | The corresponding induction variable is | ||||
905 | |||||
906 | es ((base - outer_step) + i * (inner_step + outer_step)) + outer_step */ | ||||
907 | |||||
908 | iv->base = simplify_gen_binary (MINUS, outer_mode, def, outer_step); | ||||
909 | iv->step = simplify_gen_binary (PLUS, outer_mode, inner_step, outer_step); | ||||
910 | iv->mode = inner_mode; | ||||
911 | iv->extend_mode = outer_mode; | ||||
912 | iv->extend = extend; | ||||
913 | iv->mult = const1_rtx(const_int_rtx[64 +1]); | ||||
914 | iv->delta = outer_step; | ||||
915 | iv->first_special = inner_mode != outer_mode; | ||||
916 | |||||
917 | end: | ||||
918 | if (dump_file) | ||||
919 | { | ||||
920 | fprintf (dump_file, " "); | ||||
921 | dump_iv_info (dump_file, iv); | ||||
922 | fprintf (dump_file, "\n"); | ||||
923 | } | ||||
924 | |||||
925 | record_biv (def, iv); | ||||
926 | return iv->base != NULL_RTX(rtx) 0; | ||||
927 | } | ||||
928 | |||||
929 | /* Analyzes expression RHS used at INSN and stores the result to *IV. | ||||
930 | The mode of the induction variable is MODE. */ | ||||
931 | |||||
932 | bool | ||||
933 | iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs, | ||||
934 | class rtx_iv *iv) | ||||
935 | { | ||||
936 | rtx mby = NULL_RTX(rtx) 0; | ||||
937 | rtx op0 = NULL_RTX(rtx) 0, op1 = NULL_RTX(rtx) 0; | ||||
938 | class rtx_iv iv0, iv1; | ||||
939 | enum rtx_code code = GET_CODE (rhs)((enum rtx_code) (rhs)->code); | ||||
940 | scalar_int_mode omode = mode; | ||||
941 | |||||
942 | iv->base = NULL_RTX(rtx) 0; | ||||
943 | iv->step = NULL_RTX(rtx) 0; | ||||
944 | |||||
945 | gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode)((void)(!(((machine_mode) (rhs)->mode) == mode || ((machine_mode ) (rhs)->mode) == ((void) 0, E_VOIDmode)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/loop-iv.cc" , 945, __FUNCTION__), 0 : 0)); | ||||
946 | |||||
947 | if (CONSTANT_P (rhs)((rtx_class[(int) (((enum rtx_code) (rhs)->code))]) == RTX_CONST_OBJ ) | ||||
948 | || REG_P (rhs)(((enum rtx_code) (rhs)->code) == REG) | ||||
949 | || code == SUBREG) | ||||
950 | return iv_analyze_op (insn, mode, rhs, iv); | ||||
951 | |||||
952 | switch (code) | ||||
953 | { | ||||
954 | case REG: | ||||
955 | op0 = rhs; | ||||
956 | break; | ||||
957 | |||||
958 | case SIGN_EXTEND: | ||||
959 | case ZERO_EXTEND: | ||||
960 | case NEG: | ||||
961 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
962 | /* We don't know how many bits there are in a sign-extended constant. */ | ||||
963 | if (!is_a <scalar_int_mode> (GET_MODE (op0)((machine_mode) (op0)->mode), &omode)) | ||||
964 | return false; | ||||
965 | break; | ||||
966 | |||||
967 | case PLUS: | ||||
968 | case MINUS: | ||||
969 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
970 | op1 = XEXP (rhs, 1)(((rhs)->u.fld[1]).rt_rtx); | ||||
971 | break; | ||||
972 | |||||
973 | case MULT: | ||||
974 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
975 | mby = XEXP (rhs, 1)(((rhs)->u.fld[1]).rt_rtx); | ||||
976 | if (!CONSTANT_P (mby)((rtx_class[(int) (((enum rtx_code) (mby)->code))]) == RTX_CONST_OBJ )) | ||||
977 | std::swap (op0, mby); | ||||
978 | if (!CONSTANT_P (mby)((rtx_class[(int) (((enum rtx_code) (mby)->code))]) == RTX_CONST_OBJ )) | ||||
979 | return false; | ||||
980 | break; | ||||
981 | |||||
982 | case ASHIFT: | ||||
983 | op0 = XEXP (rhs, 0)(((rhs)->u.fld[0]).rt_rtx); | ||||
984 | mby = XEXP (rhs, 1)(((rhs)->u.fld[1]).rt_rtx); | ||||
985 | if (!CONSTANT_P (mby)((rtx_class[(int) (((enum rtx_code) (mby)->code))]) == RTX_CONST_OBJ )) | ||||
986 | return false; | ||||
987 | break; | ||||
988 | |||||
989 | default: | ||||
990 | return false; | ||||
991 | } | ||||
992 | |||||
993 | if (op0 | ||||
994 | && !iv_analyze_expr (insn, omode, op0, &iv0)) | ||||
995 | return false; | ||||
996 | |||||
997 | if (op1
|
27.1 | 'op1' is null |
9.1 | 'set' is non-null |
9.1 | 'set' is non-null |
1 | Assuming 'adef' is non-null |
1 | /* Machine mode definitions for GCC; included by rtl.h and tree.h. | |||
2 | Copyright (C) 1991-2023 Free Software Foundation, Inc. | |||
3 | ||||
4 | This file is part of GCC. | |||
5 | ||||
6 | GCC is free software; you can redistribute it and/or modify it under | |||
7 | the terms of the GNU General Public License as published by the Free | |||
8 | Software Foundation; either version 3, or (at your option) any later | |||
9 | version. | |||
10 | ||||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |||
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
14 | for more details. | |||
15 | ||||
16 | You should have received a copy of the GNU General Public License | |||
17 | along with GCC; see the file COPYING3. If not see | |||
18 | <http://www.gnu.org/licenses/>. */ | |||
19 | ||||
20 | #ifndef HAVE_MACHINE_MODES | |||
21 | #define HAVE_MACHINE_MODES | |||
22 | ||||
23 | typedef opt_mode<machine_mode> opt_machine_mode; | |||
24 | ||||
25 | extern CONST_MODE_SIZE poly_uint16_pod mode_size[NUM_MACHINE_MODES]; | |||
26 | extern CONST_MODE_PRECISIONconst poly_uint16_pod mode_precision[NUM_MACHINE_MODES]; | |||
27 | extern const unsigned char mode_inner[NUM_MACHINE_MODES]; | |||
28 | extern CONST_MODE_NUNITSconst poly_uint16_pod mode_nunits[NUM_MACHINE_MODES]; | |||
29 | extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES]; | |||
30 | extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES]; | |||
31 | extern const unsigned char mode_next[NUM_MACHINE_MODES]; | |||
32 | extern const unsigned char mode_wider[NUM_MACHINE_MODES]; | |||
33 | extern const unsigned char mode_2xwider[NUM_MACHINE_MODES]; | |||
34 | ||||
35 | template<typename T> | |||
36 | struct mode_traits | |||
37 | { | |||
38 | /* For use by the machmode support code only. | |||
39 | ||||
40 | There are cases in which the machmode support code needs to forcibly | |||
41 | convert a machine_mode to a specific mode class T, and in which the | |||
42 | context guarantees that this is valid without the need for an assert. | |||
43 | This can be done using: | |||
44 | ||||
45 | return typename mode_traits<T>::from_int (mode); | |||
46 | ||||
47 | when returning a T and: | |||
48 | ||||
49 | res = T (typename mode_traits<T>::from_int (mode)); | |||
50 | ||||
51 | when assigning to a value RES that must be assignment-compatible | |||
52 | with (but possibly not the same as) T. */ | |||
53 | #ifdef USE_ENUM_MODES | |||
54 | /* Allow direct conversion of enums to specific mode classes only | |||
55 | when USE_ENUM_MODES is defined. This is only intended for use | |||
56 | by gencondmd, so that it can tell more easily when .md conditions | |||
57 | are always false. */ | |||
58 | typedef machine_mode from_int; | |||
59 | #else | |||
60 | /* Here we use an enum type distinct from machine_mode but with the | |||
61 | same range as machine_mode. T should have a constructor that | |||
62 | accepts this enum type; it should not have a constructor that | |||
63 | accepts machine_mode. | |||
64 | ||||
65 | We use this somewhat indirect approach to avoid too many constructor | |||
66 | calls when the compiler is built with -O0. For example, even in | |||
67 | unoptimized code, the return statement above would construct the | |||
68 | returned T directly from the numerical value of MODE. */ | |||
69 | enum from_int { dummy = MAX_MACHINE_MODE }; | |||
70 | #endif | |||
71 | }; | |||
72 | ||||
73 | template<> | |||
74 | struct mode_traits<machine_mode> | |||
75 | { | |||
76 | /* machine_mode itself needs no conversion. */ | |||
77 | typedef machine_mode from_int; | |||
78 | }; | |||
79 | ||||
80 | /* Always treat machine modes as fixed-size while compiling code specific | |||
81 | to targets that have no variable-size modes. */ | |||
82 | #if defined (IN_TARGET_CODE) && NUM_POLY_INT_COEFFS1 == 1 | |||
83 | #define ONLY_FIXED_SIZE_MODES0 1 | |||
84 | #else | |||
85 | #define ONLY_FIXED_SIZE_MODES0 0 | |||
86 | #endif | |||
87 | ||||
88 | /* Get the name of mode MODE as a string. */ | |||
89 | ||||
90 | extern const char * const mode_name[NUM_MACHINE_MODES]; | |||
91 | #define GET_MODE_NAME(MODE)mode_name[MODE] mode_name[MODE] | |||
92 | ||||
93 | /* Mode classes. */ | |||
94 | ||||
95 | #include "mode-classes.def" | |||
96 | #define DEF_MODE_CLASS(M) M | |||
97 | enum mode_class { MODE_CLASSES, MAX_MODE_CLASS }; | |||
98 | #undef DEF_MODE_CLASS | |||
99 | #undef MODE_CLASSES | |||
100 | ||||
101 | /* Get the general kind of object that mode MODE represents | |||
102 | (integer, floating, complex, etc.) */ | |||
103 | ||||
104 | extern const unsigned char mode_class[NUM_MACHINE_MODES]; | |||
105 | #define GET_MODE_CLASS(MODE)((enum mode_class) mode_class[MODE]) ((enum mode_class) mode_class[MODE]) | |||
106 | ||||
107 | /* Nonzero if MODE is an integral mode. */ | |||
108 | #define INTEGRAL_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_INT || ((enum mode_class ) mode_class[MODE]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [MODE]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ MODE]) == MODE_VECTOR_INT) \ | |||
109 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_INT \ | |||
110 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_PARTIAL_INT \ | |||
111 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_INT \ | |||
112 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_BOOL \ | |||
113 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_INT) | |||
114 | ||||
115 | /* Nonzero if MODE is a floating-point mode. */ | |||
116 | #define FLOAT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_FLOAT || ((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FLOAT) \ | |||
117 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_FLOAT \ | |||
118 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT \ | |||
119 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_FLOAT \ | |||
120 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FLOAT) | |||
121 | ||||
122 | /* Nonzero if MODE is a complex mode. */ | |||
123 | #define COMPLEX_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_INT || ( (enum mode_class) mode_class[MODE]) == MODE_COMPLEX_FLOAT) \ | |||
124 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_INT \ | |||
125 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_COMPLEX_FLOAT) | |||
126 | ||||
127 | /* Nonzero if MODE is a vector mode. */ | |||
128 | #define VECTOR_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_VECTOR_BOOL || ( (enum mode_class) mode_class[MODE]) == MODE_VECTOR_INT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FLOAT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM) \ | |||
129 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_BOOL \ | |||
130 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_INT \ | |||
131 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FLOAT \ | |||
132 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT \ | |||
133 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT \ | |||
134 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM \ | |||
135 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM) | |||
136 | ||||
137 | /* Nonzero if MODE is a scalar integral mode. */ | |||
138 | #define SCALAR_INT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_INT || ((enum mode_class ) mode_class[MODE]) == MODE_PARTIAL_INT) \ | |||
139 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_INT \ | |||
140 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_PARTIAL_INT) | |||
141 | ||||
142 | /* Nonzero if MODE is a scalar floating point mode. */ | |||
143 | #define SCALAR_FLOAT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_FLOAT || ((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT) \ | |||
144 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_FLOAT \ | |||
145 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT) | |||
146 | ||||
147 | /* Nonzero if MODE is a decimal floating point mode. */ | |||
148 | #define DECIMAL_FLOAT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT) \ | |||
149 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_DECIMAL_FLOAT) | |||
150 | ||||
151 | /* Nonzero if MODE is a scalar fract mode. */ | |||
152 | #define SCALAR_FRACT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT) \ | |||
153 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_FRACT) | |||
154 | ||||
155 | /* Nonzero if MODE is a scalar ufract mode. */ | |||
156 | #define SCALAR_UFRACT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT) \ | |||
157 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_UFRACT) | |||
158 | ||||
159 | /* Nonzero if MODE is a scalar fract or ufract mode. */ | |||
160 | #define ALL_SCALAR_FRACT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_UFRACT)) \ | |||
161 | (SCALAR_FRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT) || SCALAR_UFRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT)) | |||
162 | ||||
163 | /* Nonzero if MODE is a scalar accum mode. */ | |||
164 | #define SCALAR_ACCUM_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM) \ | |||
165 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_ACCUM) | |||
166 | ||||
167 | /* Nonzero if MODE is a scalar uaccum mode. */ | |||
168 | #define SCALAR_UACCUM_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM) \ | |||
169 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_UACCUM) | |||
170 | ||||
171 | /* Nonzero if MODE is a scalar accum or uaccum mode. */ | |||
172 | #define ALL_SCALAR_ACCUM_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_ACCUM) || (((enum mode_class) mode_class[MODE]) == MODE_UACCUM)) \ | |||
173 | (SCALAR_ACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM) || SCALAR_UACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM)) | |||
174 | ||||
175 | /* Nonzero if MODE is a scalar fract or accum mode. */ | |||
176 | #define SIGNED_SCALAR_FIXED_POINT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_ACCUM)) \ | |||
177 | (SCALAR_FRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT) || SCALAR_ACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM)) | |||
178 | ||||
179 | /* Nonzero if MODE is a scalar ufract or uaccum mode. */ | |||
180 | #define UNSIGNED_SCALAR_FIXED_POINT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_UFRACT) || ((( enum mode_class) mode_class[MODE]) == MODE_UACCUM)) \ | |||
181 | (SCALAR_UFRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT) || SCALAR_UACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM)) | |||
182 | ||||
183 | /* Nonzero if MODE is a scalar fract, ufract, accum or uaccum mode. */ | |||
184 | #define ALL_SCALAR_FIXED_POINT_MODE_P(MODE)(((((enum mode_class) mode_class[MODE]) == MODE_FRACT) || ((( enum mode_class) mode_class[MODE]) == MODE_ACCUM)) || ((((enum mode_class) mode_class[MODE]) == MODE_UFRACT) || (((enum mode_class ) mode_class[MODE]) == MODE_UACCUM))) \ | |||
185 | (SIGNED_SCALAR_FIXED_POINT_MODE_P (MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_ACCUM)) \ | |||
186 | || UNSIGNED_SCALAR_FIXED_POINT_MODE_P (MODE)((((enum mode_class) mode_class[MODE]) == MODE_UFRACT) || ((( enum mode_class) mode_class[MODE]) == MODE_UACCUM))) | |||
187 | ||||
188 | /* Nonzero if MODE is a scalar/vector fract mode. */ | |||
189 | #define FRACT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) \ | |||
190 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_FRACT \ | |||
191 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) | |||
192 | ||||
193 | /* Nonzero if MODE is a scalar/vector ufract mode. */ | |||
194 | #define UFRACT_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT) \ | |||
195 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_UFRACT \ | |||
196 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT) | |||
197 | ||||
198 | /* Nonzero if MODE is a scalar/vector fract or ufract mode. */ | |||
199 | #define ALL_FRACT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_UFRACT)) \ | |||
200 | (FRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || UFRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT)) | |||
201 | ||||
202 | /* Nonzero if MODE is a scalar/vector accum mode. */ | |||
203 | #define ACCUM_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM) \ | |||
204 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_ACCUM \ | |||
205 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM) | |||
206 | ||||
207 | /* Nonzero if MODE is a scalar/vector uaccum mode. */ | |||
208 | #define UACCUM_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM) \ | |||
209 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_UACCUM \ | |||
210 | || GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM) | |||
211 | ||||
212 | /* Nonzero if MODE is a scalar/vector accum or uaccum mode. */ | |||
213 | #define ALL_ACCUM_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM) || (((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_UACCUM)) \ | |||
214 | (ACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM) || UACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM)) | |||
215 | ||||
216 | /* Nonzero if MODE is a scalar/vector fract or accum mode. */ | |||
217 | #define SIGNED_FIXED_POINT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_ACCUM)) \ | |||
218 | (FRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || ACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_ACCUM)) | |||
219 | ||||
220 | /* Nonzero if MODE is a scalar/vector ufract or uaccum mode. */ | |||
221 | #define UNSIGNED_FIXED_POINT_MODE_P(MODE)((((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT) || (((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_UACCUM)) \ | |||
222 | (UFRACT_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT) || UACCUM_MODE_P (MODE)(((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UACCUM)) | |||
223 | ||||
224 | /* Nonzero if MODE is a scalar/vector fract, ufract, accum or uaccum mode. */ | |||
225 | #define ALL_FIXED_POINT_MODE_P(MODE)(((((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_ACCUM)) || ((((enum mode_class ) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class [MODE]) == MODE_VECTOR_UFRACT) || (((enum mode_class) mode_class [MODE]) == MODE_UACCUM || ((enum mode_class) mode_class[MODE] ) == MODE_VECTOR_UACCUM))) \ | |||
226 | (SIGNED_FIXED_POINT_MODE_P (MODE)((((enum mode_class) mode_class[MODE]) == MODE_FRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_FRACT) || (((enum mode_class) mode_class[MODE]) == MODE_ACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_ACCUM)) \ | |||
227 | || UNSIGNED_FIXED_POINT_MODE_P (MODE)((((enum mode_class) mode_class[MODE]) == MODE_UFRACT || ((enum mode_class) mode_class[MODE]) == MODE_VECTOR_UFRACT) || (((enum mode_class) mode_class[MODE]) == MODE_UACCUM || ((enum mode_class ) mode_class[MODE]) == MODE_VECTOR_UACCUM))) | |||
228 | ||||
229 | /* Nonzero if MODE is opaque. */ | |||
230 | #define OPAQUE_MODE_P(MODE)(((enum mode_class) mode_class[MODE]) == MODE_OPAQUE) \ | |||
231 | (GET_MODE_CLASS (MODE)((enum mode_class) mode_class[MODE]) == MODE_OPAQUE) | |||
232 | ||||
233 | /* Nonzero if CLASS modes can be widened. */ | |||
234 | #define CLASS_HAS_WIDER_MODES_P(CLASS)(CLASS == MODE_INT || CLASS == MODE_PARTIAL_INT || CLASS == MODE_FLOAT || CLASS == MODE_DECIMAL_FLOAT || CLASS == MODE_COMPLEX_FLOAT || CLASS == MODE_FRACT || CLASS == MODE_UFRACT || CLASS == MODE_ACCUM || CLASS == MODE_UACCUM) \ | |||
235 | (CLASS == MODE_INT \ | |||
236 | || CLASS == MODE_PARTIAL_INT \ | |||
237 | || CLASS == MODE_FLOAT \ | |||
238 | || CLASS == MODE_DECIMAL_FLOAT \ | |||
239 | || CLASS == MODE_COMPLEX_FLOAT \ | |||
240 | || CLASS == MODE_FRACT \ | |||
241 | || CLASS == MODE_UFRACT \ | |||
242 | || CLASS == MODE_ACCUM \ | |||
243 | || CLASS == MODE_UACCUM) | |||
244 | ||||
245 | /* An optional T (i.e. a T or nothing), where T is some form of mode class. */ | |||
246 | template<typename T> | |||
247 | class opt_mode | |||
248 | { | |||
249 | public: | |||
250 | enum from_int { dummy = MAX_MACHINE_MODE }; | |||
251 | ||||
252 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr opt_mode () : m_mode (E_VOIDmode) {} | |||
253 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr opt_mode (const T &m) : m_mode (m) {} | |||
254 | template<typename U> | |||
255 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr opt_mode (const U &m) : m_mode (T (m)) {} | |||
256 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr opt_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
257 | ||||
258 | machine_mode else_void () const; | |||
259 | machine_mode else_blk () const { return else_mode (BLKmode((void) 0, E_BLKmode)); } | |||
260 | machine_mode else_mode (machine_mode) const; | |||
261 | T require () const; | |||
262 | ||||
263 | bool exists () const; | |||
264 | template<typename U> bool exists (U *) const; | |||
265 | ||||
266 | bool operator== (const T &m) const { return m_mode == m; } | |||
267 | bool operator!= (const T &m) const { return m_mode != m; } | |||
268 | ||||
269 | private: | |||
270 | machine_mode m_mode; | |||
271 | }; | |||
272 | ||||
273 | /* If the object contains a T, return its enum value, otherwise return | |||
274 | E_VOIDmode. */ | |||
275 | ||||
276 | template<typename T> | |||
277 | ALWAYS_INLINEinline __attribute__ ((always_inline)) machine_mode | |||
278 | opt_mode<T>::else_void () const | |||
279 | { | |||
280 | return m_mode; | |||
281 | } | |||
282 | ||||
283 | /* If the T exists, return its enum value, otherwise return FALLBACK. */ | |||
284 | ||||
285 | template<typename T> | |||
286 | inline machine_mode | |||
287 | opt_mode<T>::else_mode (machine_mode fallback) const | |||
288 | { | |||
289 | return m_mode == E_VOIDmode ? fallback : m_mode; | |||
290 | } | |||
291 | ||||
292 | /* Assert that the object contains a T and return it. */ | |||
293 | ||||
294 | template<typename T> | |||
295 | inline T | |||
296 | opt_mode<T>::require () const | |||
297 | { | |||
298 | gcc_checking_assert (m_mode != E_VOIDmode)((void)(!(m_mode != E_VOIDmode) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/machmode.h" , 298, __FUNCTION__), 0 : 0)); | |||
299 | return typename mode_traits<T>::from_int (m_mode); | |||
300 | } | |||
301 | ||||
302 | /* Return true if the object contains a T rather than nothing. */ | |||
303 | ||||
304 | template<typename T> | |||
305 | ALWAYS_INLINEinline __attribute__ ((always_inline)) bool | |||
306 | opt_mode<T>::exists () const | |||
307 | { | |||
308 | return m_mode != E_VOIDmode; | |||
309 | } | |||
310 | ||||
311 | /* Return true if the object contains a T, storing it in *MODE if so. */ | |||
312 | ||||
313 | template<typename T> | |||
314 | template<typename U> | |||
315 | inline bool | |||
316 | opt_mode<T>::exists (U *mode) const | |||
317 | { | |||
318 | if (m_mode != E_VOIDmode) | |||
319 | { | |||
320 | *mode = T (typename mode_traits<T>::from_int (m_mode)); | |||
321 | return true; | |||
322 | } | |||
323 | return false; | |||
324 | } | |||
325 | ||||
326 | /* A POD version of mode class T. */ | |||
327 | ||||
328 | template<typename T> | |||
329 | struct pod_mode | |||
330 | { | |||
331 | typedef typename mode_traits<T>::from_int from_int; | |||
332 | typedef typename T::measurement_type measurement_type; | |||
333 | ||||
334 | machine_mode m_mode; | |||
335 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
336 | operator machine_mode () const { return m_mode; } | |||
337 | ||||
338 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
339 | operator T () const { return from_int (m_mode); } | |||
340 | ||||
341 | ALWAYS_INLINEinline __attribute__ ((always_inline)) pod_mode &operator = (const T &m) { m_mode = m; return *this; } | |||
342 | }; | |||
343 | ||||
344 | /* Return true if mode M has type T. */ | |||
345 | ||||
346 | template<typename T> | |||
347 | inline bool | |||
348 | is_a (machine_mode m) | |||
349 | { | |||
350 | return T::includes_p (m); | |||
351 | } | |||
352 | ||||
353 | template<typename T, typename U> | |||
354 | inline bool | |||
355 | is_a (const opt_mode<U> &m) | |||
356 | { | |||
357 | return T::includes_p (m.else_void ()); | |||
358 | } | |||
359 | ||||
360 | /* Assert that mode M has type T, and return it in that form. */ | |||
361 | ||||
362 | template<typename T> | |||
363 | inline T | |||
364 | as_a (machine_mode m) | |||
365 | { | |||
366 | gcc_checking_assert (T::includes_p (m))((void)(!(T::includes_p (m)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/machmode.h" , 366, __FUNCTION__), 0 : 0)); | |||
367 | return typename mode_traits<T>::from_int (m); | |||
368 | } | |||
369 | ||||
370 | template<typename T, typename U> | |||
371 | inline T | |||
372 | as_a (const opt_mode<U> &m) | |||
373 | { | |||
374 | return as_a <T> (m.else_void ()); | |||
375 | } | |||
376 | ||||
377 | /* Convert M to an opt_mode<T>. */ | |||
378 | ||||
379 | template<typename T> | |||
380 | inline opt_mode<T> | |||
381 | dyn_cast (machine_mode m) | |||
382 | { | |||
383 | if (T::includes_p (m)) | |||
384 | return T (typename mode_traits<T>::from_int (m)); | |||
385 | return opt_mode<T> (); | |||
386 | } | |||
387 | ||||
388 | template<typename T, typename U> | |||
389 | inline opt_mode<T> | |||
390 | dyn_cast (const opt_mode<U> &m) | |||
391 | { | |||
392 | return dyn_cast <T> (m.else_void ()); | |||
393 | } | |||
394 | ||||
395 | /* Return true if mode M has type T, storing it as a T in *RESULT | |||
396 | if so. */ | |||
397 | ||||
398 | template<typename T, typename U> | |||
399 | inline bool | |||
400 | is_a (machine_mode m, U *result) | |||
401 | { | |||
402 | if (T::includes_p (m)) | |||
403 | { | |||
404 | *result = T (typename mode_traits<T>::from_int (m)); | |||
405 | return true; | |||
406 | } | |||
407 | return false; | |||
408 | } | |||
409 | ||||
410 | /* Represents a machine mode that is known to be a SCALAR_INT_MODE_P. */ | |||
411 | class scalar_int_mode | |||
412 | { | |||
413 | public: | |||
414 | typedef mode_traits<scalar_int_mode>::from_int from_int; | |||
415 | typedef unsigned short measurement_type; | |||
416 | ||||
417 | ALWAYS_INLINEinline __attribute__ ((always_inline)) scalar_int_mode () {} | |||
418 | ||||
419 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
420 | scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
421 | ||||
422 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr operator machine_mode () const { return m_mode; } | |||
| ||||
423 | ||||
424 | static bool includes_p (machine_mode); | |||
425 | ||||
426 | protected: | |||
427 | machine_mode m_mode; | |||
428 | }; | |||
429 | ||||
430 | /* Return true if M is a scalar_int_mode. */ | |||
431 | ||||
432 | inline bool | |||
433 | scalar_int_mode::includes_p (machine_mode m) | |||
434 | { | |||
435 | return SCALAR_INT_MODE_P (m)(((enum mode_class) mode_class[m]) == MODE_INT || ((enum mode_class ) mode_class[m]) == MODE_PARTIAL_INT); | |||
436 | } | |||
437 | ||||
438 | /* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P. */ | |||
439 | class scalar_float_mode | |||
440 | { | |||
441 | public: | |||
442 | typedef mode_traits<scalar_float_mode>::from_int from_int; | |||
443 | typedef unsigned short measurement_type; | |||
444 | ||||
445 | ALWAYS_INLINEinline __attribute__ ((always_inline)) scalar_float_mode () {} | |||
446 | ||||
447 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
448 | scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
449 | ||||
450 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr operator machine_mode () const { return m_mode; } | |||
451 | ||||
452 | static bool includes_p (machine_mode); | |||
453 | ||||
454 | protected: | |||
455 | machine_mode m_mode; | |||
456 | }; | |||
457 | ||||
458 | /* Return true if M is a scalar_float_mode. */ | |||
459 | ||||
460 | inline bool | |||
461 | scalar_float_mode::includes_p (machine_mode m) | |||
462 | { | |||
463 | return SCALAR_FLOAT_MODE_P (m)(((enum mode_class) mode_class[m]) == MODE_FLOAT || ((enum mode_class ) mode_class[m]) == MODE_DECIMAL_FLOAT); | |||
464 | } | |||
465 | ||||
466 | /* Represents a machine mode that is known to be scalar. */ | |||
467 | class scalar_mode | |||
468 | { | |||
469 | public: | |||
470 | typedef mode_traits<scalar_mode>::from_int from_int; | |||
471 | typedef unsigned short measurement_type; | |||
472 | ||||
473 | ALWAYS_INLINEinline __attribute__ ((always_inline)) scalar_mode () {} | |||
474 | ||||
475 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
476 | scalar_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
477 | ||||
478 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
479 | scalar_mode (const scalar_int_mode &m) : m_mode (m) {} | |||
480 | ||||
481 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
482 | scalar_mode (const scalar_float_mode &m) : m_mode (m) {} | |||
483 | ||||
484 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
485 | scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {} | |||
486 | ||||
487 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr operator machine_mode () const { return m_mode; } | |||
488 | ||||
489 | static bool includes_p (machine_mode); | |||
490 | ||||
491 | protected: | |||
492 | machine_mode m_mode; | |||
493 | }; | |||
494 | ||||
495 | /* Return true if M represents some kind of scalar value. */ | |||
496 | ||||
497 | inline bool | |||
498 | scalar_mode::includes_p (machine_mode m) | |||
499 | { | |||
500 | switch (GET_MODE_CLASS (m)((enum mode_class) mode_class[m])) | |||
501 | { | |||
502 | case MODE_INT: | |||
503 | case MODE_PARTIAL_INT: | |||
504 | case MODE_FRACT: | |||
505 | case MODE_UFRACT: | |||
506 | case MODE_ACCUM: | |||
507 | case MODE_UACCUM: | |||
508 | case MODE_FLOAT: | |||
509 | case MODE_DECIMAL_FLOAT: | |||
510 | return true; | |||
511 | default: | |||
512 | return false; | |||
513 | } | |||
514 | } | |||
515 | ||||
516 | /* Represents a machine mode that is known to be a COMPLEX_MODE_P. */ | |||
517 | class complex_mode | |||
518 | { | |||
519 | public: | |||
520 | typedef mode_traits<complex_mode>::from_int from_int; | |||
521 | typedef unsigned short measurement_type; | |||
522 | ||||
523 | ALWAYS_INLINEinline __attribute__ ((always_inline)) complex_mode () {} | |||
524 | ||||
525 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
526 | complex_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
527 | ||||
528 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr operator machine_mode () const { return m_mode; } | |||
529 | ||||
530 | static bool includes_p (machine_mode); | |||
531 | ||||
532 | protected: | |||
533 | machine_mode m_mode; | |||
534 | }; | |||
535 | ||||
536 | /* Return true if M is a complex_mode. */ | |||
537 | ||||
538 | inline bool | |||
539 | complex_mode::includes_p (machine_mode m) | |||
540 | { | |||
541 | return COMPLEX_MODE_P (m)(((enum mode_class) mode_class[m]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class[m]) == MODE_COMPLEX_FLOAT); | |||
542 | } | |||
543 | ||||
544 | /* Return the base GET_MODE_SIZE value for MODE. */ | |||
545 | ||||
546 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
547 | mode_to_bytes (machine_mode mode) | |||
548 | { | |||
549 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
550 | return (__builtin_constant_p (mode) | |||
551 | ? mode_size_inline (mode) : mode_size[mode]); | |||
552 | #else | |||
553 | return mode_size[mode]; | |||
554 | #endif | |||
555 | } | |||
556 | ||||
557 | /* Return the base GET_MODE_BITSIZE value for MODE. */ | |||
558 | ||||
559 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
560 | mode_to_bits (machine_mode mode) | |||
561 | { | |||
562 | return mode_to_bytes (mode) * BITS_PER_UNIT(8); | |||
563 | } | |||
564 | ||||
565 | /* Return the base GET_MODE_PRECISION value for MODE. */ | |||
566 | ||||
567 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
568 | mode_to_precision (machine_mode mode) | |||
569 | { | |||
570 | return mode_precision[mode]; | |||
571 | } | |||
572 | ||||
573 | /* Return the base GET_MODE_INNER value for MODE. */ | |||
574 | ||||
575 | ALWAYS_INLINEinline __attribute__ ((always_inline)) scalar_mode | |||
576 | mode_to_inner (machine_mode mode) | |||
577 | { | |||
578 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
579 | return scalar_mode::from_int (__builtin_constant_p (mode) | |||
580 | ? mode_inner_inline (mode) | |||
581 | : mode_inner[mode]); | |||
582 | #else | |||
583 | return scalar_mode::from_int (mode_inner[mode]); | |||
584 | #endif | |||
585 | } | |||
586 | ||||
587 | /* Return the base GET_MODE_UNIT_SIZE value for MODE. */ | |||
588 | ||||
589 | ALWAYS_INLINEinline __attribute__ ((always_inline)) unsigned char | |||
590 | mode_to_unit_size (machine_mode mode) | |||
591 | { | |||
592 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
593 | return (__builtin_constant_p (mode) | |||
594 | ? mode_unit_size_inline (mode) : mode_unit_size[mode]); | |||
595 | #else | |||
596 | return mode_unit_size[mode]; | |||
597 | #endif | |||
598 | } | |||
599 | ||||
600 | /* Return the base GET_MODE_UNIT_PRECISION value for MODE. */ | |||
601 | ||||
602 | ALWAYS_INLINEinline __attribute__ ((always_inline)) unsigned short | |||
603 | mode_to_unit_precision (machine_mode mode) | |||
604 | { | |||
605 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
606 | return (__builtin_constant_p (mode) | |||
607 | ? mode_unit_precision_inline (mode) : mode_unit_precision[mode]); | |||
608 | #else | |||
609 | return mode_unit_precision[mode]; | |||
610 | #endif | |||
611 | } | |||
612 | ||||
613 | /* Return the base GET_MODE_NUNITS value for MODE. */ | |||
614 | ||||
615 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
616 | mode_to_nunits (machine_mode mode) | |||
617 | { | |||
618 | #if GCC_VERSION(4 * 1000 + 2) >= 4001 | |||
619 | return (__builtin_constant_p (mode) | |||
620 | ? mode_nunits_inline (mode) : mode_nunits[mode]); | |||
621 | #else | |||
622 | return mode_nunits[mode]; | |||
623 | #endif | |||
624 | } | |||
625 | ||||
626 | /* Get the size in bytes of an object of mode MODE. */ | |||
627 | ||||
628 | #if ONLY_FIXED_SIZE_MODES0 | |||
629 | #define GET_MODE_SIZE(MODE) ((unsigned short) mode_to_bytes (MODE).coeffs[0]) | |||
630 | #else | |||
631 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
632 | GET_MODE_SIZE (machine_mode mode) | |||
633 | { | |||
634 | return mode_to_bytes (mode); | |||
635 | } | |||
636 | ||||
637 | template<typename T> | |||
638 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_poly<typename T::measurement_type>::type | |||
639 | GET_MODE_SIZE (const T &mode) | |||
640 | { | |||
641 | return mode_to_bytes (mode); | |||
642 | } | |||
643 | ||||
644 | template<typename T> | |||
645 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_nonpoly<typename T::measurement_type>::type | |||
646 | GET_MODE_SIZE (const T &mode) | |||
647 | { | |||
648 | return mode_to_bytes (mode).coeffs[0]; | |||
649 | } | |||
650 | #endif | |||
651 | ||||
652 | /* Get the size in bits of an object of mode MODE. */ | |||
653 | ||||
654 | #if ONLY_FIXED_SIZE_MODES0 | |||
655 | #define GET_MODE_BITSIZE(MODE) ((unsigned short) mode_to_bits (MODE).coeffs[0]) | |||
656 | #else | |||
657 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
658 | GET_MODE_BITSIZE (machine_mode mode) | |||
659 | { | |||
660 | return mode_to_bits (mode); | |||
661 | } | |||
662 | ||||
663 | template<typename T> | |||
664 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_poly<typename T::measurement_type>::type | |||
665 | GET_MODE_BITSIZE (const T &mode) | |||
666 | { | |||
667 | return mode_to_bits (mode); | |||
668 | } | |||
669 | ||||
670 | template<typename T> | |||
671 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_nonpoly<typename T::measurement_type>::type | |||
672 | GET_MODE_BITSIZE (const T &mode) | |||
673 | { | |||
674 | return mode_to_bits (mode).coeffs[0]; | |||
675 | } | |||
676 | #endif | |||
677 | ||||
678 | /* Get the number of value bits of an object of mode MODE. */ | |||
679 | ||||
680 | #if ONLY_FIXED_SIZE_MODES0 | |||
681 | #define GET_MODE_PRECISION(MODE) \ | |||
682 | ((unsigned short) mode_to_precision (MODE).coeffs[0]) | |||
683 | #else | |||
684 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
685 | GET_MODE_PRECISION (machine_mode mode) | |||
686 | { | |||
687 | return mode_to_precision (mode); | |||
688 | } | |||
689 | ||||
690 | template<typename T> | |||
691 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_poly<typename T::measurement_type>::type | |||
692 | GET_MODE_PRECISION (const T &mode) | |||
693 | { | |||
694 | return mode_to_precision (mode); | |||
695 | } | |||
696 | ||||
697 | template<typename T> | |||
698 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_nonpoly<typename T::measurement_type>::type | |||
699 | GET_MODE_PRECISION (const T &mode) | |||
700 | { | |||
701 | return mode_to_precision (mode).coeffs[0]; | |||
702 | } | |||
703 | #endif | |||
704 | ||||
705 | /* Get the number of integral bits of an object of mode MODE. */ | |||
706 | extern CONST_MODE_IBITconst unsigned char mode_ibit[NUM_MACHINE_MODES]; | |||
707 | #define GET_MODE_IBIT(MODE)mode_ibit[MODE] mode_ibit[MODE] | |||
708 | ||||
709 | /* Get the number of fractional bits of an object of mode MODE. */ | |||
710 | extern CONST_MODE_FBITconst unsigned char mode_fbit[NUM_MACHINE_MODES]; | |||
711 | #define GET_MODE_FBIT(MODE)mode_fbit[MODE] mode_fbit[MODE] | |||
712 | ||||
713 | /* Get a bitmask containing 1 for all bits in a word | |||
714 | that fit within mode MODE. */ | |||
715 | ||||
716 | extern CONST_MODE_MASKconst unsigned HOST_WIDE_INTlong | |||
717 | mode_mask_array[NUM_MACHINE_MODES]; | |||
718 | ||||
719 | #define GET_MODE_MASK(MODE)mode_mask_array[MODE] mode_mask_array[MODE] | |||
720 | ||||
721 | /* Return the mode of the basic parts of MODE. For vector modes this is the | |||
722 | mode of the vector elements. For complex modes it is the mode of the real | |||
723 | and imaginary parts. For other modes it is MODE itself. */ | |||
724 | ||||
725 | #define GET_MODE_INNER(MODE)(mode_to_inner (MODE)) (mode_to_inner (MODE)) | |||
726 | ||||
727 | /* Get the size in bytes or bits of the basic parts of an | |||
728 | object of mode MODE. */ | |||
729 | ||||
730 | #define GET_MODE_UNIT_SIZE(MODE)mode_to_unit_size (MODE) mode_to_unit_size (MODE) | |||
731 | ||||
732 | #define GET_MODE_UNIT_BITSIZE(MODE)((unsigned short) (mode_to_unit_size (MODE) * (8))) \ | |||
733 | ((unsigned short) (GET_MODE_UNIT_SIZE (MODE)mode_to_unit_size (MODE) * BITS_PER_UNIT(8))) | |||
734 | ||||
735 | #define GET_MODE_UNIT_PRECISION(MODE)(mode_to_unit_precision (MODE)) (mode_to_unit_precision (MODE)) | |||
736 | ||||
737 | /* Get the number of units in an object of mode MODE. This is 2 for | |||
738 | complex modes and the number of elements for vector modes. */ | |||
739 | ||||
740 | #if ONLY_FIXED_SIZE_MODES0 | |||
741 | #define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE).coeffs[0]) | |||
742 | #else | |||
743 | ALWAYS_INLINEinline __attribute__ ((always_inline)) poly_uint16 | |||
744 | GET_MODE_NUNITS (machine_mode mode) | |||
745 | { | |||
746 | return mode_to_nunits (mode); | |||
747 | } | |||
748 | ||||
749 | template<typename T> | |||
750 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_poly<typename T::measurement_type>::type | |||
751 | GET_MODE_NUNITS (const T &mode) | |||
752 | { | |||
753 | return mode_to_nunits (mode); | |||
754 | } | |||
755 | ||||
756 | template<typename T> | |||
757 | ALWAYS_INLINEinline __attribute__ ((always_inline)) typename if_nonpoly<typename T::measurement_type>::type | |||
758 | GET_MODE_NUNITS (const T &mode) | |||
759 | { | |||
760 | return mode_to_nunits (mode).coeffs[0]; | |||
761 | } | |||
762 | #endif | |||
763 | ||||
764 | /* Get the next natural mode (not narrower, eg, QI -> HI -> SI -> DI -> TI | |||
765 | or HF -> BF -> SF -> DF -> XF -> TF). */ | |||
766 | ||||
767 | template<typename T> | |||
768 | ALWAYS_INLINEinline __attribute__ ((always_inline)) opt_mode<T> | |||
769 | GET_MODE_NEXT_MODE (const T &m) | |||
770 | { | |||
771 | return typename opt_mode<T>::from_int (mode_next[m]); | |||
772 | } | |||
773 | ||||
774 | /* Get the next wider mode (eg, QI -> HI -> SI -> DI -> TI | |||
775 | or { HF, BF } -> SF -> DF -> XF -> TF). | |||
776 | This is similar to GET_MODE_NEXT_MODE, but while GET_MODE_NEXT_MODE | |||
777 | can include mode that have the same precision (e.g. | |||
778 | GET_MODE_NEXT_MODE (HFmode) can be BFmode even when both have the same | |||
779 | precision), this one will skip those. And always VOIDmode for | |||
780 | modes whose class is !CLASS_HAS_WIDER_MODES_P. */ | |||
781 | ||||
782 | template<typename T> | |||
783 | ALWAYS_INLINEinline __attribute__ ((always_inline)) opt_mode<T> | |||
784 | GET_MODE_WIDER_MODE (const T &m) | |||
785 | { | |||
786 | return typename opt_mode<T>::from_int (mode_wider[m]); | |||
787 | } | |||
788 | ||||
789 | /* For scalars, this is a mode with twice the precision. For vectors, | |||
790 | this is a mode with the same inner mode but with twice the elements. */ | |||
791 | ||||
792 | template<typename T> | |||
793 | ALWAYS_INLINEinline __attribute__ ((always_inline)) opt_mode<T> | |||
794 | GET_MODE_2XWIDER_MODE (const T &m) | |||
795 | { | |||
796 | return typename opt_mode<T>::from_int (mode_2xwider[m]); | |||
797 | } | |||
798 | ||||
799 | /* Get the complex mode from the component mode. */ | |||
800 | extern const unsigned char mode_complex[NUM_MACHINE_MODES]; | |||
801 | #define GET_MODE_COMPLEX_MODE(MODE)((machine_mode) mode_complex[MODE]) ((machine_mode) mode_complex[MODE]) | |||
802 | ||||
803 | /* Represents a machine mode that must have a fixed size. The main | |||
804 | use of this class is to represent the modes of objects that always | |||
805 | have static storage duration, such as constant pool entries. | |||
806 | (No current target supports the concept of variable-size static data.) */ | |||
807 | class fixed_size_mode | |||
808 | { | |||
809 | public: | |||
810 | typedef mode_traits<fixed_size_mode>::from_int from_int; | |||
811 | typedef unsigned short measurement_type; | |||
812 | ||||
813 | ALWAYS_INLINEinline __attribute__ ((always_inline)) fixed_size_mode () {} | |||
814 | ||||
815 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
816 | fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {} | |||
817 | ||||
818 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
819 | fixed_size_mode (const scalar_mode &m) : m_mode (m) {} | |||
820 | ||||
821 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
822 | fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {} | |||
823 | ||||
824 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
825 | fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {} | |||
826 | ||||
827 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
828 | fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {} | |||
829 | ||||
830 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
831 | fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {} | |||
832 | ||||
833 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr | |||
834 | fixed_size_mode (const complex_mode &m) : m_mode (m) {} | |||
835 | ||||
836 | ALWAYS_INLINEinline __attribute__ ((always_inline)) CONSTEXPRconstexpr operator machine_mode () const { return m_mode; } | |||
837 | ||||
838 | static bool includes_p (machine_mode); | |||
839 | ||||
840 | protected: | |||
841 | machine_mode m_mode; | |||
842 | }; | |||
843 | ||||
844 | /* Return true if MODE has a fixed size. */ | |||
845 | ||||
846 | inline bool | |||
847 | fixed_size_mode::includes_p (machine_mode mode) | |||
848 | { | |||
849 | return mode_to_bytes (mode).is_constant (); | |||
850 | } | |||
851 | ||||
852 | /* Wrapper for mode arguments to target macros, so that if a target | |||
853 | doesn't need polynomial-sized modes, its header file can continue | |||
854 | to treat everything as fixed_size_mode. This should go away once | |||
855 | macros are moved to target hooks. It shouldn't be used in other | |||
856 | contexts. */ | |||
857 | #if NUM_POLY_INT_COEFFS1 == 1 | |||
858 | #define MACRO_MODE(MODE)(as_a <fixed_size_mode> (MODE)) (as_a <fixed_size_mode> (MODE)) | |||
859 | #else | |||
860 | #define MACRO_MODE(MODE)(as_a <fixed_size_mode> (MODE)) (MODE) | |||
861 | #endif | |||
862 | ||||
863 | extern opt_machine_mode mode_for_size (poly_uint64, enum mode_class, int); | |||
864 | ||||
865 | /* Return the machine mode to use for a MODE_INT of SIZE bits, if one | |||
866 | exists. If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE | |||
867 | will not be used. */ | |||
868 | ||||
869 | inline opt_scalar_int_mode | |||
870 | int_mode_for_size (poly_uint64 size, int limit) | |||
871 | { | |||
872 | return dyn_cast <scalar_int_mode> (mode_for_size (size, MODE_INT, limit)); | |||
873 | } | |||
874 | ||||
875 | /* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one | |||
876 | exists. */ | |||
877 | ||||
878 | inline opt_scalar_float_mode | |||
879 | float_mode_for_size (poly_uint64 size) | |||
880 | { | |||
881 | return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0)); | |||
882 | } | |||
883 | ||||
884 | /* Likewise for MODE_DECIMAL_FLOAT. */ | |||
885 | ||||
886 | inline opt_scalar_float_mode | |||
887 | decimal_float_mode_for_size (unsigned int size) | |||
888 | { | |||
889 | return dyn_cast <scalar_float_mode> | |||
890 | (mode_for_size (size, MODE_DECIMAL_FLOAT, 0)); | |||
891 | } | |||
892 | ||||
893 | extern machine_mode smallest_mode_for_size (poly_uint64, enum mode_class); | |||
894 | ||||
895 | /* Find the narrowest integer mode that contains at least SIZE bits. | |||
896 | Such a mode must exist. */ | |||
897 | ||||
898 | inline scalar_int_mode | |||
899 | smallest_int_mode_for_size (poly_uint64 size) | |||
900 | { | |||
901 | return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT)); | |||
902 | } | |||
903 | ||||
904 | extern opt_scalar_int_mode int_mode_for_mode (machine_mode); | |||
905 | extern opt_machine_mode bitwise_mode_for_mode (machine_mode); | |||
906 | extern opt_machine_mode mode_for_vector (scalar_mode, poly_uint64); | |||
907 | extern opt_machine_mode related_vector_mode (machine_mode, scalar_mode, | |||
908 | poly_uint64 = 0); | |||
909 | extern opt_machine_mode related_int_vector_mode (machine_mode); | |||
910 | ||||
911 | /* A class for iterating through possible bitfield modes. */ | |||
912 | class bit_field_mode_iterator | |||
913 | { | |||
914 | public: | |||
915 | bit_field_mode_iterator (HOST_WIDE_INTlong, HOST_WIDE_INTlong, | |||
916 | poly_int64, poly_int64, | |||
917 | unsigned int, bool); | |||
918 | bool next_mode (scalar_int_mode *); | |||
919 | bool prefer_smaller_modes (); | |||
920 | ||||
921 | private: | |||
922 | opt_scalar_int_mode m_mode; | |||
923 | /* We use signed values here because the bit position can be negative | |||
924 | for invalid input such as gcc.dg/pr48335-8.c. */ | |||
925 | HOST_WIDE_INTlong m_bitsize; | |||
926 | HOST_WIDE_INTlong m_bitpos; | |||
927 | poly_int64 m_bitregion_start; | |||
928 | poly_int64 m_bitregion_end; | |||
929 | unsigned int m_align; | |||
930 | bool m_volatilep; | |||
931 | int m_count; | |||
932 | }; | |||
933 | ||||
934 | /* Find the best mode to use to access a bit field. */ | |||
935 | ||||
936 | extern bool get_best_mode (int, int, poly_uint64, poly_uint64, unsigned int, | |||
937 | unsigned HOST_WIDE_INTlong, bool, scalar_int_mode *); | |||
938 | ||||
939 | /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */ | |||
940 | ||||
941 | extern CONST_MODE_BASE_ALIGN unsigned short mode_base_align[NUM_MACHINE_MODES]; | |||
942 | ||||
943 | extern unsigned get_mode_alignment (machine_mode); | |||
944 | ||||
945 | #define GET_MODE_ALIGNMENT(MODE)get_mode_alignment (MODE) get_mode_alignment (MODE) | |||
946 | ||||
947 | /* For each class, get the narrowest mode in that class. */ | |||
948 | ||||
949 | extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS]; | |||
950 | #define GET_CLASS_NARROWEST_MODE(CLASS)((machine_mode) class_narrowest_mode[CLASS]) \ | |||
951 | ((machine_mode) class_narrowest_mode[CLASS]) | |||
952 | ||||
953 | /* The narrowest full integer mode available on the target. */ | |||
954 | ||||
955 | #define NARROWEST_INT_MODE(scalar_int_mode (scalar_int_mode::from_int (class_narrowest_mode [MODE_INT]))) \ | |||
956 | (scalar_int_mode \ | |||
957 | (scalar_int_mode::from_int (class_narrowest_mode[MODE_INT]))) | |||
958 | ||||
959 | /* Return the narrowest mode in T's class. */ | |||
960 | ||||
961 | template<typename T> | |||
962 | inline T | |||
963 | get_narrowest_mode (T mode) | |||
964 | { | |||
965 | return typename mode_traits<T>::from_int | |||
966 | (class_narrowest_mode[GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode])]); | |||
967 | } | |||
968 | ||||
969 | /* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD | |||
970 | and the mode whose class is Pmode and whose size is POINTER_SIZE. */ | |||
971 | ||||
972 | extern scalar_int_mode byte_mode; | |||
973 | extern scalar_int_mode word_mode; | |||
974 | extern scalar_int_mode ptr_mode; | |||
975 | ||||
976 | /* Target-dependent machine mode initialization - in insn-modes.cc. */ | |||
977 | extern void init_adjust_machine_modes (void); | |||
978 | ||||
979 | #define TRULY_NOOP_TRUNCATION_MODES_P(MODE1, MODE2)(targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), GET_MODE_PRECISION (MODE2))) \ | |||
980 | (targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), \ | |||
981 | GET_MODE_PRECISION (MODE2))) | |||
982 | ||||
983 | /* Return true if MODE is a scalar integer mode that fits in a | |||
984 | HOST_WIDE_INT. */ | |||
985 | ||||
986 | inline bool | |||
987 | HWI_COMPUTABLE_MODE_P (machine_mode mode) | |||
988 | { | |||
989 | machine_mode mme = mode; | |||
990 | return (SCALAR_INT_MODE_P (mme)(((enum mode_class) mode_class[mme]) == MODE_INT || ((enum mode_class ) mode_class[mme]) == MODE_PARTIAL_INT) | |||
991 | && mode_to_precision (mme).coeffs[0] <= HOST_BITS_PER_WIDE_INT64); | |||
992 | } | |||
993 | ||||
994 | inline bool | |||
995 | HWI_COMPUTABLE_MODE_P (scalar_int_mode mode) | |||
996 | { | |||
997 | return GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT64; | |||
998 | } | |||
999 | ||||
1000 | struct int_n_data_t { | |||
1001 | /* These parts are initailized by genmodes output */ | |||
1002 | unsigned int bitsize; | |||
1003 | scalar_int_mode_pod m; | |||
1004 | /* RID_* is RID_INTN_BASE + index into this array */ | |||
1005 | }; | |||
1006 | ||||
1007 | /* This is also in tree.h. genmodes.cc guarantees the're sorted from | |||
1008 | smallest bitsize to largest bitsize. */ | |||
1009 | extern bool int_n_enabled_p[NUM_INT_N_ENTS1]; | |||
1010 | extern const int_n_data_t int_n_data[NUM_INT_N_ENTS1]; | |||
1011 | ||||
1012 | /* Return true if MODE has class MODE_INT, storing it as a scalar_int_mode | |||
1013 | in *INT_MODE if so. */ | |||
1014 | ||||
1015 | template<typename T> | |||
1016 | inline bool | |||
1017 | is_int_mode (machine_mode mode, T *int_mode) | |||
1018 | { | |||
1019 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_INT) | |||
1020 | { | |||
1021 | *int_mode = scalar_int_mode (scalar_int_mode::from_int (mode)); | |||
1022 | return true; | |||
1023 | } | |||
1024 | return false; | |||
1025 | } | |||
1026 | ||||
1027 | /* Return true if MODE has class MODE_FLOAT, storing it as a | |||
1028 | scalar_float_mode in *FLOAT_MODE if so. */ | |||
1029 | ||||
1030 | template<typename T> | |||
1031 | inline bool | |||
1032 | is_float_mode (machine_mode mode, T *float_mode) | |||
1033 | { | |||
1034 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_FLOAT) | |||
1035 | { | |||
1036 | *float_mode = scalar_float_mode (scalar_float_mode::from_int (mode)); | |||
1037 | return true; | |||
1038 | } | |||
1039 | return false; | |||
1040 | } | |||
1041 | ||||
1042 | /* Return true if MODE has class MODE_COMPLEX_INT, storing it as | |||
1043 | a complex_mode in *CMODE if so. */ | |||
1044 | ||||
1045 | template<typename T> | |||
1046 | inline bool | |||
1047 | is_complex_int_mode (machine_mode mode, T *cmode) | |||
1048 | { | |||
1049 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT) | |||
1050 | { | |||
1051 | *cmode = complex_mode (complex_mode::from_int (mode)); | |||
1052 | return true; | |||
1053 | } | |||
1054 | return false; | |||
1055 | } | |||
1056 | ||||
1057 | /* Return true if MODE has class MODE_COMPLEX_FLOAT, storing it as | |||
1058 | a complex_mode in *CMODE if so. */ | |||
1059 | ||||
1060 | template<typename T> | |||
1061 | inline bool | |||
1062 | is_complex_float_mode (machine_mode mode, T *cmode) | |||
1063 | { | |||
1064 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT) | |||
1065 | { | |||
1066 | *cmode = complex_mode (complex_mode::from_int (mode)); | |||
1067 | return true; | |||
1068 | } | |||
1069 | return false; | |||
1070 | } | |||
1071 | ||||
1072 | /* Return true if MODE is a scalar integer mode with a precision | |||
1073 | smaller than LIMIT's precision. */ | |||
1074 | ||||
1075 | inline bool | |||
1076 | is_narrower_int_mode (machine_mode mode, scalar_int_mode limit) | |||
1077 | { | |||
1078 | scalar_int_mode int_mode; | |||
1079 | return (is_a <scalar_int_mode> (mode, &int_mode) | |||
1080 | && GET_MODE_PRECISION (int_mode) < GET_MODE_PRECISION (limit)); | |||
1081 | } | |||
1082 | ||||
1083 | namespace mode_iterator | |||
1084 | { | |||
1085 | /* Start mode iterator *ITER at the first mode in class MCLASS, if any. */ | |||
1086 | ||||
1087 | template<typename T> | |||
1088 | inline void | |||
1089 | start (opt_mode<T> *iter, enum mode_class mclass) | |||
1090 | { | |||
1091 | if (GET_CLASS_NARROWEST_MODE (mclass)((machine_mode) class_narrowest_mode[mclass]) == E_VOIDmode) | |||
1092 | *iter = opt_mode<T> (); | |||
1093 | else | |||
1094 | *iter = as_a<T> (GET_CLASS_NARROWEST_MODE (mclass)((machine_mode) class_narrowest_mode[mclass])); | |||
1095 | } | |||
1096 | ||||
1097 | inline void | |||
1098 | start (machine_mode *iter, enum mode_class mclass) | |||
1099 | { | |||
1100 | *iter = GET_CLASS_NARROWEST_MODE (mclass)((machine_mode) class_narrowest_mode[mclass]); | |||
1101 | } | |||
1102 | ||||
1103 | /* Return true if mode iterator *ITER has not reached the end. */ | |||
1104 | ||||
1105 | template<typename T> | |||
1106 | inline bool | |||
1107 | iterate_p (opt_mode<T> *iter) | |||
1108 | { | |||
1109 | return iter->exists (); | |||
1110 | } | |||
1111 | ||||
1112 | inline bool | |||
1113 | iterate_p (machine_mode *iter) | |||
1114 | { | |||
1115 | return *iter != E_VOIDmode; | |||
1116 | } | |||
1117 | ||||
1118 | /* Set mode iterator *ITER to the next mode in the same class, | |||
1119 | if any. */ | |||
1120 | ||||
1121 | template<typename T> | |||
1122 | inline void | |||
1123 | get_next (opt_mode<T> *iter) | |||
1124 | { | |||
1125 | *iter = GET_MODE_NEXT_MODE (iter->require ()); | |||
1126 | } | |||
1127 | ||||
1128 | inline void | |||
1129 | get_next (machine_mode *iter) | |||
1130 | { | |||
1131 | *iter = GET_MODE_NEXT_MODE (*iter).else_void (); | |||
1132 | } | |||
1133 | ||||
1134 | /* Set mode iterator *ITER to the next mode in the same class. | |||
1135 | Such a mode is known to exist. */ | |||
1136 | ||||
1137 | template<typename T> | |||
1138 | inline void | |||
1139 | get_known_next (T *iter) | |||
1140 | { | |||
1141 | *iter = GET_MODE_NEXT_MODE (*iter).require (); | |||
1142 | } | |||
1143 | ||||
1144 | /* Set mode iterator *ITER to the next wider mode in the same class, | |||
1145 | if any. */ | |||
1146 | ||||
1147 | template<typename T> | |||
1148 | inline void | |||
1149 | get_wider (opt_mode<T> *iter) | |||
1150 | { | |||
1151 | *iter = GET_MODE_WIDER_MODE (iter->require ()); | |||
1152 | } | |||
1153 | ||||
1154 | inline void | |||
1155 | get_wider (machine_mode *iter) | |||
1156 | { | |||
1157 | *iter = GET_MODE_WIDER_MODE (*iter).else_void (); | |||
1158 | } | |||
1159 | ||||
1160 | /* Set mode iterator *ITER to the next wider mode in the same class. | |||
1161 | Such a mode is known to exist. */ | |||
1162 | ||||
1163 | template<typename T> | |||
1164 | inline void | |||
1165 | get_known_wider (T *iter) | |||
1166 | { | |||
1167 | *iter = GET_MODE_WIDER_MODE (*iter).require (); | |||
1168 | } | |||
1169 | ||||
1170 | /* Set mode iterator *ITER to the mode that is two times wider than the | |||
1171 | current one, if such a mode exists. */ | |||
1172 | ||||
1173 | template<typename T> | |||
1174 | inline void | |||
1175 | get_2xwider (opt_mode<T> *iter) | |||
1176 | { | |||
1177 | *iter = GET_MODE_2XWIDER_MODE (iter->require ()); | |||
1178 | } | |||
1179 | ||||
1180 | inline void | |||
1181 | get_2xwider (machine_mode *iter) | |||
1182 | { | |||
1183 | *iter = GET_MODE_2XWIDER_MODE (*iter).else_void (); | |||
1184 | } | |||
1185 | } | |||
1186 | ||||
1187 | /* Make ITERATOR iterate over all the modes in mode class CLASS, | |||
1188 | from narrowest to widest. */ | |||
1189 | #define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS)for (mode_iterator::start (&(ITERATOR), CLASS); mode_iterator ::iterate_p (&(ITERATOR)); mode_iterator::get_next (& (ITERATOR))) \ | |||
1190 | for (mode_iterator::start (&(ITERATOR), CLASS); \ | |||
1191 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1192 | mode_iterator::get_next (&(ITERATOR))) | |||
1193 | ||||
1194 | /* Make ITERATOR iterate over all the modes in the range [START, END), | |||
1195 | in order of increasing width. */ | |||
1196 | #define FOR_EACH_MODE(ITERATOR, START, END)for ((ITERATOR) = (START); (ITERATOR) != (END); mode_iterator ::get_known_next (&(ITERATOR))) \ | |||
1197 | for ((ITERATOR) = (START); \ | |||
1198 | (ITERATOR) != (END); \ | |||
1199 | mode_iterator::get_known_next (&(ITERATOR))) | |||
1200 | ||||
1201 | /* Make ITERATOR iterate over START and all non-narrower modes in the same | |||
1202 | class, in order of increasing width. */ | |||
1203 | #define FOR_EACH_MODE_FROM(ITERATOR, START)for ((ITERATOR) = (START); mode_iterator::iterate_p (&(ITERATOR )); mode_iterator::get_next (&(ITERATOR))) \ | |||
1204 | for ((ITERATOR) = (START); \ | |||
1205 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1206 | mode_iterator::get_next (&(ITERATOR))) | |||
1207 | ||||
1208 | /* Make ITERATOR iterate over START and all wider modes in the same | |||
1209 | class, in order of strictly increasing width. */ | |||
1210 | #define FOR_EACH_WIDER_MODE_FROM(ITERATOR, START)for ((ITERATOR) = (START); mode_iterator::iterate_p (&(ITERATOR )); mode_iterator::get_wider (&(ITERATOR))) \ | |||
1211 | for ((ITERATOR) = (START); \ | |||
1212 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1213 | mode_iterator::get_wider (&(ITERATOR))) | |||
1214 | ||||
1215 | /* Make ITERATOR iterate over modes in the range [NARROWEST, END) | |||
1216 | in order of increasing width, where NARROWEST is the narrowest mode | |||
1217 | in END's class. */ | |||
1218 | #define FOR_EACH_MODE_UNTIL(ITERATOR, END)for ((ITERATOR) = (get_narrowest_mode (END)); (ITERATOR) != ( END); mode_iterator::get_known_next (&(ITERATOR))) \ | |||
1219 | FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)for ((ITERATOR) = (get_narrowest_mode (END)); (ITERATOR) != ( END); mode_iterator::get_known_next (&(ITERATOR))) | |||
1220 | ||||
1221 | /* Make ITERATOR iterate over modes in the same class as MODE, in order | |||
1222 | of non-decreasing width. Start at next such mode after START, | |||
1223 | or don't iterate at all if there is no such mode. */ | |||
1224 | #define FOR_EACH_NEXT_MODE(ITERATOR, START)for ((ITERATOR) = (START), mode_iterator::get_next (&(ITERATOR )); mode_iterator::iterate_p (&(ITERATOR)); mode_iterator ::get_next (&(ITERATOR))) \ | |||
1225 | for ((ITERATOR) = (START), mode_iterator::get_next (&(ITERATOR)); \ | |||
1226 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1227 | mode_iterator::get_next (&(ITERATOR))) | |||
1228 | ||||
1229 | /* Make ITERATOR iterate over modes in the same class as MODE, in order | |||
1230 | of increasing width. Start at the first mode wider than START, | |||
1231 | or don't iterate at all if there is no wider mode. */ | |||
1232 | #define FOR_EACH_WIDER_MODE(ITERATOR, START)for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR )); mode_iterator::iterate_p (&(ITERATOR)); mode_iterator ::get_wider (&(ITERATOR))) \ | |||
1233 | for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR)); \ | |||
1234 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1235 | mode_iterator::get_wider (&(ITERATOR))) | |||
1236 | ||||
1237 | /* Make ITERATOR iterate over modes in the same class as MODE, in order | |||
1238 | of increasing width, and with each mode being twice the width of the | |||
1239 | previous mode. Start at the mode that is two times wider than START, | |||
1240 | or don't iterate at all if there is no such mode. */ | |||
1241 | #define FOR_EACH_2XWIDER_MODE(ITERATOR, START)for ((ITERATOR) = (START), mode_iterator::get_2xwider (&( ITERATOR)); mode_iterator::iterate_p (&(ITERATOR)); mode_iterator ::get_2xwider (&(ITERATOR))) \ | |||
1242 | for ((ITERATOR) = (START), mode_iterator::get_2xwider (&(ITERATOR)); \ | |||
1243 | mode_iterator::iterate_p (&(ITERATOR)); \ | |||
1244 | mode_iterator::get_2xwider (&(ITERATOR))) | |||
1245 | ||||
1246 | template<typename T> | |||
1247 | void | |||
1248 | gt_ggc_mx (pod_mode<T> *) | |||
1249 | { | |||
1250 | } | |||
1251 | ||||
1252 | template<typename T> | |||
1253 | void | |||
1254 | gt_pch_nx (pod_mode<T> *) | |||
1255 | { | |||
1256 | } | |||
1257 | ||||
1258 | template<typename T> | |||
1259 | void | |||
1260 | gt_pch_nx (pod_mode<T> *, gt_pointer_operator, void *) | |||
1261 | { | |||
1262 | } | |||
1263 | ||||
1264 | #endif /* not HAVE_MACHINE_MODES */ |