remove unused files
[platform/upstream/gcc48.git] / gcc / compare-elim.c
1 /* Post-reload compare elimination.
2    Copyright (C) 2010-2013 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 /* There is a set of targets whose general-purpose move or addition
21    instructions clobber the flags.  These targets cannot split their
22    CBRANCH/CSTORE etc patterns before reload is complete, lest reload
23    itself insert these instructions in between the flags setter and user.
24    Because these targets cannot split the compare from the use, they
25    cannot make use of the comparison elimination offered by the combine pass.
26
27    This is a small pass intended to provide comparison elimination similar to
28    what is available via NOTICE_UPDATE_CC for cc0 targets.  This should help
29    encourage cc0 targets to convert to an explicit post-reload representation
30    of the flags.
31
32    This pass assumes:
33
34    (0) CBRANCH/CSTORE etc have been split in pass_split_after_reload.
35
36    (1) All comparison patterns are represented as
37
38         [(set (reg:CC) (compare:CC (reg) (immediate)))]
39
40    (2) All insn patterns that modify the flags are represented as
41
42         [(set (reg) (operation)
43          (clobber (reg:CC))]
44
45    (3) If an insn of form (2) can usefully set the flags, there is
46        another pattern of the form
47
48         [(set (reg) (operation)
49          (set (reg:CCM) (compare:CCM (operation) (immediate)))]
50
51        The mode CCM will be chosen as if by SELECT_CC_MODE.
52
53    Note that unlike NOTICE_UPDATE_CC, we do not handle memory operands.
54    This could be handled as a future enhancement.
55 */
56
57 #include "config.h"
58 #include "system.h"
59 #include "coretypes.h"
60 #include "tm.h"
61 #include "rtl.h"
62 #include "tm_p.h"
63 #include "insn-config.h"
64 #include "recog.h"
65 #include "flags.h"
66 #include "basic-block.h"
67 #include "tree-pass.h"
68 #include "target.h"
69 #include "df.h"
70 #include "domwalk.h"
71
72 \f
73 /* These structures describe a comparison and how it is used.  */
74
75 /* The choice of maximum 3 uses comes from wanting to eliminate the two
76    duplicate compares from a three-way branch on the sign of a value.
77    This is also sufficient to eliminate the duplicate compare against the
78    high-part of a double-word comparison.  */
79 #define MAX_CMP_USE 3
80
81 struct comparison_use
82 {
83   /* The instruction in which the result of the compare is used.  */
84   rtx insn;
85   /* The location of the flags register within the use.  */
86   rtx *loc;
87   /* The comparison code applied against the flags register.  */
88   enum rtx_code code;
89 };
90
91 struct comparison
92 {
93   /* The comparison instruction.  */
94   rtx insn;
95
96   /* The insn prior to the comparison insn that clobbers the flags.  */
97   rtx prev_clobber;
98
99   /* The two values being compared.  These will be either REGs or
100      constants.  */
101   rtx in_a, in_b;
102
103   /* Information about how this comparison is used.  */
104   struct comparison_use uses[MAX_CMP_USE];
105
106   /* The original CC_MODE for this comparison.  */
107   enum machine_mode orig_mode;
108
109   /* The number of uses identified for this comparison.  */
110   unsigned short n_uses;
111
112   /* True if not all uses of this comparison have been identified.
113      This can happen either for overflowing the array above, or if
114      the flags register is used in some unusual context.  */
115   bool missing_uses;
116
117   /* True if its inputs are still valid at the end of the block.  */
118   bool inputs_valid;
119 };
120   
121 typedef struct comparison *comparison_struct_p;
122
123 static vec<comparison_struct_p> all_compares;
124
125 /* Look for a "conforming" comparison, as defined above.  If valid, return
126    the rtx for the COMPARE itself.  */
127
128 static rtx
129 conforming_compare (rtx insn)
130 {
131   rtx set, src, dest;
132
133   set = single_set (insn);
134   if (set == NULL)
135     return NULL;
136
137   src = SET_SRC (set);
138   if (GET_CODE (src) != COMPARE)
139     return NULL;
140
141   dest = SET_DEST (set);
142   if (!REG_P (dest) || REGNO (dest) != targetm.flags_regnum)
143     return NULL;
144
145   if (REG_P (XEXP (src, 0))
146       && REG_P (XEXP (src, 0))
147       && (REG_P (XEXP (src, 1)) || CONSTANT_P (XEXP (src, 1))))
148     return src;
149
150   return NULL;
151 }
152
153 /* Look for a pattern of the "correct" form for an insn with a flags clobber
154    for which we may be able to eliminate a compare later.  We're not looking
155    to validate any inputs at this time, merely see that the basic shape is
156    correct.  The term "arithmetic" may be somewhat misleading...  */
157
158 static bool
159 arithmetic_flags_clobber_p (rtx insn)
160 {
161   rtx pat, x;
162
163   if (!NONJUMP_INSN_P (insn))
164     return false;
165   pat = PATTERN (insn);
166   if (extract_asm_operands (pat))
167     return false;
168
169   if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) == 2)
170     {
171       x = XVECEXP (pat, 0, 0);
172       if (GET_CODE (x) != SET)
173         return false;
174       x = SET_DEST (x);
175       if (!REG_P (x))
176         return false;
177
178       x = XVECEXP (pat, 0, 1);
179       if (GET_CODE (x) == CLOBBER)
180         {
181           x = XEXP (x, 0);
182           if (REG_P (x) && REGNO (x) == targetm.flags_regnum)
183             return true;
184         }
185     }
186
187   return false;
188 }
189
190 /* Look for uses of FLAGS in INSN.  If we find one we can analyze, record
191    it in CMP; otherwise indicate that we've missed a use.  */
192
193 static void
194 find_flags_uses_in_insn (struct comparison *cmp, rtx insn)
195 {
196   df_ref *use_rec, use;
197
198   /* If we've already lost track of uses, don't bother collecting more.  */
199   if (cmp->missing_uses)
200     return;
201
202   /* Find a USE of the flags register.  */
203   for (use_rec = DF_INSN_USES (insn); (use = *use_rec) != NULL; use_rec++)
204     if (DF_REF_REGNO (use) == targetm.flags_regnum)
205       {
206         rtx x, *loc;
207
208         /* If this is an unusual use, quit.  */
209         if (DF_REF_TYPE (use) != DF_REF_REG_USE)
210           goto fail;
211
212         /* If we've run out of slots to record uses, quit.  */
213         if (cmp->n_uses == MAX_CMP_USE)
214           goto fail;
215
216         /* Unfortunately the location of the flags register, while present
217            in the reference structure, doesn't help.  We need to find the
218            comparison code that is outer to the actual flags use.  */
219         loc = DF_REF_LOC (use);
220         x = PATTERN (insn);
221         if (GET_CODE (x) == PARALLEL)
222           x = XVECEXP (x, 0, 0);
223         x = SET_SRC (x);
224         if (GET_CODE (x) == IF_THEN_ELSE)
225           x = XEXP (x, 0);
226         if (COMPARISON_P (x)
227             && loc == &XEXP (x, 0)
228             && XEXP (x, 1) == const0_rtx)
229           {
230             /* We've found a use of the flags that we understand.  */
231             struct comparison_use *cuse = &cmp->uses[cmp->n_uses++];
232             cuse->insn = insn;
233             cuse->loc = loc;
234             cuse->code = GET_CODE (x);
235           }
236         else
237           goto fail;
238       }
239   return;
240
241  fail:
242   /* We failed to recognize this use of the flags register.  */
243   cmp->missing_uses = true;
244 }
245
246 /* Identify comparison instructions within BB.  If the flags from the last
247    compare in the BB is live at the end of the block, install the compare
248    in BB->AUX.  Called via walk_dominators_tree.  */
249
250 static void
251 find_comparisons_in_bb (struct dom_walk_data *data ATTRIBUTE_UNUSED,
252                         basic_block bb)
253 {
254   struct comparison *last_cmp;
255   rtx insn, next, last_clobber;
256   bool last_cmp_valid;
257   bitmap killed;
258
259   killed = BITMAP_ALLOC (NULL);
260
261   /* The last comparison that was made.  Will be reset to NULL
262      once the flags are clobbered.  */
263   last_cmp = NULL;
264
265   /* True iff the last comparison has not been clobbered, nor
266      have its inputs.  Used to eliminate duplicate compares.  */
267   last_cmp_valid = false;
268
269   /* The last insn that clobbered the flags, if that insn is of
270      a form that may be valid for eliminating a following compare.
271      To be reset to NULL once the flags are set otherwise.  */
272   last_clobber = NULL;
273
274   /* Propagate the last live comparison throughout the extended basic block. */
275   if (single_pred_p (bb))
276     {
277       last_cmp = (struct comparison *) single_pred (bb)->aux;
278       if (last_cmp)
279         last_cmp_valid = last_cmp->inputs_valid;
280     }
281
282   for (insn = BB_HEAD (bb); insn; insn = next)
283     {
284       rtx src;
285
286       next = (insn == BB_END (bb) ? NULL_RTX : NEXT_INSN (insn));
287       if (!NONDEBUG_INSN_P (insn))
288         continue;
289
290       /* Compute the set of registers modified by this instruction.  */
291       bitmap_clear (killed);
292       df_simulate_find_defs (insn, killed);
293
294       src = conforming_compare (insn);
295       if (src)
296         {
297           enum machine_mode src_mode = GET_MODE (src);
298
299           /* Eliminate a compare that's redundant with the previous.  */
300           if (last_cmp_valid
301               && rtx_equal_p (last_cmp->in_a, XEXP (src, 0))
302               && rtx_equal_p (last_cmp->in_b, XEXP (src, 1)))
303             {
304               rtx flags, x;
305               enum machine_mode new_mode
306                 = targetm.cc_modes_compatible (last_cmp->orig_mode, src_mode);
307
308               /* New mode is incompatible with the previous compare mode.  */
309               if (new_mode == VOIDmode)
310                 continue;
311
312               if (new_mode != last_cmp->orig_mode)
313                 {
314                   flags = gen_rtx_REG (src_mode, targetm.flags_regnum);
315
316                   /* Generate new comparison for substitution.  */
317                   x = gen_rtx_COMPARE (new_mode, XEXP (src, 0), XEXP (src, 1));
318                   x = gen_rtx_SET (VOIDmode, flags, x);
319
320                   if (!validate_change (last_cmp->insn,
321                                         &PATTERN (last_cmp->insn), x, false))
322                     continue;
323
324                   last_cmp->orig_mode = new_mode;
325                 }
326
327               delete_insn (insn);
328               continue;
329             }
330
331           last_cmp = XCNEW (struct comparison);
332           last_cmp->insn = insn;
333           last_cmp->prev_clobber = last_clobber;
334           last_cmp->in_a = XEXP (src, 0);
335           last_cmp->in_b = XEXP (src, 1);
336           last_cmp->orig_mode = src_mode;
337           all_compares.safe_push (last_cmp);
338
339           /* It's unusual, but be prepared for comparison patterns that
340              also clobber an input, or perhaps a scratch.  */
341           last_clobber = NULL;
342           last_cmp_valid = true;
343         }
344
345       /* Notice if this instruction kills the flags register.  */
346       else if (bitmap_bit_p (killed, targetm.flags_regnum))
347         {
348           /* See if this insn could be the "clobber" that eliminates
349              a future comparison.   */
350           last_clobber = (arithmetic_flags_clobber_p (insn) ? insn : NULL);
351
352           /* In either case, the previous compare is no longer valid.  */
353           last_cmp = NULL;
354           last_cmp_valid = false;
355           continue;
356         }
357
358       /* Notice if this instruction uses the flags register.  */
359       else if (last_cmp)
360         find_flags_uses_in_insn (last_cmp, insn);
361
362       /* Notice if any of the inputs to the comparison have changed.  */
363       if (last_cmp_valid
364           && (bitmap_bit_p (killed, REGNO (last_cmp->in_a))
365               || (REG_P (last_cmp->in_b)
366                   && bitmap_bit_p (killed, REGNO (last_cmp->in_b)))))
367         last_cmp_valid = false;
368     }
369
370   BITMAP_FREE (killed);
371
372   /* Remember the live comparison for subsequent members of
373      the extended basic block.  */
374   if (last_cmp)
375     {
376       bb->aux = last_cmp;
377       last_cmp->inputs_valid = last_cmp_valid;
378
379       /* Look to see if the flags register is live outgoing here, and
380          incoming to any successor not part of the extended basic block.  */
381       if (bitmap_bit_p (df_get_live_out (bb), targetm.flags_regnum))
382         {
383           edge e;
384           edge_iterator ei;
385
386           FOR_EACH_EDGE (e, ei, bb->succs)
387             {
388               basic_block dest = e->dest;
389               if (bitmap_bit_p (df_get_live_in (bb),
390                                 targetm.flags_regnum)
391                   && !single_pred_p (dest))
392                 {
393                   last_cmp->missing_uses = true;
394                   break;
395                 }
396             }
397         }
398     }
399 }
400
401 /* Find all comparisons in the function.  */
402
403 static void
404 find_comparisons (void)
405 {
406   struct dom_walk_data data;
407
408   memset (&data, 0, sizeof(data));
409   data.dom_direction = CDI_DOMINATORS;
410   data.before_dom_children = find_comparisons_in_bb;
411
412   calculate_dominance_info (CDI_DOMINATORS);
413
414   init_walk_dominator_tree (&data);
415   walk_dominator_tree (&data, ENTRY_BLOCK_PTR);
416   fini_walk_dominator_tree (&data);
417
418   clear_aux_for_blocks ();
419   free_dominance_info (CDI_DOMINATORS);
420 }
421
422 /* Select an alternate CC_MODE for a comparison insn comparing A and B.
423    Note that inputs are almost certainly different than the IN_A and IN_B
424    stored in CMP -- we're called while attempting to eliminate the compare
425    after all.  Return the new FLAGS rtx if successful, else return NULL.
426    Note that this function may start a change group.  */
427
428 static rtx
429 maybe_select_cc_mode (struct comparison *cmp, rtx a ATTRIBUTE_UNUSED,
430                       rtx b ATTRIBUTE_UNUSED)
431 {
432   enum machine_mode sel_mode;
433   const int n = cmp->n_uses;
434   rtx flags = NULL;
435
436 #ifndef SELECT_CC_MODE
437   /* Minimize code differences when this target macro is undefined.  */
438   return NULL;
439 #define SELECT_CC_MODE(A,B,C) (gcc_unreachable (), VOIDmode)
440 #endif
441
442   /* If we don't have access to all of the uses, we can't validate.  */
443   if (cmp->missing_uses || n == 0)
444     return NULL;
445
446   /* Find a new mode that works for all of the uses.  Special case the
447      common case of exactly one use.  */
448   if (n == 1)
449     {
450       sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
451       if (sel_mode != cmp->orig_mode)
452         {
453           flags = gen_rtx_REG (sel_mode, targetm.flags_regnum);
454           validate_change (cmp->uses[0].insn, cmp->uses[0].loc, flags, true);
455         }
456     }
457   else
458     {
459       int i;
460
461       sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
462       for (i = 1; i < n; ++i)
463         {
464           enum machine_mode new_mode;
465           new_mode = SELECT_CC_MODE (cmp->uses[i].code, a, b);
466           if (new_mode != sel_mode)
467             {
468               sel_mode = targetm.cc_modes_compatible (sel_mode, new_mode);
469               if (sel_mode == VOIDmode)
470                 return NULL;
471             }
472         }
473       
474       if (sel_mode != cmp->orig_mode)
475         {
476           flags = gen_rtx_REG (sel_mode, targetm.flags_regnum);
477           for (i = 0; i < n; ++i)
478             validate_change (cmp->uses[i].insn, cmp->uses[i].loc, flags, true);
479         }
480     }
481
482   return flags;
483 }
484
485 /* Attempt to replace a comparison with a prior arithmetic insn that can
486    compute the same flags value as the comparison itself.  Return true if
487    successful, having made all rtl modifications necessary.  */
488
489 static bool
490 try_eliminate_compare (struct comparison *cmp)
491 {
492   rtx x, insn, bb_head, flags, in_a, cmp_src;
493
494   /* We must have found an interesting "clobber" preceding the compare.  */
495   if (cmp->prev_clobber == NULL)
496     return false;
497
498   /* ??? For the moment we don't handle comparisons for which IN_B
499      is a register.  We accepted these during initial comparison 
500      recognition in order to eliminate duplicate compares.
501      An improvement here would be to handle x = a - b; if (a cmp b).  */
502   if (!CONSTANT_P (cmp->in_b))
503     return false;
504
505   /* Verify that IN_A is not clobbered in between CMP and PREV_CLOBBER.
506      Given that this target requires this pass, we can assume that most
507      insns do clobber the flags, and so the distance between the compare
508      and the clobber is likely to be small.  */
509   /* ??? This is one point at which one could argue that DF_REF_CHAIN would
510      be useful, but it is thought to be too heavy-weight a solution here.  */
511
512   in_a = cmp->in_a;
513   insn = cmp->insn;
514   bb_head = BB_HEAD (BLOCK_FOR_INSN (insn));
515   for (insn = PREV_INSN (insn);
516        insn != cmp->prev_clobber;
517        insn = PREV_INSN (insn))
518     {
519       const int abnormal_flags
520         = (DF_REF_CONDITIONAL | DF_REF_PARTIAL | DF_REF_MAY_CLOBBER
521            | DF_REF_MUST_CLOBBER | DF_REF_SIGN_EXTRACT
522            | DF_REF_ZERO_EXTRACT | DF_REF_STRICT_LOW_PART
523            | DF_REF_PRE_POST_MODIFY);
524       df_ref *def_rec, def;
525
526       /* Note that the BB_HEAD is always either a note or a label, but in
527          any case it means that IN_A is defined outside the block.  */
528       if (insn == bb_head)
529         return false;
530       if (NOTE_P (insn) || DEBUG_INSN_P (insn))
531         continue;
532
533       /* Find a possible def of IN_A in INSN.  */
534       for (def_rec = DF_INSN_DEFS (insn); (def = *def_rec) != NULL; def_rec++)
535         if (DF_REF_REGNO (def) == REGNO (in_a))
536           break;
537
538       /* No definitions of IN_A; continue searching.  */
539       if (def == NULL)
540         continue;
541
542       /* Bail if this is not a totally normal set of IN_A.  */
543       if (DF_REF_IS_ARTIFICIAL (def))
544         return false;
545       if (DF_REF_FLAGS (def) & abnormal_flags)
546         return false;
547
548       /* We've found an insn between the compare and the clobber that sets
549          IN_A.  Given that pass_cprop_hardreg has not yet run, we still find
550          situations in which we can usefully look through a copy insn.  */
551       x = single_set (insn);
552       if (x == NULL)
553         return false;
554       in_a = SET_SRC (x);
555       if (!REG_P (in_a))
556         return false;
557     }
558
559   /* We've reached PREV_CLOBBER without finding a modification of IN_A.
560      Validate that PREV_CLOBBER itself does in fact refer to IN_A.  Do
561      recall that we've already validated the shape of PREV_CLOBBER.  */
562   x = XVECEXP (PATTERN (insn), 0, 0);
563   if (rtx_equal_p (SET_DEST (x), in_a))
564     cmp_src = SET_SRC (x);
565
566   /* Also check operations with implicit extensions, e.g.:
567      [(set (reg:DI)
568            (zero_extend:DI (plus:SI (reg:SI)(reg:SI))))
569       (set (reg:CCZ flags)
570            (compare:CCZ
571              (plus:SI (reg:SI)(reg:SI))
572              (const_int 0)))]                           */
573   else if (REG_P (SET_DEST (x))
574            && REG_P (in_a)
575            && REGNO (SET_DEST (x)) == REGNO (in_a)
576            && (GET_CODE (SET_SRC (x)) == ZERO_EXTEND
577                || GET_CODE (SET_SRC (x)) == SIGN_EXTEND)
578            && GET_MODE (XEXP (SET_SRC (x), 0)) == GET_MODE (in_a))
579     cmp_src = XEXP (SET_SRC (x), 0);
580   else
581     return false;
582
583   /* Determine if we ought to use a different CC_MODE here.  */
584   flags = maybe_select_cc_mode (cmp, cmp_src, cmp->in_b);
585   if (flags == NULL)
586     flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum);
587
588   /* Generate a new comparison for installation in the setter.  */
589   x = copy_rtx (cmp_src);
590   x = gen_rtx_COMPARE (GET_MODE (flags), x, cmp->in_b);
591   x = gen_rtx_SET (VOIDmode, flags, x);
592
593   /* Succeed if the new instruction is valid.  Note that we may have started
594      a change group within maybe_select_cc_mode, therefore we must continue. */
595   validate_change (insn, &XVECEXP (PATTERN (insn), 0, 1), x, true);
596   if (!apply_change_group ())
597     return false;
598  
599   /* Success.  Delete the compare insn...  */
600   delete_insn (cmp->insn);
601
602   /* ... and any notes that are now invalid due to multiple sets.  */
603   x = find_regno_note (insn, REG_UNUSED, targetm.flags_regnum);
604   if (x)
605     remove_note (insn, x);
606   x = find_reg_note (insn, REG_EQUAL, NULL);
607   if (x)
608     remove_note (insn, x);
609   x = find_reg_note (insn, REG_EQUIV, NULL);
610   if (x)
611     remove_note (insn, x);
612
613   return true;
614 }
615
616 /* Main entry point to the pass.  */
617
618 static unsigned int
619 execute_compare_elim_after_reload (void)
620 {
621   df_analyze ();
622
623   gcc_checking_assert (!all_compares.exists ());
624
625   /* Locate all comparisons and their uses, and eliminate duplicates.  */
626   find_comparisons ();
627   if (all_compares.exists ())
628     {
629       struct comparison *cmp;
630       size_t i;
631
632       /* Eliminate comparisons that are redundant with flags computation.  */
633       FOR_EACH_VEC_ELT (all_compares, i, cmp)
634         {
635           try_eliminate_compare (cmp);
636           XDELETE (cmp);
637         }
638
639       all_compares.release ();
640     }
641
642   return 0;
643 }
644
645 static bool
646 gate_compare_elim_after_reload (void)
647 {
648   /* Setting this target hook value is how a backend indicates the need.  */
649   if (targetm.flags_regnum == INVALID_REGNUM)
650     return false;
651   return flag_compare_elim_after_reload;
652 }
653
654 struct rtl_opt_pass pass_compare_elim_after_reload =
655 {
656  {
657   RTL_PASS,
658   "cmpelim",                            /* name */
659   OPTGROUP_NONE,                        /* optinfo_flags */
660   gate_compare_elim_after_reload,       /* gate */
661   execute_compare_elim_after_reload,    /* execute */
662   NULL,                                 /* sub */
663   NULL,                                 /* next */
664   0,                                    /* static_pass_number */
665   TV_NONE,                              /* tv_id */
666   0,                                    /* properties_required */
667   0,                                    /* properties_provided */
668   0,                                    /* properties_destroyed */
669   0,                                    /* todo_flags_start */
670   TODO_df_finish
671   | TODO_df_verify
672   | TODO_verify_rtl_sharing
673   | TODO_ggc_collect                    /* todo_flags_finish */
674  }
675 };