OSDN Git Service

* ifcvt.c: Include except.h.
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
1 /* If-conversion support.
2    Copyright (C) 2000, 2001, 2002 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
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING.  If not, write to the Free
18    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23
24 #include "rtl.h"
25 #include "regs.h"
26 #include "function.h"
27 #include "flags.h"
28 #include "insn-config.h"
29 #include "recog.h"
30 #include "except.h"
31 #include "hard-reg-set.h"
32 #include "basic-block.h"
33 #include "expr.h"
34 #include "real.h"
35 #include "output.h"
36 #include "toplev.h"
37 #include "tm_p.h"
38
39
40 #ifndef HAVE_conditional_execution
41 #define HAVE_conditional_execution 0
42 #endif
43 #ifndef HAVE_conditional_move
44 #define HAVE_conditional_move 0
45 #endif
46 #ifndef HAVE_incscc
47 #define HAVE_incscc 0
48 #endif
49 #ifndef HAVE_decscc
50 #define HAVE_decscc 0
51 #endif
52 #ifndef HAVE_trap
53 #define HAVE_trap 0
54 #endif
55 #ifndef HAVE_conditional_trap
56 #define HAVE_conditional_trap 0
57 #endif
58
59 #ifndef MAX_CONDITIONAL_EXECUTE
60 #define MAX_CONDITIONAL_EXECUTE   (BRANCH_COST + 1)
61 #endif
62
63 #define NULL_EDGE       ((struct edge_def *)NULL)
64 #define NULL_BLOCK      ((struct basic_block_def *)NULL)
65
66 /* # of IF-THEN or IF-THEN-ELSE blocks we looked at  */
67 static int num_possible_if_blocks;
68
69 /* # of IF-THEN or IF-THEN-ELSE blocks were converted to conditional
70    execution.  */
71 static int num_updated_if_blocks;
72
73 /* # of basic blocks that were removed.  */
74 static int num_removed_blocks;
75
76 /* True if life data ok at present.  */
77 static bool life_data_ok;
78
79 /* The post-dominator relation on the original block numbers.  */
80 static sbitmap *post_dominators;
81
82 /* Forward references.  */
83 static int count_bb_insns               PARAMS ((basic_block));
84 static rtx first_active_insn            PARAMS ((basic_block));
85 static int last_active_insn_p           PARAMS ((basic_block, rtx));
86 static int seq_contains_jump            PARAMS ((rtx));
87
88 static int cond_exec_process_insns      PARAMS ((rtx, rtx, rtx, rtx, int));
89 static rtx cond_exec_get_condition      PARAMS ((rtx));
90 static int cond_exec_process_if_block   PARAMS ((basic_block, basic_block,
91                                                  basic_block, basic_block));
92
93 static rtx noce_get_condition           PARAMS ((rtx, rtx *));
94 static int noce_operand_ok              PARAMS ((rtx));
95 static int noce_process_if_block        PARAMS ((basic_block, basic_block,
96                                                  basic_block, basic_block));
97
98 static int process_if_block             PARAMS ((basic_block, basic_block,
99                                                  basic_block, basic_block));
100 static void merge_if_block              PARAMS ((basic_block, basic_block,
101                                                  basic_block, basic_block));
102
103 static int find_if_header               PARAMS ((basic_block));
104 static int find_if_block                PARAMS ((basic_block, edge, edge));
105 static int find_if_case_1               PARAMS ((basic_block, edge, edge));
106 static int find_if_case_2               PARAMS ((basic_block, edge, edge));
107 static int find_cond_trap               PARAMS ((basic_block, edge, edge));
108 static rtx block_has_only_trap          PARAMS ((basic_block));
109 static int find_memory                  PARAMS ((rtx *, void *));
110 static int dead_or_predicable           PARAMS ((basic_block, basic_block,
111                                                  basic_block, basic_block, int));
112 static void noce_emit_move_insn         PARAMS ((rtx, rtx));
113 \f
114 /* Abuse the basic_block AUX field to store the original block index,
115    as well as a flag indicating that the block should be rescaned for
116    life analysis.  */
117
118 #define SET_ORIG_INDEX(BB,I)    ((BB)->aux = (void *)((size_t)(I)))
119 #define ORIG_INDEX(BB)          ((size_t)(BB)->aux)
120
121 \f
122 /* Count the number of non-jump active insns in BB.  */
123
124 static int
125 count_bb_insns (bb)
126      basic_block bb;
127 {
128   int count = 0;
129   rtx insn = bb->head;
130
131   while (1)
132     {
133       if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN)
134         count++;
135
136       if (insn == bb->end)
137         break;
138       insn = NEXT_INSN (insn);
139     }
140
141   return count;
142 }
143
144 /* Return the first non-jump active insn in the basic block.  */
145
146 static rtx
147 first_active_insn (bb)
148      basic_block bb;
149 {
150   rtx insn = bb->head;
151
152   if (GET_CODE (insn) == CODE_LABEL)
153     {
154       if (insn == bb->end)
155         return NULL_RTX;
156       insn = NEXT_INSN (insn);
157     }
158
159   while (GET_CODE (insn) == NOTE)
160     {
161       if (insn == bb->end)
162         return NULL_RTX;
163       insn = NEXT_INSN (insn);
164     }
165
166   if (GET_CODE (insn) == JUMP_INSN)
167     return NULL_RTX;
168
169   return insn;
170 }
171
172 /* Return true if INSN is the last active non-jump insn in BB.  */
173
174 static int
175 last_active_insn_p (bb, insn)
176      basic_block bb;
177      rtx insn;
178 {
179   do
180     {
181       if (insn == bb->end)
182         return TRUE;
183       insn = NEXT_INSN (insn);
184     }
185   while (GET_CODE (insn) == NOTE);
186
187   return GET_CODE (insn) == JUMP_INSN;
188 }
189
190 /* It is possible, especially when having dealt with multi-word 
191    arithmetic, for the expanders to have emitted jumps.  Search
192    through the sequence and return TRUE if a jump exists so that
193    we can abort the conversion.  */
194
195 static int
196 seq_contains_jump (insn)
197      rtx insn;
198 {
199   while (insn)
200     {
201       if (GET_CODE (insn) == JUMP_INSN)
202         return 1;
203       insn = NEXT_INSN (insn);
204     }
205   return 0;
206 }
207 \f
208 /* Go through a bunch of insns, converting them to conditional
209    execution format if possible.  Return TRUE if all of the non-note
210    insns were processed.  */
211
212 static int
213 cond_exec_process_insns (start, end, test, prob_val, mod_ok)
214      rtx start;                 /* first insn to look at */
215      rtx end;                   /* last insn to look at */
216      rtx test;                  /* conditional execution test */
217      rtx prob_val;              /* probability of branch taken.  */
218      int mod_ok;                /* true if modifications ok last insn.  */
219 {
220   int must_be_last = FALSE;
221   rtx insn;
222   rtx pattern;
223
224   for (insn = start; ; insn = NEXT_INSN (insn))
225     {
226       if (GET_CODE (insn) == NOTE)
227         goto insn_done;
228
229       if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
230         abort ();
231
232       /* Remove USE insns that get in the way.  */
233       if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
234         {
235           /* ??? Ug.  Actually unlinking the thing is problematic, 
236              given what we'd have to coordinate with our callers.  */
237           PUT_CODE (insn, NOTE);
238           NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
239           NOTE_SOURCE_FILE (insn) = 0;
240           goto insn_done;
241         }
242
243       /* Last insn wasn't last?  */
244       if (must_be_last)
245         return FALSE;
246
247       if (modified_in_p (test, insn))
248         {
249           if (!mod_ok)
250             return FALSE;
251           must_be_last = TRUE;
252         }
253
254       /* Now build the conditional form of the instruction.  */
255       pattern = PATTERN (insn);
256
257       /* If the machine needs to modify the insn being conditionally executed,
258          say for example to force a constant integer operand into a temp
259          register, do so here.  */
260 #ifdef IFCVT_MODIFY_INSN
261       IFCVT_MODIFY_INSN (pattern, insn);
262       if (! pattern)
263         return FALSE;
264 #endif
265
266       validate_change (insn, &PATTERN (insn),
267                        gen_rtx_COND_EXEC (VOIDmode, copy_rtx (test),
268                                           pattern), 1);
269
270       if (GET_CODE (insn) == CALL_INSN && prob_val)
271         validate_change (insn, &REG_NOTES (insn),
272                          alloc_EXPR_LIST (REG_BR_PROB, prob_val,
273                                           REG_NOTES (insn)), 1);
274
275     insn_done:
276       if (insn == end)
277         break;
278     }
279
280   return TRUE;
281 }
282
283 /* Return the condition for a jump.  Do not do any special processing.  */
284
285 static rtx
286 cond_exec_get_condition (jump)
287      rtx jump;
288 {
289   rtx test_if, cond;
290
291   if (any_condjump_p (jump))
292     test_if = SET_SRC (pc_set (jump));
293   else
294     return NULL_RTX;
295   cond = XEXP (test_if, 0);
296
297   /* If this branches to JUMP_LABEL when the condition is false,
298      reverse the condition.  */
299   if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
300       && XEXP (XEXP (test_if, 2), 0) == JUMP_LABEL (jump))
301     {
302       enum rtx_code rev = reversed_comparison_code (cond, jump);
303       if (rev == UNKNOWN)
304         return NULL_RTX;
305
306       cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
307                              XEXP (cond, 1));
308     }
309
310   return cond;
311 }
312
313 /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
314    to conditional execution.  Return TRUE if we were successful at
315    converting the the block.  */
316
317 static int
318 cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
319      basic_block test_bb;       /* Basic block test is in */
320      basic_block then_bb;       /* Basic block for THEN block */
321      basic_block else_bb;       /* Basic block for ELSE block */
322      basic_block join_bb;       /* Basic block the join label is in */
323 {
324   rtx test_expr;                /* expression in IF_THEN_ELSE that is tested */
325   rtx then_start;               /* first insn in THEN block */
326   rtx then_end;                 /* last insn + 1 in THEN block */
327   rtx else_start = NULL_RTX;    /* first insn in ELSE block or NULL */
328   rtx else_end = NULL_RTX;      /* last insn + 1 in ELSE block */
329   int max;                      /* max # of insns to convert.  */
330   int then_mod_ok;              /* whether conditional mods are ok in THEN */
331   rtx true_expr;                /* test for else block insns */
332   rtx false_expr;               /* test for then block insns */
333   rtx true_prob_val;            /* probability of else block */
334   rtx false_prob_val;           /* probability of then block */
335   int n_insns;
336   enum rtx_code false_code;
337
338   /* Find the conditional jump to the ELSE or JOIN part, and isolate
339      the test.  */
340   test_expr = cond_exec_get_condition (test_bb->end);
341   if (! test_expr)
342     return FALSE;
343
344   /* If the conditional jump is more than just a conditional jump,
345      then we can not do conditional execution conversion on this block.  */
346   if (!onlyjump_p (test_bb->end))
347     return FALSE;
348
349   /* Collect the bounds of where we're to search.  */
350
351   then_start = then_bb->head;
352   then_end = then_bb->end;
353
354   /* Skip a label heading THEN block.  */
355   if (GET_CODE (then_start) == CODE_LABEL)
356     then_start = NEXT_INSN (then_start);
357
358   /* Skip a (use (const_int 0)) or branch as the final insn.  */
359   if (GET_CODE (then_end) == INSN
360       && GET_CODE (PATTERN (then_end)) == USE
361       && GET_CODE (XEXP (PATTERN (then_end), 0)) == CONST_INT)
362     then_end = PREV_INSN (then_end);
363   else if (GET_CODE (then_end) == JUMP_INSN)
364     then_end = PREV_INSN (then_end);
365
366   if (else_bb)
367     {
368       /* Skip the ELSE block's label.  */
369       else_start = NEXT_INSN (else_bb->head);
370       else_end = else_bb->end;
371
372       /* Skip a (use (const_int 0)) or branch as the final insn.  */
373       if (GET_CODE (else_end) == INSN
374           && GET_CODE (PATTERN (else_end)) == USE
375           && GET_CODE (XEXP (PATTERN (else_end), 0)) == CONST_INT)
376         else_end = PREV_INSN (else_end);
377       else if (GET_CODE (else_end) == JUMP_INSN)
378         else_end = PREV_INSN (else_end);
379     }
380
381   /* How many instructions should we convert in total?  */
382   n_insns = 0;
383   if (else_bb)
384     {
385       max = 2 * MAX_CONDITIONAL_EXECUTE;
386       n_insns = count_bb_insns (else_bb);
387     }
388   else
389     max = MAX_CONDITIONAL_EXECUTE;
390   n_insns += count_bb_insns (then_bb);
391   if (n_insns > max)
392     return FALSE;
393
394   /* Map test_expr/test_jump into the appropriate MD tests to use on
395      the conditionally executed code.  */
396   
397   true_expr = test_expr;
398
399   false_code = reversed_comparison_code (true_expr, test_bb->end);
400   if (false_code != UNKNOWN)
401     false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
402                                  XEXP (true_expr, 0), XEXP (true_expr, 1));
403   else
404     false_expr = NULL_RTX;
405
406 #ifdef IFCVT_MODIFY_TESTS
407   /* If the machine description needs to modify the tests, such as setting a
408      conditional execution register from a comparison, it can do so here.  */
409   IFCVT_MODIFY_TESTS (true_expr, false_expr, test_bb, then_bb, else_bb,
410                       join_bb);
411
412   /* See if the conversion failed */
413   if (!true_expr || !false_expr)
414     goto fail;
415 #endif
416
417   true_prob_val = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
418   if (true_prob_val)
419     {
420       true_prob_val = XEXP (true_prob_val, 0);
421       false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val));
422     }
423   else
424     false_prob_val = NULL_RTX;
425
426   /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
427      on then THEN block.  */
428   then_mod_ok = (else_bb == NULL_BLOCK);
429
430   /* Go through the THEN and ELSE blocks converting the insns if possible
431      to conditional execution.  */
432
433   if (then_end
434       && (! false_expr
435           || ! cond_exec_process_insns (then_start, then_end, false_expr,
436                                         false_prob_val, then_mod_ok)))
437     goto fail;
438
439   if (else_bb
440       && ! cond_exec_process_insns (else_start, else_end,
441                                     true_expr, true_prob_val, TRUE))
442     goto fail;
443
444   if (! apply_change_group ())
445     return FALSE;
446
447 #ifdef IFCVT_MODIFY_FINAL
448   /* Do any machine dependent final modifications */
449   IFCVT_MODIFY_FINAL (test_bb, then_bb, else_bb, join_bb);
450 #endif
451
452   /* Conversion succeeded.  */
453   if (rtl_dump_file)
454     fprintf (rtl_dump_file, "%d insn%s converted to conditional execution.\n",
455              n_insns, (n_insns == 1) ? " was" : "s were");
456
457   /* Merge the blocks!  */
458   merge_if_block (test_bb, then_bb, else_bb, join_bb);
459   return TRUE;
460
461  fail:
462 #ifdef IFCVT_MODIFY_CANCEL
463   /* Cancel any machine dependent changes.  */
464   IFCVT_MODIFY_CANCEL (test_bb, then_bb, else_bb, join_bb);
465 #endif
466
467   cancel_changes (0);
468   return FALSE;
469 }
470 \f
471 /* Used by noce_process_if_block to communicate with its subroutines. 
472
473    The subroutines know that A and B may be evaluated freely.  They
474    know that X is a register.  They should insert new instructions 
475    before cond_earliest.  */
476
477 struct noce_if_info
478 {
479   basic_block test_bb;
480   rtx insn_a, insn_b;
481   rtx x, a, b;
482   rtx jump, cond, cond_earliest;
483 };
484
485 static rtx noce_emit_store_flag         PARAMS ((struct noce_if_info *,
486                                                  rtx, int, int));
487 static int noce_try_store_flag          PARAMS ((struct noce_if_info *));
488 static int noce_try_store_flag_inc      PARAMS ((struct noce_if_info *));
489 static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *));
490 static int noce_try_store_flag_mask     PARAMS ((struct noce_if_info *));
491 static rtx noce_emit_cmove              PARAMS ((struct noce_if_info *,
492                                                  rtx, enum rtx_code, rtx,
493                                                  rtx, rtx, rtx));
494 static int noce_try_cmove               PARAMS ((struct noce_if_info *));
495 static int noce_try_cmove_arith         PARAMS ((struct noce_if_info *));
496 static rtx noce_get_alt_condition       PARAMS ((struct noce_if_info *,
497                                                  rtx, rtx *));
498 static int noce_try_minmax              PARAMS ((struct noce_if_info *));
499 static int noce_try_abs                 PARAMS ((struct noce_if_info *));
500
501 /* Helper function for noce_try_store_flag*.  */
502
503 static rtx
504 noce_emit_store_flag (if_info, x, reversep, normalize)
505      struct noce_if_info *if_info;
506      rtx x;
507      int reversep, normalize;
508 {
509   rtx cond = if_info->cond;
510   int cond_complex;
511   enum rtx_code code;
512
513   cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
514                   || ! general_operand (XEXP (cond, 1), VOIDmode));
515
516   /* If earliest == jump, or when the condition is complex, try to
517      build the store_flag insn directly.  */
518
519   if (cond_complex)
520     cond = XEXP (SET_SRC (pc_set (if_info->jump)), 0);
521
522   if (reversep)
523     code = reversed_comparison_code (cond, if_info->jump);
524   else
525     code = GET_CODE (cond);
526
527   if ((if_info->cond_earliest == if_info->jump || cond_complex)
528       && (normalize == 0 || STORE_FLAG_VALUE == normalize))
529     {
530       rtx tmp;
531
532       tmp = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
533                             XEXP (cond, 1));
534       tmp = gen_rtx_SET (VOIDmode, x, tmp);
535
536       start_sequence ();
537       tmp = emit_insn (tmp);
538
539       if (recog_memoized (tmp) >= 0)
540         {
541           tmp = get_insns ();
542           end_sequence ();
543           emit_insns (tmp);
544
545           if_info->cond_earliest = if_info->jump;
546
547           return x;
548         }
549
550       end_sequence ();
551     }
552
553   /* Don't even try if the comparison operands are weird.  */
554   if (cond_complex)
555     return NULL_RTX;
556
557   return emit_store_flag (x, code, XEXP (cond, 0),
558                           XEXP (cond, 1), VOIDmode,
559                           (code == LTU || code == LEU
560                            || code == GEU || code == GTU), normalize);
561 }
562
563 /* Emit instruction to move an rtx into STRICT_LOW_PART.  */
564 static void
565 noce_emit_move_insn (x, y)
566      rtx x, y;
567 {
568   enum machine_mode outmode, inmode;
569   rtx outer, inner;
570   int bitpos;
571
572   if (GET_CODE (x) != STRICT_LOW_PART)
573     {
574       emit_move_insn (x, y);
575       return;
576     }
577
578   outer = XEXP (x, 0);
579   inner = XEXP (outer, 0);
580   outmode = GET_MODE (outer);
581   inmode = GET_MODE (inner);
582   bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
583   store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y,
584                    GET_MODE_BITSIZE (inmode));
585 }
586
587 /* Convert "if (test) x = 1; else x = 0".
588
589    Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
590    tried in noce_try_store_flag_constants after noce_try_cmove has had
591    a go at the conversion.  */
592
593 static int
594 noce_try_store_flag (if_info)
595      struct noce_if_info *if_info;
596 {
597   int reversep;
598   rtx target, seq;
599
600   if (GET_CODE (if_info->b) == CONST_INT
601       && INTVAL (if_info->b) == STORE_FLAG_VALUE
602       && if_info->a == const0_rtx)
603     reversep = 0;
604   else if (if_info->b == const0_rtx
605            && GET_CODE (if_info->a) == CONST_INT
606            && INTVAL (if_info->a) == STORE_FLAG_VALUE
607            && (reversed_comparison_code (if_info->cond, if_info->jump)
608                != UNKNOWN))
609     reversep = 1;
610   else
611     return FALSE;
612
613   start_sequence ();
614
615   target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
616   if (target)
617     {
618       if (target != if_info->x)
619         noce_emit_move_insn (if_info->x, target);
620
621       seq = get_insns ();
622       end_sequence ();
623       emit_insns_before (seq, if_info->cond_earliest);
624
625       return TRUE;
626     }
627   else
628     {
629       end_sequence ();
630       return FALSE;
631     }
632 }
633
634 /* Convert "if (test) x = a; else x = b", for A and B constant.  */
635
636 static int
637 noce_try_store_flag_constants (if_info)
638      struct noce_if_info *if_info;
639 {
640   rtx target, seq;
641   int reversep;
642   HOST_WIDE_INT itrue, ifalse, diff, tmp;
643   int normalize, can_reverse;
644   enum machine_mode mode;
645
646   if (! no_new_pseudos
647       && GET_CODE (if_info->a) == CONST_INT
648       && GET_CODE (if_info->b) == CONST_INT)
649     {
650       mode = GET_MODE (if_info->x);
651       ifalse = INTVAL (if_info->a);
652       itrue = INTVAL (if_info->b);
653
654       /* Make sure we can represent the difference between the two values.  */
655       if ((itrue - ifalse > 0)
656           != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
657         return FALSE;
658
659       diff = trunc_int_for_mode (itrue - ifalse, mode);
660
661       can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
662                      != UNKNOWN);
663
664       reversep = 0;
665       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
666         normalize = 0;
667       else if (ifalse == 0 && exact_log2 (itrue) >= 0
668                && (STORE_FLAG_VALUE == 1
669                    || BRANCH_COST >= 2))
670         normalize = 1;
671       else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
672                && (STORE_FLAG_VALUE == 1 || BRANCH_COST >= 2))
673         normalize = 1, reversep = 1;
674       else if (itrue == -1
675                && (STORE_FLAG_VALUE == -1
676                    || BRANCH_COST >= 2))
677         normalize = -1;
678       else if (ifalse == -1 && can_reverse
679                && (STORE_FLAG_VALUE == -1 || BRANCH_COST >= 2))
680         normalize = -1, reversep = 1;
681       else if ((BRANCH_COST >= 2 && STORE_FLAG_VALUE == -1)
682                || BRANCH_COST >= 3)
683         normalize = -1;
684       else
685         return FALSE;
686
687       if (reversep)
688         {
689           tmp = itrue; itrue = ifalse; ifalse = tmp;
690           diff = trunc_int_for_mode (-diff, mode);
691         }
692
693       start_sequence ();
694       target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
695       if (! target)
696         {
697           end_sequence ();
698           return FALSE;
699         }
700
701       /* if (test) x = 3; else x = 4;
702          =>   x = 3 + (test == 0);  */
703       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
704         {
705           target = expand_simple_binop (mode,
706                                         (diff == STORE_FLAG_VALUE
707                                          ? PLUS : MINUS),
708                                         GEN_INT (ifalse), target, if_info->x, 0,
709                                         OPTAB_WIDEN);
710         }
711
712       /* if (test) x = 8; else x = 0;
713          =>   x = (test != 0) << 3;  */
714       else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
715         {
716           target = expand_simple_binop (mode, ASHIFT,
717                                         target, GEN_INT (tmp), if_info->x, 0,
718                                         OPTAB_WIDEN);
719         }
720
721       /* if (test) x = -1; else x = b;
722          =>   x = -(test != 0) | b;  */
723       else if (itrue == -1)
724         {
725           target = expand_simple_binop (mode, IOR,
726                                         target, GEN_INT (ifalse), if_info->x, 0,
727                                         OPTAB_WIDEN);
728         }
729
730       /* if (test) x = a; else x = b;
731          =>   x = (-(test != 0) & (b - a)) + a;  */
732       else
733         {
734           target = expand_simple_binop (mode, AND,
735                                         target, GEN_INT (diff), if_info->x, 0,
736                                         OPTAB_WIDEN);
737           if (target)
738             target = expand_simple_binop (mode, PLUS,
739                                           target, GEN_INT (ifalse),
740                                           if_info->x, 0, OPTAB_WIDEN);
741         }
742
743       if (! target)
744         {
745           end_sequence ();
746           return FALSE;
747         }
748
749       if (target != if_info->x)
750         noce_emit_move_insn (if_info->x, target);
751
752       seq = get_insns ();
753       end_sequence ();
754
755       if (seq_contains_jump (seq))
756         return FALSE;
757
758       emit_insns_before (seq, if_info->cond_earliest);
759
760       return TRUE;
761     }
762
763   return FALSE;
764 }
765
766 /* Convert "if (test) foo++" into "foo += (test != 0)", and 
767    similarly for "foo--".  */
768
769 static int
770 noce_try_store_flag_inc (if_info)
771      struct noce_if_info *if_info;
772 {
773   rtx target, seq;
774   int subtract, normalize;
775
776   if (! no_new_pseudos
777       && (BRANCH_COST >= 2
778           || HAVE_incscc
779           || HAVE_decscc)
780       /* Should be no `else' case to worry about.  */
781       && if_info->b == if_info->x
782       && GET_CODE (if_info->a) == PLUS
783       && (XEXP (if_info->a, 1) == const1_rtx
784           || XEXP (if_info->a, 1) == constm1_rtx)
785       && rtx_equal_p (XEXP (if_info->a, 0), if_info->x)
786       && (reversed_comparison_code (if_info->cond, if_info->jump)
787           != UNKNOWN))
788     {
789       if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
790         subtract = 0, normalize = 0;
791       else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
792         subtract = 1, normalize = 0;
793       else
794         subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
795       
796       start_sequence ();
797
798       target = noce_emit_store_flag (if_info,
799                                      gen_reg_rtx (GET_MODE (if_info->x)),
800                                      1, normalize);
801
802       if (target)
803         target = expand_simple_binop (GET_MODE (if_info->x),
804                                       subtract ? MINUS : PLUS,
805                                       if_info->x, target, if_info->x,
806                                       0, OPTAB_WIDEN);
807       if (target)
808         {
809           if (target != if_info->x)
810             noce_emit_move_insn (if_info->x, target);
811
812           seq = get_insns ();
813           end_sequence ();
814
815           if (seq_contains_jump (seq))
816             return FALSE;
817
818           emit_insns_before (seq, if_info->cond_earliest);
819
820           return TRUE;
821         }
822
823       end_sequence ();
824     }
825
826   return FALSE;
827 }
828
829 /* Convert "if (test) x = 0;" to "x &= -(test == 0);"  */
830
831 static int
832 noce_try_store_flag_mask (if_info)
833      struct noce_if_info *if_info;
834 {
835   rtx target, seq;
836   int reversep;
837
838   reversep = 0;
839   if (! no_new_pseudos
840       && (BRANCH_COST >= 2
841           || STORE_FLAG_VALUE == -1)
842       && ((if_info->a == const0_rtx
843            && rtx_equal_p (if_info->b, if_info->x))
844           || ((reversep = (reversed_comparison_code (if_info->cond,
845                                                      if_info->jump)
846                            != UNKNOWN))
847               && if_info->b == const0_rtx
848               && rtx_equal_p (if_info->a, if_info->x))))
849     {
850       start_sequence ();
851       target = noce_emit_store_flag (if_info,
852                                      gen_reg_rtx (GET_MODE (if_info->x)),
853                                      reversep, -1);
854       if (target)
855         target = expand_simple_binop (GET_MODE (if_info->x), AND,
856                                       if_info->x, target, if_info->x, 0,
857                                       OPTAB_WIDEN);
858
859       if (target)
860         {
861           if (target != if_info->x)
862             noce_emit_move_insn (if_info->x, target);
863
864           seq = get_insns ();
865           end_sequence ();
866
867           if (seq_contains_jump (seq))
868             return FALSE;
869
870           emit_insns_before (seq, if_info->cond_earliest);
871
872           return TRUE;
873         }
874
875       end_sequence ();
876     }
877
878   return FALSE;
879 }
880
881 /* Helper function for noce_try_cmove and noce_try_cmove_arith.  */
882
883 static rtx
884 noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
885      struct noce_if_info *if_info;
886      rtx x, cmp_a, cmp_b, vfalse, vtrue;
887      enum rtx_code code;
888 {
889   /* If earliest == jump, try to build the cmove insn directly.
890      This is helpful when combine has created some complex condition
891      (like for alpha's cmovlbs) that we can't hope to regenerate
892      through the normal interface.  */
893
894   if (if_info->cond_earliest == if_info->jump)
895     {
896       rtx tmp;
897
898       tmp = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
899       tmp = gen_rtx_IF_THEN_ELSE (GET_MODE (x), tmp, vtrue, vfalse);
900       tmp = gen_rtx_SET (VOIDmode, x, tmp);
901
902       start_sequence ();
903       tmp = emit_insn (tmp);
904
905       if (recog_memoized (tmp) >= 0)
906         {
907           tmp = get_insns ();
908           end_sequence ();
909           emit_insns (tmp);
910
911           return x;
912         }
913
914       end_sequence ();
915     }
916
917   /* Don't even try if the comparison operands are weird.  */
918   if (! general_operand (cmp_a, GET_MODE (cmp_a))
919       || ! general_operand (cmp_b, GET_MODE (cmp_b)))
920     return NULL_RTX;
921
922 #if HAVE_conditional_move
923   return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode,
924                                 vtrue, vfalse, GET_MODE (x),
925                                 (code == LTU || code == GEU
926                                  || code == LEU || code == GTU));
927 #else
928   /* We'll never get here, as noce_process_if_block doesn't call the
929      functions involved.  Ifdef code, however, should be discouraged
930      because it leads to typos in the code not selected.  However, 
931      emit_conditional_move won't exist either.  */
932   return NULL_RTX;
933 #endif
934 }
935
936 /* Try only simple constants and registers here.  More complex cases
937    are handled in noce_try_cmove_arith after noce_try_store_flag_arith
938    has had a go at it.  */
939
940 static int
941 noce_try_cmove (if_info)
942      struct noce_if_info *if_info;
943 {
944   enum rtx_code code;
945   rtx target, seq;
946
947   if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode))
948       && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode)))
949     {
950       start_sequence ();
951
952       code = GET_CODE (if_info->cond);
953       target = noce_emit_cmove (if_info, if_info->x, code,
954                                 XEXP (if_info->cond, 0),
955                                 XEXP (if_info->cond, 1),
956                                 if_info->a, if_info->b);
957
958       if (target)
959         {
960           if (target != if_info->x)
961             noce_emit_move_insn (if_info->x, target);
962
963           seq = get_insns ();
964           end_sequence ();
965           emit_insns_before (seq, if_info->cond_earliest);
966           return TRUE;
967         }
968       else
969         {
970           end_sequence ();
971           return FALSE;
972         }
973     }
974
975   return FALSE;
976 }
977
978 /* Try more complex cases involving conditional_move.  */
979
980 static int
981 noce_try_cmove_arith (if_info)
982      struct noce_if_info *if_info;
983 {
984   rtx a = if_info->a;
985   rtx b = if_info->b;
986   rtx x = if_info->x;
987   rtx insn_a, insn_b;
988   rtx tmp, target;
989   int is_mem = 0;
990   enum rtx_code code;
991
992   /* A conditional move from two memory sources is equivalent to a
993      conditional on their addresses followed by a load.  Don't do this
994      early because it'll screw alias analysis.  Note that we've
995      already checked for no side effects.  */
996   if (! no_new_pseudos && cse_not_expected
997       && GET_CODE (a) == MEM && GET_CODE (b) == MEM
998       && BRANCH_COST >= 5)
999     {
1000       a = XEXP (a, 0);
1001       b = XEXP (b, 0);
1002       x = gen_reg_rtx (Pmode);
1003       is_mem = 1;
1004     }
1005
1006   /* ??? We could handle this if we knew that a load from A or B could
1007      not fault.  This is also true if we've already loaded
1008      from the address along the path from ENTRY.  */
1009   else if (may_trap_p (a) || may_trap_p (b))
1010     return FALSE;
1011
1012   /* if (test) x = a + b; else x = c - d;
1013      => y = a + b;
1014         x = c - d;
1015         if (test)
1016           x = y;
1017   */
1018   
1019   code = GET_CODE (if_info->cond);
1020   insn_a = if_info->insn_a;
1021   insn_b = if_info->insn_b;
1022
1023   /* Possibly rearrange operands to make things come out more natural.  */
1024   if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)
1025     {
1026       int reversep = 0;
1027       if (rtx_equal_p (b, x))
1028         reversep = 1;
1029       else if (general_operand (b, GET_MODE (b)))
1030         reversep = 1;
1031
1032       if (reversep)
1033         {
1034           code = reversed_comparison_code (if_info->cond, if_info->jump);
1035           tmp = a, a = b, b = tmp;
1036           tmp = insn_a, insn_a = insn_b, insn_b = tmp;
1037         }
1038     }
1039
1040   start_sequence ();
1041
1042   /* If either operand is complex, load it into a register first.
1043      The best way to do this is to copy the original insn.  In this
1044      way we preserve any clobbers etc that the insn may have had.  
1045      This is of course not possible in the IS_MEM case.  */
1046   if (! general_operand (a, GET_MODE (a)))
1047     {
1048       rtx set;
1049
1050       if (no_new_pseudos)
1051         goto end_seq_and_fail;
1052
1053       if (is_mem)
1054         {
1055           tmp = gen_reg_rtx (GET_MODE (a));
1056           tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, a));
1057         }
1058       else if (! insn_a)
1059         goto end_seq_and_fail;
1060       else
1061         {
1062           a = gen_reg_rtx (GET_MODE (a));
1063           tmp = copy_rtx (insn_a);
1064           set = single_set (tmp);
1065           SET_DEST (set) = a;
1066           tmp = emit_insn (PATTERN (tmp));
1067         }
1068       if (recog_memoized (tmp) < 0)
1069         goto end_seq_and_fail;
1070     }
1071   if (! general_operand (b, GET_MODE (b)))
1072     {
1073       rtx set;
1074
1075       if (no_new_pseudos)
1076         goto end_seq_and_fail;
1077
1078       if (is_mem)
1079         {
1080           tmp = gen_reg_rtx (GET_MODE (b));
1081           tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
1082         }
1083       else if (! insn_b)
1084         goto end_seq_and_fail;
1085       else
1086         {
1087           b = gen_reg_rtx (GET_MODE (b));
1088           tmp = copy_rtx (insn_b);
1089           set = single_set (tmp);
1090           SET_DEST (set) = b;
1091           tmp = emit_insn (PATTERN (tmp));
1092         }
1093       if (recog_memoized (tmp) < 0)
1094         goto end_seq_and_fail;
1095     }
1096
1097   target = noce_emit_cmove (if_info, x, code, XEXP (if_info->cond, 0),
1098                             XEXP (if_info->cond, 1), a, b);
1099
1100   if (! target)
1101     goto end_seq_and_fail;
1102
1103   /* If we're handling a memory for above, emit the load now.  */
1104   if (is_mem)
1105     {
1106       tmp = gen_rtx_MEM (GET_MODE (if_info->x), target);
1107
1108       /* Copy over flags as appropriate.  */
1109       if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
1110         MEM_VOLATILE_P (tmp) = 1;
1111       if (MEM_IN_STRUCT_P (if_info->a) && MEM_IN_STRUCT_P (if_info->b))
1112         MEM_IN_STRUCT_P (tmp) = 1;
1113       if (MEM_SCALAR_P (if_info->a) && MEM_SCALAR_P (if_info->b))
1114         MEM_SCALAR_P (tmp) = 1;
1115       if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
1116         set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a));
1117       set_mem_align (tmp,
1118                      MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
1119
1120       noce_emit_move_insn (if_info->x, tmp);
1121     }
1122   else if (target != x)
1123     noce_emit_move_insn (x, target);
1124
1125   tmp = get_insns ();
1126   end_sequence ();
1127   emit_insns_before (tmp, if_info->cond_earliest);
1128   return TRUE;
1129
1130  end_seq_and_fail:
1131   end_sequence ();
1132   return FALSE;
1133 }
1134
1135 /* For most cases, the simplified condition we found is the best
1136    choice, but this is not the case for the min/max/abs transforms.
1137    For these we wish to know that it is A or B in the condition.  */
1138
1139 static rtx
1140 noce_get_alt_condition (if_info, target, earliest)
1141      struct noce_if_info *if_info;
1142      rtx target;
1143      rtx *earliest;
1144 {
1145   rtx cond, set, insn;
1146   int reverse;
1147
1148   /* If target is already mentioned in the known condition, return it.  */
1149   if (reg_mentioned_p (target, if_info->cond))
1150     {
1151       *earliest = if_info->cond_earliest;
1152       return if_info->cond;
1153     }
1154
1155   set = pc_set (if_info->jump);
1156   cond = XEXP (SET_SRC (set), 0);
1157   reverse
1158     = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
1159       && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump);
1160
1161   /* If we're looking for a constant, try to make the conditional
1162      have that constant in it.  There are two reasons why it may
1163      not have the constant we want:
1164
1165      1. GCC may have needed to put the constant in a register, because
1166         the target can't compare directly against that constant.  For
1167         this case, we look for a SET immediately before the comparison
1168         that puts a constant in that register.
1169
1170      2. GCC may have canonicalized the conditional, for example
1171         replacing "if x < 4" with "if x <= 3".  We can undo that (or
1172         make equivalent types of changes) to get the constants we need
1173         if they're off by one in the right direction.  */
1174
1175   if (GET_CODE (target) == CONST_INT)
1176     {
1177       enum rtx_code code = GET_CODE (if_info->cond);
1178       rtx op_a = XEXP (if_info->cond, 0);
1179       rtx op_b = XEXP (if_info->cond, 1);
1180       rtx prev_insn;
1181
1182       /* First, look to see if we put a constant in a register.  */
1183       prev_insn = PREV_INSN (if_info->cond_earliest);
1184       if (prev_insn
1185           && INSN_P (prev_insn)
1186           && GET_CODE (PATTERN (prev_insn)) == SET)
1187         {
1188           rtx src = find_reg_equal_equiv_note (prev_insn);
1189           if (!src)
1190             src = SET_SRC (PATTERN (prev_insn));
1191           if (GET_CODE (src) == CONST_INT)
1192             {
1193               if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
1194                 op_a = src;
1195               else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
1196                 op_b = src;
1197
1198               if (GET_CODE (op_a) == CONST_INT)
1199                 {
1200                   rtx tmp = op_a;
1201                   op_a = op_b;
1202                   op_b = tmp;
1203                   code = swap_condition (code);
1204                 }
1205             }
1206         }
1207
1208       /* Now, look to see if we can get the right constant by
1209          adjusting the conditional.  */
1210       if (GET_CODE (op_b) == CONST_INT)
1211         {
1212           HOST_WIDE_INT desired_val = INTVAL (target);
1213           HOST_WIDE_INT actual_val = INTVAL (op_b);
1214
1215           switch (code)
1216             {
1217             case LT:
1218               if (actual_val == desired_val + 1)
1219                 {
1220                   code = LE;
1221                   op_b = GEN_INT (desired_val);
1222                 }
1223               break;
1224             case LE:
1225               if (actual_val == desired_val - 1)
1226                 {
1227                   code = LT;
1228                   op_b = GEN_INT (desired_val);
1229                 }
1230               break;
1231             case GT:
1232               if (actual_val == desired_val - 1)
1233                 {
1234                   code = GE;
1235                   op_b = GEN_INT (desired_val);
1236                 }
1237               break;
1238             case GE:
1239               if (actual_val == desired_val + 1)
1240                 {
1241                   code = GT;
1242                   op_b = GEN_INT (desired_val);
1243                 }
1244               break;
1245             default:
1246               break;
1247             }
1248         }
1249
1250       /* If we made any changes, generate a new conditional that is
1251          equivalent to what we started with, but has the right
1252          constants in it.  */
1253       if (code != GET_CODE (if_info->cond)
1254           || op_a != XEXP (if_info->cond, 0)
1255           || op_b != XEXP (if_info->cond, 1))
1256         {
1257           cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
1258           *earliest = if_info->cond_earliest;
1259           return cond;
1260         }
1261     }
1262
1263   cond = canonicalize_condition (if_info->jump, cond, reverse,
1264                                  earliest, target);
1265   if (! cond || ! reg_mentioned_p (target, cond))
1266     return NULL;
1267
1268   /* We almost certainly searched back to a different place.
1269      Need to re-verify correct lifetimes.  */
1270
1271   /* X may not be mentioned in the range (cond_earliest, jump].  */
1272   for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
1273     if (INSN_P (insn) && reg_mentioned_p (if_info->x, insn))
1274       return NULL;
1275
1276   /* A and B may not be modified in the range [cond_earliest, jump).  */
1277   for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
1278     if (INSN_P (insn)
1279         && (modified_in_p (if_info->a, insn)
1280             || modified_in_p (if_info->b, insn)))
1281       return NULL;
1282
1283   return cond;
1284 }
1285
1286 /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc.  */
1287
1288 static int
1289 noce_try_minmax (if_info)
1290      struct noce_if_info *if_info;
1291
1292   rtx cond, earliest, target, seq;
1293   enum rtx_code code, op;
1294   int unsignedp;
1295
1296   /* ??? Can't guarantee that expand_binop won't create pseudos.  */
1297   if (no_new_pseudos)
1298     return FALSE;
1299
1300   /* ??? Reject modes with NaNs or signed zeros since we don't know how
1301      they will be resolved with an SMIN/SMAX.  It wouldn't be too hard
1302      to get the target to tell us...  */
1303   if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))
1304       || HONOR_NANS (GET_MODE (if_info->x)))
1305     return FALSE;
1306
1307   cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
1308   if (!cond)
1309     return FALSE;
1310
1311   /* Verify the condition is of the form we expect, and canonicalize
1312      the comparison code.  */
1313   code = GET_CODE (cond);
1314   if (rtx_equal_p (XEXP (cond, 0), if_info->a))
1315     {
1316       if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
1317         return FALSE;
1318     }
1319   else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
1320     {
1321       if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
1322         return FALSE;
1323       code = swap_condition (code);
1324     }
1325   else
1326     return FALSE;
1327
1328   /* Determine what sort of operation this is.  Note that the code is for
1329      a taken branch, so the code->operation mapping appears backwards.  */
1330   switch (code)
1331     {
1332     case LT:
1333     case LE:
1334     case UNLT:
1335     case UNLE:
1336       op = SMAX;
1337       unsignedp = 0;
1338       break;
1339     case GT:
1340     case GE:
1341     case UNGT:
1342     case UNGE:
1343       op = SMIN;
1344       unsignedp = 0;
1345       break;
1346     case LTU:
1347     case LEU:
1348       op = UMAX;
1349       unsignedp = 1;
1350       break;
1351     case GTU:
1352     case GEU:
1353       op = UMIN;
1354       unsignedp = 1;
1355       break;
1356     default:
1357       return FALSE;
1358     }
1359
1360   start_sequence ();
1361
1362   target = expand_simple_binop (GET_MODE (if_info->x), op,
1363                                 if_info->a, if_info->b,
1364                                 if_info->x, unsignedp, OPTAB_WIDEN);
1365   if (! target)
1366     {
1367       end_sequence ();
1368       return FALSE;
1369     }
1370   if (target != if_info->x)
1371     noce_emit_move_insn (if_info->x, target);
1372
1373   seq = get_insns ();
1374   end_sequence ();  
1375
1376   if (seq_contains_jump (seq))
1377     return FALSE;
1378
1379   emit_insns_before (seq, earliest);
1380   if_info->cond = cond;
1381   if_info->cond_earliest = earliest;
1382
1383   return TRUE;
1384 }
1385
1386 /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc.  */
1387
1388 static int
1389 noce_try_abs (if_info)
1390      struct noce_if_info *if_info;
1391
1392   rtx cond, earliest, target, seq, a, b, c;
1393   int negate;
1394
1395   /* ??? Can't guarantee that expand_binop won't create pseudos.  */
1396   if (no_new_pseudos)
1397     return FALSE;
1398
1399   /* Recognize A and B as constituting an ABS or NABS.  */
1400   a = if_info->a;
1401   b = if_info->b;
1402   if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
1403     negate = 0;
1404   else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
1405     {
1406       c = a; a = b; b = c;
1407       negate = 1;
1408     }
1409   else
1410     return FALSE;
1411    
1412   cond = noce_get_alt_condition (if_info, b, &earliest);
1413   if (!cond)
1414     return FALSE;
1415
1416   /* Verify the condition is of the form we expect.  */
1417   if (rtx_equal_p (XEXP (cond, 0), b))
1418     c = XEXP (cond, 1);
1419   else if (rtx_equal_p (XEXP (cond, 1), b))
1420     c = XEXP (cond, 0);
1421   else
1422     return FALSE;
1423
1424   /* Verify that C is zero.  Search backward through the block for
1425      a REG_EQUAL note if necessary.  */
1426   if (REG_P (c))
1427     {
1428       rtx insn, note = NULL;
1429       for (insn = earliest;
1430            insn != if_info->test_bb->head;
1431            insn = PREV_INSN (insn))
1432         if (INSN_P (insn) 
1433             && ((note = find_reg_note (insn, REG_EQUAL, c))
1434                 || (note = find_reg_note (insn, REG_EQUIV, c))))
1435           break;
1436       if (! note)
1437         return FALSE;
1438       c = XEXP (note, 0);
1439     }
1440   if (GET_CODE (c) == MEM
1441       && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
1442       && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
1443     c = get_pool_constant (XEXP (c, 0));
1444
1445   /* Work around funny ideas get_condition has wrt canonicalization.
1446      Note that these rtx constants are known to be CONST_INT, and 
1447      therefore imply integer comparisons.  */
1448   if (c == constm1_rtx && GET_CODE (cond) == GT)
1449     ;
1450   else if (c == const1_rtx && GET_CODE (cond) == LT)
1451     ;
1452   else if (c != CONST0_RTX (GET_MODE (b)))
1453     return FALSE;
1454
1455   /* Determine what sort of operation this is.  */
1456   switch (GET_CODE (cond))
1457     {
1458     case LT:
1459     case LE:
1460     case UNLT:
1461     case UNLE:
1462       negate = !negate;
1463       break;
1464     case GT:
1465     case GE:
1466     case UNGT:
1467     case UNGE:
1468       break;
1469     default:
1470       return FALSE;
1471     }
1472
1473   start_sequence ();
1474
1475   target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0);
1476
1477   /* ??? It's a quandry whether cmove would be better here, especially
1478      for integers.  Perhaps combine will clean things up.  */
1479   if (target && negate)
1480     target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0);
1481
1482   if (! target)
1483     {
1484       end_sequence ();
1485       return FALSE;
1486     }
1487
1488   if (target != if_info->x)
1489     noce_emit_move_insn (if_info->x, target);
1490
1491   seq = get_insns ();
1492   end_sequence ();  
1493
1494   if (seq_contains_jump (seq))
1495     return FALSE;
1496
1497   emit_insns_before (seq, earliest);
1498   if_info->cond = cond;
1499   if_info->cond_earliest = earliest;
1500
1501   return TRUE;
1502 }
1503
1504 /* Look for the condition for the jump first.  We'd prefer to avoid
1505    get_condition if we can -- it tries to look back for the contents
1506    of an original compare.  On targets that use normal integers for
1507    comparisons, e.g. alpha, this is wasteful.  */
1508
1509 static rtx
1510 noce_get_condition (jump, earliest)
1511      rtx jump;
1512      rtx *earliest;
1513 {
1514   rtx cond;
1515   rtx set;
1516
1517   /* If the condition variable is a register and is MODE_INT, accept it.
1518      Otherwise, fall back on get_condition.  */
1519
1520   if (! any_condjump_p (jump))
1521     return NULL_RTX;
1522
1523   set = pc_set (jump);
1524
1525   cond = XEXP (SET_SRC (set), 0);
1526   if (GET_CODE (XEXP (cond, 0)) == REG
1527       && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_INT)
1528     {
1529       *earliest = jump;
1530
1531       /* If this branches to JUMP_LABEL when the condition is false,
1532          reverse the condition.  */
1533       if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
1534           && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump))
1535         cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
1536                                GET_MODE (cond), XEXP (cond, 0),
1537                                XEXP (cond, 1));
1538     }
1539   else
1540     cond = get_condition (jump, earliest);
1541
1542   return cond;
1543 }
1544
1545 /* Return true if OP is ok for if-then-else processing.  */
1546
1547 static int
1548 noce_operand_ok (op)
1549      rtx op;
1550 {
1551   /* We special-case memories, so handle any of them with
1552      no address side effects.  */
1553   if (GET_CODE (op) == MEM)
1554     return ! side_effects_p (XEXP (op, 0));
1555
1556   if (side_effects_p (op))
1557     return FALSE;
1558
1559   return ! may_trap_p (op);
1560 }
1561
1562 /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
1563    without using conditional execution.  Return TRUE if we were
1564    successful at converting the the block.  */
1565
1566 static int
1567 noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
1568      basic_block test_bb;       /* Basic block test is in */
1569      basic_block then_bb;       /* Basic block for THEN block */
1570      basic_block else_bb;       /* Basic block for ELSE block */
1571      basic_block join_bb;       /* Basic block the join label is in */
1572 {
1573   /* We're looking for patterns of the form
1574
1575      (1) if (...) x = a; else x = b;
1576      (2) x = b; if (...) x = a;
1577      (3) if (...) x = a;   // as if with an initial x = x.
1578
1579      The later patterns require jumps to be more expensive.
1580
1581      ??? For future expansion, look for multiple X in such patterns.  */
1582
1583   struct noce_if_info if_info;
1584   rtx insn_a, insn_b;
1585   rtx set_a, set_b;
1586   rtx orig_x, x, a, b;
1587   rtx jump, cond, insn;
1588
1589   /* If this is not a standard conditional jump, we can't parse it.  */
1590   jump = test_bb->end;
1591   cond = noce_get_condition (jump, &if_info.cond_earliest);
1592   if (! cond)
1593     return FALSE;
1594
1595   /* If the conditional jump is more than just a conditional jump,
1596      then we can not do if-conversion on this block.  */
1597   if (! onlyjump_p (jump))
1598     return FALSE;
1599
1600   /* We must be comparing objects whose modes imply the size.  */
1601   if (GET_MODE (XEXP (cond, 0)) == BLKmode)
1602     return FALSE;
1603
1604   /* Look for one of the potential sets.  */
1605   insn_a = first_active_insn (then_bb);
1606   if (! insn_a
1607       || ! last_active_insn_p (then_bb, insn_a)
1608       || (set_a = single_set (insn_a)) == NULL_RTX)
1609     return FALSE;
1610
1611   x = SET_DEST (set_a);
1612   a = SET_SRC (set_a);
1613
1614   /* Look for the other potential set.  Make sure we've got equivalent
1615      destinations.  */
1616   /* ??? This is overconservative.  Storing to two different mems is
1617      as easy as conditionally computing the address.  Storing to a
1618      single mem merely requires a scratch memory to use as one of the
1619      destination addresses; often the memory immediately below the
1620      stack pointer is available for this.  */
1621   set_b = NULL_RTX;
1622   if (else_bb)
1623     {
1624       insn_b = first_active_insn (else_bb);
1625       if (! insn_b
1626           || ! last_active_insn_p (else_bb, insn_b)
1627           || (set_b = single_set (insn_b)) == NULL_RTX
1628           || ! rtx_equal_p (x, SET_DEST (set_b)))
1629         return FALSE;
1630     }
1631   else
1632     {
1633       insn_b = prev_nonnote_insn (if_info.cond_earliest);
1634       if (! insn_b
1635           || GET_CODE (insn_b) != INSN
1636           || (set_b = single_set (insn_b)) == NULL_RTX
1637           || ! rtx_equal_p (x, SET_DEST (set_b))
1638           || reg_mentioned_p (x, cond)
1639           || reg_mentioned_p (x, a)
1640           || reg_mentioned_p (x, SET_SRC (set_b)))
1641         insn_b = set_b = NULL_RTX;
1642     }
1643   b = (set_b ? SET_SRC (set_b) : x);
1644
1645   /* X may not be mentioned in the range (cond_earliest, jump].  */
1646   for (insn = jump; insn != if_info.cond_earliest; insn = PREV_INSN (insn))
1647     if (INSN_P (insn) && reg_mentioned_p (x, insn))
1648       return FALSE;
1649
1650   /* A and B may not be modified in the range [cond_earliest, jump).  */
1651   for (insn = if_info.cond_earliest; insn != jump; insn = NEXT_INSN (insn))
1652     if (INSN_P (insn)
1653         && (modified_in_p (a, insn) || modified_in_p (b, insn)))
1654       return FALSE;
1655
1656   /* Only operate on register destinations, and even then avoid extending
1657      the lifetime of hard registers on small register class machines.  */
1658   orig_x = x;
1659   if (GET_CODE (x) != REG
1660       || (SMALL_REGISTER_CLASSES
1661           && REGNO (x) < FIRST_PSEUDO_REGISTER))
1662     {
1663       if (no_new_pseudos)
1664         return FALSE;
1665       x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
1666                                  ? XEXP (x, 0) : x));
1667     }
1668
1669   /* Don't operate on sources that may trap or are volatile.  */
1670   if (! noce_operand_ok (a) || ! noce_operand_ok (b))
1671     return FALSE;
1672
1673   /* Set up the info block for our subroutines.  */
1674   if_info.test_bb = test_bb;
1675   if_info.cond = cond;
1676   if_info.jump = jump;
1677   if_info.insn_a = insn_a;
1678   if_info.insn_b = insn_b;
1679   if_info.x = x;
1680   if_info.a = a;
1681   if_info.b = b;
1682
1683   /* Try optimizations in some approximation of a useful order.  */
1684   /* ??? Should first look to see if X is live incoming at all.  If it
1685      isn't, we don't need anything but an unconditional set.  */
1686
1687   /* Look and see if A and B are really the same.  Avoid creating silly
1688      cmove constructs that no one will fix up later.  */
1689   if (rtx_equal_p (a, b))
1690     {
1691       /* If we have an INSN_B, we don't have to create any new rtl.  Just
1692          move the instruction that we already have.  If we don't have an
1693          INSN_B, that means that A == X, and we've got a noop move.  In
1694          that case don't do anything and let the code below delete INSN_A.  */
1695       if (insn_b && else_bb)
1696         {
1697           rtx note;
1698
1699           if (else_bb && insn_b == else_bb->end)
1700             else_bb->end = PREV_INSN (insn_b);
1701           reorder_insns (insn_b, insn_b, PREV_INSN (if_info.cond_earliest));
1702
1703           /* If there was a REG_EQUAL note, delete it since it may have been
1704              true due to this insn being after a jump.  */
1705           if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
1706             remove_note (insn_b, note);
1707
1708           insn_b = NULL_RTX;
1709         }
1710       /* If we have "x = b; if (...) x = a;", and x has side-effects, then
1711          x must be executed twice.  */
1712       else if (insn_b && side_effects_p (orig_x))
1713         return FALSE;
1714         
1715       x = orig_x;
1716       goto success;
1717     }
1718
1719   if (noce_try_store_flag (&if_info))
1720     goto success;
1721   if (noce_try_minmax (&if_info))
1722     goto success;
1723   if (noce_try_abs (&if_info))
1724     goto success;
1725   if (HAVE_conditional_move
1726       && noce_try_cmove (&if_info))
1727     goto success;
1728   if (! HAVE_conditional_execution)
1729     {
1730       if (noce_try_store_flag_constants (&if_info))
1731         goto success;
1732       if (noce_try_store_flag_inc (&if_info))
1733         goto success;
1734       if (noce_try_store_flag_mask (&if_info))
1735         goto success;
1736       if (HAVE_conditional_move
1737           && noce_try_cmove_arith (&if_info))
1738         goto success;
1739     }
1740
1741   return FALSE;
1742
1743  success:
1744   /* The original sets may now be killed.  */
1745   delete_insn (insn_a);
1746
1747   /* Several special cases here: First, we may have reused insn_b above,
1748      in which case insn_b is now NULL.  Second, we want to delete insn_b
1749      if it came from the ELSE block, because follows the now correct
1750      write that appears in the TEST block.  However, if we got insn_b from
1751      the TEST block, it may in fact be loading data needed for the comparison.
1752      We'll let life_analysis remove the insn if it's really dead.  */
1753   if (insn_b && else_bb)
1754     delete_insn (insn_b);
1755
1756   /* The new insns will have been inserted before cond_earliest.  We should
1757      be able to remove the jump with impunity, but the condition itself may
1758      have been modified by gcse to be shared across basic blocks.  */
1759   delete_insn (jump);
1760
1761   /* If we used a temporary, fix it up now.  */
1762   if (orig_x != x)
1763     {
1764       start_sequence ();
1765       noce_emit_move_insn (copy_rtx (orig_x), x);
1766       insn_b = gen_sequence ();
1767       end_sequence ();
1768
1769       emit_insn_after (insn_b, test_bb->end);
1770     }
1771
1772   /* Merge the blocks!  */
1773   merge_if_block (test_bb, then_bb, else_bb, join_bb);
1774
1775   return TRUE;
1776 }
1777 \f
1778 /* Attempt to convert an IF-THEN or IF-THEN-ELSE block into
1779    straight line code.  Return true if successful.  */
1780
1781 static int
1782 process_if_block (test_bb, then_bb, else_bb, join_bb)
1783      basic_block test_bb;       /* Basic block test is in */
1784      basic_block then_bb;       /* Basic block for THEN block */
1785      basic_block else_bb;       /* Basic block for ELSE block */
1786      basic_block join_bb;       /* Basic block the join label is in */
1787 {
1788   if (! reload_completed
1789       && noce_process_if_block (test_bb, then_bb, else_bb, join_bb))
1790     return TRUE;
1791
1792   if (HAVE_conditional_execution
1793       && reload_completed
1794       && cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb))
1795     return TRUE;
1796
1797   return FALSE;
1798 }
1799
1800 /* Merge the blocks and mark for local life update.  */
1801
1802 static void
1803 merge_if_block (test_bb, then_bb, else_bb, join_bb)
1804      basic_block test_bb;       /* Basic block test is in */
1805      basic_block then_bb;       /* Basic block for THEN block */
1806      basic_block else_bb;       /* Basic block for ELSE block */
1807      basic_block join_bb;       /* Basic block the join label is in */
1808 {
1809   basic_block combo_bb;
1810
1811   /* All block merging is done into the lower block numbers.  */
1812
1813   combo_bb = test_bb;
1814
1815   /* First merge TEST block into THEN block.  This is a no-brainer since
1816      the THEN block did not have a code label to begin with.  */
1817   if (then_bb)
1818     {
1819       if (combo_bb->global_live_at_end)
1820         COPY_REG_SET (combo_bb->global_live_at_end,
1821                       then_bb->global_live_at_end);
1822       merge_blocks_nomove (combo_bb, then_bb);
1823       num_removed_blocks++;
1824     }
1825
1826   /* The ELSE block, if it existed, had a label.  That label count
1827      will almost always be zero, but odd things can happen when labels
1828      get their addresses taken.  */
1829   if (else_bb)
1830     {
1831       merge_blocks_nomove (combo_bb, else_bb);
1832       num_removed_blocks++;
1833     }
1834
1835   /* If there was no join block reported, that means it was not adjacent
1836      to the others, and so we cannot merge them.  */
1837
1838   if (! join_bb)
1839     {
1840       rtx last = combo_bb->end;
1841
1842       /* The outgoing edge for the current COMBO block should already
1843          be correct.  Verify this.  */
1844       if (combo_bb->succ == NULL_EDGE)
1845         {
1846           if (find_reg_note (last, REG_NORETURN, NULL))
1847             ;
1848           else if (GET_CODE (last) == INSN
1849                    && GET_CODE (PATTERN (last)) == TRAP_IF
1850                    && TRAP_CONDITION (PATTERN (last)) == const_true_rtx)
1851             ;
1852           else
1853             abort ();
1854         }
1855
1856       /* There should still be something at the end of the THEN or ELSE
1857          blocks taking us to our final destination.  */
1858       else if (GET_CODE (last) == JUMP_INSN)
1859         ;
1860       else if (combo_bb->succ->dest == EXIT_BLOCK_PTR
1861                && GET_CODE (last) == CALL_INSN
1862                && SIBLING_CALL_P (last))
1863         ;
1864       else if ((combo_bb->succ->flags & EDGE_EH)
1865                && can_throw_internal (last))
1866         ;
1867       else
1868         abort ();
1869     }
1870
1871   /* The JOIN block may have had quite a number of other predecessors too.
1872      Since we've already merged the TEST, THEN and ELSE blocks, we should
1873      have only one remaining edge from our if-then-else diamond.  If there
1874      is more than one remaining edge, it must come from elsewhere.  There
1875      may be zero incoming edges if the THEN block didn't actually join 
1876      back up (as with a call to abort).  */
1877   else if ((join_bb->pred == NULL
1878             || join_bb->pred->pred_next == NULL)
1879            && join_bb != EXIT_BLOCK_PTR)
1880     {
1881       /* We can merge the JOIN.  */
1882       if (combo_bb->global_live_at_end)
1883         COPY_REG_SET (combo_bb->global_live_at_end,
1884                       join_bb->global_live_at_end);
1885       merge_blocks_nomove (combo_bb, join_bb);
1886       num_removed_blocks++;
1887     }
1888   else
1889     {
1890       /* We cannot merge the JOIN.  */
1891
1892       /* The outgoing edge for the current COMBO block should already
1893          be correct.  Verify this.  */
1894       if (combo_bb->succ->succ_next != NULL_EDGE
1895           || combo_bb->succ->dest != join_bb)
1896         abort ();
1897
1898       /* Remove the jump and cruft from the end of the COMBO block.  */
1899       if (join_bb != EXIT_BLOCK_PTR)
1900         tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
1901     }
1902
1903   num_updated_if_blocks++;
1904 }
1905 \f
1906 /* Find a block ending in a simple IF condition.  Return TRUE if
1907    we were able to transform it in some way.  */
1908
1909 static int
1910 find_if_header (test_bb)
1911      basic_block test_bb;
1912 {
1913   edge then_edge;
1914   edge else_edge;
1915
1916   /* The kind of block we're looking for has exactly two successors.  */
1917   if ((then_edge = test_bb->succ) == NULL_EDGE
1918       || (else_edge = then_edge->succ_next) == NULL_EDGE
1919       || else_edge->succ_next != NULL_EDGE)
1920     return FALSE;
1921
1922   /* Neither edge should be abnormal.  */
1923   if ((then_edge->flags & EDGE_COMPLEX)
1924       || (else_edge->flags & EDGE_COMPLEX))
1925     return FALSE;
1926
1927   /* The THEN edge is canonically the one that falls through.  */
1928   if (then_edge->flags & EDGE_FALLTHRU)
1929     ;
1930   else if (else_edge->flags & EDGE_FALLTHRU)
1931     {
1932       edge e = else_edge;
1933       else_edge = then_edge;
1934       then_edge = e;
1935     }
1936   else
1937     /* Otherwise this must be a multiway branch of some sort.  */
1938     return FALSE;
1939
1940   if (find_if_block (test_bb, then_edge, else_edge))
1941     goto success;
1942   if (HAVE_trap && HAVE_conditional_trap
1943       && find_cond_trap (test_bb, then_edge, else_edge))
1944     goto success;
1945   if (post_dominators
1946       && (! HAVE_conditional_execution || reload_completed))
1947     {
1948       if (find_if_case_1 (test_bb, then_edge, else_edge))
1949         goto success;
1950       if (find_if_case_2 (test_bb, then_edge, else_edge))
1951         goto success;
1952     }
1953
1954   return FALSE;
1955
1956  success:
1957   if (rtl_dump_file)
1958     fprintf (rtl_dump_file, "Conversion succeeded.\n");
1959   return TRUE;
1960 }
1961
1962 /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
1963    block.  If so, we'll try to convert the insns to not require the branch.
1964    Return TRUE if we were successful at converting the the block.  */
1965
1966 static int
1967 find_if_block (test_bb, then_edge, else_edge)
1968       basic_block test_bb;
1969       edge then_edge, else_edge;
1970 {
1971   basic_block then_bb = then_edge->dest;
1972   basic_block else_bb = else_edge->dest;
1973   basic_block join_bb = NULL_BLOCK;
1974   edge then_succ = then_bb->succ;
1975   edge else_succ = else_bb->succ;
1976   int next_index;
1977
1978   /* The THEN block of an IF-THEN combo must have exactly one predecessor.  */
1979   if (then_bb->pred->pred_next != NULL_EDGE)
1980     return FALSE;
1981
1982   /* The THEN block of an IF-THEN combo must have zero or one successors.  */
1983   if (then_succ != NULL_EDGE
1984       && (then_succ->succ_next != NULL_EDGE
1985           || (then_succ->flags & EDGE_COMPLEX)))
1986     return FALSE;
1987
1988   /* If the THEN block has no successors, conditional execution can still
1989      make a conditional call.  Don't do this unless the ELSE block has
1990      only one incoming edge -- the CFG manipulation is too ugly otherwise.
1991      Check for the last insn of the THEN block being an indirect jump, which
1992      is listed as not having any successors, but confuses the rest of the CE
1993      code processing.  XXX we should fix this in the future.  */
1994   if (then_succ == NULL)
1995     {
1996       if (else_bb->pred->pred_next == NULL_EDGE)
1997         {
1998           rtx last_insn = then_bb->end;
1999
2000           while (last_insn
2001                  && GET_CODE (last_insn) == NOTE
2002                  && last_insn != then_bb->head)
2003             last_insn = PREV_INSN (last_insn);
2004
2005           if (last_insn
2006               && GET_CODE (last_insn) == JUMP_INSN
2007               && ! simplejump_p (last_insn))
2008             return FALSE;
2009
2010           join_bb = else_bb;
2011           else_bb = NULL_BLOCK;
2012         }
2013       else
2014         return FALSE;
2015     }
2016
2017   /* If the THEN block's successor is the other edge out of the TEST block,
2018      then we have an IF-THEN combo without an ELSE.  */
2019   else if (then_succ->dest == else_bb)
2020     {
2021       join_bb = else_bb;
2022       else_bb = NULL_BLOCK;
2023     }
2024
2025   /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
2026      has exactly one predecessor and one successor, and the outgoing edge
2027      is not complex, then we have an IF-THEN-ELSE combo.  */
2028   else if (else_succ != NULL_EDGE
2029            && then_succ->dest == else_succ->dest
2030            && else_bb->pred->pred_next == NULL_EDGE
2031            && else_succ->succ_next == NULL_EDGE
2032            && ! (else_succ->flags & EDGE_COMPLEX))
2033     join_bb = else_succ->dest;
2034
2035   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
2036   else
2037     return FALSE;          
2038
2039   num_possible_if_blocks++;
2040
2041   if (rtl_dump_file)
2042     {
2043       if (else_bb)
2044         fprintf (rtl_dump_file,
2045                  "\nIF-THEN-ELSE block found, start %d, then %d, else %d, join %d\n",
2046                  test_bb->index, then_bb->index, else_bb->index,
2047                  join_bb->index);
2048       else
2049         fprintf (rtl_dump_file,
2050                  "\nIF-THEN block found, start %d, then %d, join %d\n",
2051                  test_bb->index, then_bb->index, join_bb->index);
2052     }
2053
2054   /* Make sure IF, THEN, and ELSE, blocks are adjacent.  Actually, we
2055      get the first condition for free, since we've already asserted that
2056      there's a fallthru edge from IF to THEN.  */
2057   /* ??? As an enhancement, move the ELSE block.  Have to deal with
2058      BLOCK notes, if by no other means than aborting the merge if they
2059      exist.  Sticky enough I don't want to think about it now.  */
2060   next_index = then_bb->index;
2061   if (else_bb && ++next_index != else_bb->index)
2062     return FALSE;
2063   if (++next_index != join_bb->index && join_bb->index != EXIT_BLOCK)
2064     {
2065       if (else_bb)
2066         join_bb = NULL;
2067       else
2068         return FALSE;
2069     }
2070
2071   /* Do the real work.  */
2072   return process_if_block (test_bb, then_bb, else_bb, join_bb);
2073 }
2074
2075 /* Convert a branch over a trap, or a branch to a trap,
2076    into a conditional trap.  */
2077
2078 static int
2079 find_cond_trap (test_bb, then_edge, else_edge)
2080      basic_block test_bb;
2081      edge then_edge, else_edge;
2082 {
2083   basic_block then_bb, else_bb, join_bb, trap_bb;
2084   rtx trap, jump, cond, cond_earliest, seq;
2085   enum rtx_code code;
2086
2087   then_bb = then_edge->dest;
2088   else_bb = else_edge->dest;
2089   join_bb = NULL;
2090
2091   /* Locate the block with the trap instruction.  */
2092   /* ??? While we look for no successors, we really ought to allow
2093      EH successors.  Need to fix merge_if_block for that to work.  */
2094   /* ??? We can't currently handle merging the blocks if they are not
2095      already adjacent.  Prevent losage in merge_if_block by detecting
2096      this now.  */
2097   if ((trap = block_has_only_trap (then_bb)) != NULL)
2098     {
2099       trap_bb = then_bb;
2100       if (else_bb->index != then_bb->index + 1)
2101         return FALSE;
2102       join_bb = else_bb;
2103       else_bb = NULL;
2104     }
2105   else if ((trap = block_has_only_trap (else_bb)) != NULL)
2106     {
2107       trap_bb = else_bb;
2108       if (else_bb->index != then_bb->index + 1)
2109         else_bb = NULL;
2110       else if (then_bb->succ
2111           && ! then_bb->succ->succ_next
2112           && ! (then_bb->succ->flags & EDGE_COMPLEX)
2113           && then_bb->succ->dest->index == else_bb->index + 1)
2114         join_bb = then_bb->succ->dest;
2115     }
2116   else
2117     return FALSE;
2118
2119   if (rtl_dump_file)
2120     {
2121       if (trap_bb == then_bb)
2122         fprintf (rtl_dump_file,
2123                  "\nTRAP-IF block found, start %d, trap %d",
2124                  test_bb->index, then_bb->index);
2125       else
2126         fprintf (rtl_dump_file,
2127                  "\nTRAP-IF block found, start %d, then %d, trap %d",
2128                  test_bb->index, then_bb->index, trap_bb->index);
2129       if (join_bb)
2130         fprintf (rtl_dump_file, ", join %d\n", join_bb->index);
2131       else
2132         fputc ('\n', rtl_dump_file);
2133     }
2134
2135   /* If this is not a standard conditional jump, we can't parse it.  */
2136   jump = test_bb->end;
2137   cond = noce_get_condition (jump, &cond_earliest);
2138   if (! cond)
2139     return FALSE;
2140
2141   /* If the conditional jump is more than just a conditional jump,
2142      then we can not do if-conversion on this block.  */
2143   if (! onlyjump_p (jump))
2144     return FALSE;
2145
2146   /* We must be comparing objects whose modes imply the size.  */
2147   if (GET_MODE (XEXP (cond, 0)) == BLKmode)
2148     return FALSE;
2149
2150   /* Reverse the comparison code, if necessary.  */
2151   code = GET_CODE (cond);
2152   if (then_bb == trap_bb)
2153     {
2154       code = reversed_comparison_code (cond, jump);
2155       if (code == UNKNOWN)
2156         return FALSE;
2157     }
2158
2159   /* Attempt to generate the conditional trap.  */
2160   seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
2161                        TRAP_CODE (PATTERN (trap)));
2162   if (seq == NULL)
2163     return FALSE;
2164
2165   /* Emit the new insns before cond_earliest; delete the old jump.  */
2166   emit_insn_before (seq, cond_earliest);
2167   delete_insn (jump);
2168
2169   /* Delete the trap block together with its insn.  */
2170   if (trap_bb == then_bb)
2171     then_bb = NULL;
2172   else if (else_bb == NULL)
2173     ;
2174   else if (trap_bb == else_bb)
2175     else_bb = NULL;
2176   else
2177     abort ();
2178   flow_delete_block (trap_bb);
2179   num_removed_blocks++;
2180
2181   /* Merge what's left.  */
2182   merge_if_block (test_bb, then_bb, else_bb, join_bb);
2183
2184   return TRUE;
2185 }
2186
2187 /* Subroutine of find_cond_trap: if BB contains only a trap insn, 
2188    return it.  */
2189
2190 static rtx
2191 block_has_only_trap (bb)
2192      basic_block bb;
2193 {
2194   rtx trap;
2195
2196   /* We're not the exit block.  */
2197   if (bb == EXIT_BLOCK_PTR)
2198     return NULL_RTX;
2199
2200   /* The block must have no successors.  */
2201   if (bb->succ)
2202     return NULL_RTX;
2203
2204   /* The only instruction in the THEN block must be the trap.  */
2205   trap = first_active_insn (bb);
2206   if (! (trap == bb->end
2207          && GET_CODE (PATTERN (trap)) == TRAP_IF
2208          && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
2209     return NULL_RTX;
2210
2211   return trap;
2212 }
2213
2214 /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
2215    transformable, but not necessarily the other.  There need be no
2216    JOIN block.
2217
2218    Return TRUE if we were successful at converting the the block.
2219
2220    Cases we'd like to look at:
2221
2222    (1)
2223         if (test) goto over; // x not live
2224         x = a;
2225         goto label;
2226         over:
2227
2228    becomes
2229
2230         x = a;
2231         if (! test) goto label;
2232
2233    (2)
2234         if (test) goto E; // x not live
2235         x = big();
2236         goto L;
2237         E:
2238         x = b;
2239         goto M;
2240
2241    becomes
2242
2243         x = b;
2244         if (test) goto M;
2245         x = big();
2246         goto L;
2247
2248    (3) // This one's really only interesting for targets that can do
2249        // multiway branching, e.g. IA-64 BBB bundles.  For other targets
2250        // it results in multiple branches on a cache line, which often
2251        // does not sit well with predictors.
2252
2253         if (test1) goto E; // predicted not taken
2254         x = a;
2255         if (test2) goto F;
2256         ...
2257         E:
2258         x = b;
2259         J:
2260
2261    becomes
2262
2263         x = a;
2264         if (test1) goto E;
2265         if (test2) goto F;
2266
2267    Notes:
2268
2269    (A) Don't do (2) if the branch is predicted against the block we're
2270    eliminating.  Do it anyway if we can eliminate a branch; this requires
2271    that the sole successor of the eliminated block postdominate the other
2272    side of the if.
2273
2274    (B) With CE, on (3) we can steal from both sides of the if, creating
2275
2276         if (test1) x = a;
2277         if (!test1) x = b;
2278         if (test1) goto J;
2279         if (test2) goto F;
2280         ...
2281         J:
2282
2283    Again, this is most useful if J postdominates.
2284
2285    (C) CE substitutes for helpful life information.
2286
2287    (D) These heuristics need a lot of work.  */
2288
2289 /* Tests for case 1 above.  */
2290
2291 static int
2292 find_if_case_1 (test_bb, then_edge, else_edge)
2293       basic_block test_bb;
2294       edge then_edge, else_edge;
2295 {
2296   basic_block then_bb = then_edge->dest;
2297   basic_block else_bb = else_edge->dest, new_bb;
2298   edge then_succ = then_bb->succ;
2299
2300   /* THEN has one successor.  */
2301   if (!then_succ || then_succ->succ_next != NULL)
2302     return FALSE;
2303
2304   /* THEN does not fall through, but is not strange either.  */
2305   if (then_succ->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
2306     return FALSE;
2307
2308   /* THEN has one predecessor.  */
2309   if (then_bb->pred->pred_next != NULL)
2310     return FALSE;
2311
2312   /* THEN must do something.  */
2313   if (forwarder_block_p (then_bb))
2314     return FALSE;
2315
2316   num_possible_if_blocks++;
2317   if (rtl_dump_file)
2318     fprintf (rtl_dump_file,
2319              "\nIF-CASE-1 found, start %d, then %d\n",
2320              test_bb->index, then_bb->index);
2321
2322   /* THEN is small.  */
2323   if (count_bb_insns (then_bb) > BRANCH_COST)
2324     return FALSE;
2325
2326   /* Registers set are dead, or are predicable.  */
2327   if (! dead_or_predicable (test_bb, then_bb, else_bb, 
2328                             then_bb->succ->dest, 1))
2329     return FALSE;
2330
2331   /* Conversion went ok, including moving the insns and fixing up the
2332      jump.  Adjust the CFG to match.  */
2333
2334   bitmap_operation (test_bb->global_live_at_end,
2335                     else_bb->global_live_at_start,
2336                     then_bb->global_live_at_end, BITMAP_IOR);
2337   
2338   new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
2339   /* Make rest of code believe that the newly created block is the THEN_BB
2340      block we are going to remove.  */
2341   if (new_bb)
2342     new_bb->aux = then_bb->aux;
2343   flow_delete_block (then_bb);
2344   /* We've possibly created jump to next insn, cleanup_cfg will solve that
2345      later.  */
2346
2347   num_removed_blocks++;
2348   num_updated_if_blocks++;
2349
2350   return TRUE;
2351 }
2352
2353 /* Test for case 2 above.  */
2354
2355 static int
2356 find_if_case_2 (test_bb, then_edge, else_edge)
2357       basic_block test_bb;
2358       edge then_edge, else_edge;
2359 {
2360   basic_block then_bb = then_edge->dest;
2361   basic_block else_bb = else_edge->dest;
2362   edge else_succ = else_bb->succ;
2363   rtx note;
2364
2365   /* ELSE has one successor.  */
2366   if (!else_succ || else_succ->succ_next != NULL)
2367     return FALSE;
2368
2369   /* ELSE outgoing edge is not complex.  */
2370   if (else_succ->flags & EDGE_COMPLEX)
2371     return FALSE;
2372
2373   /* ELSE has one predecessor.  */
2374   if (else_bb->pred->pred_next != NULL)
2375     return FALSE;
2376
2377   /* THEN is not EXIT.  */
2378   if (then_bb->index < 0)
2379     return FALSE;
2380
2381   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
2382   note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
2383   if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
2384     ;
2385   else if (else_succ->dest->index < 0
2386            || TEST_BIT (post_dominators[ORIG_INDEX (then_bb)], 
2387                         ORIG_INDEX (else_succ->dest)))
2388     ;
2389   else
2390     return FALSE;
2391
2392   num_possible_if_blocks++;
2393   if (rtl_dump_file)
2394     fprintf (rtl_dump_file,
2395              "\nIF-CASE-2 found, start %d, else %d\n",
2396              test_bb->index, else_bb->index);
2397
2398   /* ELSE is small.  */
2399   if (count_bb_insns (then_bb) > BRANCH_COST)
2400     return FALSE;
2401
2402   /* Registers set are dead, or are predicable.  */
2403   if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
2404     return FALSE;
2405
2406   /* Conversion went ok, including moving the insns and fixing up the
2407      jump.  Adjust the CFG to match.  */
2408
2409   bitmap_operation (test_bb->global_live_at_end,
2410                     then_bb->global_live_at_start,
2411                     else_bb->global_live_at_end, BITMAP_IOR);
2412   
2413   flow_delete_block (else_bb);
2414
2415   num_removed_blocks++;
2416   num_updated_if_blocks++;
2417
2418   /* ??? We may now fallthru from one of THEN's successors into a join
2419      block.  Rerun cleanup_cfg?  Examine things manually?  Wait?  */
2420
2421   return TRUE;
2422 }
2423
2424 /* A subroutine of dead_or_predicable called through for_each_rtx.
2425    Return 1 if a memory is found.  */
2426
2427 static int
2428 find_memory (px, data)
2429      rtx *px;
2430      void *data ATTRIBUTE_UNUSED;
2431 {
2432   return GET_CODE (*px) == MEM;
2433 }
2434
2435 /* Used by the code above to perform the actual rtl transformations.
2436    Return TRUE if successful.
2437
2438    TEST_BB is the block containing the conditional branch.  MERGE_BB
2439    is the block containing the code to manipulate.  NEW_DEST is the
2440    label TEST_BB should be branching to after the conversion.
2441    REVERSEP is true if the sense of the branch should be reversed.  */
2442
2443 static int
2444 dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
2445      basic_block test_bb, merge_bb, other_bb;
2446      basic_block new_dest;
2447      int reversep;
2448 {
2449   rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX;
2450
2451   jump = test_bb->end;
2452
2453   /* Find the extent of the real code in the merge block.  */
2454   head = merge_bb->head;
2455   end = merge_bb->end;
2456
2457   if (GET_CODE (head) == CODE_LABEL)
2458     head = NEXT_INSN (head);
2459   if (GET_CODE (head) == NOTE)
2460     {
2461       if (head == end)
2462         {
2463           head = end = NULL_RTX;
2464           goto no_body;
2465         }
2466       head = NEXT_INSN (head);
2467     }
2468
2469   if (GET_CODE (end) == JUMP_INSN)
2470     {
2471       if (head == end)
2472         {
2473           head = end = NULL_RTX;
2474           goto no_body;
2475         }
2476       end = PREV_INSN (end);
2477     }
2478
2479   /* Disable handling dead code by conditional execution if the machine needs
2480      to do anything funny with the tests, etc.  */
2481 #ifndef IFCVT_MODIFY_TESTS
2482   if (HAVE_conditional_execution)
2483     {
2484       /* In the conditional execution case, we have things easy.  We know
2485          the condition is reversable.  We don't have to check life info,
2486          becase we're going to conditionally execute the code anyway.
2487          All that's left is making sure the insns involved can actually
2488          be predicated.  */
2489
2490       rtx cond, prob_val;
2491
2492       cond = cond_exec_get_condition (jump);
2493       if (! cond)
2494         return FALSE;
2495
2496       prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
2497       if (prob_val)
2498         prob_val = XEXP (prob_val, 0);
2499
2500       if (reversep)
2501         {
2502           enum rtx_code rev = reversed_comparison_code (cond, jump);
2503           if (rev == UNKNOWN)
2504             return FALSE;
2505           cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
2506                                  XEXP (cond, 1));
2507           if (prob_val)
2508             prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
2509         }
2510
2511       if (! cond_exec_process_insns (head, end, cond, prob_val, 0))
2512         goto cancel;
2513
2514       earliest = jump;
2515     }
2516   else
2517 #endif
2518     {
2519       /* In the non-conditional execution case, we have to verify that there
2520          are no trapping operations, no calls, no references to memory, and
2521          that any registers modified are dead at the branch site.  */
2522
2523       rtx insn, cond, prev;
2524       regset_head merge_set_head, tmp_head, test_live_head, test_set_head;
2525       regset merge_set, tmp, test_live, test_set;
2526       struct propagate_block_info *pbi;
2527       int i, fail = 0;
2528
2529       /* Check for no calls or trapping operations.  */
2530       for (insn = head; ; insn = NEXT_INSN (insn))
2531         {
2532           if (GET_CODE (insn) == CALL_INSN)
2533             return FALSE;
2534           if (INSN_P (insn))
2535             {
2536               if (may_trap_p (PATTERN (insn)))
2537                 return FALSE;
2538
2539               /* ??? Even non-trapping memories such as stack frame
2540                  references must be avoided.  For stores, we collect
2541                  no lifetime info; for reads, we'd have to assert
2542                  true_dependence false against every store in the
2543                  TEST range.  */
2544               if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
2545                 return FALSE;
2546             }
2547           if (insn == end)
2548             break;
2549         }
2550
2551       if (! any_condjump_p (jump))
2552         return FALSE;
2553
2554       /* Find the extent of the conditional.  */
2555       cond = noce_get_condition (jump, &earliest);
2556       if (! cond)
2557         return FALSE;
2558
2559       /* Collect:
2560            MERGE_SET = set of registers set in MERGE_BB
2561            TEST_LIVE = set of registers live at EARLIEST
2562            TEST_SET  = set of registers set between EARLIEST and the
2563                        end of the block.  */
2564
2565       tmp = INITIALIZE_REG_SET (tmp_head);
2566       merge_set = INITIALIZE_REG_SET (merge_set_head);
2567       test_live = INITIALIZE_REG_SET (test_live_head);
2568       test_set = INITIALIZE_REG_SET (test_set_head);
2569
2570       /* ??? bb->local_set is only valid during calculate_global_regs_live,
2571          so we must recompute usage for MERGE_BB.  Not so bad, I suppose, 
2572          since we've already asserted that MERGE_BB is small.  */
2573       propagate_block (merge_bb, tmp, merge_set, merge_set, 0);
2574
2575       /* For small register class machines, don't lengthen lifetimes of
2576          hard registers before reload.  */
2577       if (SMALL_REGISTER_CLASSES && ! reload_completed)
2578         {
2579           EXECUTE_IF_SET_IN_BITMAP
2580             (merge_set, 0, i,
2581              {
2582                if (i < FIRST_PSEUDO_REGISTER
2583                    && ! fixed_regs[i]
2584                    && ! global_regs[i])
2585                 fail = 1;
2586              });
2587         }
2588
2589       /* For TEST, we're interested in a range of insns, not a whole block.
2590          Moreover, we're interested in the insns live from OTHER_BB.  */
2591
2592       COPY_REG_SET (test_live, other_bb->global_live_at_start);
2593       pbi = init_propagate_block_info (test_bb, test_live, test_set, test_set,
2594                                        0);
2595
2596       for (insn = jump; ; insn = prev)
2597         {
2598           prev = propagate_one_insn (pbi, insn);
2599           if (insn == earliest)
2600             break;
2601         }
2602
2603       free_propagate_block_info (pbi);
2604
2605       /* We can perform the transformation if
2606            MERGE_SET & (TEST_SET | TEST_LIVE)
2607          and
2608            TEST_SET & merge_bb->global_live_at_start
2609          are empty.  */
2610
2611       bitmap_operation (tmp, test_set, test_live, BITMAP_IOR);
2612       bitmap_operation (tmp, tmp, merge_set, BITMAP_AND);
2613       EXECUTE_IF_SET_IN_BITMAP(tmp, 0, i, fail = 1);
2614
2615       bitmap_operation (tmp, test_set, merge_bb->global_live_at_start,
2616                         BITMAP_AND);
2617       EXECUTE_IF_SET_IN_BITMAP(tmp, 0, i, fail = 1);
2618
2619       FREE_REG_SET (tmp);
2620       FREE_REG_SET (merge_set);
2621       FREE_REG_SET (test_live);
2622       FREE_REG_SET (test_set);
2623
2624       if (fail)
2625         return FALSE;
2626     }
2627
2628  no_body:
2629   /* We don't want to use normal invert_jump or redirect_jump because
2630      we don't want to delete_insn called.  Also, we want to do our own
2631      change group management.  */
2632
2633   old_dest = JUMP_LABEL (jump);
2634   if (other_bb != new_dest)
2635     {
2636       new_label = block_label (new_dest);
2637       if (reversep
2638           ? ! invert_jump_1 (jump, new_label)
2639           : ! redirect_jump_1 (jump, new_label))
2640         goto cancel;
2641     }
2642
2643   if (! apply_change_group ())
2644     return FALSE;
2645
2646   if (other_bb != new_dest)
2647     {
2648       if (old_dest)
2649         LABEL_NUSES (old_dest) -= 1;
2650       if (new_label)
2651         LABEL_NUSES (new_label) += 1;
2652       JUMP_LABEL (jump) = new_label;
2653       if (reversep)
2654         invert_br_probabilities (jump);
2655
2656       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
2657       if (reversep)
2658         {
2659           gcov_type count, probability;
2660           count = BRANCH_EDGE (test_bb)->count;
2661           BRANCH_EDGE (test_bb)->count = FALLTHRU_EDGE (test_bb)->count;
2662           FALLTHRU_EDGE (test_bb)->count = count;
2663           probability = BRANCH_EDGE (test_bb)->probability;
2664           BRANCH_EDGE (test_bb)->probability
2665             = FALLTHRU_EDGE (test_bb)->probability;
2666           FALLTHRU_EDGE (test_bb)->probability = probability;
2667           update_br_prob_note (test_bb);
2668         }
2669     }
2670
2671   /* Move the insns out of MERGE_BB to before the branch.  */
2672   if (head != NULL)
2673     {
2674       if (end == merge_bb->end)
2675         merge_bb->end = PREV_INSN (head);
2676
2677       if (squeeze_notes (&head, &end))
2678         return TRUE;
2679
2680       reorder_insns (head, end, PREV_INSN (earliest));
2681     }
2682
2683   /* Remove the jump and edge if we can.  */
2684   if (other_bb == new_dest)
2685     {
2686       delete_insn (jump);
2687       remove_edge (BRANCH_EDGE (test_bb));
2688       /* ??? Can't merge blocks here, as then_bb is still in use.
2689          At minimum, the merge will get done just before bb-reorder.  */
2690     }
2691
2692   return TRUE;
2693
2694  cancel:
2695   cancel_changes (0);
2696   return FALSE;
2697 }
2698 \f
2699 /* Main entry point for all if-conversion.  */
2700
2701 void
2702 if_convert (x_life_data_ok)
2703      int x_life_data_ok;
2704 {
2705   int block_num;
2706
2707   num_possible_if_blocks = 0;
2708   num_updated_if_blocks = 0;
2709   num_removed_blocks = 0;
2710   life_data_ok = (x_life_data_ok != 0);
2711
2712   /* Free up basic_block_for_insn so that we don't have to keep it 
2713      up to date, either here or in merge_blocks_nomove.  */
2714   free_basic_block_vars (1);
2715
2716   /* Compute postdominators if we think we'll use them.  */
2717   post_dominators = NULL;
2718   if (HAVE_conditional_execution || life_data_ok)
2719     {
2720       post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
2721       calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS);
2722     }
2723   if (life_data_ok)
2724     clear_bb_flags ();
2725
2726   /* Record initial block numbers.  */
2727   for (block_num = 0; block_num < n_basic_blocks; block_num++)
2728     SET_ORIG_INDEX (BASIC_BLOCK (block_num), block_num);
2729
2730   /* Go through each of the basic blocks looking for things to convert.  */
2731   for (block_num = 0; block_num < n_basic_blocks; )
2732     {
2733       basic_block bb = BASIC_BLOCK (block_num);
2734       if (find_if_header (bb))
2735         block_num = bb->index;
2736       else 
2737         block_num++;
2738     }
2739
2740   if (post_dominators)
2741     sbitmap_vector_free (post_dominators);
2742
2743   if (rtl_dump_file)
2744     fflush (rtl_dump_file);
2745
2746   clear_aux_for_blocks ();
2747
2748   /* Rebuild life info for basic blocks that require it.  */
2749   if (num_removed_blocks && life_data_ok)
2750     {
2751       /* If we allocated new pseudos, we must resize the array for sched1.  */
2752       if (max_regno < max_reg_num ())
2753         {
2754           max_regno = max_reg_num ();
2755           allocate_reg_info (max_regno, FALSE, FALSE);
2756         }
2757       update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
2758                                         PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
2759                                         | PROP_KILL_DEAD_CODE);
2760     }
2761
2762   /* Write the final stats.  */
2763   if (rtl_dump_file && num_possible_if_blocks > 0)
2764     {
2765       fprintf (rtl_dump_file,
2766                "\n%d possible IF blocks searched.\n",
2767                num_possible_if_blocks);
2768       fprintf (rtl_dump_file,
2769                "%d IF blocks converted.\n",
2770                num_updated_if_blocks);
2771       fprintf (rtl_dump_file,
2772                "%d basic blocks deleted.\n\n\n",
2773                num_removed_blocks);
2774     }
2775
2776 #ifdef ENABLE_CHECKING
2777   verify_flow_info ();
2778 #endif
2779 }