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