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