Mercurial > hg > CbC > GCC_original
annotate gcc/loop-iv.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
rev | line source |
---|---|
0 | 1 /* Rtl-level induction variable analysis. |
16 | 2 Copyright (C) 2004-2017 Free Software Foundation, Inc. |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 |
0 | 4 This file is part of GCC. |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
5 |
0 | 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. | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
10 |
0 | 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. | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
15 |
0 | 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: | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
37 |
16 | 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). | |
0 | 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. | |
16 | 46 iv_analyze_expr (insn, mode, expr, iv): Stores to IV the description of iv |
0 | 47 corresponding to expression EXPR evaluated at INSN. All registers used bu |
16 | 48 EXPR must also be used in INSN. MODE is the mode of EXPR. |
0 | 49 */ |
50 | |
51 #include "config.h" | |
52 #include "system.h" | |
53 #include "coretypes.h" | |
16 | 54 #include "backend.h" |
0 | 55 #include "rtl.h" |
16 | 56 #include "df.h" |
57 #include "memmodel.h" | |
58 #include "emit-rtl.h" | |
59 #include "diagnostic-core.h" | |
0 | 60 #include "cfgloop.h" |
61 #include "intl.h" | |
16 | 62 #include "dumpfile.h" |
63 #include "rtl-iter.h" | |
0 | 64 |
65 /* Possible return values of iv_get_reaching_def. */ | |
66 | |
67 enum iv_grd_result | |
68 { | |
69 /* More than one reaching def, or reaching def that does not | |
70 dominate the use. */ | |
71 GRD_INVALID, | |
72 | |
73 /* The use is trivial invariant of the loop, i.e. is not changed | |
74 inside the loop. */ | |
75 GRD_INVARIANT, | |
76 | |
77 /* The use is reached by initial value and a value from the | |
78 previous iteration. */ | |
79 GRD_MAYBE_BIV, | |
80 | |
81 /* The use has single dominating def. */ | |
82 GRD_SINGLE_DOM | |
83 }; | |
84 | |
85 /* Information about a biv. */ | |
86 | |
87 struct biv_entry | |
88 { | |
89 unsigned regno; /* The register of the biv. */ | |
90 struct rtx_iv iv; /* Value of the biv. */ | |
91 }; | |
92 | |
93 static bool clean_slate = true; | |
94 | |
95 static unsigned int iv_ref_table_size = 0; | |
96 | |
97 /* Table of rtx_ivs indexed by the df_ref uid field. */ | |
98 static struct rtx_iv ** iv_ref_table; | |
99 | |
100 /* Induction variable stored at the reference. */ | |
16 | 101 #define DF_REF_IV(REF) iv_ref_table[DF_REF_ID (REF)] |
102 #define DF_REF_IV_SET(REF, IV) iv_ref_table[DF_REF_ID (REF)] = (IV) | |
0 | 103 |
104 /* The current loop. */ | |
105 | |
106 static struct loop *current_loop; | |
107 | |
16 | 108 /* Hashtable helper. */ |
109 | |
110 struct biv_entry_hasher : free_ptr_hash <biv_entry> | |
111 { | |
112 typedef rtx_def *compare_type; | |
113 static inline hashval_t hash (const biv_entry *); | |
114 static inline bool equal (const biv_entry *, const rtx_def *); | |
115 }; | |
116 | |
117 /* Returns hash value for biv B. */ | |
118 | |
119 inline hashval_t | |
120 biv_entry_hasher::hash (const biv_entry *b) | |
121 { | |
122 return b->regno; | |
123 } | |
124 | |
125 /* Compares biv B and register R. */ | |
126 | |
127 inline bool | |
128 biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r) | |
129 { | |
130 return b->regno == REGNO (r); | |
131 } | |
132 | |
0 | 133 /* Bivs of the current loop. */ |
134 | |
16 | 135 static hash_table<biv_entry_hasher> *bivs; |
136 | |
137 static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); | |
138 | |
139 /* Return the RTX code corresponding to the IV extend code EXTEND. */ | |
140 static inline enum rtx_code | |
141 iv_extend_to_rtx_code (enum iv_extend_code extend) | |
142 { | |
143 switch (extend) | |
144 { | |
145 case IV_SIGN_EXTEND: | |
146 return SIGN_EXTEND; | |
147 case IV_ZERO_EXTEND: | |
148 return ZERO_EXTEND; | |
149 case IV_UNKNOWN_EXTEND: | |
150 return UNKNOWN; | |
151 } | |
152 gcc_unreachable (); | |
153 } | |
0 | 154 |
155 /* Dumps information about IV to FILE. */ | |
156 | |
157 extern void dump_iv_info (FILE *, struct rtx_iv *); | |
158 void | |
159 dump_iv_info (FILE *file, struct rtx_iv *iv) | |
160 { | |
161 if (!iv->base) | |
162 { | |
163 fprintf (file, "not simple"); | |
164 return; | |
165 } | |
166 | |
167 if (iv->step == const0_rtx | |
168 && !iv->first_special) | |
169 fprintf (file, "invariant "); | |
170 | |
171 print_rtl (file, iv->base); | |
172 if (iv->step != const0_rtx) | |
173 { | |
174 fprintf (file, " + "); | |
175 print_rtl (file, iv->step); | |
176 fprintf (file, " * iteration"); | |
177 } | |
178 fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode)); | |
179 | |
180 if (iv->mode != iv->extend_mode) | |
181 fprintf (file, " %s to %s", | |
16 | 182 rtx_name[iv_extend_to_rtx_code (iv->extend)], |
0 | 183 GET_MODE_NAME (iv->extend_mode)); |
184 | |
185 if (iv->mult != const1_rtx) | |
186 { | |
187 fprintf (file, " * "); | |
188 print_rtl (file, iv->mult); | |
189 } | |
190 if (iv->delta != const0_rtx) | |
191 { | |
192 fprintf (file, " + "); | |
193 print_rtl (file, iv->delta); | |
194 } | |
195 if (iv->first_special) | |
196 fprintf (file, " (first special)"); | |
197 } | |
198 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
199 static void |
0 | 200 check_iv_ref_table_size (void) |
201 { | |
16 | 202 if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ()) |
0 | 203 { |
204 unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4); | |
205 iv_ref_table = XRESIZEVEC (struct rtx_iv *, iv_ref_table, new_size); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
206 memset (&iv_ref_table[iv_ref_table_size], 0, |
0 | 207 (new_size - iv_ref_table_size) * sizeof (struct rtx_iv *)); |
208 iv_ref_table_size = new_size; | |
209 } | |
210 } | |
211 | |
212 | |
213 /* Checks whether REG is a well-behaved register. */ | |
214 | |
215 static bool | |
216 simple_reg_p (rtx reg) | |
217 { | |
218 unsigned r; | |
219 | |
220 if (GET_CODE (reg) == SUBREG) | |
221 { | |
222 if (!subreg_lowpart_p (reg)) | |
223 return false; | |
224 reg = SUBREG_REG (reg); | |
225 } | |
226 | |
227 if (!REG_P (reg)) | |
228 return false; | |
229 | |
230 r = REGNO (reg); | |
231 if (HARD_REGISTER_NUM_P (r)) | |
232 return false; | |
233 | |
234 if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT) | |
235 return false; | |
236 | |
237 return true; | |
238 } | |
239 | |
240 /* Clears the information about ivs stored in df. */ | |
241 | |
242 static void | |
243 clear_iv_info (void) | |
244 { | |
245 unsigned i, n_defs = DF_DEFS_TABLE_SIZE (); | |
246 struct rtx_iv *iv; | |
247 | |
248 check_iv_ref_table_size (); | |
249 for (i = 0; i < n_defs; i++) | |
250 { | |
251 iv = iv_ref_table[i]; | |
252 if (iv) | |
253 { | |
254 free (iv); | |
255 iv_ref_table[i] = NULL; | |
256 } | |
257 } | |
258 | |
16 | 259 bivs->empty (); |
0 | 260 } |
261 | |
262 | |
263 /* Prepare the data for an induction variable analysis of a LOOP. */ | |
264 | |
265 void | |
266 iv_analysis_loop_init (struct loop *loop) | |
267 { | |
268 current_loop = loop; | |
269 | |
270 /* Clear the information from the analysis of the previous loop. */ | |
271 if (clean_slate) | |
272 { | |
273 df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN); | |
16 | 274 bivs = new hash_table<biv_entry_hasher> (10); |
0 | 275 clean_slate = false; |
276 } | |
277 else | |
278 clear_iv_info (); | |
279 | |
280 /* Get rid of the ud chains before processing the rescans. Then add | |
281 the problem back. */ | |
282 df_remove_problem (df_chain); | |
283 df_process_deferred_rescans (); | |
16 | 284 df_set_flags (DF_RD_PRUNE_DEAD_DEFS); |
0 | 285 df_chain_add_problem (DF_UD_CHAIN); |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
286 df_note_add_problem (); |
16 | 287 df_analyze_loop (loop); |
0 | 288 if (dump_file) |
289 df_dump_region (dump_file); | |
290 | |
291 check_iv_ref_table_size (); | |
292 } | |
293 | |
294 /* Finds the definition of REG that dominates loop latch and stores | |
295 it to DEF. Returns false if there is not a single definition | |
296 dominating the latch. If REG has no definition in loop, DEF | |
297 is set to NULL and true is returned. */ | |
298 | |
299 static bool | |
300 latch_dominating_def (rtx reg, df_ref *def) | |
301 { | |
302 df_ref single_rd = NULL, adef; | |
303 unsigned regno = REGNO (reg); | |
304 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch); | |
305 | |
306 for (adef = DF_REG_DEF_CHAIN (regno); adef; adef = DF_REF_NEXT_REG (adef)) | |
307 { | |
308 if (!bitmap_bit_p (df->blocks_to_analyze, DF_REF_BBNO (adef)) | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
309 || !bitmap_bit_p (&bb_info->out, DF_REF_ID (adef))) |
0 | 310 continue; |
311 | |
312 /* More than one reaching definition. */ | |
313 if (single_rd) | |
314 return false; | |
315 | |
316 if (!just_once_each_iteration_p (current_loop, DF_REF_BB (adef))) | |
317 return false; | |
318 | |
319 single_rd = adef; | |
320 } | |
321 | |
322 *def = single_rd; | |
323 return true; | |
324 } | |
325 | |
326 /* Gets definition of REG reaching its use in INSN and stores it to DEF. */ | |
327 | |
328 static enum iv_grd_result | |
16 | 329 iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def) |
0 | 330 { |
331 df_ref use, adef; | |
332 basic_block def_bb, use_bb; | |
16 | 333 rtx_insn *def_insn; |
0 | 334 bool dom_p; |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
335 |
0 | 336 *def = NULL; |
337 if (!simple_reg_p (reg)) | |
338 return GRD_INVALID; | |
339 if (GET_CODE (reg) == SUBREG) | |
340 reg = SUBREG_REG (reg); | |
341 gcc_assert (REG_P (reg)); | |
342 | |
343 use = df_find_use (insn, reg); | |
344 gcc_assert (use != NULL); | |
345 | |
346 if (!DF_REF_CHAIN (use)) | |
347 return GRD_INVARIANT; | |
348 | |
349 /* More than one reaching def. */ | |
350 if (DF_REF_CHAIN (use)->next) | |
351 return GRD_INVALID; | |
352 | |
353 adef = DF_REF_CHAIN (use)->ref; | |
354 | |
355 /* We do not handle setting only part of the register. */ | |
356 if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE) | |
357 return GRD_INVALID; | |
358 | |
359 def_insn = DF_REF_INSN (adef); | |
360 def_bb = DF_REF_BB (adef); | |
361 use_bb = BLOCK_FOR_INSN (insn); | |
362 | |
363 if (use_bb == def_bb) | |
364 dom_p = (DF_INSN_LUID (def_insn) < DF_INSN_LUID (insn)); | |
365 else | |
366 dom_p = dominated_by_p (CDI_DOMINATORS, use_bb, def_bb); | |
367 | |
368 if (dom_p) | |
369 { | |
370 *def = adef; | |
371 return GRD_SINGLE_DOM; | |
372 } | |
373 | |
374 /* The definition does not dominate the use. This is still OK if | |
375 this may be a use of a biv, i.e. if the def_bb dominates loop | |
376 latch. */ | |
377 if (just_once_each_iteration_p (current_loop, def_bb)) | |
378 return GRD_MAYBE_BIV; | |
379 | |
380 return GRD_INVALID; | |
381 } | |
382 | |
383 /* Sets IV to invariant CST in MODE. Always returns true (just for | |
384 consistency with other iv manipulation functions that may fail). */ | |
385 | |
386 static bool | |
16 | 387 iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst) |
0 | 388 { |
389 iv->mode = mode; | |
390 iv->base = cst; | |
391 iv->step = const0_rtx; | |
392 iv->first_special = false; | |
16 | 393 iv->extend = IV_UNKNOWN_EXTEND; |
0 | 394 iv->extend_mode = iv->mode; |
395 iv->delta = const0_rtx; | |
396 iv->mult = const1_rtx; | |
397 | |
398 return true; | |
399 } | |
400 | |
401 /* Evaluates application of subreg to MODE on IV. */ | |
402 | |
403 static bool | |
16 | 404 iv_subreg (struct rtx_iv *iv, scalar_int_mode mode) |
0 | 405 { |
406 /* If iv is invariant, just calculate the new value. */ | |
407 if (iv->step == const0_rtx | |
408 && !iv->first_special) | |
409 { | |
410 rtx val = get_iv_value (iv, const0_rtx); | |
16 | 411 val = lowpart_subreg (mode, val, |
412 iv->extend == IV_UNKNOWN_EXTEND | |
413 ? iv->mode : iv->extend_mode); | |
0 | 414 |
415 iv->base = val; | |
16 | 416 iv->extend = IV_UNKNOWN_EXTEND; |
0 | 417 iv->mode = iv->extend_mode = mode; |
418 iv->delta = const0_rtx; | |
419 iv->mult = const1_rtx; | |
420 return true; | |
421 } | |
422 | |
423 if (iv->extend_mode == mode) | |
424 return true; | |
425 | |
426 if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode)) | |
427 return false; | |
428 | |
16 | 429 iv->extend = IV_UNKNOWN_EXTEND; |
0 | 430 iv->mode = mode; |
431 | |
432 iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta, | |
433 simplify_gen_binary (MULT, iv->extend_mode, | |
434 iv->base, iv->mult)); | |
435 iv->step = simplify_gen_binary (MULT, iv->extend_mode, iv->step, iv->mult); | |
436 iv->mult = const1_rtx; | |
437 iv->delta = const0_rtx; | |
438 iv->first_special = false; | |
439 | |
440 return true; | |
441 } | |
442 | |
443 /* Evaluates application of EXTEND to MODE on IV. */ | |
444 | |
445 static bool | |
16 | 446 iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) |
0 | 447 { |
448 /* If iv is invariant, just calculate the new value. */ | |
449 if (iv->step == const0_rtx | |
450 && !iv->first_special) | |
451 { | |
452 rtx val = get_iv_value (iv, const0_rtx); | |
16 | 453 if (iv->extend_mode != iv->mode |
454 && iv->extend != IV_UNKNOWN_EXTEND | |
455 && iv->extend != extend) | |
456 val = lowpart_subreg (iv->mode, val, iv->extend_mode); | |
457 val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode, | |
458 val, | |
459 iv->extend == extend | |
460 ? iv->extend_mode : iv->mode); | |
0 | 461 iv->base = val; |
16 | 462 iv->extend = IV_UNKNOWN_EXTEND; |
0 | 463 iv->mode = iv->extend_mode = mode; |
464 iv->delta = const0_rtx; | |
465 iv->mult = const1_rtx; | |
466 return true; | |
467 } | |
468 | |
469 if (mode != iv->extend_mode) | |
470 return false; | |
471 | |
16 | 472 if (iv->extend != IV_UNKNOWN_EXTEND |
0 | 473 && iv->extend != extend) |
474 return false; | |
475 | |
476 iv->extend = extend; | |
477 | |
478 return true; | |
479 } | |
480 | |
481 /* Evaluates negation of IV. */ | |
482 | |
483 static bool | |
484 iv_neg (struct rtx_iv *iv) | |
485 { | |
16 | 486 if (iv->extend == IV_UNKNOWN_EXTEND) |
0 | 487 { |
488 iv->base = simplify_gen_unary (NEG, iv->extend_mode, | |
489 iv->base, iv->extend_mode); | |
490 iv->step = simplify_gen_unary (NEG, iv->extend_mode, | |
491 iv->step, iv->extend_mode); | |
492 } | |
493 else | |
494 { | |
495 iv->delta = simplify_gen_unary (NEG, iv->extend_mode, | |
496 iv->delta, iv->extend_mode); | |
497 iv->mult = simplify_gen_unary (NEG, iv->extend_mode, | |
498 iv->mult, iv->extend_mode); | |
499 } | |
500 | |
501 return true; | |
502 } | |
503 | |
504 /* Evaluates addition or subtraction (according to OP) of IV1 to IV0. */ | |
505 | |
506 static bool | |
507 iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op) | |
508 { | |
16 | 509 scalar_int_mode mode; |
0 | 510 rtx arg; |
511 | |
512 /* Extend the constant to extend_mode of the other operand if necessary. */ | |
16 | 513 if (iv0->extend == IV_UNKNOWN_EXTEND |
0 | 514 && iv0->mode == iv0->extend_mode |
515 && iv0->step == const0_rtx | |
516 && GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode)) | |
517 { | |
518 iv0->extend_mode = iv1->extend_mode; | |
519 iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode, | |
520 iv0->base, iv0->mode); | |
521 } | |
16 | 522 if (iv1->extend == IV_UNKNOWN_EXTEND |
0 | 523 && iv1->mode == iv1->extend_mode |
524 && iv1->step == const0_rtx | |
525 && GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode)) | |
526 { | |
527 iv1->extend_mode = iv0->extend_mode; | |
528 iv1->base = simplify_gen_unary (ZERO_EXTEND, iv1->extend_mode, | |
529 iv1->base, iv1->mode); | |
530 } | |
531 | |
532 mode = iv0->extend_mode; | |
533 if (mode != iv1->extend_mode) | |
534 return false; | |
535 | |
16 | 536 if (iv0->extend == IV_UNKNOWN_EXTEND |
537 && iv1->extend == IV_UNKNOWN_EXTEND) | |
0 | 538 { |
539 if (iv0->mode != iv1->mode) | |
540 return false; | |
541 | |
542 iv0->base = simplify_gen_binary (op, mode, iv0->base, iv1->base); | |
543 iv0->step = simplify_gen_binary (op, mode, iv0->step, iv1->step); | |
544 | |
545 return true; | |
546 } | |
547 | |
548 /* Handle addition of constant. */ | |
16 | 549 if (iv1->extend == IV_UNKNOWN_EXTEND |
0 | 550 && iv1->mode == mode |
551 && iv1->step == const0_rtx) | |
552 { | |
553 iv0->delta = simplify_gen_binary (op, mode, iv0->delta, iv1->base); | |
554 return true; | |
555 } | |
556 | |
16 | 557 if (iv0->extend == IV_UNKNOWN_EXTEND |
0 | 558 && iv0->mode == mode |
559 && iv0->step == const0_rtx) | |
560 { | |
561 arg = iv0->base; | |
562 *iv0 = *iv1; | |
563 if (op == MINUS | |
564 && !iv_neg (iv0)) | |
565 return false; | |
566 | |
567 iv0->delta = simplify_gen_binary (PLUS, mode, iv0->delta, arg); | |
568 return true; | |
569 } | |
570 | |
571 return false; | |
572 } | |
573 | |
574 /* Evaluates multiplication of IV by constant CST. */ | |
575 | |
576 static bool | |
577 iv_mult (struct rtx_iv *iv, rtx mby) | |
578 { | |
16 | 579 scalar_int_mode mode = iv->extend_mode; |
0 | 580 |
581 if (GET_MODE (mby) != VOIDmode | |
582 && GET_MODE (mby) != mode) | |
583 return false; | |
584 | |
16 | 585 if (iv->extend == IV_UNKNOWN_EXTEND) |
0 | 586 { |
587 iv->base = simplify_gen_binary (MULT, mode, iv->base, mby); | |
588 iv->step = simplify_gen_binary (MULT, mode, iv->step, mby); | |
589 } | |
590 else | |
591 { | |
592 iv->delta = simplify_gen_binary (MULT, mode, iv->delta, mby); | |
593 iv->mult = simplify_gen_binary (MULT, mode, iv->mult, mby); | |
594 } | |
595 | |
596 return true; | |
597 } | |
598 | |
599 /* Evaluates shift of IV by constant CST. */ | |
600 | |
601 static bool | |
602 iv_shift (struct rtx_iv *iv, rtx mby) | |
603 { | |
16 | 604 scalar_int_mode mode = iv->extend_mode; |
0 | 605 |
606 if (GET_MODE (mby) != VOIDmode | |
607 && GET_MODE (mby) != mode) | |
608 return false; | |
609 | |
16 | 610 if (iv->extend == IV_UNKNOWN_EXTEND) |
0 | 611 { |
612 iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby); | |
613 iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby); | |
614 } | |
615 else | |
616 { | |
617 iv->delta = simplify_gen_binary (ASHIFT, mode, iv->delta, mby); | |
618 iv->mult = simplify_gen_binary (ASHIFT, mode, iv->mult, mby); | |
619 } | |
620 | |
621 return true; | |
622 } | |
623 | |
624 /* The recursive part of get_biv_step. Gets the value of the single value | |
625 defined by DEF wrto initial value of REG inside loop, in shape described | |
626 at get_biv_step. */ | |
627 | |
628 static bool | |
16 | 629 get_biv_step_1 (df_ref def, scalar_int_mode outer_mode, rtx reg, |
630 rtx *inner_step, scalar_int_mode *inner_mode, | |
631 enum iv_extend_code *extend, | |
0 | 632 rtx *outer_step) |
633 { | |
634 rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX; | |
16 | 635 rtx next, nextr; |
0 | 636 enum rtx_code code; |
16 | 637 rtx_insn *insn = DF_REF_INSN (def); |
0 | 638 df_ref next_def; |
639 enum iv_grd_result res; | |
640 | |
641 set = single_set (insn); | |
642 if (!set) | |
643 return false; | |
644 | |
645 rhs = find_reg_equal_equiv_note (insn); | |
646 if (rhs) | |
647 rhs = XEXP (rhs, 0); | |
648 else | |
649 rhs = SET_SRC (set); | |
650 | |
651 code = GET_CODE (rhs); | |
652 switch (code) | |
653 { | |
654 case SUBREG: | |
655 case REG: | |
656 next = rhs; | |
657 break; | |
658 | |
659 case PLUS: | |
660 case MINUS: | |
661 op0 = XEXP (rhs, 0); | |
662 op1 = XEXP (rhs, 1); | |
663 | |
664 if (code == PLUS && CONSTANT_P (op0)) | |
16 | 665 std::swap (op0, op1); |
0 | 666 |
667 if (!simple_reg_p (op0) | |
668 || !CONSTANT_P (op1)) | |
669 return false; | |
670 | |
671 if (GET_MODE (rhs) != outer_mode) | |
672 { | |
673 /* ppc64 uses expressions like | |
674 | |
675 (set x:SI (plus:SI (subreg:SI y:DI) 1)). | |
676 | |
677 this is equivalent to | |
678 | |
679 (set x':DI (plus:DI y:DI 1)) | |
680 (set x:SI (subreg:SI (x':DI)). */ | |
681 if (GET_CODE (op0) != SUBREG) | |
682 return false; | |
683 if (GET_MODE (SUBREG_REG (op0)) != outer_mode) | |
684 return false; | |
685 } | |
686 | |
687 next = op0; | |
688 break; | |
689 | |
690 case SIGN_EXTEND: | |
691 case ZERO_EXTEND: | |
692 if (GET_MODE (rhs) != outer_mode) | |
693 return false; | |
694 | |
695 op0 = XEXP (rhs, 0); | |
696 if (!simple_reg_p (op0)) | |
697 return false; | |
698 | |
699 next = op0; | |
700 break; | |
701 | |
702 default: | |
703 return false; | |
704 } | |
705 | |
706 if (GET_CODE (next) == SUBREG) | |
707 { | |
708 if (!subreg_lowpart_p (next)) | |
709 return false; | |
710 | |
711 nextr = SUBREG_REG (next); | |
712 if (GET_MODE (nextr) != outer_mode) | |
713 return false; | |
714 } | |
715 else | |
716 nextr = next; | |
717 | |
718 res = iv_get_reaching_def (insn, nextr, &next_def); | |
719 | |
720 if (res == GRD_INVALID || res == GRD_INVARIANT) | |
721 return false; | |
722 | |
723 if (res == GRD_MAYBE_BIV) | |
724 { | |
725 if (!rtx_equal_p (nextr, reg)) | |
726 return false; | |
727 | |
728 *inner_step = const0_rtx; | |
16 | 729 *extend = IV_UNKNOWN_EXTEND; |
0 | 730 *inner_mode = outer_mode; |
731 *outer_step = const0_rtx; | |
732 } | |
16 | 733 else if (!get_biv_step_1 (next_def, outer_mode, reg, |
734 inner_step, inner_mode, extend, | |
0 | 735 outer_step)) |
736 return false; | |
737 | |
738 if (GET_CODE (next) == SUBREG) | |
739 { | |
16 | 740 scalar_int_mode amode; |
741 if (!is_a <scalar_int_mode> (GET_MODE (next), &amode) | |
742 || GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode)) | |
0 | 743 return false; |
744 | |
745 *inner_mode = amode; | |
746 *inner_step = simplify_gen_binary (PLUS, outer_mode, | |
747 *inner_step, *outer_step); | |
748 *outer_step = const0_rtx; | |
16 | 749 *extend = IV_UNKNOWN_EXTEND; |
0 | 750 } |
751 | |
752 switch (code) | |
753 { | |
754 case REG: | |
755 case SUBREG: | |
756 break; | |
757 | |
758 case PLUS: | |
759 case MINUS: | |
760 if (*inner_mode == outer_mode | |
761 /* See comment in previous switch. */ | |
762 || GET_MODE (rhs) != outer_mode) | |
763 *inner_step = simplify_gen_binary (code, outer_mode, | |
764 *inner_step, op1); | |
765 else | |
766 *outer_step = simplify_gen_binary (code, outer_mode, | |
767 *outer_step, op1); | |
768 break; | |
769 | |
770 case SIGN_EXTEND: | |
771 case ZERO_EXTEND: | |
772 gcc_assert (GET_MODE (op0) == *inner_mode | |
16 | 773 && *extend == IV_UNKNOWN_EXTEND |
0 | 774 && *outer_step == const0_rtx); |
775 | |
16 | 776 *extend = (code == SIGN_EXTEND) ? IV_SIGN_EXTEND : IV_ZERO_EXTEND; |
0 | 777 break; |
778 | |
779 default: | |
780 return false; | |
781 } | |
782 | |
783 return true; | |
784 } | |
785 | |
786 /* Gets the operation on register REG inside loop, in shape | |
787 | |
788 OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP)) | |
789 | |
790 If the operation cannot be described in this shape, return false. | |
791 LAST_DEF is the definition of REG that dominates loop latch. */ | |
792 | |
793 static bool | |
16 | 794 get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg, |
795 rtx *inner_step, scalar_int_mode *inner_mode, | |
796 enum iv_extend_code *extend, rtx *outer_step) | |
0 | 797 { |
16 | 798 if (!get_biv_step_1 (last_def, outer_mode, reg, |
799 inner_step, inner_mode, extend, | |
0 | 800 outer_step)) |
801 return false; | |
802 | |
16 | 803 gcc_assert ((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND)); |
804 gcc_assert (*inner_mode != outer_mode || *outer_step == const0_rtx); | |
0 | 805 |
806 return true; | |
807 } | |
808 | |
809 /* Records information that DEF is induction variable IV. */ | |
810 | |
811 static void | |
812 record_iv (df_ref def, struct rtx_iv *iv) | |
813 { | |
814 struct rtx_iv *recorded_iv = XNEW (struct rtx_iv); | |
815 | |
816 *recorded_iv = *iv; | |
817 check_iv_ref_table_size (); | |
818 DF_REF_IV_SET (def, recorded_iv); | |
819 } | |
820 | |
821 /* If DEF was already analyzed for bivness, store the description of the biv to | |
822 IV and return true. Otherwise return false. */ | |
823 | |
824 static bool | |
825 analyzed_for_bivness_p (rtx def, struct rtx_iv *iv) | |
826 { | |
16 | 827 struct biv_entry *biv = bivs->find_with_hash (def, REGNO (def)); |
0 | 828 |
829 if (!biv) | |
830 return false; | |
831 | |
832 *iv = biv->iv; | |
833 return true; | |
834 } | |
835 | |
836 static void | |
837 record_biv (rtx def, struct rtx_iv *iv) | |
838 { | |
839 struct biv_entry *biv = XNEW (struct biv_entry); | |
16 | 840 biv_entry **slot = bivs->find_slot_with_hash (def, REGNO (def), INSERT); |
0 | 841 |
842 biv->regno = REGNO (def); | |
843 biv->iv = *iv; | |
844 gcc_assert (!*slot); | |
845 *slot = biv; | |
846 } | |
847 | |
848 /* Determines whether DEF is a biv and if so, stores its description | |
16 | 849 to *IV. OUTER_MODE is the mode of DEF. */ |
0 | 850 |
851 static bool | |
16 | 852 iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv) |
0 | 853 { |
854 rtx inner_step, outer_step; | |
16 | 855 scalar_int_mode inner_mode; |
856 enum iv_extend_code extend; | |
0 | 857 df_ref last_def; |
858 | |
859 if (dump_file) | |
860 { | |
861 fprintf (dump_file, "Analyzing "); | |
862 print_rtl (dump_file, def); | |
863 fprintf (dump_file, " for bivness.\n"); | |
864 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
865 |
0 | 866 if (!REG_P (def)) |
867 { | |
868 if (!CONSTANT_P (def)) | |
869 return false; | |
870 | |
16 | 871 return iv_constant (iv, outer_mode, def); |
0 | 872 } |
873 | |
874 if (!latch_dominating_def (def, &last_def)) | |
875 { | |
876 if (dump_file) | |
877 fprintf (dump_file, " not simple.\n"); | |
878 return false; | |
879 } | |
880 | |
881 if (!last_def) | |
16 | 882 return iv_constant (iv, outer_mode, def); |
0 | 883 |
884 if (analyzed_for_bivness_p (def, iv)) | |
885 { | |
886 if (dump_file) | |
887 fprintf (dump_file, " already analysed.\n"); | |
888 return iv->base != NULL_RTX; | |
889 } | |
890 | |
16 | 891 if (!get_biv_step (last_def, outer_mode, def, &inner_step, &inner_mode, |
892 &extend, &outer_step)) | |
0 | 893 { |
894 iv->base = NULL_RTX; | |
895 goto end; | |
896 } | |
897 | |
898 /* Loop transforms base to es (base + inner_step) + outer_step, | |
899 where es means extend of subreg between inner_mode and outer_mode. | |
900 The corresponding induction variable is | |
901 | |
902 es ((base - outer_step) + i * (inner_step + outer_step)) + outer_step */ | |
903 | |
904 iv->base = simplify_gen_binary (MINUS, outer_mode, def, outer_step); | |
905 iv->step = simplify_gen_binary (PLUS, outer_mode, inner_step, outer_step); | |
906 iv->mode = inner_mode; | |
907 iv->extend_mode = outer_mode; | |
908 iv->extend = extend; | |
909 iv->mult = const1_rtx; | |
910 iv->delta = outer_step; | |
911 iv->first_special = inner_mode != outer_mode; | |
912 | |
913 end: | |
914 if (dump_file) | |
915 { | |
916 fprintf (dump_file, " "); | |
917 dump_iv_info (dump_file, iv); | |
918 fprintf (dump_file, "\n"); | |
919 } | |
920 | |
921 record_biv (def, iv); | |
922 return iv->base != NULL_RTX; | |
923 } | |
924 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
925 /* Analyzes expression RHS used at INSN and stores the result to *IV. |
0 | 926 The mode of the induction variable is MODE. */ |
927 | |
928 bool | |
16 | 929 iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs, |
930 struct rtx_iv *iv) | |
0 | 931 { |
16 | 932 rtx mby = NULL_RTX; |
0 | 933 rtx op0 = NULL_RTX, op1 = NULL_RTX; |
934 struct rtx_iv iv0, iv1; | |
935 enum rtx_code code = GET_CODE (rhs); | |
16 | 936 scalar_int_mode omode = mode; |
937 | |
0 | 938 iv->base = NULL_RTX; |
939 iv->step = NULL_RTX; | |
940 | |
941 gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode); | |
942 | |
943 if (CONSTANT_P (rhs) | |
944 || REG_P (rhs) | |
945 || code == SUBREG) | |
16 | 946 return iv_analyze_op (insn, mode, rhs, iv); |
0 | 947 |
948 switch (code) | |
949 { | |
950 case REG: | |
951 op0 = rhs; | |
952 break; | |
953 | |
954 case SIGN_EXTEND: | |
955 case ZERO_EXTEND: | |
956 case NEG: | |
957 op0 = XEXP (rhs, 0); | |
16 | 958 /* We don't know how many bits there are in a sign-extended constant. */ |
959 if (!is_a <scalar_int_mode> (GET_MODE (op0), &omode)) | |
960 return false; | |
0 | 961 break; |
962 | |
963 case PLUS: | |
964 case MINUS: | |
965 op0 = XEXP (rhs, 0); | |
966 op1 = XEXP (rhs, 1); | |
967 break; | |
968 | |
969 case MULT: | |
970 op0 = XEXP (rhs, 0); | |
971 mby = XEXP (rhs, 1); | |
972 if (!CONSTANT_P (mby)) | |
16 | 973 std::swap (op0, mby); |
0 | 974 if (!CONSTANT_P (mby)) |
975 return false; | |
976 break; | |
977 | |
978 case ASHIFT: | |
979 op0 = XEXP (rhs, 0); | |
980 mby = XEXP (rhs, 1); | |
981 if (!CONSTANT_P (mby)) | |
982 return false; | |
983 break; | |
984 | |
985 default: | |
986 return false; | |
987 } | |
988 | |
989 if (op0 | |
16 | 990 && !iv_analyze_expr (insn, omode, op0, &iv0)) |
0 | 991 return false; |
992 | |
993 if (op1 | |
16 | 994 && !iv_analyze_expr (insn, omode, op1, &iv1)) |
0 | 995 return false; |
996 | |
997 switch (code) | |
998 { | |
999 case SIGN_EXTEND: | |
16 | 1000 if (!iv_extend (&iv0, IV_SIGN_EXTEND, mode)) |
1001 return false; | |
1002 break; | |
1003 | |
0 | 1004 case ZERO_EXTEND: |
16 | 1005 if (!iv_extend (&iv0, IV_ZERO_EXTEND, mode)) |
0 | 1006 return false; |
1007 break; | |
1008 | |
1009 case NEG: | |
1010 if (!iv_neg (&iv0)) | |
1011 return false; | |
1012 break; | |
1013 | |
1014 case PLUS: | |
1015 case MINUS: | |
1016 if (!iv_add (&iv0, &iv1, code)) | |
1017 return false; | |
1018 break; | |
1019 | |
1020 case MULT: | |
1021 if (!iv_mult (&iv0, mby)) | |
1022 return false; | |
1023 break; | |
1024 | |
1025 case ASHIFT: | |
1026 if (!iv_shift (&iv0, mby)) | |
1027 return false; | |
1028 break; | |
1029 | |
1030 default: | |
1031 break; | |
1032 } | |
1033 | |
1034 *iv = iv0; | |
1035 return iv->base != NULL_RTX; | |
1036 } | |
1037 | |
1038 /* Analyzes iv DEF and stores the result to *IV. */ | |
1039 | |
1040 static bool | |
1041 iv_analyze_def (df_ref def, struct rtx_iv *iv) | |
1042 { | |
16 | 1043 rtx_insn *insn = DF_REF_INSN (def); |
0 | 1044 rtx reg = DF_REF_REG (def); |
1045 rtx set, rhs; | |
1046 | |
1047 if (dump_file) | |
1048 { | |
1049 fprintf (dump_file, "Analyzing def of "); | |
1050 print_rtl (dump_file, reg); | |
1051 fprintf (dump_file, " in insn "); | |
1052 print_rtl_single (dump_file, insn); | |
1053 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1054 |
0 | 1055 check_iv_ref_table_size (); |
1056 if (DF_REF_IV (def)) | |
1057 { | |
1058 if (dump_file) | |
1059 fprintf (dump_file, " already analysed.\n"); | |
1060 *iv = *DF_REF_IV (def); | |
1061 return iv->base != NULL_RTX; | |
1062 } | |
1063 | |
1064 iv->base = NULL_RTX; | |
1065 iv->step = NULL_RTX; | |
1066 | |
16 | 1067 scalar_int_mode mode; |
1068 if (!REG_P (reg) || !is_a <scalar_int_mode> (GET_MODE (reg), &mode)) | |
0 | 1069 return false; |
1070 | |
1071 set = single_set (insn); | |
1072 if (!set) | |
1073 return false; | |
1074 | |
1075 if (!REG_P (SET_DEST (set))) | |
1076 return false; | |
1077 | |
1078 gcc_assert (SET_DEST (set) == reg); | |
1079 rhs = find_reg_equal_equiv_note (insn); | |
1080 if (rhs) | |
1081 rhs = XEXP (rhs, 0); | |
1082 else | |
1083 rhs = SET_SRC (set); | |
1084 | |
16 | 1085 iv_analyze_expr (insn, mode, rhs, iv); |
0 | 1086 record_iv (def, iv); |
1087 | |
1088 if (dump_file) | |
1089 { | |
1090 print_rtl (dump_file, reg); | |
1091 fprintf (dump_file, " in insn "); | |
1092 print_rtl_single (dump_file, insn); | |
1093 fprintf (dump_file, " is "); | |
1094 dump_iv_info (dump_file, iv); | |
1095 fprintf (dump_file, "\n"); | |
1096 } | |
1097 | |
1098 return iv->base != NULL_RTX; | |
1099 } | |
1100 | |
16 | 1101 /* Analyzes operand OP of INSN and stores the result to *IV. MODE is the |
1102 mode of OP. */ | |
0 | 1103 |
1104 static bool | |
16 | 1105 iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv) |
0 | 1106 { |
1107 df_ref def = NULL; | |
1108 enum iv_grd_result res; | |
1109 | |
1110 if (dump_file) | |
1111 { | |
1112 fprintf (dump_file, "Analyzing operand "); | |
1113 print_rtl (dump_file, op); | |
1114 fprintf (dump_file, " of insn "); | |
1115 print_rtl_single (dump_file, insn); | |
1116 } | |
1117 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1118 if (function_invariant_p (op)) |
0 | 1119 res = GRD_INVARIANT; |
1120 else if (GET_CODE (op) == SUBREG) | |
1121 { | |
16 | 1122 scalar_int_mode inner_mode; |
1123 if (!subreg_lowpart_p (op) | |
1124 || !is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &inner_mode)) | |
0 | 1125 return false; |
1126 | |
16 | 1127 if (!iv_analyze_op (insn, inner_mode, SUBREG_REG (op), iv)) |
0 | 1128 return false; |
1129 | |
16 | 1130 return iv_subreg (iv, mode); |
0 | 1131 } |
1132 else | |
1133 { | |
1134 res = iv_get_reaching_def (insn, op, &def); | |
1135 if (res == GRD_INVALID) | |
1136 { | |
1137 if (dump_file) | |
1138 fprintf (dump_file, " not simple.\n"); | |
1139 return false; | |
1140 } | |
1141 } | |
1142 | |
1143 if (res == GRD_INVARIANT) | |
1144 { | |
16 | 1145 iv_constant (iv, mode, op); |
0 | 1146 |
1147 if (dump_file) | |
1148 { | |
1149 fprintf (dump_file, " "); | |
1150 dump_iv_info (dump_file, iv); | |
1151 fprintf (dump_file, "\n"); | |
1152 } | |
1153 return true; | |
1154 } | |
1155 | |
1156 if (res == GRD_MAYBE_BIV) | |
16 | 1157 return iv_analyze_biv (mode, op, iv); |
0 | 1158 |
1159 return iv_analyze_def (def, iv); | |
1160 } | |
1161 | |
16 | 1162 /* Analyzes value VAL at INSN and stores the result to *IV. MODE is the |
1163 mode of VAL. */ | |
0 | 1164 |
1165 bool | |
16 | 1166 iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv) |
0 | 1167 { |
1168 rtx reg; | |
1169 | |
1170 /* We must find the insn in that val is used, so that we get to UD chains. | |
1171 Since the function is sometimes called on result of get_condition, | |
1172 this does not necessarily have to be directly INSN; scan also the | |
1173 following insns. */ | |
1174 if (simple_reg_p (val)) | |
1175 { | |
1176 if (GET_CODE (val) == SUBREG) | |
1177 reg = SUBREG_REG (val); | |
1178 else | |
1179 reg = val; | |
1180 | |
1181 while (!df_find_use (insn, reg)) | |
1182 insn = NEXT_INSN (insn); | |
1183 } | |
1184 | |
16 | 1185 return iv_analyze_op (insn, mode, val, iv); |
0 | 1186 } |
1187 | |
1188 /* Analyzes definition of DEF in INSN and stores the result to IV. */ | |
1189 | |
1190 bool | |
16 | 1191 iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv) |
0 | 1192 { |
1193 df_ref adef; | |
1194 | |
1195 adef = df_find_def (insn, def); | |
1196 if (!adef) | |
1197 return false; | |
1198 | |
1199 return iv_analyze_def (adef, iv); | |
1200 } | |
1201 | |
1202 /* Checks whether definition of register REG in INSN is a basic induction | |
16 | 1203 variable. MODE is the mode of REG. |
1204 | |
1205 IV analysis must have been initialized (via a call to | |
0 | 1206 iv_analysis_loop_init) for this function to produce a result. */ |
1207 | |
1208 bool | |
16 | 1209 biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg) |
0 | 1210 { |
1211 struct rtx_iv iv; | |
1212 df_ref def, last_def; | |
1213 | |
1214 if (!simple_reg_p (reg)) | |
1215 return false; | |
1216 | |
1217 def = df_find_def (insn, reg); | |
1218 gcc_assert (def != NULL); | |
1219 if (!latch_dominating_def (reg, &last_def)) | |
1220 return false; | |
1221 if (last_def != def) | |
1222 return false; | |
1223 | |
16 | 1224 if (!iv_analyze_biv (mode, reg, &iv)) |
0 | 1225 return false; |
1226 | |
1227 return iv.step != const0_rtx; | |
1228 } | |
1229 | |
1230 /* Calculates value of IV at ITERATION-th iteration. */ | |
1231 | |
1232 rtx | |
1233 get_iv_value (struct rtx_iv *iv, rtx iteration) | |
1234 { | |
1235 rtx val; | |
1236 | |
1237 /* We would need to generate some if_then_else patterns, and so far | |
1238 it is not needed anywhere. */ | |
1239 gcc_assert (!iv->first_special); | |
1240 | |
1241 if (iv->step != const0_rtx && iteration != const0_rtx) | |
1242 val = simplify_gen_binary (PLUS, iv->extend_mode, iv->base, | |
1243 simplify_gen_binary (MULT, iv->extend_mode, | |
1244 iv->step, iteration)); | |
1245 else | |
1246 val = iv->base; | |
1247 | |
1248 if (iv->extend_mode == iv->mode) | |
1249 return val; | |
1250 | |
1251 val = lowpart_subreg (iv->mode, val, iv->extend_mode); | |
1252 | |
16 | 1253 if (iv->extend == IV_UNKNOWN_EXTEND) |
0 | 1254 return val; |
1255 | |
16 | 1256 val = simplify_gen_unary (iv_extend_to_rtx_code (iv->extend), |
1257 iv->extend_mode, val, iv->mode); | |
0 | 1258 val = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta, |
1259 simplify_gen_binary (MULT, iv->extend_mode, | |
1260 iv->mult, val)); | |
1261 | |
1262 return val; | |
1263 } | |
1264 | |
1265 /* Free the data for an induction variable analysis. */ | |
1266 | |
1267 void | |
1268 iv_analysis_done (void) | |
1269 { | |
1270 if (!clean_slate) | |
1271 { | |
1272 clear_iv_info (); | |
1273 clean_slate = true; | |
1274 df_finish_pass (true); | |
16 | 1275 delete bivs; |
1276 bivs = NULL; | |
0 | 1277 free (iv_ref_table); |
1278 iv_ref_table = NULL; | |
1279 iv_ref_table_size = 0; | |
1280 } | |
1281 } | |
1282 | |
1283 /* Computes inverse to X modulo (1 << MOD). */ | |
1284 | |
16 | 1285 static uint64_t |
1286 inverse (uint64_t x, int mod) | |
0 | 1287 { |
16 | 1288 uint64_t mask = |
1289 ((uint64_t) 1 << (mod - 1) << 1) - 1; | |
1290 uint64_t rslt = 1; | |
0 | 1291 int i; |
1292 | |
1293 for (i = 0; i < mod - 1; i++) | |
1294 { | |
1295 rslt = (rslt * x) & mask; | |
1296 x = (x * x) & mask; | |
1297 } | |
1298 | |
1299 return rslt; | |
1300 } | |
1301 | |
16 | 1302 /* Checks whether any register in X is in set ALT. */ |
1303 | |
1304 static bool | |
1305 altered_reg_used (const_rtx x, bitmap alt) | |
0 | 1306 { |
16 | 1307 subrtx_iterator::array_type array; |
1308 FOR_EACH_SUBRTX (iter, array, x, NONCONST) | |
1309 { | |
1310 const_rtx x = *iter; | |
1311 if (REG_P (x) && REGNO_REG_SET_P (alt, REGNO (x))) | |
1312 return true; | |
1313 } | |
1314 return false; | |
0 | 1315 } |
1316 | |
1317 /* Marks registers altered by EXPR in set ALT. */ | |
1318 | |
1319 static void | |
1320 mark_altered (rtx expr, const_rtx by ATTRIBUTE_UNUSED, void *alt) | |
1321 { | |
1322 if (GET_CODE (expr) == SUBREG) | |
1323 expr = SUBREG_REG (expr); | |
1324 if (!REG_P (expr)) | |
1325 return; | |
1326 | |
1327 SET_REGNO_REG_SET ((bitmap) alt, REGNO (expr)); | |
1328 } | |
1329 | |
1330 /* Checks whether RHS is simple enough to process. */ | |
1331 | |
1332 static bool | |
1333 simple_rhs_p (rtx rhs) | |
1334 { | |
1335 rtx op0, op1; | |
1336 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1337 if (function_invariant_p (rhs) |
0 | 1338 || (REG_P (rhs) && !HARD_REGISTER_P (rhs))) |
1339 return true; | |
1340 | |
1341 switch (GET_CODE (rhs)) | |
1342 { | |
1343 case PLUS: | |
1344 case MINUS: | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1345 case AND: |
0 | 1346 op0 = XEXP (rhs, 0); |
1347 op1 = XEXP (rhs, 1); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1348 /* Allow reg OP const and reg OP reg. */ |
0 | 1349 if (!(REG_P (op0) && !HARD_REGISTER_P (op0)) |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1350 && !function_invariant_p (op0)) |
0 | 1351 return false; |
1352 if (!(REG_P (op1) && !HARD_REGISTER_P (op1)) | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1353 && !function_invariant_p (op1)) |
0 | 1354 return false; |
1355 | |
1356 return true; | |
1357 | |
1358 case ASHIFT: | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1359 case ASHIFTRT: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1360 case LSHIFTRT: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1361 case MULT: |
0 | 1362 op0 = XEXP (rhs, 0); |
1363 op1 = XEXP (rhs, 1); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1364 /* Allow reg OP const. */ |
0 | 1365 if (!(REG_P (op0) && !HARD_REGISTER_P (op0))) |
1366 return false; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1367 if (!function_invariant_p (op1)) |
0 | 1368 return false; |
1369 | |
1370 return true; | |
1371 | |
1372 default: | |
1373 return false; | |
1374 } | |
1375 } | |
1376 | |
16 | 1377 /* If REGNO has a single definition, return its known value, otherwise return |
1378 null. */ | |
1379 | |
1380 static rtx | |
1381 find_single_def_src (unsigned int regno) | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1382 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1383 df_ref adef; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1384 rtx set, src; |
16 | 1385 |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1386 for (;;) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1387 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1388 rtx note; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1389 adef = DF_REG_DEF_CHAIN (regno); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1390 if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL |
16 | 1391 || DF_REF_IS_ARTIFICIAL (adef)) |
1392 return NULL_RTX; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1393 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1394 set = single_set (DF_REF_INSN (adef)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1395 if (set == NULL || !REG_P (SET_DEST (set)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1396 || REGNO (SET_DEST (set)) != regno) |
16 | 1397 return NULL_RTX; |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1398 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1399 note = find_reg_equal_equiv_note (DF_REF_INSN (adef)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1400 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1401 if (note && function_invariant_p (XEXP (note, 0))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1402 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1403 src = XEXP (note, 0); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1404 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1405 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1406 src = SET_SRC (set); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1407 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1408 if (REG_P (src)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1409 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1410 regno = REGNO (src); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1411 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1412 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1413 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1414 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1415 if (!function_invariant_p (src)) |
16 | 1416 return NULL_RTX; |
1417 | |
1418 return src; | |
1419 } | |
1420 | |
1421 /* If any registers in *EXPR that have a single definition, try to replace | |
1422 them with the known-equivalent values. */ | |
1423 | |
1424 static void | |
1425 replace_single_def_regs (rtx *expr) | |
1426 { | |
1427 subrtx_var_iterator::array_type array; | |
1428 repeat: | |
1429 FOR_EACH_SUBRTX_VAR (iter, array, *expr, NONCONST) | |
1430 { | |
1431 rtx x = *iter; | |
1432 if (REG_P (x)) | |
1433 if (rtx new_x = find_single_def_src (REGNO (x))) | |
1434 { | |
1435 *expr = simplify_replace_rtx (*expr, x, new_x); | |
1436 goto repeat; | |
1437 } | |
1438 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1439 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1440 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1441 /* A subroutine of simplify_using_initial_values, this function examines INSN |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1442 to see if it contains a suitable set that we can use to make a replacement. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1443 If it is suitable, return true and set DEST and SRC to the lhs and rhs of |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1444 the set; return false otherwise. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1445 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1446 static bool |
16 | 1447 suitable_set_for_replacement (rtx_insn *insn, rtx *dest, rtx *src) |
0 | 1448 { |
1449 rtx set = single_set (insn); | |
1450 rtx lhs = NULL_RTX, rhs; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1451 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1452 if (!set) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1453 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1454 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1455 lhs = SET_DEST (set); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1456 if (!REG_P (lhs)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1457 return false; |
0 | 1458 |
1459 rhs = find_reg_equal_equiv_note (insn); | |
1460 if (rhs) | |
1461 rhs = XEXP (rhs, 0); | |
1462 else | |
1463 rhs = SET_SRC (set); | |
1464 | |
1465 if (!simple_rhs_p (rhs)) | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1466 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1467 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1468 *dest = lhs; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1469 *src = rhs; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1470 return true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1471 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1472 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1473 /* Using the data returned by suitable_set_for_replacement, replace DEST |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1474 with SRC in *EXPR and return the new expression. Also call |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1475 replace_single_def_regs if the replacement changed something. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1476 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1477 replace_in_expr (rtx *expr, rtx dest, rtx src) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1478 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1479 rtx old = *expr; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1480 *expr = simplify_replace_rtx (*expr, dest, src); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1481 if (old == *expr) |
0 | 1482 return; |
16 | 1483 replace_single_def_regs (expr); |
0 | 1484 } |
1485 | |
1486 /* Checks whether A implies B. */ | |
1487 | |
1488 static bool | |
1489 implies_p (rtx a, rtx b) | |
1490 { | |
16 | 1491 rtx op0, op1, opb0, opb1; |
1492 machine_mode mode; | |
1493 | |
1494 if (rtx_equal_p (a, b)) | |
1495 return true; | |
0 | 1496 |
1497 if (GET_CODE (a) == EQ) | |
1498 { | |
1499 op0 = XEXP (a, 0); | |
1500 op1 = XEXP (a, 1); | |
1501 | |
16 | 1502 if (REG_P (op0) |
1503 || (GET_CODE (op0) == SUBREG | |
1504 && REG_P (SUBREG_REG (op0)))) | |
0 | 1505 { |
16 | 1506 rtx r = simplify_replace_rtx (b, op0, op1); |
0 | 1507 if (r == const_true_rtx) |
1508 return true; | |
1509 } | |
1510 | |
16 | 1511 if (REG_P (op1) |
1512 || (GET_CODE (op1) == SUBREG | |
1513 && REG_P (SUBREG_REG (op1)))) | |
0 | 1514 { |
16 | 1515 rtx r = simplify_replace_rtx (b, op1, op0); |
0 | 1516 if (r == const_true_rtx) |
1517 return true; | |
1518 } | |
1519 } | |
1520 | |
1521 if (b == const_true_rtx) | |
1522 return true; | |
1523 | |
1524 if ((GET_RTX_CLASS (GET_CODE (a)) != RTX_COMM_COMPARE | |
1525 && GET_RTX_CLASS (GET_CODE (a)) != RTX_COMPARE) | |
1526 || (GET_RTX_CLASS (GET_CODE (b)) != RTX_COMM_COMPARE | |
1527 && GET_RTX_CLASS (GET_CODE (b)) != RTX_COMPARE)) | |
1528 return false; | |
1529 | |
1530 op0 = XEXP (a, 0); | |
1531 op1 = XEXP (a, 1); | |
1532 opb0 = XEXP (b, 0); | |
1533 opb1 = XEXP (b, 1); | |
1534 | |
1535 mode = GET_MODE (op0); | |
1536 if (mode != GET_MODE (opb0)) | |
1537 mode = VOIDmode; | |
1538 else if (mode == VOIDmode) | |
1539 { | |
1540 mode = GET_MODE (op1); | |
1541 if (mode != GET_MODE (opb1)) | |
1542 mode = VOIDmode; | |
1543 } | |
1544 | |
1545 /* A < B implies A + 1 <= B. */ | |
1546 if ((GET_CODE (a) == GT || GET_CODE (a) == LT) | |
1547 && (GET_CODE (b) == GE || GET_CODE (b) == LE)) | |
1548 { | |
1549 | |
1550 if (GET_CODE (a) == GT) | |
16 | 1551 std::swap (op0, op1); |
0 | 1552 |
1553 if (GET_CODE (b) == GE) | |
16 |