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