]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/auto-inc-dec.c
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / auto-inc-dec.c
1 /* Discovery of auto-inc and auto-dec instructions.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Free Software Foundation, Inc.
4 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "tm_p.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
31 #include "insn-config.h"
32 #include "regs.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "except.h"
36 #include "diagnostic-core.h"
37 #include "recog.h"
38 #include "expr.h"
39 #include "tree-pass.h"
40 #include "df.h"
41 #include "dbgcnt.h"
42 #include "target.h"
43
44 /* This pass was originally removed from flow.c. However there is
45 almost nothing that remains of that code.
46
47 There are (4) basic forms that are matched:
48
49 (1) FORM_PRE_ADD
50 a <- b + c
51 ...
52 *a
53
54 becomes
55
56 a <- b
57 ...
58 *(a += c) pre
59
60
61 (2) FORM_PRE_INC
62 a += c
63 ...
64 *a
65
66 becomes
67
68 *(a += c) pre
69
70
71 (3) FORM_POST_ADD
72 *a
73 ...
74 b <- a + c
75
76 (For this case to be true, b must not be assigned or used between
77 the *a and the assignment to b. B must also be a Pmode reg.)
78
79 becomes
80
81 b <- a
82 ...
83 *(b += c) post
84
85
86 (4) FORM_POST_INC
87 *a
88 ...
89 a <- a + c
90
91 becomes
92
93 *(a += c) post
94
95 There are three types of values of c.
96
97 1) c is a constant equal to the width of the value being accessed by
98 the pointer. This is useful for machines that have
99 HAVE_PRE_INCREMENT, HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT or
100 HAVE_POST_DECREMENT defined.
101
102 2) c is a constant not equal to the width of the value being accessed
103 by the pointer. This is useful for machines that have
104 HAVE_PRE_MODIFY_DISP, HAVE_POST_MODIFY_DISP defined.
105
106 3) c is a register. This is useful for machines that have
107 HAVE_PRE_MODIFY_REG, HAVE_POST_MODIFY_REG
108
109 The is one special case: if a already had an offset equal to it +-
110 its width and that offset is equal to -c when the increment was
111 before the ref or +c if the increment was after the ref, then if we
112 can do the combination but switch the pre/post bit. */
113
114 #ifdef AUTO_INC_DEC
115
116 enum form
117 {
118 FORM_PRE_ADD,
119 FORM_PRE_INC,
120 FORM_POST_ADD,
121 FORM_POST_INC,
122 FORM_last
123 };
124
125 /* The states of the second operands of mem refs and inc insns. If no
126 second operand of the mem_ref was found, it is assumed to just be
127 ZERO. SIZE is the size of the mode accessed in the memref. The
128 ANY is used for constants that are not +-size or 0. REG is used if
129 the forms are reg1 + reg2. */
130
131 enum inc_state
132 {
133 INC_ZERO, /* == 0 */
134 INC_NEG_SIZE, /* == +size */
135 INC_POS_SIZE, /* == -size */
136 INC_NEG_ANY, /* == some -constant */
137 INC_POS_ANY, /* == some +constant */
138 INC_REG, /* == some register */
139 INC_last
140 };
141
142 /* The eight forms that pre/post inc/dec can take. */
143 enum gen_form
144 {
145 NOTHING,
146 SIMPLE_PRE_INC, /* ++size */
147 SIMPLE_POST_INC, /* size++ */
148 SIMPLE_PRE_DEC, /* --size */
149 SIMPLE_POST_DEC, /* size-- */
150 DISP_PRE, /* ++con */
151 DISP_POST, /* con++ */
152 REG_PRE, /* ++reg */
153 REG_POST /* reg++ */
154 };
155
156 /* Tmp mem rtx for use in cost modeling. */
157 static rtx mem_tmp;
158
159 static enum inc_state
160 set_inc_state (HOST_WIDE_INT val, int size)
161 {
162 if (val == 0)
163 return INC_ZERO;
164 if (val < 0)
165 return (val == -size) ? INC_NEG_SIZE : INC_NEG_ANY;
166 else
167 return (val == size) ? INC_POS_SIZE : INC_POS_ANY;
168 }
169
170 /* The DECISION_TABLE that describes what form, if any, the increment
171 or decrement will take. It is a three dimensional table. The first
172 index is the type of constant or register found as the second
173 operand of the inc insn. The second index is the type of constant
174 or register found as the second operand of the memory reference (if
175 no second operand exists, 0 is used). The third index is the form
176 and location (relative to the mem reference) of inc insn. */
177
178 static bool initialized = false;
179 static enum gen_form decision_table[INC_last][INC_last][FORM_last];
180
181 static void
182 init_decision_table (void)
183 {
184 enum gen_form value;
185
186 if (HAVE_PRE_INCREMENT || HAVE_PRE_MODIFY_DISP)
187 {
188 /* Prefer the simple form if both are available. */
189 value = (HAVE_PRE_INCREMENT) ? SIMPLE_PRE_INC : DISP_PRE;
190
191 decision_table[INC_POS_SIZE][INC_ZERO][FORM_PRE_ADD] = value;
192 decision_table[INC_POS_SIZE][INC_ZERO][FORM_PRE_INC] = value;
193
194 decision_table[INC_POS_SIZE][INC_POS_SIZE][FORM_POST_ADD] = value;
195 decision_table[INC_POS_SIZE][INC_POS_SIZE][FORM_POST_INC] = value;
196 }
197
198 if (HAVE_POST_INCREMENT || HAVE_POST_MODIFY_DISP)
199 {
200 /* Prefer the simple form if both are available. */
201 value = (HAVE_POST_INCREMENT) ? SIMPLE_POST_INC : DISP_POST;
202
203 decision_table[INC_POS_SIZE][INC_ZERO][FORM_POST_ADD] = value;
204 decision_table[INC_POS_SIZE][INC_ZERO][FORM_POST_INC] = value;
205
206 decision_table[INC_POS_SIZE][INC_NEG_SIZE][FORM_PRE_ADD] = value;
207 decision_table[INC_POS_SIZE][INC_NEG_SIZE][FORM_PRE_INC] = value;
208 }
209
210 if (HAVE_PRE_DECREMENT || HAVE_PRE_MODIFY_DISP)
211 {
212 /* Prefer the simple form if both are available. */
213 value = (HAVE_PRE_DECREMENT) ? SIMPLE_PRE_DEC : DISP_PRE;
214
215 decision_table[INC_NEG_SIZE][INC_ZERO][FORM_PRE_ADD] = value;
216 decision_table[INC_NEG_SIZE][INC_ZERO][FORM_PRE_INC] = value;
217
218 decision_table[INC_NEG_SIZE][INC_NEG_SIZE][FORM_POST_ADD] = value;
219 decision_table[INC_NEG_SIZE][INC_NEG_SIZE][FORM_POST_INC] = value;
220 }
221
222 if (HAVE_POST_DECREMENT || HAVE_POST_MODIFY_DISP)
223 {
224 /* Prefer the simple form if both are available. */
225 value = (HAVE_POST_DECREMENT) ? SIMPLE_POST_DEC : DISP_POST;
226
227 decision_table[INC_NEG_SIZE][INC_ZERO][FORM_POST_ADD] = value;
228 decision_table[INC_NEG_SIZE][INC_ZERO][FORM_POST_INC] = value;
229
230 decision_table[INC_NEG_SIZE][INC_POS_SIZE][FORM_PRE_ADD] = value;
231 decision_table[INC_NEG_SIZE][INC_POS_SIZE][FORM_PRE_INC] = value;
232 }
233
234 if (HAVE_PRE_MODIFY_DISP)
235 {
236 decision_table[INC_POS_ANY][INC_ZERO][FORM_PRE_ADD] = DISP_PRE;
237 decision_table[INC_POS_ANY][INC_ZERO][FORM_PRE_INC] = DISP_PRE;
238
239 decision_table[INC_POS_ANY][INC_POS_ANY][FORM_POST_ADD] = DISP_PRE;
240 decision_table[INC_POS_ANY][INC_POS_ANY][FORM_POST_INC] = DISP_PRE;
241
242 decision_table[INC_NEG_ANY][INC_ZERO][FORM_PRE_ADD] = DISP_PRE;
243 decision_table[INC_NEG_ANY][INC_ZERO][FORM_PRE_INC] = DISP_PRE;
244
245 decision_table[INC_NEG_ANY][INC_NEG_ANY][FORM_POST_ADD] = DISP_PRE;
246 decision_table[INC_NEG_ANY][INC_NEG_ANY][FORM_POST_INC] = DISP_PRE;
247 }
248
249 if (HAVE_POST_MODIFY_DISP)
250 {
251 decision_table[INC_POS_ANY][INC_ZERO][FORM_POST_ADD] = DISP_POST;
252 decision_table[INC_POS_ANY][INC_ZERO][FORM_POST_INC] = DISP_POST;
253
254 decision_table[INC_POS_ANY][INC_NEG_ANY][FORM_PRE_ADD] = DISP_POST;
255 decision_table[INC_POS_ANY][INC_NEG_ANY][FORM_PRE_INC] = DISP_POST;
256
257 decision_table[INC_NEG_ANY][INC_ZERO][FORM_POST_ADD] = DISP_POST;
258 decision_table[INC_NEG_ANY][INC_ZERO][FORM_POST_INC] = DISP_POST;
259
260 decision_table[INC_NEG_ANY][INC_POS_ANY][FORM_PRE_ADD] = DISP_POST;
261 decision_table[INC_NEG_ANY][INC_POS_ANY][FORM_PRE_INC] = DISP_POST;
262 }
263
264 /* This is much simpler than the other cases because we do not look
265 for the reg1-reg2 case. Note that we do not have a INC_POS_REG
266 and INC_NEG_REG states. Most of the use of such states would be
267 on a target that had an R1 - R2 update address form.
268
269 There is the remote possibility that you could also catch a = a +
270 b; *(a - b) as a postdecrement of (a + b). However, it is
271 unclear if *(a - b) would ever be generated on a machine that did
272 not have that kind of addressing mode. The IA-64 and RS6000 will
273 not do this, and I cannot speak for any other. If any
274 architecture does have an a-b update for, these cases should be
275 added. */
276 if (HAVE_PRE_MODIFY_REG)
277 {
278 decision_table[INC_REG][INC_ZERO][FORM_PRE_ADD] = REG_PRE;
279 decision_table[INC_REG][INC_ZERO][FORM_PRE_INC] = REG_PRE;
280
281 decision_table[INC_REG][INC_REG][FORM_POST_ADD] = REG_PRE;
282 decision_table[INC_REG][INC_REG][FORM_POST_INC] = REG_PRE;
283 }
284
285 if (HAVE_POST_MODIFY_REG)
286 {
287 decision_table[INC_REG][INC_ZERO][FORM_POST_ADD] = REG_POST;
288 decision_table[INC_REG][INC_ZERO][FORM_POST_INC] = REG_POST;
289 }
290
291 initialized = true;
292 }
293
294 /* Parsed fields of an inc insn of the form "reg_res = reg0+reg1" or
295 "reg_res = reg0+c". */
296
297 static struct inc_insn
298 {
299 rtx insn; /* The insn being parsed. */
300 rtx pat; /* The pattern of the insn. */
301 bool reg1_is_const; /* True if reg1 is const, false if reg1 is a reg. */
302 enum form form;
303 rtx reg_res;
304 rtx reg0;
305 rtx reg1;
306 enum inc_state reg1_state;/* The form of the const if reg1 is a const. */
307 HOST_WIDE_INT reg1_val;/* Value if reg1 is const. */
308 } inc_insn;
309
310
311 /* Dump the parsed inc insn to FILE. */
312
313 static void
314 dump_inc_insn (FILE *file)
315 {
316 const char *f = ((inc_insn.form == FORM_PRE_ADD)
317 || (inc_insn.form == FORM_PRE_INC)) ? "pre" : "post";
318
319 dump_insn_slim (file, inc_insn.insn);
320
321 switch (inc_insn.form)
322 {
323 case FORM_PRE_ADD:
324 case FORM_POST_ADD:
325 if (inc_insn.reg1_is_const)
326 fprintf (file, "found %s add(%d) r[%d]=r[%d]+%d\n",
327 f, INSN_UID (inc_insn.insn),
328 REGNO (inc_insn.reg_res),
329 REGNO (inc_insn.reg0), (int) inc_insn.reg1_val);
330 else
331 fprintf (file, "found %s add(%d) r[%d]=r[%d]+r[%d]\n",
332 f, INSN_UID (inc_insn.insn),
333 REGNO (inc_insn.reg_res),
334 REGNO (inc_insn.reg0), REGNO (inc_insn.reg1));
335 break;
336
337 case FORM_PRE_INC:
338 case FORM_POST_INC:
339 if (inc_insn.reg1_is_const)
340 fprintf (file, "found %s inc(%d) r[%d]+=%d\n",
341 f, INSN_UID (inc_insn.insn),
342 REGNO (inc_insn.reg_res), (int) inc_insn.reg1_val);
343 else
344 fprintf (file, "found %s inc(%d) r[%d]+=r[%d]\n",
345 f, INSN_UID (inc_insn.insn),
346 REGNO (inc_insn.reg_res), REGNO (inc_insn.reg1));
347 break;
348
349 default:
350 break;
351 }
352 }
353
354
355 /* Parsed fields of a mem ref of the form "*(reg0+reg1)" or "*(reg0+c)". */
356
357 static struct mem_insn
358 {
359 rtx insn; /* The insn being parsed. */
360 rtx pat; /* The pattern of the insn. */
361 rtx *mem_loc; /* The address of the field that holds the mem */
362 /* that is to be replaced. */
363 bool reg1_is_const; /* True if reg1 is const, false if reg1 is a reg. */
364 rtx reg0;
365 rtx reg1; /* This is either a reg or a const depending on
366 reg1_is_const. */
367 enum inc_state reg1_state;/* The form of the const if reg1 is a const. */
368 HOST_WIDE_INT reg1_val;/* Value if reg1 is const. */
369 } mem_insn;
370
371
372 /* Dump the parsed mem insn to FILE. */
373
374 static void
375 dump_mem_insn (FILE *file)
376 {
377 dump_insn_slim (file, mem_insn.insn);
378
379 if (mem_insn.reg1_is_const)
380 fprintf (file, "found mem(%d) *(r[%d]+%d)\n",
381 INSN_UID (mem_insn.insn),
382 REGNO (mem_insn.reg0), (int) mem_insn.reg1_val);
383 else
384 fprintf (file, "found mem(%d) *(r[%d]+r[%d])\n",
385 INSN_UID (mem_insn.insn),
386 REGNO (mem_insn.reg0), REGNO (mem_insn.reg1));
387 }
388
389
390 /* The following three arrays contain pointers to instructions. They
391 are indexed by REGNO. At any point in the basic block where we are
392 looking these three arrays contain, respectively, the next insn
393 that uses REGNO, the next inc or add insn that uses REGNO and the
394 next insn that sets REGNO.
395
396 The arrays are not cleared when we move from block to block so
397 whenever an insn is retrieved from these arrays, it's block number
398 must be compared with the current block.
399 */
400
401 static rtx *reg_next_use = NULL;
402 static rtx *reg_next_inc_use = NULL;
403 static rtx *reg_next_def = NULL;
404
405
406 /* Move dead note that match PATTERN to TO_INSN from FROM_INSN. We do
407 not really care about moving any other notes from the inc or add
408 insn. Moving the REG_EQUAL and REG_EQUIV is clearly wrong and it
409 does not appear that there are any other kinds of relevant notes. */
410
411 static void
412 move_dead_notes (rtx to_insn, rtx from_insn, rtx pattern)
413 {
414 rtx note;
415 rtx next_note;
416 rtx prev_note = NULL;
417
418 for (note = REG_NOTES (from_insn); note; note = next_note)
419 {
420 next_note = XEXP (note, 1);
421
422 if ((REG_NOTE_KIND (note) == REG_DEAD)
423 && pattern == XEXP (note, 0))
424 {
425 XEXP (note, 1) = REG_NOTES (to_insn);
426 REG_NOTES (to_insn) = note;
427 if (prev_note)
428 XEXP (prev_note, 1) = next_note;
429 else
430 REG_NOTES (from_insn) = next_note;
431 }
432 else prev_note = note;
433 }
434 }
435
436
437 /* Create a mov insn DEST_REG <- SRC_REG and insert it before
438 NEXT_INSN. */
439
440 static rtx
441 insert_move_insn_before (rtx next_insn, rtx dest_reg, rtx src_reg)
442 {
443 rtx insns;
444
445 start_sequence ();
446 emit_move_insn (dest_reg, src_reg);
447 insns = get_insns ();
448 end_sequence ();
449 emit_insn_before (insns, next_insn);
450 return insns;
451 }
452
453
454 /* Change mem_insn.mem_loc so that uses NEW_ADDR which has an
455 increment of INC_REG. To have reached this point, the change is a
456 legitimate one from a dataflow point of view. The only questions
457 are is this a valid change to the instruction and is this a
458 profitable change to the instruction. */
459
460 static bool
461 attempt_change (rtx new_addr, rtx inc_reg)
462 {
463 /* There are four cases: For the two cases that involve an add
464 instruction, we are going to have to delete the add and insert a
465 mov. We are going to assume that the mov is free. This is
466 fairly early in the backend and there are a lot of opportunities
467 for removing that move later. In particular, there is the case
468 where the move may be dead, this is what dead code elimination
469 passes are for. The two cases where we have an inc insn will be
470 handled mov free. */
471
472 basic_block bb = BLOCK_FOR_INSN (mem_insn.insn);
473 rtx mov_insn = NULL;
474 int regno;
475 rtx mem = *mem_insn.mem_loc;
476 enum machine_mode mode = GET_MODE (mem);
477 rtx new_mem;
478 int old_cost = 0;
479 int new_cost = 0;
480 bool speed = optimize_bb_for_speed_p (bb);
481
482 PUT_MODE (mem_tmp, mode);
483 XEXP (mem_tmp, 0) = new_addr;
484
485 old_cost = (set_src_cost (mem, speed)
486 + set_rtx_cost (PATTERN (inc_insn.insn), speed));
487 new_cost = set_src_cost (mem_tmp, speed);
488
489 /* The first item of business is to see if this is profitable. */
490 if (old_cost < new_cost)
491 {
492 if (dump_file)
493 fprintf (dump_file, "cost failure old=%d new=%d\n", old_cost, new_cost);
494 return false;
495 }
496
497 /* Jump through a lot of hoops to keep the attributes up to date. We
498 do not want to call one of the change address variants that take
499 an offset even though we know the offset in many cases. These
500 assume you are changing where the address is pointing by the
501 offset. */
502 new_mem = replace_equiv_address_nv (mem, new_addr);
503 if (! validate_change (mem_insn.insn, mem_insn.mem_loc, new_mem, 0))
504 {
505 if (dump_file)
506 fprintf (dump_file, "validation failure\n");
507 return false;
508 }
509
510 /* From here to the end of the function we are committed to the
511 change, i.e. nothing fails. Generate any necessary movs, move
512 any regnotes, and fix up the reg_next_{use,inc_use,def}. */
513 switch (inc_insn.form)
514 {
515 case FORM_PRE_ADD:
516 /* Replace the addition with a move. Do it at the location of
517 the addition since the operand of the addition may change
518 before the memory reference. */
519 mov_insn = insert_move_insn_before (inc_insn.insn,
520 inc_insn.reg_res, inc_insn.reg0);
521 move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
522
523 regno = REGNO (inc_insn.reg_res);
524 reg_next_def[regno] = mov_insn;
525 reg_next_use[regno] = NULL;
526 regno = REGNO (inc_insn.reg0);
527 reg_next_use[regno] = mov_insn;
528 df_recompute_luids (bb);
529 break;
530
531 case FORM_POST_INC:
532 regno = REGNO (inc_insn.reg_res);
533 if (reg_next_use[regno] == reg_next_inc_use[regno])
534 reg_next_inc_use[regno] = NULL;
535
536 /* Fallthru. */
537 case FORM_PRE_INC:
538 regno = REGNO (inc_insn.reg_res);
539 reg_next_def[regno] = mem_insn.insn;
540 reg_next_use[regno] = NULL;
541
542 break;
543
544 case FORM_POST_ADD:
545 mov_insn = insert_move_insn_before (mem_insn.insn,
546 inc_insn.reg_res, inc_insn.reg0);
547 move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
548
549 /* Do not move anything to the mov insn because the instruction
550 pointer for the main iteration has not yet hit that. It is
551 still pointing to the mem insn. */
552 regno = REGNO (inc_insn.reg_res);
553 reg_next_def[regno] = mem_insn.insn;
554 reg_next_use[regno] = NULL;
555
556 regno = REGNO (inc_insn.reg0);
557 reg_next_use[regno] = mem_insn.insn;
558 if ((reg_next_use[regno] == reg_next_inc_use[regno])
559 || (reg_next_inc_use[regno] == inc_insn.insn))
560 reg_next_inc_use[regno] = NULL;
561 df_recompute_luids (bb);
562 break;
563
564 case FORM_last:
565 default:
566 gcc_unreachable ();
567 }
568
569 if (!inc_insn.reg1_is_const)
570 {
571 regno = REGNO (inc_insn.reg1);
572 reg_next_use[regno] = mem_insn.insn;
573 if ((reg_next_use[regno] == reg_next_inc_use[regno])
574 || (reg_next_inc_use[regno] == inc_insn.insn))
575 reg_next_inc_use[regno] = NULL;
576 }
577
578 delete_insn (inc_insn.insn);
579
580 if (dump_file && mov_insn)
581 {
582 fprintf (dump_file, "inserting mov ");
583 dump_insn_slim (dump_file, mov_insn);
584 }
585
586 /* Record that this insn has an implicit side effect. */
587 add_reg_note (mem_insn.insn, REG_INC, inc_reg);
588
589 if (dump_file)
590 {
591 fprintf (dump_file, "****success ");
592 dump_insn_slim (dump_file, mem_insn.insn);
593 }
594
595 return true;
596 }
597
598
599 /* Try to combine the instruction in INC_INSN with the instruction in
600 MEM_INSN. First the form is determined using the DECISION_TABLE
601 and the results of parsing the INC_INSN and the MEM_INSN.
602 Assuming the form is ok, a prototype new address is built which is
603 passed to ATTEMPT_CHANGE for final processing. */
604
605 static bool
606 try_merge (void)
607 {
608 enum gen_form gen_form;
609 rtx mem = *mem_insn.mem_loc;
610 rtx inc_reg = inc_insn.form == FORM_POST_ADD ?
611 inc_insn.reg_res : mem_insn.reg0;
612
613 /* The width of the mem being accessed. */
614 int size = GET_MODE_SIZE (GET_MODE (mem));
615 rtx last_insn = NULL;
616 enum machine_mode reg_mode = GET_MODE (inc_reg);
617
618 switch (inc_insn.form)
619 {
620 case FORM_PRE_ADD:
621 case FORM_PRE_INC:
622 last_insn = mem_insn.insn;
623 break;
624 case FORM_POST_INC:
625 case FORM_POST_ADD:
626 last_insn = inc_insn.insn;
627 break;
628 case FORM_last:
629 default:
630 gcc_unreachable ();
631 }
632
633 /* Cannot handle auto inc of the stack. */
634 if (inc_reg == stack_pointer_rtx)
635 {
636 if (dump_file)
637 fprintf (dump_file, "cannot inc stack %d failure\n", REGNO (inc_reg));
638 return false;
639 }
640
641 /* Look to see if the inc register is dead after the memory
642 reference. If it is, do not do the combination. */
643 if (find_regno_note (last_insn, REG_DEAD, REGNO (inc_reg)))
644 {
645 if (dump_file)
646 fprintf (dump_file, "dead failure %d\n", REGNO (inc_reg));
647 return false;
648 }
649
650 mem_insn.reg1_state = (mem_insn.reg1_is_const)
651 ? set_inc_state (mem_insn.reg1_val, size) : INC_REG;
652 inc_insn.reg1_state = (inc_insn.reg1_is_const)
653 ? set_inc_state (inc_insn.reg1_val, size) : INC_REG;
654
655 /* Now get the form that we are generating. */
656 gen_form = decision_table
657 [inc_insn.reg1_state][mem_insn.reg1_state][inc_insn.form];
658
659 if (dbg_cnt (auto_inc_dec) == false)
660 return false;
661
662 switch (gen_form)
663 {
664 default:
665 case NOTHING:
666 return false;
667
668 case SIMPLE_PRE_INC: /* ++size */
669 if (dump_file)
670 fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
671 return attempt_change (gen_rtx_PRE_INC (reg_mode, inc_reg), inc_reg);
672 break;
673
674 case SIMPLE_POST_INC: /* size++ */
675 if (dump_file)
676 fprintf (dump_file, "trying SIMPLE_POST_INC\n");
677 return attempt_change (gen_rtx_POST_INC (reg_mode, inc_reg), inc_reg);
678 break;
679
680 case SIMPLE_PRE_DEC: /* --size */
681 if (dump_file)
682 fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
683 return attempt_change (gen_rtx_PRE_DEC (reg_mode, inc_reg), inc_reg);
684 break;
685
686 case SIMPLE_POST_DEC: /* size-- */
687 if (dump_file)
688 fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
689 return attempt_change (gen_rtx_POST_DEC (reg_mode, inc_reg), inc_reg);
690 break;
691
692 case DISP_PRE: /* ++con */
693 if (dump_file)
694 fprintf (dump_file, "trying DISP_PRE\n");
695 return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
696 inc_reg,
697 gen_rtx_PLUS (reg_mode,
698 inc_reg,
699 inc_insn.reg1)),
700 inc_reg);
701 break;
702
703 case DISP_POST: /* con++ */
704 if (dump_file)
705 fprintf (dump_file, "trying POST_DISP\n");
706 return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
707 inc_reg,
708 gen_rtx_PLUS (reg_mode,
709 inc_reg,
710 inc_insn.reg1)),
711 inc_reg);
712 break;
713
714 case REG_PRE: /* ++reg */
715 if (dump_file)
716 fprintf (dump_file, "trying PRE_REG\n");
717 return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
718 inc_reg,
719 gen_rtx_PLUS (reg_mode,
720 inc_reg,
721 inc_insn.reg1)),
722 inc_reg);
723 break;
724
725 case REG_POST: /* reg++ */
726 if (dump_file)
727 fprintf (dump_file, "trying POST_REG\n");
728 return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
729 inc_reg,
730 gen_rtx_PLUS (reg_mode,
731 inc_reg,
732 inc_insn.reg1)),
733 inc_reg);
734 break;
735 }
736 }
737
738 /* Return the next insn that uses (if reg_next_use is passed in
739 NEXT_ARRAY) or defines (if reg_next_def is passed in NEXT_ARRAY)
740 REGNO in BB. */
741
742 static rtx
743 get_next_ref (int regno, basic_block bb, rtx *next_array)
744 {
745 rtx insn = next_array[regno];
746
747 /* Lazy about cleaning out the next_arrays. */
748 if (insn && BLOCK_FOR_INSN (insn) != bb)
749 {
750 next_array[regno] = NULL;
751 insn = NULL;
752 }
753
754 return insn;
755 }
756
757
758 /* Reverse the operands in a mem insn. */
759
760 static void
761 reverse_mem (void)
762 {
763 rtx tmp = mem_insn.reg1;
764 mem_insn.reg1 = mem_insn.reg0;
765 mem_insn.reg0 = tmp;
766 }
767
768
769 /* Reverse the operands in a inc insn. */
770
771 static void
772 reverse_inc (void)
773 {
774 rtx tmp = inc_insn.reg1;
775 inc_insn.reg1 = inc_insn.reg0;
776 inc_insn.reg0 = tmp;
777 }
778
779
780 /* Return true if INSN is of a form "a = b op c" where a and b are
781 regs. op is + if c is a reg and +|- if c is a const. Fill in
782 INC_INSN with what is found.
783
784 This function is called in two contexts, if BEFORE_MEM is true,
785 this is called for each insn in the basic block. If BEFORE_MEM is
786 false, it is called for the instruction in the block that uses the
787 index register for some memory reference that is currently being
788 processed. */
789
790 static bool
791 parse_add_or_inc (rtx insn, bool before_mem)
792 {
793 rtx pat = single_set (insn);
794 if (!pat)
795 return false;
796
797 /* Result must be single reg. */
798 if (!REG_P (SET_DEST (pat)))
799 return false;
800
801 if ((GET_CODE (SET_SRC (pat)) != PLUS)
802 && (GET_CODE (SET_SRC (pat)) != MINUS))
803 return false;
804
805 if (!REG_P (XEXP (SET_SRC (pat), 0)))
806 return false;
807
808 inc_insn.insn = insn;
809 inc_insn.pat = pat;
810 inc_insn.reg_res = SET_DEST (pat);
811 inc_insn.reg0 = XEXP (SET_SRC (pat), 0);
812 if (rtx_equal_p (inc_insn.reg_res, inc_insn.reg0))
813 inc_insn.form = before_mem ? FORM_PRE_INC : FORM_POST_INC;
814 else
815 inc_insn.form = before_mem ? FORM_PRE_ADD : FORM_POST_ADD;
816
817 if (CONST_INT_P (XEXP (SET_SRC (pat), 1)))
818 {
819 /* Process a = b + c where c is a const. */
820 inc_insn.reg1_is_const = true;
821 if (GET_CODE (SET_SRC (pat)) == PLUS)
822 {
823 inc_insn.reg1 = XEXP (SET_SRC (pat), 1);
824 inc_insn.reg1_val = INTVAL (inc_insn.reg1);
825 }
826 else
827 {
828 inc_insn.reg1_val = -INTVAL (XEXP (SET_SRC (pat), 1));
829 inc_insn.reg1 = GEN_INT (inc_insn.reg1_val);
830 }
831 return true;
832 }
833 else if ((HAVE_PRE_MODIFY_REG || HAVE_POST_MODIFY_REG)
834 && (REG_P (XEXP (SET_SRC (pat), 1)))
835 && GET_CODE (SET_SRC (pat)) == PLUS)
836 {
837 /* Process a = b + c where c is a reg. */
838 inc_insn.reg1 = XEXP (SET_SRC (pat), 1);
839 inc_insn.reg1_is_const = false;
840
841 if (inc_insn.form == FORM_PRE_INC
842 || inc_insn.form == FORM_POST_INC)
843 return true;
844 else if (rtx_equal_p (inc_insn.reg_res, inc_insn.reg1))
845 {
846 /* Reverse the two operands and turn *_ADD into *_INC since
847 a = c + a. */
848 reverse_inc ();
849 inc_insn.form = before_mem ? FORM_PRE_INC : FORM_POST_INC;
850 return true;
851 }
852 else
853 return true;
854 }
855
856 return false;
857 }
858
859
860 /* A recursive function that checks all of the mem uses in
861 ADDRESS_OF_X to see if any single one of them is compatible with
862 what has been found in inc_insn.
863
864 -1 is returned for success. 0 is returned if nothing was found and
865 1 is returned for failure. */
866
867 static int
868 find_address (rtx *address_of_x)
869 {
870 rtx x = *address_of_x;
871 enum rtx_code code = GET_CODE (x);
872 const char *const fmt = GET_RTX_FORMAT (code);
873 int i;
874 int value = 0;
875 int tem;
876
877 if (code == MEM && rtx_equal_p (XEXP (x, 0), inc_insn.reg_res))
878 {
879 /* Match with *reg0. */
880 mem_insn.mem_loc = address_of_x;
881 mem_insn.reg0 = inc_insn.reg_res;
882 mem_insn.reg1_is_const = true;
883 mem_insn.reg1_val = 0;
884 mem_insn.reg1 = GEN_INT (0);
885 return -1;
886 }
887 if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
888 && rtx_equal_p (XEXP (XEXP (x, 0), 0), inc_insn.reg_res))
889 {
890 rtx b = XEXP (XEXP (x, 0), 1);
891 mem_insn.mem_loc = address_of_x;
892 mem_insn.reg0 = inc_insn.reg_res;
893 mem_insn.reg1 = b;
894 mem_insn.reg1_is_const = inc_insn.reg1_is_const;
895 if (CONST_INT_P (b))
896 {
897 /* Match with *(reg0 + reg1) where reg1 is a const. */
898 HOST_WIDE_INT val = INTVAL (b);
899 if (inc_insn.reg1_is_const
900 && (inc_insn.reg1_val == val || inc_insn.reg1_val == -val))
901 {
902 mem_insn.reg1_val = val;
903 return -1;
904 }
905 }
906 else if (!inc_insn.reg1_is_const
907 && rtx_equal_p (inc_insn.reg1, b))
908 /* Match with *(reg0 + reg1). */
909 return -1;
910 }
911
912 if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
913 {
914 /* If REG occurs inside a MEM used in a bit-field reference,
915 that is unacceptable. */
916 if (find_address (&XEXP (x, 0)))
917 return 1;
918 }
919
920 if (x == inc_insn.reg_res)
921 return 1;
922
923 /* Time for some deep diving. */
924 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
925 {
926 if (fmt[i] == 'e')
927 {
928 tem = find_address (&XEXP (x, i));
929 /* If this is the first use, let it go so the rest of the
930 insn can be checked. */
931 if (value == 0)
932 value = tem;
933 else if (tem != 0)
934 /* More than one match was found. */
935 return 1;
936 }
937 else if (fmt[i] == 'E')
938 {
939 int j;
940 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
941 {
942 tem = find_address (&XVECEXP (x, i, j));
943 /* If this is the first use, let it go so the rest of
944 the insn can be checked. */
945 if (value == 0)
946 value = tem;
947 else if (tem != 0)
948 /* More than one match was found. */
949 return 1;
950 }
951 }
952 }
953 return value;
954 }
955
956 /* Once a suitable mem reference has been found and the MEM_INSN
957 structure has been filled in, FIND_INC is called to see if there is
958 a suitable add or inc insn that follows the mem reference and
959 determine if it is suitable to merge.
960
961 In the case where the MEM_INSN has two registers in the reference,
962 this function may be called recursively. The first time looking
963 for an add of the first register, and if that fails, looking for an
964 add of the second register. The FIRST_TRY parameter is used to
965 only allow the parameters to be reversed once. */
966
967 static bool
968 find_inc (bool first_try)
969 {
970 rtx insn;
971 basic_block bb = BLOCK_FOR_INSN (mem_insn.insn);
972 rtx other_insn;
973 df_ref *def_rec;
974
975 /* Make sure this reg appears only once in this insn. */
976 if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
977 {
978 if (dump_file)
979 fprintf (dump_file, "mem count failure\n");
980 return false;
981 }
982
983 if (dump_file)
984 dump_mem_insn (dump_file);
985
986 /* Find the next use that is an inc. */
987 insn = get_next_ref (REGNO (mem_insn.reg0),
988 BLOCK_FOR_INSN (mem_insn.insn),
989 reg_next_inc_use);
990 if (!insn)
991 return false;
992
993 /* Even though we know the next use is an add or inc because it came
994 from the reg_next_inc_use, we must still reparse. */
995 if (!parse_add_or_inc (insn, false))
996 {
997 /* Next use was not an add. Look for one extra case. It could be
998 that we have:
999
1000 *(a + b)
1001 ...= a;
1002 ...= b + a
1003
1004 if we reverse the operands in the mem ref we would
1005 find this. Only try it once though. */
1006 if (first_try && !mem_insn.reg1_is_const)
1007 {
1008 reverse_mem ();
1009 return find_inc (false);
1010 }
1011 else
1012 return false;
1013 }
1014
1015 /* Need to assure that none of the operands of the inc instruction are
1016 assigned to by the mem insn. */
1017 for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
1018 {
1019 df_ref def = *def_rec;
1020 unsigned int regno = DF_REF_REGNO (def);
1021 if ((regno == REGNO (inc_insn.reg0))
1022 || (regno == REGNO (inc_insn.reg_res)))
1023 {
1024 if (dump_file)
1025 fprintf (dump_file, "inc conflicts with store failure.\n");
1026 return false;
1027 }
1028 if (!inc_insn.reg1_is_const && (regno == REGNO (inc_insn.reg1)))
1029 {
1030 if (dump_file)
1031 fprintf (dump_file, "inc conflicts with store failure.\n");
1032 return false;
1033 }
1034 }
1035
1036 if (dump_file)
1037 dump_inc_insn (dump_file);
1038
1039 if (inc_insn.form == FORM_POST_ADD)
1040 {
1041 /* Make sure that there is no insn that assigns to inc_insn.res
1042 between the mem_insn and the inc_insn. */
1043 rtx other_insn = get_next_ref (REGNO (inc_insn.reg_res),
1044 BLOCK_FOR_INSN (mem_insn.insn),
1045 reg_next_def);
1046 if (other_insn != inc_insn.insn)
1047 {
1048 if (dump_file)
1049 fprintf (dump_file,
1050 "result of add is assigned to between mem and inc insns.\n");
1051 return false;
1052 }
1053
1054 other_insn = get_next_ref (REGNO (inc_insn.reg_res),
1055 BLOCK_FOR_INSN (mem_insn.insn),
1056 reg_next_use);
1057 if (other_insn
1058 && (other_insn != inc_insn.insn)
1059 && (DF_INSN_LUID (inc_insn.insn) > DF_INSN_LUID (other_insn)))
1060 {
1061 if (dump_file)
1062 fprintf (dump_file,
1063 "result of add is used between mem and inc insns.\n");
1064 return false;
1065 }
1066
1067 /* For the post_add to work, the result_reg of the inc must not be
1068 used in the mem insn since this will become the new index
1069 register. */
1070 if (reg_overlap_mentioned_p (inc_insn.reg_res, PATTERN (mem_insn.insn)))
1071 {
1072 if (dump_file)
1073 fprintf (dump_file, "base reg replacement failure.\n");
1074 return false;
1075 }
1076 }
1077
1078 if (mem_insn.reg1_is_const)
1079 {
1080 if (mem_insn.reg1_val == 0)
1081 {
1082 if (!inc_insn.reg1_is_const)
1083 {
1084 /* The mem looks like *r0 and the rhs of the add has two
1085 registers. */
1086 int luid = DF_INSN_LUID (inc_insn.insn);
1087 if (inc_insn.form == FORM_POST_ADD)
1088 {
1089 /* The trick is that we are not going to increment r0,
1090 we are going to increment the result of the add insn.
1091 For this trick to be correct, the result reg of
1092 the inc must be a valid addressing reg. */
1093 addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
1094 if (GET_MODE (inc_insn.reg_res)
1095 != targetm.addr_space.address_mode (as))
1096 {
1097 if (dump_file)
1098 fprintf (dump_file, "base reg mode failure.\n");
1099 return false;
1100 }
1101
1102 /* We also need to make sure that the next use of
1103 inc result is after the inc. */
1104 other_insn
1105 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);
1106 if (other_insn && luid > DF_INSN_LUID (other_insn))
1107 return false;
1108
1109 if (!rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
1110 reverse_inc ();
1111 }
1112
1113 other_insn
1114 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
1115 if (other_insn && luid > DF_INSN_LUID (other_insn))
1116 return false;
1117 }
1118 }
1119 /* Both the inc/add and the mem have a constant. Need to check
1120 that the constants are ok. */
1121 else if ((mem_insn.reg1_val != inc_insn.reg1_val)
1122 && (mem_insn.reg1_val != -inc_insn.reg1_val))
1123 return false;
1124 }
1125 else
1126 {
1127 /* The mem insn is of the form *(a + b) where a and b are both
1128 regs. It may be that in order to match the add or inc we
1129 need to treat it as if it was *(b + a). It may also be that
1130 the add is of the form a + c where c does not match b and
1131 then we just abandon this. */
1132
1133 int luid = DF_INSN_LUID (inc_insn.insn);
1134 rtx other_insn;
1135
1136 /* Make sure this reg appears only once in this insn. */
1137 if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg1, 1) != 1)
1138 return false;
1139
1140 if (inc_insn.form == FORM_POST_ADD)
1141 {
1142 /* For this trick to be correct, the result reg of the inc
1143 must be a valid addressing reg. */
1144 addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
1145 if (GET_MODE (inc_insn.reg_res)
1146 != targetm.addr_space.address_mode (as))
1147 {
1148 if (dump_file)
1149 fprintf (dump_file, "base reg mode failure.\n");
1150 return false;
1151 }
1152
1153 if (rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
1154 {
1155 if (!rtx_equal_p (mem_insn.reg1, inc_insn.reg1))
1156 {
1157 /* See comment above on find_inc (false) call. */
1158 if (first_try)
1159 {
1160 reverse_mem ();
1161 return find_inc (false);
1162 }
1163 else
1164 return false;
1165 }
1166
1167 /* Need to check that there are no assignments to b
1168 before the add insn. */
1169 other_insn
1170 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
1171 if (other_insn && luid > DF_INSN_LUID (other_insn))
1172 return false;
1173 /* All ok for the next step. */
1174 }
1175 else
1176 {
1177 /* We know that mem_insn.reg0 must equal inc_insn.reg1
1178 or else we would not have found the inc insn. */
1179 reverse_mem ();
1180 if (!rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
1181 {
1182 /* See comment above on find_inc (false) call. */
1183 if (first_try)
1184 return find_inc (false);
1185 else
1186 return false;
1187 }
1188 /* To have gotten here know that.
1189 *(b + a)
1190
1191 ... = (b + a)
1192
1193 We also know that the lhs of the inc is not b or a. We
1194 need to make sure that there are no assignments to b
1195 between the mem ref and the inc. */
1196
1197 other_insn
1198 = get_next_ref (REGNO (inc_insn.reg0), bb, reg_next_def);
1199 if (other_insn && luid > DF_INSN_LUID (other_insn))
1200 return false;
1201 }
1202
1203 /* Need to check that the next use of the add result is later than
1204 add insn since this will be the reg incremented. */
1205 other_insn
1206 = get_next_ref (REGNO (inc_insn.reg_res), bb, reg_next_use);
1207 if (other_insn && luid > DF_INSN_LUID (other_insn))
1208 return false;
1209 }
1210 else /* FORM_POST_INC. There is less to check here because we
1211 know that operands must line up. */
1212 {
1213 if (!rtx_equal_p (mem_insn.reg1, inc_insn.reg1))
1214 /* See comment above on find_inc (false) call. */
1215 {
1216 if (first_try)
1217 {
1218 reverse_mem ();
1219 return find_inc (false);
1220 }
1221 else
1222 return false;
1223 }
1224
1225 /* To have gotten here know that.
1226 *(a + b)
1227
1228 ... = (a + b)
1229
1230 We also know that the lhs of the inc is not b. We need to make
1231 sure that there are no assignments to b between the mem ref and
1232 the inc. */
1233 other_insn
1234 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
1235 if (other_insn && luid > DF_INSN_LUID (other_insn))
1236 return false;
1237 }
1238 }
1239
1240 if (inc_insn.form == FORM_POST_INC)
1241 {
1242 other_insn
1243 = get_next_ref (REGNO (inc_insn.reg0), bb, reg_next_use);
1244 /* When we found inc_insn, we were looking for the
1245 next add or inc, not the next insn that used the
1246 reg. Because we are going to increment the reg
1247 in this form, we need to make sure that there
1248 were no intervening uses of reg. */
1249 if (inc_insn.insn != other_insn)
1250 return false;
1251 }
1252
1253 return try_merge ();
1254 }
1255
1256
1257 /* A recursive function that walks ADDRESS_OF_X to find all of the mem
1258 uses in pat that could be used as an auto inc or dec. It then
1259 calls FIND_INC for each one. */
1260
1261 static bool
1262 find_mem (rtx *address_of_x)
1263 {
1264 rtx x = *address_of_x;
1265 enum rtx_code code = GET_CODE (x);
1266 const char *const fmt = GET_RTX_FORMAT (code);
1267 int i;
1268
1269 if (code == MEM && REG_P (XEXP (x, 0)))
1270 {
1271 /* Match with *reg0. */
1272 mem_insn.mem_loc = address_of_x;
1273 mem_insn.reg0 = XEXP (x, 0);
1274 mem_insn.reg1_is_const = true;
1275 mem_insn.reg1_val = 0;
1276 mem_insn.reg1 = GEN_INT (0);
1277 if (find_inc (true))
1278 return true;
1279 }
1280 if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
1281 && REG_P (XEXP (XEXP (x, 0), 0)))
1282 {
1283 rtx reg1 = XEXP (XEXP (x, 0), 1);
1284 mem_insn.mem_loc = address_of_x;
1285 mem_insn.reg0 = XEXP (XEXP (x, 0), 0);
1286 mem_insn.reg1 = reg1;
1287 if (CONST_INT_P (reg1))
1288 {
1289 mem_insn.reg1_is_const = true;
1290 /* Match with *(reg0 + c) where c is a const. */
1291 mem_insn.reg1_val = INTVAL (reg1);
1292 if (find_inc (true))
1293 return true;
1294 }
1295 else if (REG_P (reg1))
1296 {
1297 /* Match with *(reg0 + reg1). */
1298 mem_insn.reg1_is_const = false;
1299 if (find_inc (true))
1300 return true;
1301 }
1302 }
1303
1304 if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
1305 {
1306 /* If REG occurs inside a MEM used in a bit-field reference,
1307 that is unacceptable. */
1308 return false;
1309 }
1310
1311 /* Time for some deep diving. */
1312 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1313 {
1314 if (fmt[i] == 'e')
1315 {
1316 if (find_mem (&XEXP (x, i)))
1317 return true;
1318 }
1319 else if (fmt[i] == 'E')
1320 {
1321 int j;
1322 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1323 if (find_mem (&XVECEXP (x, i, j)))
1324 return true;
1325 }
1326 }
1327 return false;
1328 }
1329
1330
1331 /* Try to combine all incs and decs by constant values with memory
1332 references in BB. */
1333
1334 static void
1335 merge_in_block (int max_reg, basic_block bb)
1336 {
1337 rtx insn;
1338 rtx curr;
1339 int success_in_block = 0;
1340
1341 if (dump_file)
1342 fprintf (dump_file, "\n\nstarting bb %d\n", bb->index);
1343
1344 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
1345 {
1346 unsigned int uid = INSN_UID (insn);
1347 bool insn_is_add_or_inc = true;
1348
1349 if (!NONDEBUG_INSN_P (insn))
1350 continue;
1351
1352 /* This continue is deliberate. We do not want the uses of the
1353 jump put into reg_next_use because it is not considered safe to
1354 combine a preincrement with a jump. */
1355 if (JUMP_P (insn))
1356 continue;
1357
1358 if (dump_file)
1359 dump_insn_slim (dump_file, insn);
1360
1361 /* Does this instruction increment or decrement a register? */
1362 if (parse_add_or_inc (insn, true))
1363 {
1364 int regno = REGNO (inc_insn.reg_res);
1365 /* Cannot handle case where there are three separate regs
1366 before a mem ref. Too many moves would be needed to be
1367 profitable. */
1368 if ((inc_insn.form == FORM_PRE_INC) || inc_insn.reg1_is_const)
1369 {
1370 mem_insn.insn = get_next_ref (regno, bb, reg_next_use);
1371 if (mem_insn.insn)
1372 {
1373 bool ok = true;
1374 if (!inc_insn.reg1_is_const)
1375 {
1376 /* We are only here if we are going to try a
1377 HAVE_*_MODIFY_REG type transformation. c is a
1378 reg and we must sure that the path from the
1379 inc_insn to the mem_insn.insn is both def and use
1380 clear of c because the inc insn is going to move
1381 into the mem_insn.insn. */
1382 int luid = DF_INSN_LUID (mem_insn.insn);
1383 rtx other_insn
1384 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);
1385
1386 if (other_insn && luid > DF_INSN_LUID (other_insn))
1387 ok = false;
1388
1389 other_insn
1390 = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
1391
1392 if (other_insn && luid > DF_INSN_LUID (other_insn))
1393 ok = false;
1394 }
1395
1396 if (dump_file)
1397 dump_inc_insn (dump_file);
1398
1399 if (ok && find_address (&PATTERN (mem_insn.insn)) == -1)
1400 {
1401 if (dump_file)
1402 dump_mem_insn (dump_file);
1403 if (try_merge ())
1404 {
1405 success_in_block++;
1406 insn_is_add_or_inc = false;
1407 }
1408 }
1409 }
1410 }
1411 }
1412 else
1413 {
1414 insn_is_add_or_inc = false;
1415 mem_insn.insn = insn;
1416 if (find_mem (&PATTERN (insn)))
1417 success_in_block++;
1418 }
1419
1420 /* If the inc insn was merged with a mem, the inc insn is gone
1421 and there is noting to update. */
1422 if (DF_INSN_UID_GET (uid))
1423 {
1424 df_ref *def_rec;
1425 df_ref *use_rec;
1426 /* Need to update next use. */
1427 for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
1428 {
1429 df_ref def = *def_rec;
1430 reg_next_use[DF_REF_REGNO (def)] = NULL;
1431 reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
1432 reg_next_def[DF_REF_REGNO (def)] = insn;
1433 }
1434
1435 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
1436 {
1437 df_ref use = *use_rec;
1438 reg_next_use[DF_REF_REGNO (use)] = insn;
1439 if (insn_is_add_or_inc)
1440 reg_next_inc_use[DF_REF_REGNO (use)] = insn;
1441 else
1442 reg_next_inc_use[DF_REF_REGNO (use)] = NULL;
1443 }
1444 }
1445 else if (dump_file)
1446 fprintf (dump_file, "skipping update of deleted insn %d\n", uid);
1447 }
1448
1449 /* If we were successful, try again. There may have been several
1450 opportunities that were interleaved. This is rare but
1451 gcc.c-torture/compile/pr17273.c actually exhibits this. */
1452 if (success_in_block)
1453 {
1454 /* In this case, we must clear these vectors since the trick of
1455 testing if the stale insn in the block will not work. */
1456 memset (reg_next_use, 0, max_reg * sizeof(rtx));
1457 memset (reg_next_inc_use, 0, max_reg * sizeof(rtx));
1458 memset (reg_next_def, 0, max_reg * sizeof(rtx));
1459 df_recompute_luids (bb);
1460 merge_in_block (max_reg, bb);
1461 }
1462 }
1463
1464 #endif
1465
1466 static unsigned int
1467 rest_of_handle_auto_inc_dec (void)
1468 {
1469 #ifdef AUTO_INC_DEC
1470 basic_block bb;
1471 int max_reg = max_reg_num ();
1472
1473 if (!initialized)
1474 init_decision_table ();
1475
1476 mem_tmp = gen_rtx_MEM (Pmode, NULL_RTX);
1477
1478 df_note_add_problem ();
1479 df_analyze ();
1480
1481 reg_next_use = XCNEWVEC (rtx, max_reg);
1482 reg_next_inc_use = XCNEWVEC (rtx, max_reg);
1483 reg_next_def = XCNEWVEC (rtx, max_reg);
1484 FOR_EACH_BB (bb)
1485 merge_in_block (max_reg, bb);
1486
1487 free (reg_next_use);
1488 free (reg_next_inc_use);
1489 free (reg_next_def);
1490
1491 mem_tmp = NULL;
1492 #endif
1493 return 0;
1494 }
1495
1496
1497 /* Discover auto-inc auto-dec instructions. */
1498
1499 static bool
1500 gate_auto_inc_dec (void)
1501 {
1502 #ifdef AUTO_INC_DEC
1503 return (optimize > 0 && flag_auto_inc_dec);
1504 #else
1505 return false;
1506 #endif
1507 }
1508
1509
1510 struct rtl_opt_pass pass_inc_dec =
1511 {
1512 {
1513 RTL_PASS,
1514 "auto_inc_dec", /* name */
1515 OPTGROUP_NONE, /* optinfo_flags */
1516 gate_auto_inc_dec, /* gate */
1517 rest_of_handle_auto_inc_dec, /* execute */
1518 NULL, /* sub */
1519 NULL, /* next */
1520 0, /* static_pass_number */
1521 TV_AUTO_INC_DEC, /* tv_id */
1522 0, /* properties_required */
1523 0, /* properties_provided */
1524 0, /* properties_destroyed */
1525 0, /* todo_flags_start */
1526 TODO_df_finish, /* todo_flags_finish */
1527 }
1528 };