xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/sh/sh_treg_combine.cc (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /* An SH specific RTL pass that tries to combine comparisons and redundant
2    condition code register stores across multiple basic blocks.
3    Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License 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 #define INCLUDE_ALGORITHM
23 #define INCLUDE_LIST
24 #define INCLUDE_VECTOR
25 #include "system.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "memmodel.h"
32 #include "optabs.h"
33 #include "emit-rtl.h"
34 #include "recog.h"
35 #include "cfgrtl.h"
36 #include "tree-pass.h"
37 #include "expr.h"
38 
39 /*
40 This pass tries to optimize for example this:
41 	mov.l	@(4,r4),r1
42 	tst	r1,r1
43 	movt	r1
44 	tst	r1,r1
45 	bt/s	.L5
46 
47 into something simpler:
48 	mov.l	@(4,r4),r1
49 	tst	r1,r1
50 	bf/s	.L5
51 
52 Such sequences can be identified by looking for conditional branches and
53 checking whether the ccreg is set before the conditional branch
54 by testing another register for != 0, which was set by a ccreg store.
55 This can be optimized by eliminating the redundant comparison and
56 inverting the branch condition.  There can be multiple comparisons in
57 different basic blocks that all end up in the redunant test insn before the
58 conditional branch.  Some example RTL ...
59 
60 Example 1)
61 ----------
62 
63 [bb 3]
64 (set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 0)))
65 (set (reg:SI 167) (xor:SI (reg:SI 147 t) (const_int 1)))
66 -> bb 5
67 
68 [bb 4]
69 (set (reg:SI 147 t) (eq:SI (reg:SI 177) (const_int 0)))
70 (set (reg:SI 167) (reg:SI 147 t))
71 -> bb 5
72 
73 [bb 5]
74 (set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
75 (set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
76                         (label_ref:SI 50) (pc)))
77 
78 In [bb 4] elimination of the comparison would require inversion of the branch
79 condition and compensation of other BBs.
80 Instead the comparison in [bb 3] can be replaced with the comparison in [bb 5]
81 by using a reg-reg move.  In [bb 4] a logical not is used to compensate the
82 inverted condition.
83 
84 [bb 3]
85 (set (reg:SI 167) (reg:SI 173))
86 -> bb 5
87 
88 [BB 4]
89 (set (reg:SI 147 t) (eq:SI (reg:SI 177) (const_int 0)))
90 (set (reg:SI 167) (reg:SI 147 t))
91 -> bb 5
92 
93 [bb 5]
94 (set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
95 (set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0)))
96                         (label_ref:SI 50) (pc)))
97 
98 
99 Example 2)
100 ----------
101 
102 [bb 3]
103 (set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
104 (set (reg:SI 167) (reg:SI 147 t))
105 -> bb 5
106 
107 [bb 4]
108 (set (reg:SI 147 t) (gt:SI (reg:SI 177) (reg:SI 179)))
109 (set (reg:SI 167) (reg:SI 147 t))
110 -> bb 5
111 
112 [bb 5]
113 (set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
114 (set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
115                         (label_ref:SI 51) (pc)))
116 
117 The common comparison is factored out and the branch condition is inverted:
118 
119 [bb 3]
120 (set (reg:SI 167) (reg:SI 173))
121 (set (reg:SI 200) (reg:SI 175))
122 -> bb 5
123 
124 [bb 4]
125 (set (reg:SI 167) (reg:SI 177))
126 (set (reg:SI 200) (reg:SI 179))
127 -> bb 5
128 
129 [bb 5]
130 (set (reg:SI 147 t) (gt:SI (reg:SI 167) (reg:SI 200)))
131 (set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0))
132                         (label_ref:SI 51) (pc)))
133 
134 
135 Example 3)
136 ----------
137 
138 [bb 3]
139 (set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
140 (set (reg:SI 167) (reg:SI 147 t))
141 -> bb 5
142 
143 [bb 4]
144 (set (reg:SI 147 t) (ge:SI (reg:SI 179) (reg:SI 177)))
145 (set (reg:SI 167) (reg:SI 147 t))
146 -> bb 5
147 
148 [bb 5]
149 (set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
150 (set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
151                         (label_ref:SI 51) (pc)))
152 
153 The T bit lifetime is extended and the branch condition is inverted:
154 
155 [bb 3]
156 (set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
157 -> bb 5
158 
159 [bb 4]
160 (set (reg:SI 147 t) (ge:SI (reg:SI 179) (reg:SI 177)))
161 -> bb 5
162 
163 [bb 5]
164 (set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0))
165                         (label_ref:SI 51) (pc)))
166 
167 
168 Example 4)
169 ----------
170 
171 [bb 3]
172 (set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 5)))
173 (set (reg:SI 167) (reg:SI 147 t))
174 -> bb 5
175 
176 [bb 4]
177 (set (reg:SI 147 t) (eq:SI (reg:SI 176) (const_int 5)))
178 (set (reg:SI 167) (xor:SI (reg:SI 147 t) (const_int 1)))
179 -> bb 5
180 
181 [bb 5]
182 (set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
183 (set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
184                         (label_ref:SI 50) (pc)))
185 
186 In this case the comparisons are the same and could be combined, but the
187 branch condition is different for [bb 3] and [bb 5].  Since the comparison
188 is not a zero comparison, we can't negate one of the operands.  The best thing
189 we can do here is to eliminate the comparison before the cbranch and invert
190 the ccreg in one of the BBs.  On SH2A this will utilize the 'nott' instruction.
191 
192 [bb 3]
193 (set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 5)))
194 -> bb 5
195 
196 [bb 4]
197 (set (reg:SI 147 t) (eq:SI (reg:SI 176) (const_int 5)))
198 (set (reg:SI 147 t) (xor:SI (reg:SI 147 t) (const_int 1)))
199 -> bb 5
200 
201 [bb 5]
202 (set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0))  // inverted
203                         (label_ref:SI 50) (pc)))
204 
205 
206 In order to handle cases such as above the RTL pass does the following:
207 
208 - Find the ccreg sets (comparisons) and ccreg stores
209   (inverting and non-inverting) in all related BBs.
210 
211 - If the comparison types in the BBs are all the same, try to combine the
212   comparisons in the BBs and replace the zero comparison before the cbranch
213   with the common comparison.
214 
215     - If the cstores are the same, move the comparison before the cbranch
216       and replace the comparisons in the BBs with reg-reg copies to get the
217       operands in place (create new pseudo regs).
218 
219     - If the cstores differ and the comparison is a test against zero,
220       use reg-reg copies for the dominating cstores and logical not cstores
221       for the subordinate cstores.
222 
223 - If the comparison types in the BBs are not the same, or the first approach
224   doesn't work out for some reason, try to eliminate the comparison before the
225   cbranch by extending the lifetime of the ccreg by leaving the individual
226   comparisons but eliminating the cstores.
227   If the cstores are all the same this is straight forward.
228   If they're not, try to reverse the ccreg for the subordinate cstore type
229   and eliminate the dominating one.
230 */
231 
232 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
233 // Helper functions
234 
235 #define log_msg(...)\
236   do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); } while (0)
237 
238 #define log_insn(i)\
239   do { if (dump_file != NULL) print_rtl_single (dump_file, \
240 						(const_rtx)i); } while (0)
241 
242 #define log_rtx(r)\
243   do { if (dump_file != NULL) print_rtl (dump_file, (const_rtx)r); } while (0)
244 
245 #define log_return(retval, ...)\
246   do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); \
247        return retval; } while (0)
248 
249 #define log_return_void(...)\
250   do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); \
251        return; } while (0)
252 
253 struct set_of_reg
254 {
255   // The insn where the search stopped or NULL.
256   rtx_insn *insn;
257 
258   // The set rtx of the specified reg if found, NULL_RTX otherwise.
259   // Notice that the set rtx can also be in a parallel.
260   const_rtx set_rtx;
261 
262   // The set source operand rtx if found, NULL_RTX otherwise.
263   rtx
264   set_src (void) const
265   {
266     return set_rtx == NULL_RTX ? NULL_RTX : XEXP (set_rtx, 1);
267   }
268 
269   // The set destination operand rtx if found, NULL_RTX otherwise.
270   rtx
271   set_dst (void) const
272   {
273     return set_rtx == NULL_RTX ? NULL_RTX : XEXP (set_rtx, 0);
274   }
275 
276   bool
277   empty (void) const
278   {
279     return insn == NULL_RTX || set_rtx == NULL_RTX;
280   }
281 };
282 
283 // Given a reg rtx and a start insn find the insn (in the same basic block)
284 // that sets the reg.
285 static set_of_reg
286 find_set_of_reg_bb (rtx reg, rtx_insn *insn)
287 {
288   set_of_reg result = { insn, NULL_RTX };
289 
290   if (!REG_P (reg) || insn == NULL)
291     return result;
292 
293   for (result.insn = insn; result.insn != NULL;
294        result.insn = prev_nonnote_insn_bb (result.insn))
295     {
296       if (BARRIER_P (result.insn))
297 	return result;
298       if (!NONJUMP_INSN_P (result.insn))
299 	continue;
300       if (reg_set_p (reg, result.insn))
301 	{
302 	  result.set_rtx = set_of (reg, result.insn);
303 	  if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
304 	    result.set_rtx = NULL_RTX;
305 	  return result;
306 	}
307     }
308 
309   return result;
310 }
311 
312 static bool
313 reg_dead_after_insn (const_rtx reg, const_rtx insn)
314 {
315   return find_regno_note (insn, REG_DEAD, REGNO (reg)) != NULL_RTX;
316 }
317 
318 static bool
319 reg_unused_after_insn (const_rtx reg, const_rtx insn)
320 {
321   return find_regno_note (insn, REG_UNUSED, REGNO (reg)) != NULL_RTX;
322 }
323 
324 // Check whether the two specified basic blocks are adjacent, i.e. there's no
325 // other basic block in between them.
326 static bool
327 is_adjacent_bb (basic_block a, basic_block b)
328 {
329   basic_block bb0[] = { a, b };
330   basic_block bb1[] = { b, a };
331 
332   for (int i = 0; i < 2; ++i)
333     for (edge_iterator ei = ei_start (bb0[i]->succs);
334 	 !ei_end_p (ei); ei_next (&ei))
335       if (ei_edge (ei)->dest == bb1[i])
336 	return true;
337 
338   return false;
339 }
340 
341 // Internal function of trace_reg_uses.
342 static void
343 trace_reg_uses_1 (rtx reg, rtx_insn *start_insn, basic_block bb, int& count,
344 		  std::vector<basic_block>& visited_bb, rtx abort_at_insn)
345 {
346   if (bb == NULL)
347     return;
348 
349   if (std::find (visited_bb.begin (), visited_bb.end (), bb)
350       != visited_bb.end ())
351     log_return_void ("[bb %d] already visited\n", bb->index);
352 
353   visited_bb.push_back (bb);
354 
355   if (BB_END (bb) == NULL_RTX)
356     log_return_void ("[bb %d] BB_END is null\n", bb->index);
357 
358   if (start_insn == NULL_RTX)
359     log_return_void ("[bb %d] start_insn is null\n", bb->index);
360 
361   rtx end_insn = NEXT_INSN (BB_END (bb));
362   if (end_insn == NULL_RTX)
363     log_return_void ("[bb %d] end_insn is null\n", bb->index);
364 
365   for (rtx_insn *i = NEXT_INSN (start_insn); i != end_insn; i = NEXT_INSN (i))
366     {
367       if (INSN_P (i))
368 	{
369 	  if (NONDEBUG_INSN_P (i)
370 	      && (reg_overlap_mentioned_p (reg, PATTERN (i))
371 		  || (CALL_P (i) && find_reg_fusage (i, USE, reg))))
372 	    {
373 	      log_msg ("found use in [bb %d] at insn:\n", bb->index);
374 	      log_insn (i);
375 	      log_msg ("\n");
376 	      count += 1;
377 	    }
378 
379 	  // Stop following this BB if the reg is set or dies along the way.
380 	  if (reg_set_p (reg, i) || reg_dead_after_insn (reg, i))
381 	    return;
382 	}
383 
384       if (abort_at_insn != NULL_RTX && abort_at_insn == i)
385 	return;
386     }
387 
388   for (edge_iterator ei = ei_start (bb->succs); !ei_end_p (ei); ei_next (&ei))
389     {
390       basic_block succ_bb = ei_edge (ei)->dest;
391       trace_reg_uses_1 (reg, BB_HEAD (succ_bb), succ_bb, count, visited_bb,
392 			abort_at_insn);
393     }
394 }
395 
396 // Trace uses of the specified reg in all basic blocks that are reachable from
397 // the specified insn.  If 'abort_at_insn' is not null, abort the trace at
398 // that insn.  If the insn 'abort_at_insn' uses the specified reg, it is also
399 // counted.
400 static int
401 trace_reg_uses (rtx reg, rtx_insn *start_insn, rtx abort_at_insn)
402 {
403   log_msg ("\ntrace_reg_uses\nreg = ");
404   log_rtx (reg);
405   log_msg ("\nstart_insn = ");
406   log_insn (start_insn);
407 
408   int count = 0;
409   std::vector<basic_block> visited_bb;
410   visited_bb.reserve (32);
411 
412   trace_reg_uses_1 (reg, start_insn, BLOCK_FOR_INSN (start_insn),
413 		    count, visited_bb, abort_at_insn);
414   return count;
415 }
416 
417 static bool
418 is_conditional_insn (rtx_insn* i)
419 {
420   if (! (INSN_P (i) && NONDEBUG_INSN_P (i)))
421     return false;
422 
423   rtx p = PATTERN (i);
424   return GET_CODE (p) == SET && GET_CODE (XEXP (p, 1)) == IF_THEN_ELSE;
425 }
426 
427 // FIXME: Remove dependency on SH predicate function somehow.
428 extern int t_reg_operand (rtx, machine_mode);
429 extern int negt_reg_operand (rtx, machine_mode);
430 
431 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
432 // RTL pass class
433 
434 class sh_treg_combine : public rtl_opt_pass
435 {
436 public:
437   sh_treg_combine (gcc::context* ctx, bool split_insns, const char* name);
438   virtual ~sh_treg_combine (void);
439   virtual bool gate (function *);
440   virtual unsigned int execute (function *);
441 
442 private:
443   // Type of ccreg store that is supported.
444   enum cstore_type_t
445   {
446     cstore_normal = 0,
447     cstore_inverted = 1,
448     cstore_unknown = -1
449   };
450 
451   // Type of branch condition that is supported.
452   enum branch_condition_type_t
453   {
454     branch_if_true = 1,
455     branch_if_false = 0,
456     unknown_branch_condition = -1
457   };
458 
459   // For each basic block there can be a trace entry which consists of an
460   // insn that sets the ccreg (usually a comparison) and a ccreg store.
461   struct bb_entry
462   {
463     basic_block bb;
464     set_of_reg setcc;
465     set_of_reg cstore;
466     cstore_type_t cstore_type;
467     std::vector<set_of_reg> cstore_reg_reg_copies;
468 
469     bb_entry (basic_block b)
470     : bb (b), setcc (), cstore (), cstore_type (cstore_unknown) { }
471 
472     rtx comparison_rtx (void) const { return setcc.set_src (); }
473   };
474 
475   // A ccreg trace for a conditional branch.
476   struct cbranch_trace
477   {
478     rtx_insn *cbranch_insn;
479     rtx* condition_rtx_in_insn;
480     branch_condition_type_t cbranch_type;
481 
482     // The comparison against zero right before the conditional branch.
483     set_of_reg setcc;
484 
485     // All BBs that are related to the cbranch.  The last BB in the list is
486     // the BB of the cbranch itself and might be empty.
487     std::list<bb_entry> bb_entries;
488 
489     cbranch_trace (rtx_insn *insn)
490     : cbranch_insn (insn),
491       condition_rtx_in_insn (NULL),
492       cbranch_type (unknown_branch_condition),
493       setcc ()
494     {
495       if (is_conditional_insn (cbranch_insn))
496 	condition_rtx_in_insn = &XEXP (XEXP (PATTERN (cbranch_insn), 1), 0);
497       else if (rtx x = pc_set (cbranch_insn))
498 	condition_rtx_in_insn = &XEXP (XEXP (x, 1), 0);
499     }
500 
501     basic_block bb (void) const { return BLOCK_FOR_INSN (cbranch_insn); }
502 
503     rtx
504     branch_condition_rtx (void) const
505     {
506       return condition_rtx_in_insn != NULL ? *condition_rtx_in_insn : NULL;
507     }
508     rtx&
509     branch_condition_rtx_ref (void) const
510     {
511       // Before anything gets to invoke this function, there are other checks
512       // in place to make sure that we have a known branch condition and thus
513       // the ref to the rtx in the insn.
514       gcc_assert (condition_rtx_in_insn != NULL);
515       return *condition_rtx_in_insn;
516     }
517 
518     bool
519     can_invert_condition (void) const
520     {
521       // The branch condition can be inverted safely only if the condition
522       // reg is dead after the cbranch.
523       return reg_dead_after_insn (XEXP (branch_condition_rtx (), 0),
524 				  cbranch_insn);
525     }
526   };
527 
528   static const pass_data default_pass_data;
529 
530   // Tells whether modified or newly added insns are to be split at the end
531   // of the pass.
532   const bool m_split_insns;
533 
534   // rtx of the ccreg that is obtained from the target.
535   rtx m_ccreg;
536 
537   // Newly added or modified insns.
538   std::vector<rtx> m_touched_insns;
539 
540   // Given an rtx determine whether it's a comparison with a constant zero.
541   static bool is_cmp_eq_zero (const_rtx i);
542 
543   // Update the stored mode of the ccreg from the given branch condition rtx.
544   void update_ccreg_mode (const_rtx cond);
545 
546   // Given an rtx, figure out the branch condition, assuming that it is
547   // in canonical form:
548   //   (ne (reg) (const_int 0))
549   //   (eq (reg) (const_int 0))
550   branch_condition_type_t branch_condition_type (const_rtx cond) const;
551 
552   // Return true if the specified rtx is either a normal ccreg or
553   // a negated form of the ccreg.
554   bool is_normal_ccreg (const_rtx x) const;
555   bool is_inverted_ccreg (const_rtx x) const;
556 
557   // Given a reg rtx and a start insn rtx, try to find the insn in the same
558   // basic block that sets the specified reg.
559   // Return how the search ended and the insn where it stopped or NULL_RTX.
560   enum record_return_t
561   {
562     set_found,
563     set_not_found,
564     other_set_found
565   };
566   record_return_t record_set_of_reg (rtx reg, rtx_insn *start_insn,
567                                      bb_entry& e);
568 
569   // Tells whether the cbranch insn of the specified bb_entry can be removed
570   // safely without triggering any side effects.
571   bool can_remove_cstore (const bb_entry& e,
572 			  const cbranch_trace& trace) const;
573 
574   // Tells whether the setcc insn of the specified bb_entry can be removed
575   // safely without triggering any side effects.
576   bool can_remove_comparison (const bb_entry& e,
577 			      const cbranch_trace& trace) const;
578 
579   // Tells whether the two specified comparison rtx can be combined into a
580   // single comparison.
581   bool can_combine_comparisons (const_rtx x, const_rtx y) const;
582 
583   // Tells whether the ccreg usage can be extended from the bb_entry on until
584   // the final cbranch of the trace.
585   bool can_extend_ccreg_usage (const bb_entry& e,
586 			       const cbranch_trace& trace) const;
587 
588   // Create an insn rtx that performs a logical not (test != 0) on the src_reg
589   // and stores the result in dst_reg.
590   rtx make_not_reg_insn (rtx dst_reg, rtx src_reg) const;
591 
592   // Create an insn rtx that inverts the ccreg.
593   rtx_insn *make_inv_ccreg_insn (void) const;
594 
595   // Adds the specified insn to the set of modified or newly added insns that
596   // might need splitting at the end of the pass.
597   rtx touched_insn (rtx i);
598 
599   // Try to invert the branch condition of the specified trace.
600   bool try_invert_branch_condition (cbranch_trace& trace);
601 
602   // Try to optimize a cbranch trace by combining comparisons in BBs and
603   // eliminate the cstores.
604   bool try_combine_comparisons (cbranch_trace& trace,
605 				int cstore_count, int inv_cstore_count,
606 				cstore_type_t dominating_cstore);
607 
608   // Try to optimize a cbranch trace by eliminating the cstores in BBs only.
609   bool try_eliminate_cstores (cbranch_trace& trace,
610 			      int cstore_count, int inv_cstore_count,
611 			      cstore_type_t dominating_cstore);
612 
613   // Given a branch insn, try to optimize its branch condition.
614   // If any insns are modified or added they are added to 'm_touched_insns'.
615   void try_optimize_cbranch (rtx_insn *i);
616 };
617 
618 
619 const pass_data sh_treg_combine::default_pass_data =
620 {
621   RTL_PASS,		// type
622   "",			// name (overwritten by the constructor)
623   OPTGROUP_NONE,	// optinfo_flags
624   TV_OPTIMIZE,		// tv_id
625   0,			// properties_required
626   0,			// properties_provided
627   0,			// properties_destroyed
628   0,			// todo_flags_start
629   TODO_df_finish | TODO_df_verify	// todo_flags_finish
630 };
631 
632 sh_treg_combine::sh_treg_combine (gcc::context* ctx, bool split_insns,
633 				  const char* name)
634 : rtl_opt_pass (default_pass_data, ctx),
635   m_split_insns (split_insns),
636   m_ccreg (NULL_RTX)
637 {
638   // Overwrite default name in pass_data base class.
639   this->name = name;
640 }
641 
642 sh_treg_combine::~sh_treg_combine (void)
643 {
644 }
645 
646 void sh_treg_combine::update_ccreg_mode (const_rtx cond)
647 {
648   if (REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) != REGNO (m_ccreg))
649     return;
650 
651   machine_mode m = GET_MODE (XEXP (cond, 0));
652   if (m == GET_MODE (m_ccreg))
653     return;
654 
655   PUT_MODE (m_ccreg, m);
656   log_msg ("updated ccreg mode: ");
657   log_rtx (m_ccreg);
658   log_msg ("\n");
659 }
660 
661 bool
662 sh_treg_combine::is_cmp_eq_zero (const_rtx i)
663 {
664   return i != NULL_RTX && GET_CODE (i) == EQ
665 	 && REG_P (XEXP (i, 0)) && XEXP (i, 1) == const0_rtx;
666 }
667 
668 sh_treg_combine::branch_condition_type_t
669 sh_treg_combine::branch_condition_type (const_rtx cond) const
670 {
671   if (cond == NULL_RTX)
672     return unknown_branch_condition;
673 
674   if (GET_CODE (cond) == NE
675       && REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) == REGNO (m_ccreg)
676       && XEXP (cond, 1) == const0_rtx)
677     return branch_if_true;
678 
679   else if (GET_CODE (cond) == EQ
680       && REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) == REGNO (m_ccreg)
681       && XEXP (cond, 1) == const0_rtx)
682     return branch_if_false;
683 
684   else
685     return unknown_branch_condition;
686 }
687 
688 bool
689 sh_treg_combine::is_normal_ccreg (const_rtx x) const
690 {
691   return t_reg_operand (const_cast<rtx> (x), VOIDmode);
692 }
693 
694 bool
695 sh_treg_combine::is_inverted_ccreg (const_rtx x) const
696 {
697   return negt_reg_operand (const_cast<rtx> (x), VOIDmode);
698 }
699 
700 sh_treg_combine::record_return_t
701 sh_treg_combine::record_set_of_reg (rtx reg, rtx_insn *start_insn,
702 				    bb_entry& new_entry)
703 {
704   log_msg ("\n[bb %d]\n", new_entry.bb->index);
705 
706   if (start_insn == NULL_RTX)
707     log_return (set_not_found, "set of reg not found.  empty BB?\n");
708 
709   new_entry.cstore_type = cstore_unknown;
710 
711   for (rtx_insn *i = start_insn; i != NULL; )
712     {
713       new_entry.cstore = find_set_of_reg_bb (reg, i);
714 
715       if (new_entry.cstore.set_src () == NULL_RTX)
716 	log_return (set_not_found, "set of reg not found (cstore)\n");
717 
718       log_insn (new_entry.cstore.insn);
719       log_msg ("\n");
720 
721       if (is_normal_ccreg (new_entry.cstore.set_src ()))
722 	{
723 	  log_msg ("normal condition store\n");
724 	  new_entry.cstore_type = cstore_normal;
725 	}
726       else if (is_inverted_ccreg (new_entry.cstore.set_src ()))
727 	{
728 	  log_msg ("inverted condition store\n");
729 	  new_entry.cstore_type = cstore_inverted;
730 	}
731       else if (REG_P (new_entry.cstore.set_src ()))
732 	{
733 	  // If it's a reg-reg copy follow the copied reg.
734 	  new_entry.cstore_reg_reg_copies.push_back (new_entry.cstore);
735 	  reg = new_entry.cstore.set_src ();
736 	  i = new_entry.cstore.insn;
737 
738 	  log_msg ("reg-reg copy.  tracing ");
739 	  log_rtx (reg);
740 	  log_msg ("\n");
741 	  continue;
742 	}
743       else
744 	log_return (other_set_found, "not a condition store\n");
745 
746       gcc_assert (new_entry.cstore_type != cstore_unknown);
747 
748       // Now see how the ccreg was set.
749       // For now it must be in the same BB.
750       log_msg ("tracing ccreg\n");
751       new_entry.setcc =
752 	  find_set_of_reg_bb (m_ccreg,
753 			      prev_nonnote_insn_bb (new_entry.cstore.insn));
754 
755       // If cstore was found but setcc was not found continue anyway, as
756       // for some of the optimization types the setcc is irrelevant.
757       if (new_entry.setcc.set_src () == NULL_RTX)
758 	log_return (set_found, "set of ccreg not found\n");
759 
760       else if (GET_CODE (new_entry.setcc.set_rtx) == SET)
761 	{
762 	  // Also allow insns that set the ccreg, but are not true comparison
763 	  // insns, as long as they are sets and not e.g. clobbers.
764 	  log_insn (new_entry.setcc.insn);
765 	  log_msg ("\n");
766 	  return set_found;
767 	}
768       else
769 	// If cstore was found but setcc was not found continue anyway, as
770 	// for some of the optimization types the setcc is irrelevant.
771  	log_return (set_found, "unknown set of ccreg\n");
772     }
773 
774   log_return (set_not_found, "set of reg not found\n");
775 }
776 
777 bool
778 sh_treg_combine::can_remove_cstore (const bb_entry& e,
779 				    const cbranch_trace& trace) const
780 {
781   if (volatile_insn_p (PATTERN (e.cstore.insn)))
782     {
783       log_msg ("can't remove insn\n");
784       log_insn (e.cstore.insn);
785       log_return (false, "\nbecause it's volatile\n");
786     }
787 
788   // On SH there are parallel patterns which store the ccreg multiple times.
789   // In this case it's not safe.
790   rtx cstore_pat = PATTERN (e.cstore.insn);
791   if (GET_CODE (cstore_pat) == PARALLEL)
792     for (int i = 0; i < XVECLEN (cstore_pat, 0); ++i)
793       {
794 	rtx x = XVECEXP (cstore_pat, 0, i);
795 
796 	// It's the cstore set that we're referring to, ignore that one.
797 	if (x != e.cstore.set_rtx
798 	    && GET_CODE (x) == SET && reg_referenced_p (m_ccreg, x))
799 	  {
800 	    log_msg ("can't remove insn\n");
801 	    log_insn (e.cstore.insn);
802 	    log_return (false, "\nbecause it's a multiple ccreg store\n");
803 	  }
804       }
805 
806   // If the cstore sets the ccreg (e.g. negc) and the ccreg is used afterwards
807   // it's not safe.
808   if (modified_in_p (m_ccreg, e.cstore.insn)
809       && !(reg_dead_after_insn (m_ccreg, e.cstore.insn)
810 	   || reg_unused_after_insn (m_ccreg, e.cstore.insn)))
811     {
812       log_msg ("can't remove insn\n");
813       log_insn (e.cstore.insn);
814       log_return (false, "\nbecause it sets the ccreg\n");
815     }
816 
817   // If the cstore destination reg is copied around check the reg-reg
818   // copies.  At every reg-reg copy the copied reg must be dead and there
819   // must not be a usage of the copied regs between the reg-reg copies.
820   // Otherwise we assume that the result of the cstore is used in some
821   // other way.
822   rtx_insn *prev_insn = e.cstore.insn;
823   for (std::vector<set_of_reg>::const_reverse_iterator i =
824 	   e.cstore_reg_reg_copies.rbegin ();
825        i != e.cstore_reg_reg_copies.rend (); ++i)
826     {
827       if (!reg_dead_after_insn (i->set_src (), i->insn))
828 	{
829 	  log_msg ("can't remove insn\n");
830 	  log_insn (i->insn);
831 	  log_return (false, "\nbecause source of reg-reg copy doesn't die\n");
832 	}
833 
834      if (reg_used_between_p (i->set_src (), prev_insn, i->insn))
835 	{
836 	  log_msg ("can't remove insn\n");
837 	  log_insn (i->insn);
838 	  log_return (false, "\nbecause reg %d is otherwise used\n",
839 			     REGNO (i->set_src ()));
840 	}
841 
842       prev_insn = i->insn;
843     }
844 
845   // The cstore_dst reg must die after the test before the cbranch, otherwise
846   // it's not safe to remove the cstore.
847   // If the cstore destination reg is copied around check the effective
848   // destination reg of the cstore.  The reg-reg copies are recorded in
849   // reverse order, i.e. the most recent reg-reg copy in the insn list
850   // comes first.
851   rtx cstore_dst = e.cstore_reg_reg_copies.empty ()
852 		   ? e.cstore.set_dst ()
853 		   : e.cstore_reg_reg_copies.front ().set_dst ();
854 
855   if (!reg_dead_after_insn (cstore_dst, trace.setcc.insn))
856     {
857       log_msg ("can't remove insn\n");
858       log_insn (e.cstore.insn);
859       log_return (false, "\nbecause its effective target reg %d doesn't die "
860 			 "after trace.setcc.insn\n", REGNO (cstore_dst));
861     }
862 
863   // Also check that the cstore_dst reg is not used in other reachable code
864   // paths before it dies.
865   // Count the uses of the effective cstore_dst reg (i.e. the last known reg
866   // that holds the cstore value after reg-reg copies) in all BBs that can be
867   // reached from bb_entry's BB including the BB of the cstore insn.
868   // If we get more than 1 uses we assume that it's used somewhere else and is
869   // not safe to be removed.
870   int cstore_dst_use_count = trace_reg_uses (cstore_dst, e.cstore.insn,
871 					     trace.setcc.insn);
872   if (cstore_dst_use_count > 1)
873     {
874       log_msg ("can't remove insn\n");
875       log_insn (e.cstore.insn);
876       log_return (false, "\nbecause its effective target reg %d is used "
877 			 "in %d other places\n", REGNO (cstore_dst),
878 			  cstore_dst_use_count - 1);
879     }
880 
881   return true;
882 }
883 
884 bool
885 sh_treg_combine::can_remove_comparison (const bb_entry& e,
886 					const cbranch_trace&/* trace*/) const
887 {
888   // If the ccreg is used otherwise between the comparison and the cstore,
889   // it's not safe.
890   if (reg_used_between_p (m_ccreg, e.setcc.insn, e.cstore.insn))
891     {
892       log_msg ("can't remove insn\n");
893       log_insn (e.setcc.insn);
894       log_return (false, "\nbecause the ccreg is used otherwise\n");
895     }
896 
897   if (!reg_dead_after_insn (m_ccreg, e.cstore.insn)
898       && !reg_unused_after_insn (m_ccreg, e.cstore.insn))
899     {
900       log_msg ("can't remove insn\n");
901       log_insn (e.cstore.insn);
902       log_return (false, "\nbecause ccreg is not dead or unused afterwards\n");
903     }
904 
905   // On SH there are also multiple set patterns that can be used for
906   // comparisons, such as "shll".  It's not safe to remove those.
907   if (multiple_sets (e.setcc.insn))
908     {
909       log_msg ("can't remove insn\n");
910       log_insn (e.cstore.insn);
911       log_return (false, "\nbecause it's a multiple set\n");
912     }
913 
914   return true;
915 }
916 
917 rtx
918 sh_treg_combine::make_not_reg_insn (rtx dst_reg, rtx src_reg) const
919 {
920   // On SH we can do only SImode and DImode comparisons.
921   if (! (GET_MODE (src_reg) == SImode || GET_MODE (src_reg) == DImode))
922     return NULL;
923 
924   // On SH we can store the ccreg into an SImode or DImode reg only.
925   if (! (GET_MODE (dst_reg) == SImode || GET_MODE (dst_reg) == DImode))
926     return NULL;
927 
928   start_sequence ();
929 
930   emit_insn (gen_rtx_SET (m_ccreg, gen_rtx_fmt_ee (EQ, SImode,
931 						   src_reg, const0_rtx)));
932 
933   if (GET_MODE (dst_reg) == SImode)
934     emit_move_insn (dst_reg, m_ccreg);
935   else if (GET_MODE (dst_reg) == DImode)
936     {
937       emit_move_insn (gen_lowpart (SImode, dst_reg), m_ccreg);
938       emit_move_insn (gen_highpart (SImode, dst_reg), const0_rtx);
939     }
940   else
941     gcc_unreachable ();
942 
943   rtx i = get_insns ();
944   end_sequence ();
945 
946   return i;
947 }
948 
949 rtx_insn *
950 sh_treg_combine::make_inv_ccreg_insn (void) const
951 {
952   start_sequence ();
953   rtx_insn *i = emit_insn (gen_rtx_SET (m_ccreg,
954                                         gen_rtx_fmt_ee (XOR, GET_MODE (m_ccreg),
955                                                         m_ccreg, const1_rtx)));
956   end_sequence ();
957   return i;
958 }
959 
960 rtx
961 sh_treg_combine::touched_insn (rtx i)
962 {
963   m_touched_insns.push_back (i);
964   return i;
965 }
966 
967 bool
968 sh_treg_combine::can_combine_comparisons (const_rtx x, const_rtx y) const
969 {
970   if (GET_CODE (x) != GET_CODE (y))
971     return false;
972 
973   rtx x_op0 = XEXP (x, 0);
974   rtx x_op1 = XEXP (x, 1);
975 
976   rtx y_op0 = XEXP (y, 0);
977   rtx y_op1 = XEXP (y, 1);
978 
979   if (!REG_P (x_op0) || !REG_P (y_op0))
980     return false;
981 
982   if (GET_MODE (x_op0) != GET_MODE (y_op0))
983     return false;
984 
985   // rtx_equal_p also compares the reg numbers which we do not care about
986   // here, as long as both are regs and the modes are the same.
987   if (REG_P (x_op1))
988     return REG_P (y_op1) && GET_MODE (x_op1) == GET_MODE (y_op1);
989 
990   return rtx_equal_p (x_op1, y_op1);
991 }
992 
993 bool
994 sh_treg_combine::can_extend_ccreg_usage (const bb_entry& e,
995 					 const cbranch_trace& trace) const
996 {
997   // Check if the ccreg is not modified by other insins in the BB path until
998   // the final cbranch of the trace.
999   // Start checking after the cstore that follows the setcc, assuming that
1000   // the cstore will be removed.
1001 
1002   // The assumption here is that the specified bb_entry's BB is a direct
1003   // predecessor of the trace.cbranch_insn's BB.
1004   if (e.bb != trace.bb () && !is_adjacent_bb (e.bb, trace.bb ()))
1005     log_return (false,
1006 	"can't extend ccreg usage -- [bb %d] and [bb %d] are not adjacent\n",
1007 	e.bb->index, trace.bb ()->index);
1008 
1009   if (e.cstore.empty ())
1010     log_return (false, "can't extend ccreg usage -- no cstore\n");
1011 
1012   // The entry's cstore is in the same BB as the final cbranch.
1013   if (e.bb == trace.bb ())
1014     {
1015       if (reg_set_between_p (m_ccreg, e.cstore.insn, trace.setcc.insn))
1016 	log_return (false,
1017 	    "can't extend ccreg usage -- it's modified between e.cstore.insn "
1018 	    "and trace.setcc.insn");
1019       else
1020 	return true;
1021     }
1022 
1023   // The entry's cstore and the final cbranch are in different BBs.
1024   if (reg_set_between_p (m_ccreg, e.cstore.insn, NEXT_INSN (BB_END (e.bb))))
1025     log_return (false,
1026 	"can't extend ccreg usage -- it's modified in [bb %d]", e.bb->index);
1027 
1028   if (reg_set_between_p (m_ccreg, PREV_INSN (BB_HEAD (trace.bb ())),
1029 			 trace.setcc.insn))
1030     log_return (false,
1031 	"can't extend ccreg usage -- it's modified in [bb %d]",
1032 	trace.bb ()->index);
1033 
1034   return true;
1035 }
1036 
1037 bool
1038 sh_treg_combine::try_invert_branch_condition (cbranch_trace& trace)
1039 {
1040   log_msg ("inverting branch condition\n");
1041 
1042   rtx& comp = trace.branch_condition_rtx_ref ();
1043 
1044   rtx_code rev_cmp_code = reversed_comparison_code (comp, trace.cbranch_insn);
1045 
1046   if (rev_cmp_code == UNKNOWN)
1047     log_return (false, "reversed_comparison_code = UNKNOWN\n");
1048 
1049   validate_change (trace.cbranch_insn, &comp,
1050 		   gen_rtx_fmt_ee (rev_cmp_code,
1051 				   GET_MODE (comp), XEXP (comp, 0),
1052 				   XEXP (comp, 1)),
1053 		   1);
1054 
1055   if (verify_changes (num_validated_changes ()))
1056     confirm_change_group ();
1057   else
1058     log_return (false, "verify_changed failed\n");
1059 
1060   touched_insn (trace.cbranch_insn);
1061   return true;
1062 }
1063 
1064 bool
1065 sh_treg_combine::try_combine_comparisons (cbranch_trace& trace,
1066 					  int cstore_count,
1067 					  int inv_cstore_count,
1068 					  cstore_type_t dominating_cstore)
1069 {
1070   log_msg ("\ntry_combine_comparisons\n");
1071 
1072   // This function will always try to create new pseudos.
1073   if (!can_create_pseudo_p ())
1074     log_return (false, "can't create pseudos\n");
1075 
1076   // Check that all ccset insns are comparisons and all comparison types in
1077   // all BBs are the same and could be combined into one single comparison.
1078   rtx comp = NULL_RTX;
1079   rtx comp_insn = NULL_RTX;
1080 
1081   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1082        i != trace.bb_entries.end (); ++i)
1083     {
1084       int i_empty_count = i->setcc.empty () + i->cstore.empty ();
1085 
1086       // A completly empty entry is OK (could be the BB of the cbranch).
1087       if (i_empty_count == 2)
1088 	continue;
1089 
1090       // Otherwise we need both, the setcc and the cstore.
1091       if (i_empty_count != 0)
1092 	log_return (false, "bb entry is not a setcc cstore pair\n");
1093 
1094       rtx other_comp = i->comparison_rtx ();
1095 
1096       if (!COMPARISON_P (other_comp))
1097 	{
1098 	  log_msg ("setcc is not a comparison:\n");
1099 	  log_rtx (other_comp);
1100 	  log_return (false, "\n");
1101 	}
1102 
1103       if (comp_insn == NULL_RTX)
1104 	{
1105 	  comp = other_comp;
1106 	  comp_insn = i->setcc.insn;
1107 	}
1108       else if (!can_combine_comparisons (comp, other_comp))
1109 	return false;
1110 
1111       // The goal here is to eliminate all cstores and comparisons in the BBs.
1112       // Thus check if every cstore can actually be removed safely.
1113       if (!can_remove_cstore (*i, trace) || !can_remove_comparison (*i, trace))
1114 	return false;
1115     }
1116 
1117   // FIXME: The first operand of the comparison must be a simple reg.
1118   // This effectively prohibits combining div0s comparisons such as
1119   //    (lt:SI (xor:SI (reg:SI) (reg:SI)))
1120   if (!REG_P (XEXP (comp, 0)))
1121     {
1122       log_msg ("comparison operand 0\n");
1123       log_rtx (XEXP (comp, 0));
1124       log_return (false, "\nis not a reg\n");
1125     }
1126 
1127   rtx comp_op0 = gen_reg_rtx (GET_MODE (XEXP (comp, 0)));
1128   rtx comp_op1 = REG_P (XEXP (comp, 1))
1129 		 ? gen_reg_rtx (GET_MODE (XEXP (comp, 1)))
1130 		 : XEXP (comp, 1);
1131 
1132   // If there are both, inverting and non-inverting cstores, they can only
1133   // be eliminated if the comparison can be inverted.  We assume that the
1134   // comparison insns that we find are already minimal and canonicalized.
1135   // There is one special case though, where an integer comparison
1136   //     (eq (reg) (const_int 0))
1137   // can be inverted with a sequence
1138   //     (set (t) (eq (reg) (const_int 0))
1139   //     (set (reg) (t))
1140   //     (eq (reg) (const_int 0))
1141   //
1142   // FIXME: On SH2A it might be better to use the nott insn in this case,
1143   // i.e. do the try_eliminate_cstores approach instead.
1144   if (inv_cstore_count != 0 && cstore_count != 0)
1145     {
1146       if (make_not_reg_insn (comp_op0, comp_op0) == NULL_RTX)
1147 	log_return (false, "make_not_reg_insn failed.\n");
1148 
1149       for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1150 	   i != trace.bb_entries.end (); ++i)
1151 	{
1152 	  if (i->setcc.empty () || i->cstore.empty ())
1153 	    continue;
1154 
1155 	  if (i->cstore_type != dominating_cstore
1156 	      && !is_cmp_eq_zero (i->comparison_rtx ()))
1157 	    {
1158 	      log_msg ("can't invert comparison in insn\n");
1159 	      log_insn (i->setcc.insn);
1160 	      log_return (false,
1161 		"\nbecause it's not a (eq (reg) (const_int 0))\n");
1162 	    }
1163 	}
1164     }
1165 
1166   if (dominating_cstore == cstore_normal
1167       && !try_invert_branch_condition (trace))
1168     return false;
1169 
1170   // Replace the test insn before the cbranch with the common comparison.
1171   // Instead of creating a new insn from scratch we copy the common comparison
1172   // pattern.  This simplifies handling parallel comparison patterns, such as
1173   // FP comparisons on SH, which have an extra use on FPSCR.
1174   log_msg ("installing common comparison in [bb %d]\n", trace.bb ()->index);
1175 
1176   rtx common_comp_pat = copy_rtx (PATTERN (comp_insn));
1177   rtx common_comp = const_cast<rtx> (set_of (m_ccreg, common_comp_pat));
1178 
1179   gcc_assert (common_comp != NULL_RTX);
1180 
1181   XEXP (XEXP (common_comp, 1), 0) = comp_op0;
1182   XEXP (XEXP (common_comp, 1), 1) = comp_op1;
1183 
1184   log_rtx (common_comp_pat);
1185   log_msg ("\n");
1186 
1187   rtx common_comp_insn = touched_insn (emit_insn_after (common_comp_pat,
1188 							trace.setcc.insn));
1189 
1190   if (REG_P (comp_op0))
1191     add_reg_note (common_comp_insn, REG_DEAD, copy_rtx (comp_op0));
1192   if (REG_P (comp_op1))
1193     add_reg_note (common_comp_insn, REG_DEAD, copy_rtx (comp_op1));
1194 
1195   delete_insn (trace.setcc.insn);
1196 
1197   // Replace comparison and cstore insns with reg-reg moves in all BBs.
1198   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1199        i != trace.bb_entries.end (); ++i)
1200     {
1201       if (i->setcc.empty () || i->cstore.empty ())
1202 	continue;
1203 
1204       rtx i_comp_op0 = XEXP (i->comparison_rtx (), 0);
1205       rtx i_comp_op1 = XEXP (i->comparison_rtx (), 1);
1206 
1207       if (i->cstore_type == dominating_cstore)
1208 	{
1209 	  log_msg ("replacing comparison and cstore with reg move "
1210 		   "in [bb %d]\n", i->bb->index);
1211 
1212 	  rtx new_i = touched_insn (
1213 		emit_insn_after (gen_move_insn (comp_op0, i_comp_op0),
1214 				 i->setcc.insn));
1215 
1216 	  if (REG_P (i_comp_op0)
1217 	      && reg_dead_after_insn (i_comp_op0, i->setcc.insn))
1218 	    add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op0));
1219 
1220 	  // If the second operand is a reg, have to emit a move insn.
1221 	  // Otherwise assume it's a const_int and just reference it.
1222 	  if (REG_P (comp_op1))
1223 	    {
1224 	      new_i = touched_insn (
1225 		  emit_insn_after (gen_move_insn (comp_op1, i_comp_op1),
1226 				   i->setcc.insn));
1227 
1228 	      if (reg_dead_after_insn (i_comp_op1, i->setcc.insn))
1229 		add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op1));
1230 	    }
1231 	}
1232       else
1233 	{
1234 	  log_msg ("replacing comparison and cstore with inverting reg move "
1235 		   "in [bb %d]\n", i->bb->index);
1236 
1237 	  rtx new_i = make_not_reg_insn (comp_op0, i_comp_op0);
1238 	  if (REG_P (i_comp_op0)
1239 	      && reg_dead_after_insn (i_comp_op0, i->setcc.insn))
1240 	    add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op0));
1241 
1242 	  touched_insn (emit_insn_after (new_i, i->setcc.insn));
1243 	}
1244 
1245       delete_insn (i->cstore.insn);
1246       delete_insn (i->setcc.insn);
1247     }
1248 
1249   return true;
1250 }
1251 
1252 bool
1253 sh_treg_combine::try_eliminate_cstores (cbranch_trace& trace,
1254 					int cstore_count, int inv_cstore_count,
1255 					cstore_type_t dominating_cstore)
1256 {
1257   log_msg ("\ntry_eliminate_cstores\n");
1258 
1259   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1260        i != trace.bb_entries.end (); ++i)
1261     {
1262       // A completly empty entry is OK (could be the BB of the cbranch).
1263       if (i->setcc.empty () && i->cstore.empty ())
1264 	continue;
1265 
1266       // We're going to eliminate cstores, but for that they have to be
1267       // there.  We don't care about the setcc in this case.
1268       if (i->cstore.empty ())
1269 	log_return (false, "bb entry cstore empty -- aborting\n");
1270 
1271       // The goal here is to eliminate all cstores in the BBs and extend the
1272       // ccreg usage.
1273       if (!can_extend_ccreg_usage (*i, trace))
1274 	return false;
1275 
1276       // If the cstore can't be removed we can keep it around as long as
1277       // it doesn't modify the ccreg.
1278       if (!can_remove_cstore (*i, trace)
1279 	  && modified_in_p (m_ccreg, i->cstore.insn))
1280 	log_return (false, "cstore sets ccreg -- aborting\n");
1281     }
1282 
1283   // If there are both, inverting and non-inverting cstores, we'll have to
1284   // invert the ccreg as a replacement for one of them.
1285   if (cstore_count != 0 && inv_cstore_count != 0)
1286     {
1287       rtx_insn *i = make_inv_ccreg_insn ();
1288       if (recog_memoized (i) < 0)
1289 	{
1290 	  log_msg ("failed to match ccreg inversion insn:\n");
1291 	  log_rtx (PATTERN (i));
1292 	  log_return (false, "\naborting\n");
1293 	}
1294     }
1295 
1296   if (dominating_cstore == cstore_normal
1297       && !try_invert_branch_condition (trace))
1298     return false;
1299 
1300   // Eliminate cstores in all BBs.
1301   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1302        i != trace.bb_entries.end (); ++i)
1303     {
1304       if (i->cstore.empty ())
1305 	continue;
1306 
1307       if (i->cstore_type == dominating_cstore)
1308 	log_msg ("removing cstore in [bb %d]\n", i->bb->index);
1309       else
1310 	{
1311 	  log_msg ("replacing cstore with ccreg inversion in [bb %d]\n",
1312 		   i->bb->index);
1313 
1314 	  touched_insn (
1315 	    emit_insn_after (make_inv_ccreg_insn (), i->cstore.insn));
1316 	}
1317 
1318       if (can_remove_cstore (*i, trace))
1319 	delete_insn (i->cstore.insn);
1320     }
1321 
1322   log_msg ("removing test insn before cbranch\n");
1323   delete_insn (trace.setcc.insn);
1324   return true;
1325 }
1326 
1327 void
1328 sh_treg_combine::try_optimize_cbranch (rtx_insn *insn)
1329 {
1330   cbranch_trace trace (insn);
1331 
1332   log_msg ("\n\n--------------------------------------\n");
1333   log_msg ("found cbranch insn in [bb %d]:\n", trace.bb ()->index);
1334   log_insn (insn);
1335 
1336   trace.cbranch_type = branch_condition_type (trace.branch_condition_rtx ());
1337 
1338   if (trace.cbranch_type == branch_if_true)
1339     log_msg ("condition: branch if true\n");
1340   else if (trace.cbranch_type == branch_if_false)
1341     log_msg ("condition: branch if false\n");
1342   else
1343     {
1344       log_msg ("unknown branch condition\n");
1345       log_rtx (trace.branch_condition_rtx ());
1346       log_return_void ("\n");
1347     }
1348 
1349   update_ccreg_mode (trace.branch_condition_rtx ());
1350 
1351   // Scan the insns backwards for an insn that sets the ccreg by testing a
1352   // reg against zero like
1353   //   (set (reg ccreg) (eq (reg) (const_int 0)))
1354   // The testing insn could also be outside of the current basic block, but
1355   // for now we limit the search to the current basic block.
1356   trace.setcc = find_set_of_reg_bb (m_ccreg, prev_nonnote_insn_bb (insn));
1357 
1358   if (trace.setcc.set_src () == NULL_RTX)
1359     log_return_void ("could not find set of ccreg in current BB\n");
1360 
1361   if (!is_cmp_eq_zero (trace.setcc.set_src ())
1362       && !is_inverted_ccreg (trace.setcc.set_src ()))
1363     {
1364       log_msg ("unsupported set of ccreg in current BB: ");
1365       log_rtx (trace.setcc.set_src ());
1366       log_return_void ("\n");
1367     }
1368 
1369   rtx trace_reg = XEXP (trace.setcc.set_src (), 0);
1370 
1371   log_msg ("set of ccreg:\n");
1372   log_insn (trace.setcc.insn);
1373 
1374   // See if we can remove the trace.setcc insn safely.
1375   if (reg_used_between_p (m_ccreg, trace.setcc.insn, trace.cbranch_insn))
1376     log_return_void ("ccreg used between testing insn and branch insn\n");
1377 
1378   if (volatile_insn_p (PATTERN (trace.setcc.insn)))
1379     {
1380       log_msg ("can't remove insn\n");
1381       log_insn (trace.setcc.insn);
1382       log_return_void ("\nbecause it's volatile\n");
1383     }
1384 
1385   // If the ccreg is inverted before cbranch try inverting the branch
1386   // condition.
1387   if (is_inverted_ccreg (trace.setcc.set_src ()))
1388     {
1389       if (!trace.can_invert_condition ())
1390 	log_return_void ("branch condition can't be inverted - aborting\n");
1391 
1392       if (try_invert_branch_condition (trace))
1393 	delete_insn (trace.setcc.insn);
1394 
1395       return;
1396     }
1397 
1398   // Now that we have an insn which tests some reg and sets the condition
1399   // reg before the conditional branch, try to figure out how that tested
1400   // reg was formed, i.e. find all the insns that set the tested reg in
1401   // some way.
1402   // The tested reg might be set in multiple basic blocks so we need to
1403   // check all basic blocks which can reach this current basic block.
1404   // If the set of reg is an inverting or non-inverting store of the condition
1405   // register, check how the ccreg value was obtained.
1406   log_msg ("\ntracing ");
1407   log_rtx (trace_reg);
1408   log_msg ("\n");
1409 
1410 
1411   // First check the basic block where the conditional branch is in.
1412   // If we find it here there's no point in checking other BBs.
1413   trace.bb_entries.push_front (bb_entry (trace.bb ()));
1414 
1415   record_return_t res =
1416       record_set_of_reg (trace_reg, prev_nonnote_insn_bb (trace.setcc.insn),
1417 			 trace.bb_entries.front ());
1418 
1419   if (res == other_set_found)
1420     log_return_void ("other set found - aborting trace\n");
1421   else if (res == set_not_found)
1422     {
1423       // It seems the initial search in the BB of the conditional branch
1424       // didn't find anything.  Now look in all predecessor BBs.
1425       for (edge_iterator ei = ei_start (trace.bb ()->preds);
1426 	   !ei_end_p (ei); ei_next (&ei))
1427 	{
1428 	  edge e = ei_edge (ei);
1429 	  trace.bb_entries.push_front (bb_entry (e->src));
1430 
1431 	  res = record_set_of_reg (trace_reg, BB_END (e->src),
1432 				   trace.bb_entries.front ());
1433 	  if (res != set_found)
1434 	    log_return_void ("set not found - aborting trace\n");
1435 	}
1436     }
1437 
1438   if (dump_file != NULL)
1439     {
1440       log_msg ("\ncbranch trace summary:\n");
1441       for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1442 	   i != trace.bb_entries.end (); ++i)
1443 	{
1444 	  log_msg ("\n[bb %d]\n", i->bb->index);
1445 	  if (!i->setcc.empty ())
1446 	    {
1447 	      log_rtx (i->setcc.set_rtx);
1448 	      log_msg ("\n");
1449 	    }
1450 	  if (!i->cstore.empty ())
1451 	    {
1452 	      log_rtx (i->cstore.set_rtx);
1453 	      log_msg ("\n");
1454 	    }
1455 
1456 	  for (std::vector<set_of_reg>::const_reverse_iterator j =
1457 		   i->cstore_reg_reg_copies.rbegin ();
1458 	       j != i->cstore_reg_reg_copies.rend (); ++j)
1459 	    {
1460 	      log_rtx (j->set_rtx);
1461 	      log_msg ("\n");
1462 	    }
1463 	}
1464 
1465       log_rtx (trace.setcc.set_rtx);
1466       log_msg ("\n");
1467       log_rtx (PATTERN (trace.cbranch_insn));
1468       log_msg ("\n");
1469     }
1470 
1471   // Check that we don't have any empty BBs.
1472   // Only the BB with the cbranch may be empty.
1473   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1474        i != trace.bb_entries.end (); ++i)
1475     if (i->setcc.empty () && i->cstore.empty () && i->bb != trace.bb ())
1476       log_return_void ("\n[bb %d] is empty - aborting.\n", i->bb->index);
1477 
1478   // Determine the dominating cstore type
1479   // FIXME: Try to take the probabilities of the BBs into account somehow.
1480   int cstore_count = 0;
1481   int inv_cstore_count = 0;
1482 
1483   for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
1484        i != trace.bb_entries.end (); ++i)
1485     {
1486       if (i->cstore_type == cstore_normal)
1487 	cstore_count += 1;
1488       else if (i->cstore_type == cstore_inverted)
1489 	inv_cstore_count += 1;
1490     }
1491 
1492   log_msg ("cstore count = %d  inverted cstore count = %d\n",
1493 	   cstore_count, inv_cstore_count);
1494 
1495   // This puts a priority on inverting cstores.
1496   cstore_type_t dominating_cstore = inv_cstore_count >= cstore_count
1497 				    ? cstore_inverted
1498 				    : cstore_normal;
1499 
1500   if (dominating_cstore == cstore_inverted)
1501       log_msg ("will try to eliminate inverted cstore\n");
1502   else if (dominating_cstore == cstore_normal)
1503     {
1504       log_msg ("will try to eliminate normal cstore\n");
1505       if (!trace.can_invert_condition ())
1506 	log_return_void ("branch condition can't be inverted - aborting\n");
1507     }
1508   else
1509     gcc_unreachable ();
1510 
1511   if (try_combine_comparisons (trace, cstore_count, inv_cstore_count,
1512 			       dominating_cstore))
1513     return;
1514 
1515   try_eliminate_cstores (trace, cstore_count, inv_cstore_count,
1516 			 dominating_cstore);
1517 }
1518 
1519 bool
1520 sh_treg_combine::gate (function *)
1521 {
1522   return optimize > 0;
1523 }
1524 
1525 unsigned int
1526 sh_treg_combine::execute (function *fun)
1527 {
1528   unsigned int ccr0 = INVALID_REGNUM;
1529   unsigned int ccr1 = INVALID_REGNUM;
1530 
1531   if (targetm.fixed_condition_code_regs (&ccr0, &ccr1)
1532       && ccr0 != INVALID_REGNUM)
1533     {
1534       // Initially create a reg rtx with VOIDmode.
1535       // When the first conditional branch is discovered, the mode is changed
1536       // to the mode that is actually used by the target.
1537       m_ccreg = gen_rtx_REG (VOIDmode, ccr0);
1538     }
1539 
1540   if (m_ccreg == NULL_RTX)
1541     log_return (0, "no ccreg.\n\n");
1542 
1543   if (STORE_FLAG_VALUE != 1)
1544     log_return (0, "unsupported STORE_FLAG_VALUE %d", STORE_FLAG_VALUE);
1545 
1546   log_msg ("ccreg: ");
1547   log_rtx (m_ccreg);
1548   log_msg ("  STORE_FLAG_VALUE = %d\n", STORE_FLAG_VALUE);
1549 
1550   // Look for basic blocks that end with a conditional branch or for
1551   // conditional insns and try to optimize them.
1552   basic_block bb;
1553   FOR_EACH_BB_FN (bb, fun)
1554     {
1555       rtx_insn* i = BB_END (bb);
1556       if (i == NULL || i == PREV_INSN (BB_HEAD (bb)))
1557 	continue;
1558 
1559       // A conditional branch is always the last insn of a basic block.
1560       if (any_condjump_p (i) && onlyjump_p (i))
1561 	{
1562 	  try_optimize_cbranch (i);
1563 	  i = PREV_INSN (i);
1564 	}
1565 
1566       // Check all insns in block for conditional insns.
1567       for (; i != NULL && i != PREV_INSN (BB_HEAD (bb)); i = PREV_INSN (i))
1568 	if (is_conditional_insn (i))
1569 	  try_optimize_cbranch (i);
1570     }
1571 
1572   log_msg ("\n\n");
1573 
1574   // If new insns are created and this pass is executed after all insns
1575   // have been split already, we must split the insns we've changed or added
1576   // ourselves here.
1577   // FIXME: Multi-word operations (which emit multiple insns) are not handled
1578   // properly here, since only one insn will end up in 'm_touched_insns'.
1579   // On SH this is not a problem though.
1580   if (m_split_insns)
1581     for (std::vector<rtx>::const_iterator i = m_touched_insns.begin ();
1582 	 i != m_touched_insns.end (); ++i)
1583       {
1584 	log_msg ("trying to split insn:\n");
1585 	log_insn (*i);
1586 	log_msg ("\n");
1587 	try_split (PATTERN (*i), safe_as_a <rtx_insn *> (*i), 0);
1588       }
1589 
1590   m_touched_insns.clear ();
1591   log_return (0, "\n\n");
1592 }
1593 
1594 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1595 // This allows instantiating the pass somewhere else without having to pull
1596 // in a header file.
1597 opt_pass*
1598 make_pass_sh_treg_combine (gcc::context* ctx, bool split_insns,
1599 			   const char* name)
1600 {
1601   return new sh_treg_combine (ctx, split_insns, name);
1602 }
1603