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